panda-core 0.11.0 → 0.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +15 -0
- data/app/assets/tailwind/application.css +5 -0
- data/app/models/panda/core/user.rb +20 -11
- data/config/brakeman.ignore +51 -0
- data/db/migrate/20250809000001_create_panda_core_users.rb +1 -1
- data/db/migrate/20251203100000_rename_is_admin_to_admin_in_panda_core_users.rb +18 -0
- data/lib/panda/core/configuration.rb +4 -0
- data/lib/panda/core/engine/autoload_config.rb +9 -10
- data/lib/panda/core/engine/omniauth_config.rb +82 -36
- data/lib/panda/core/engine/route_config.rb +37 -0
- data/lib/panda/core/engine.rb +46 -41
- data/lib/panda/core/middleware.rb +146 -0
- data/lib/panda/core/testing/rails_helper.rb +17 -8
- data/lib/panda/core/testing/support/authentication_helpers.rb +6 -6
- data/lib/panda/core/testing/support/authentication_test_helpers.rb +2 -12
- data/lib/panda/core/testing/support/system/browser_console_logger.rb +1 -2
- data/lib/panda/core/testing/support/system/chrome_path.rb +38 -0
- data/lib/panda/core/testing/support/system/cuprite_helpers.rb +79 -0
- data/lib/panda/core/testing/support/system/cuprite_setup.rb +61 -66
- data/lib/panda/core/testing/support/system/system_test_helpers.rb +11 -11
- data/lib/panda/core/version.rb +1 -1
- data/lib/tasks/panda/core/users.rake +3 -3
- data/lib/tasks/panda/shared.rake +31 -5
- data/public/panda-core-assets/favicons/browserconfig.xml +1 -1
- data/public/panda-core-assets/favicons/site.webmanifest +1 -1
- data/public/panda-core-assets/panda-core-0.11.0.css +2 -0
- data/public/panda-core-assets/panda-core.css +2 -2
- metadata +8 -8
- data/lib/panda/core/engine/middleware_config.rb +0 -17
- data/lib/panda/core/testing/support/system/better_system_tests.rb +0 -180
- data/lib/panda/core/testing/support/system/capybara_config.rb +0 -64
- data/lib/panda/core/testing/support/system/ci_capybara_config.rb +0 -77
- data/public/panda-core-assets/panda-core-0.10.6.css +0 -2
- data/public/panda-core-assets/panda-core-0.10.7.css +0 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1865844f240222fd1894bae360505e3954858ac363b49d4bd0aa59bb8699fdcc
|
|
4
|
+
data.tar.gz: a85741affaa234bd9899c670da3b7a4eab5c7aa65bf09ba89081b49606ecbf66
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a873452e2589d9fc7e4254f7ef81b4bb8cbccc2a57fd19d17f95aed22609d1226711579fe905b5caf269fec5506a203fa93ab16b10073ec372bf033e0ccd70be
|
|
7
|
+
data.tar.gz: c1be83e01a08ff7a6ddce1b2afc321ec780dd5f2b00837220c411838f39e0dd9584419737239c8640a25e15b4d86ea190109fc22c26291ea21d6551317082773
|
data/README.md
CHANGED
|
@@ -271,6 +271,21 @@ bundle exec rspec spec/generators
|
|
|
271
271
|
bundle exec rspec spec/system
|
|
272
272
|
```
|
|
273
273
|
|
|
274
|
+
### CI/Docker parity
|
|
275
|
+
|
|
276
|
+
The GitHub Actions workflow now builds a reusable CI image (Chrome + PostgreSQL + Ruby). You can reuse it locally:
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
bin/ci build # build the CI image locally
|
|
280
|
+
bin/ci test # run the suite inside the container
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
To dry-run the workflow with `act` (uses the locally built image tagged `:local`):
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
act -j test-stable
|
|
287
|
+
```
|
|
288
|
+
|
|
274
289
|
## Contributing
|
|
275
290
|
|
|
276
291
|
1. Fork it
|
|
@@ -153,6 +153,11 @@
|
|
|
153
153
|
html[data-theme='sky'] .bg-gradient-admin {
|
|
154
154
|
background: linear-gradient(to bottom right, rgb(20, 32, 74), rgb(42, 102, 159));
|
|
155
155
|
}
|
|
156
|
+
|
|
157
|
+
/* Remove rounded bottom-left corner on admin sidebar */
|
|
158
|
+
.bg-gradient-admin {
|
|
159
|
+
border-bottom-left-radius: 0;
|
|
160
|
+
}
|
|
156
161
|
}
|
|
157
162
|
|
|
158
163
|
/* Form input styles */
|
|
@@ -19,16 +19,15 @@ module Panda
|
|
|
19
19
|
|
|
20
20
|
before_save :downcase_email
|
|
21
21
|
|
|
22
|
+
# Determine which column stores admin flag (supports legacy `admin` and new `is_admin`)
|
|
23
|
+
def self.admin_column
|
|
24
|
+
# Prefer canonical `admin` if available, otherwise fall back to legacy `is_admin`
|
|
25
|
+
@admin_column ||= column_names.include?("admin") ? "admin" : "is_admin"
|
|
26
|
+
end
|
|
27
|
+
|
|
22
28
|
# Scopes
|
|
23
|
-
# Support both 'admin' (newer) and 'is_admin' (older) column names
|
|
24
29
|
scope :admins, -> {
|
|
25
|
-
|
|
26
|
-
where(admin: true)
|
|
27
|
-
elsif column_names.include?("is_admin")
|
|
28
|
-
where(is_admin: true)
|
|
29
|
-
else
|
|
30
|
-
none
|
|
31
|
-
end
|
|
30
|
+
where(admin_column => true)
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
def self.find_or_create_from_auth_hash(auth_hash)
|
|
@@ -48,7 +47,7 @@ module Panda
|
|
|
48
47
|
email: auth_hash.info.email.downcase,
|
|
49
48
|
name: auth_hash.info.name || "Unknown User",
|
|
50
49
|
image_url: auth_hash.info.image,
|
|
51
|
-
|
|
50
|
+
admin_column => User.count.zero? # First user is admin
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
user = create!(attributes)
|
|
@@ -62,10 +61,20 @@ module Panda
|
|
|
62
61
|
end
|
|
63
62
|
|
|
64
63
|
# Admin status check
|
|
65
|
-
# Note: Column is named 'admin' in newer schemas, 'is_admin' in older ones
|
|
66
64
|
def admin?
|
|
67
|
-
|
|
65
|
+
ActiveRecord::Type::Boolean.new.cast(admin)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Support both legacy `admin` and new `is_admin` columns
|
|
69
|
+
def admin
|
|
70
|
+
self[self.class.admin_column]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def admin=(value)
|
|
74
|
+
self[self.class.admin_column] = ActiveRecord::Type::Boolean.new.cast(value)
|
|
68
75
|
end
|
|
76
|
+
alias_method :is_admin, :admin
|
|
77
|
+
alias_method :is_admin=, :admin=
|
|
69
78
|
|
|
70
79
|
def active_for_authentication?
|
|
71
80
|
true
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"ignored_warnings": [
|
|
3
|
+
{
|
|
4
|
+
"warning_type": "Command Injection",
|
|
5
|
+
"warning_code": 14,
|
|
6
|
+
"fingerprint": "29d5b60b583fc98e293f6ac47f153bbf5db48a03963f8c9a7711bd251ecf2d81",
|
|
7
|
+
"check_name": "Execute",
|
|
8
|
+
"message": "Possible command injection",
|
|
9
|
+
"file": "lib/panda/core/testing/support/system/cuprite_helpers.rb",
|
|
10
|
+
"line": 78,
|
|
11
|
+
"link": "https://brakemanscanner.org/docs/warning_types/command_injection/",
|
|
12
|
+
"code": "system(\"ffmpeg -y -framerate 8 -pattern_type glob -i '#{File.join(dir, \"frames\")}/*.png' -c:v libx264 -pix_fmt yuv420p '#{capybara_artifacts_dir.join(\"#{example.metadata[:full_description].parameterize}.mp4\")}'\\n\")",
|
|
13
|
+
"render_path": null,
|
|
14
|
+
"location": {
|
|
15
|
+
"type": "method",
|
|
16
|
+
"class": "Panda::Core::Testing::CupriteHelpers",
|
|
17
|
+
"method": "record_video!"
|
|
18
|
+
},
|
|
19
|
+
"user_input": "File.join(dir, \"frames\")",
|
|
20
|
+
"confidence": "Medium",
|
|
21
|
+
"cwe_id": [
|
|
22
|
+
77
|
|
23
|
+
],
|
|
24
|
+
"note": "This does not use user input and is based on environment variables and the current folder"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"warning_type": "Command Injection",
|
|
28
|
+
"warning_code": 14,
|
|
29
|
+
"fingerprint": "d3c339f054cbd511956e04eaf8763bc722bd2e4559a1c1fec58749abef9792cd",
|
|
30
|
+
"check_name": "Execute",
|
|
31
|
+
"message": "Possible command injection",
|
|
32
|
+
"file": "lib/panda/core/testing/support/system/chrome_verification.rb",
|
|
33
|
+
"line": 43,
|
|
34
|
+
"link": "https://brakemanscanner.org/docs/warning_types/command_injection/",
|
|
35
|
+
"code": "Process.spawn(*[BrowserPath.resolve, v.nil? ? (\"--#{k}\") : (\"--#{k}=#{v}\"), \"about:blank\"], :out => (File::NULL), :err => (File::NULL))",
|
|
36
|
+
"render_path": null,
|
|
37
|
+
"location": {
|
|
38
|
+
"type": "method",
|
|
39
|
+
"class": "Panda::Core::Testing::Support::System::ChromeVerification",
|
|
40
|
+
"method": "s(:self).verify!"
|
|
41
|
+
},
|
|
42
|
+
"user_input": "k",
|
|
43
|
+
"confidence": "Medium",
|
|
44
|
+
"cwe_id": [
|
|
45
|
+
77
|
|
46
|
+
],
|
|
47
|
+
"note": "Chrome verification uses a fixed set of browser flags from CHROME_FLAGS constant; no user input is accepted"
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"brakeman_version": "7.1.1"
|
|
51
|
+
}
|
|
@@ -11,7 +11,7 @@ class CreatePandaCoreUsers < ActiveRecord::Migration[7.1]
|
|
|
11
11
|
t.string :name
|
|
12
12
|
t.string :email, null: false
|
|
13
13
|
t.string :image_url
|
|
14
|
-
t.boolean :
|
|
14
|
+
t.boolean :admin, default: false, null: false
|
|
15
15
|
t.string :current_theme
|
|
16
16
|
t.string :oauth_avatar_url
|
|
17
17
|
t.timestamps
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class RenameIsAdminToAdminInPandaCoreUsers < ActiveRecord::Migration[7.1]
|
|
4
|
+
def up
|
|
5
|
+
# If apps created an `is_admin` column during the brief rename, move it back
|
|
6
|
+
return unless column_exists?(:panda_core_users, :is_admin)
|
|
7
|
+
return if column_exists?(:panda_core_users, :admin)
|
|
8
|
+
|
|
9
|
+
rename_column :panda_core_users, :is_admin, :admin
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def down
|
|
13
|
+
return unless column_exists?(:panda_core_users, :admin)
|
|
14
|
+
return if column_exists?(:panda_core_users, :is_admin)
|
|
15
|
+
|
|
16
|
+
rename_column :panda_core_users, :admin, :is_admin
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require "active_support/core_ext/numeric/bytes"
|
|
2
|
+
|
|
1
3
|
module Panda
|
|
2
4
|
module Core
|
|
3
5
|
class Configuration
|
|
@@ -7,6 +9,7 @@ module Panda
|
|
|
7
9
|
:cache_store,
|
|
8
10
|
:parent_controller,
|
|
9
11
|
:parent_mailer,
|
|
12
|
+
:auto_mount_engine,
|
|
10
13
|
:mailer_sender,
|
|
11
14
|
:mailer_default_url_options,
|
|
12
15
|
:session_token_cookie,
|
|
@@ -38,6 +41,7 @@ module Panda
|
|
|
38
41
|
@cache_store = :memory_store
|
|
39
42
|
@parent_controller = "ActionController::API"
|
|
40
43
|
@parent_mailer = "ActionMailer::Base"
|
|
44
|
+
@auto_mount_engine = true
|
|
41
45
|
@mailer_sender = "support@example.com"
|
|
42
46
|
@mailer_default_url_options = {host: "localhost:3000"}
|
|
43
47
|
@session_token_cookie = :panda_session
|
|
@@ -3,21 +3,20 @@
|
|
|
3
3
|
module Panda
|
|
4
4
|
module Core
|
|
5
5
|
class Engine < ::Rails::Engine
|
|
6
|
-
# Autoload paths configuration
|
|
7
6
|
module AutoloadConfig
|
|
8
7
|
extend ActiveSupport::Concern
|
|
9
8
|
|
|
10
9
|
included do
|
|
11
|
-
|
|
10
|
+
# These must run BEFORE initialization, so this is allowed
|
|
11
|
+
config.autoload_paths << root.join("app/builders")
|
|
12
|
+
config.autoload_paths << root.join("app/components")
|
|
13
|
+
config.autoload_paths << root.join("app/services")
|
|
14
|
+
config.autoload_paths << root.join("app/models")
|
|
15
|
+
config.autoload_paths << root.join("app/helpers")
|
|
16
|
+
config.autoload_paths << root.join("app/constraints")
|
|
12
17
|
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
# Zeitwerk will automatically discover nested modules from these roots
|
|
16
|
-
config.autoload_paths += Dir[root.join("app", "models")]
|
|
17
|
-
config.autoload_paths += Dir[root.join("app", "controllers")]
|
|
18
|
-
config.autoload_paths += Dir[root.join("app", "builders")]
|
|
19
|
-
config.autoload_paths += Dir[root.join("app", "components")]
|
|
20
|
-
config.autoload_paths += Dir[root.join("app", "services")]
|
|
18
|
+
# Mirror eager-load as needed
|
|
19
|
+
config.eager_load_paths.concat(config.autoload_paths)
|
|
21
20
|
end
|
|
22
21
|
end
|
|
23
22
|
end
|
|
@@ -1,51 +1,97 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "active_support/concern"
|
|
4
|
+
|
|
3
5
|
module Panda
|
|
4
6
|
module Core
|
|
5
7
|
class Engine < ::Rails::Engine
|
|
6
|
-
# OmniAuth configuration
|
|
7
8
|
module OmniauthConfig
|
|
8
9
|
extend ActiveSupport::Concern
|
|
9
10
|
|
|
11
|
+
PROVIDER_REGISTRY = {
|
|
12
|
+
# Microsoft
|
|
13
|
+
"microsoft" => :microsoft_graph,
|
|
14
|
+
"microsoft_graph" => :microsoft_graph,
|
|
15
|
+
|
|
16
|
+
# Google
|
|
17
|
+
"google" => :google_oauth2,
|
|
18
|
+
"google_oauth2" => :google_oauth2,
|
|
19
|
+
"gmail" => :google_oauth2,
|
|
20
|
+
|
|
21
|
+
# GitHub
|
|
22
|
+
"github" => :github,
|
|
23
|
+
"gh" => :github,
|
|
24
|
+
|
|
25
|
+
# Developer
|
|
26
|
+
"developer" => :developer
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
10
29
|
included do
|
|
11
|
-
initializer
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
configure do |config|
|
|
20
|
-
config.path_prefix = "#{Panda::Core.config.admin_path}/auth"
|
|
21
|
-
# POST-only for CSRF protection (CVE-2015-9284)
|
|
22
|
-
# All login forms use POST via form_tag method: "post"
|
|
23
|
-
config.allowed_request_methods = [:post]
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
Panda::Core.config.authentication_providers.each do |provider_name, settings|
|
|
27
|
-
# Build provider options, allowing custom path name override
|
|
28
|
-
provider_options = settings[:options] || {}
|
|
29
|
-
|
|
30
|
-
# If path_name is specified, use it to override the default strategy name in URLs
|
|
31
|
-
if settings[:path_name].present?
|
|
32
|
-
provider_options = provider_options.merge(name: settings[:path_name])
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
case provider_name.to_s
|
|
36
|
-
when "microsoft_graph"
|
|
37
|
-
provider :microsoft_graph, settings[:client_id], settings[:client_secret], provider_options
|
|
38
|
-
when "google_oauth2"
|
|
39
|
-
provider :google_oauth2, settings[:client_id], settings[:client_secret], provider_options
|
|
40
|
-
when "github"
|
|
41
|
-
provider :github, settings[:client_id], settings[:client_secret], provider_options
|
|
42
|
-
when "developer"
|
|
43
|
-
provider :developer if Rails.env.development?
|
|
44
|
-
end
|
|
45
|
-
end
|
|
30
|
+
if respond_to?(:initializer)
|
|
31
|
+
initializer "panda_core.omniauth" do |app|
|
|
32
|
+
require_relative "../oauth_providers"
|
|
33
|
+
Panda::Core::OAuthProviders.setup
|
|
34
|
+
|
|
35
|
+
load_yaml_provider_overrides!
|
|
36
|
+
configure_omniauth_globals
|
|
37
|
+
mount_omniauth_middleware(app)
|
|
46
38
|
end
|
|
47
39
|
end
|
|
48
40
|
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
# 1. YAML overrides
|
|
45
|
+
def load_yaml_provider_overrides!
|
|
46
|
+
path = Panda::Core::Engine.root.join("config/providers.yml")
|
|
47
|
+
return unless File.exist?(path)
|
|
48
|
+
|
|
49
|
+
yaml = YAML.load_file(path) || {}
|
|
50
|
+
(yaml["providers"] || {}).each do |name, settings|
|
|
51
|
+
Panda::Core.config.authentication_providers[name.to_s] ||= {}
|
|
52
|
+
Panda::Core.config.authentication_providers[name.to_s].deep_merge!(settings)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# 2. Global settings
|
|
57
|
+
def configure_omniauth_globals
|
|
58
|
+
OmniAuth.configure do |c|
|
|
59
|
+
c.allowed_request_methods = [:post]
|
|
60
|
+
c.path_prefix = "#{Panda::Core.config.admin_path}/auth"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# 3. Middleware insertion
|
|
65
|
+
def mount_omniauth_middleware(app)
|
|
66
|
+
ctx = self # Capture the Engine/Concern context
|
|
67
|
+
|
|
68
|
+
Panda::Core::Middleware.use(app, OmniAuth::Builder) do
|
|
69
|
+
Panda::Core.config.authentication_providers.each do |name, settings|
|
|
70
|
+
ctx.send(:configure_provider, self, name, settings)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# 4. Provider builder
|
|
76
|
+
def configure_provider(builder, name, settings)
|
|
77
|
+
symbol = PROVIDER_REGISTRY[name.to_s]
|
|
78
|
+
|
|
79
|
+
unless symbol
|
|
80
|
+
Rails.logger.warn("[panda-core] Unknown OmniAuth provider: #{name.inspect}")
|
|
81
|
+
return
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
return if symbol == :developer && !Rails.env.development?
|
|
85
|
+
|
|
86
|
+
options = (settings[:options] || {}).dup
|
|
87
|
+
options[:name] = settings[:path_name] if settings[:path_name].present?
|
|
88
|
+
|
|
89
|
+
if settings[:client_id] && settings[:client_secret]
|
|
90
|
+
builder.provider symbol, settings[:client_id], settings[:client_secret], options
|
|
91
|
+
else
|
|
92
|
+
builder.provider symbol, options
|
|
93
|
+
end
|
|
94
|
+
end
|
|
49
95
|
end
|
|
50
96
|
end
|
|
51
97
|
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Panda
|
|
4
|
+
module Core
|
|
5
|
+
class Engine < ::Rails::Engine
|
|
6
|
+
# Automatically mount the engine into host applications
|
|
7
|
+
module RouteConfig
|
|
8
|
+
extend ActiveSupport::Concern
|
|
9
|
+
|
|
10
|
+
included do
|
|
11
|
+
# Append Core routes to the host app after initialization so
|
|
12
|
+
# engine routes are available without manual mounting.
|
|
13
|
+
config.after_initialize do |app|
|
|
14
|
+
next unless Panda::Core.config.auto_mount_engine
|
|
15
|
+
|
|
16
|
+
route_set = app.routes
|
|
17
|
+
already_mounted =
|
|
18
|
+
route_set.routes.any? do |route|
|
|
19
|
+
route.app == Panda::Core::Engine ||
|
|
20
|
+
(route.app.respond_to?(:app) && route.app.app == Panda::Core::Engine)
|
|
21
|
+
end
|
|
22
|
+
already_mounted ||= route_set.named_routes.key?(:panda_core)
|
|
23
|
+
|
|
24
|
+
next if already_mounted
|
|
25
|
+
|
|
26
|
+
route_set.append do
|
|
27
|
+
# Re-check inside the mapper to avoid duplicate mounts during reloads
|
|
28
|
+
next if route_set.named_routes.key?(:panda_core)
|
|
29
|
+
|
|
30
|
+
mount Panda::Core::Engine => "/", as: "panda_core"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/panda/core/engine.rb
CHANGED
|
@@ -1,82 +1,86 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
require "rails
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails"
|
|
4
4
|
require "omniauth"
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
# Issue: https://github.com/cookpad/omniauth-rails_csrf_protection/issues/23
|
|
9
|
-
# This can be removed once the gem is updated or Rails 8.2 is released
|
|
10
|
-
#
|
|
11
|
-
# We suppress the warning by temporarily redirecting stderr since
|
|
12
|
-
# ActiveSupport::Deprecation.silence was removed in Rails 8.1
|
|
13
|
-
original_stderr = $stderr
|
|
14
|
-
$stderr = StringIO.new
|
|
15
|
-
begin
|
|
16
|
-
require "omniauth/rails_csrf_protection"
|
|
17
|
-
ensure
|
|
18
|
-
$stderr = original_stderr
|
|
19
|
-
end
|
|
6
|
+
require "panda/core/middleware"
|
|
7
|
+
require "panda/core/module_registry"
|
|
20
8
|
|
|
21
|
-
#
|
|
9
|
+
# Shared engine mixins
|
|
22
10
|
require_relative "shared/inflections_config"
|
|
23
11
|
require_relative "shared/generator_config"
|
|
24
12
|
|
|
25
|
-
#
|
|
13
|
+
# Engine mixins
|
|
26
14
|
require_relative "engine/autoload_config"
|
|
27
|
-
require_relative "engine/middleware_config"
|
|
28
15
|
require_relative "engine/importmap_config"
|
|
29
16
|
require_relative "engine/omniauth_config"
|
|
30
17
|
require_relative "engine/phlex_config"
|
|
31
18
|
require_relative "engine/admin_controller_config"
|
|
32
|
-
|
|
33
|
-
# Load module registry
|
|
34
|
-
require_relative "module_registry"
|
|
19
|
+
require_relative "engine/route_config"
|
|
35
20
|
|
|
36
21
|
module Panda
|
|
37
22
|
module Core
|
|
38
23
|
class Engine < ::Rails::Engine
|
|
39
24
|
isolate_namespace Panda::Core
|
|
40
25
|
|
|
41
|
-
#
|
|
26
|
+
#
|
|
27
|
+
# Include shared behaviours
|
|
28
|
+
#
|
|
42
29
|
include Shared::InflectionsConfig
|
|
43
30
|
include Shared::GeneratorConfig
|
|
44
31
|
|
|
45
|
-
#
|
|
32
|
+
#
|
|
33
|
+
# Include engine-level concerns
|
|
34
|
+
#
|
|
46
35
|
include AutoloadConfig
|
|
47
|
-
include MiddlewareConfig
|
|
48
36
|
include ImportmapConfig
|
|
49
37
|
include OmniauthConfig
|
|
50
38
|
include PhlexConfig
|
|
51
39
|
include AdminControllerConfig
|
|
40
|
+
include RouteConfig
|
|
52
41
|
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
#
|
|
43
|
+
# Misc configuration point
|
|
44
|
+
#
|
|
45
|
+
initializer "panda_core.configuration" do
|
|
46
|
+
# Intentionally quiet — used as a stable anchor point
|
|
55
47
|
end
|
|
56
48
|
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
initializer "
|
|
62
|
-
|
|
63
|
-
|
|
49
|
+
#
|
|
50
|
+
# Static asset handling for:
|
|
51
|
+
# /panda-core-assets
|
|
52
|
+
#
|
|
53
|
+
initializer "panda_core.static_assets" do |app|
|
|
54
|
+
Panda::Core::Middleware.use(
|
|
55
|
+
app,
|
|
56
|
+
Rack::Static,
|
|
64
57
|
urls: ["/panda-core-assets"],
|
|
65
58
|
root: Panda::Core::Engine.root.join("public"),
|
|
66
59
|
header_rules: [
|
|
67
|
-
|
|
68
|
-
|
|
60
|
+
[
|
|
61
|
+
:all,
|
|
62
|
+
{
|
|
63
|
+
"Cache-Control" =>
|
|
64
|
+
Rails.env.development? ?
|
|
65
|
+
"no-cache, no-store, must-revalidate" :
|
|
66
|
+
"public, max-age=31536000"
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
69
|
]
|
|
70
|
+
)
|
|
70
71
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
Panda::Core::Middleware.use(
|
|
73
|
+
app,
|
|
74
|
+
Panda::Core::ModuleRegistry::JavaScriptMiddleware
|
|
75
|
+
)
|
|
74
76
|
end
|
|
75
77
|
end
|
|
76
78
|
end
|
|
77
79
|
end
|
|
78
80
|
|
|
79
|
-
#
|
|
81
|
+
#
|
|
82
|
+
# Register engine with ModuleRegistry
|
|
83
|
+
#
|
|
80
84
|
Panda::Core::ModuleRegistry.register(
|
|
81
85
|
gem_name: "panda-core",
|
|
82
86
|
engine: "Panda::Core::Engine",
|
|
@@ -85,6 +89,7 @@ Panda::Core::ModuleRegistry.register(
|
|
|
85
89
|
components: "app/components/panda/core/**/*.rb",
|
|
86
90
|
helpers: "app/helpers/panda/core/**/*.rb",
|
|
87
91
|
views: "app/views/panda/core/**/*.erb",
|
|
92
|
+
layouts: "app/views/layouts/panda/core/**/*.erb",
|
|
88
93
|
javascripts: "app/assets/javascript/panda/core/**/*.js"
|
|
89
94
|
}
|
|
90
95
|
)
|