panda-core 0.12.5 → 1.1.0
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/LICENSE +1 -1
- data/README.md +53 -0
- data/app/assets/builds/panda_core_admin.css +2 -0
- data/app/assets/tailwind/application.css +236 -36
- data/app/builders/panda/core/form_builder.rb +120 -18
- data/app/components/panda/core/UI/badge.html.erb +10 -0
- data/app/components/panda/core/UI/badge.rb +14 -30
- data/app/components/panda/core/UI/button.html.erb +5 -0
- data/app/components/panda/core/UI/button.rb +11 -15
- data/app/components/panda/core/UI/card.html.erb +3 -0
- data/app/components/panda/core/UI/card.rb +7 -6
- data/app/components/panda/core/admin/attribute_diff_component.html.erb +21 -0
- data/app/components/panda/core/admin/attribute_diff_component.rb +29 -0
- data/app/components/panda/core/admin/breadcrumb_component.html.erb +36 -0
- data/app/components/panda/core/admin/breadcrumb_component.rb +12 -64
- data/app/components/panda/core/admin/breadcrumbs_component.html.erb +16 -0
- data/app/components/panda/core/admin/breadcrumbs_component.rb +26 -0
- data/app/components/panda/core/admin/button_component.html.erb +9 -0
- data/app/components/panda/core/admin/button_component.rb +36 -31
- data/app/components/panda/core/admin/callout_component.html.erb +17 -0
- data/app/components/panda/core/admin/callout_component.rb +57 -0
- data/app/components/panda/core/admin/code_block_component.html.erb +9 -0
- data/app/components/panda/core/admin/code_block_component.rb +23 -0
- data/app/components/panda/core/admin/container_component.html.erb +27 -0
- data/app/components/panda/core/admin/container_component.rb +11 -77
- data/app/components/panda/core/admin/contributors_summary_component.html.erb +15 -0
- data/app/components/panda/core/admin/contributors_summary_component.rb +23 -0
- data/app/components/panda/core/admin/dashboard_default_content_component.html.erb +70 -0
- data/app/components/panda/core/admin/dashboard_default_content_component.rb +32 -0
- data/app/components/panda/core/admin/delete_button_component.html.erb +4 -0
- data/app/components/panda/core/admin/delete_button_component.rb +41 -0
- data/app/components/panda/core/admin/dropdown_button_component.html.erb +28 -0
- data/app/components/panda/core/admin/dropdown_button_component.rb +100 -0
- data/app/components/panda/core/admin/dropdown_component.html.erb +32 -0
- data/app/components/panda/core/admin/dropdown_component.rb +65 -0
- data/app/components/panda/core/admin/empty_state_component.html.erb +16 -0
- data/app/components/panda/core/admin/empty_state_component.rb +25 -0
- data/app/components/panda/core/admin/file_gallery_component.html.erb +58 -0
- data/app/components/panda/core/admin/file_gallery_component.rb +26 -98
- data/app/components/panda/core/admin/filter_pills_component.html.erb +6 -0
- data/app/components/panda/core/admin/filter_pills_component.rb +29 -0
- data/app/components/panda/core/admin/flash_message_component.html.erb +11 -0
- data/app/components/panda/core/admin/flash_message_component.rb +33 -60
- data/app/components/panda/core/admin/form_error_component.html.erb +7 -0
- data/app/components/panda/core/admin/form_error_component.rb +8 -16
- data/app/components/panda/core/admin/form_footer_component.html.erb +16 -0
- data/app/components/panda/core/admin/form_footer_component.rb +65 -0
- data/app/components/panda/core/admin/form_input_component.html.erb +1 -0
- data/app/components/panda/core/admin/form_input_component.rb +21 -13
- data/app/components/panda/core/admin/form_section_component.html.erb +16 -0
- data/app/components/panda/core/admin/form_section_component.rb +64 -0
- data/app/components/panda/core/admin/form_select_component.html.erb +5 -0
- data/app/components/panda/core/admin/form_select_component.rb +25 -26
- data/app/components/panda/core/admin/heading_component.html.erb +26 -0
- data/app/components/panda/core/admin/heading_component.rb +23 -60
- data/app/components/panda/core/admin/login_form_component.html.erb +38 -0
- data/app/components/panda/core/admin/login_form_component.rb +28 -0
- data/app/components/panda/core/admin/main_layout_component.html.erb +88 -0
- data/app/components/panda/core/admin/main_layout_component.rb +19 -0
- data/app/components/panda/core/admin/my_profile/connected_account_component.html.erb +41 -0
- data/app/components/panda/core/admin/my_profile/connected_account_component.rb +27 -0
- data/app/components/panda/core/admin/navigation/item_component.html.erb +34 -0
- data/app/components/panda/core/admin/navigation/item_component.rb +69 -0
- data/app/components/panda/core/admin/navigation/sub_item_component.html.erb +9 -0
- data/app/components/panda/core/admin/navigation/sub_item_component.rb +44 -0
- data/app/components/panda/core/admin/navigation/user_menu_component.html.erb +30 -0
- data/app/components/panda/core/admin/navigation/user_menu_component.rb +36 -0
- data/app/components/panda/core/admin/page_header_component.html.erb +28 -0
- data/app/components/panda/core/admin/page_header_component.rb +19 -35
- data/app/components/panda/core/admin/pagination_component.html.erb +33 -0
- data/app/components/panda/core/admin/pagination_component.rb +56 -0
- data/app/components/panda/core/admin/panel_component.html.erb +19 -0
- data/app/components/panda/core/admin/panel_component.rb +4 -29
- data/app/components/panda/core/admin/prose_panel_component.html.erb +6 -0
- data/app/components/panda/core/admin/prose_panel_component.rb +43 -0
- data/app/components/panda/core/admin/search_bar_component.html.erb +19 -0
- data/app/components/panda/core/admin/search_bar_component.rb +31 -0
- data/app/components/panda/core/admin/search_filter_bar_component.html.erb +22 -0
- data/app/components/panda/core/admin/search_filter_bar_component.rb +27 -0
- data/app/components/panda/core/admin/secret_field_component.html.erb +24 -0
- data/app/components/panda/core/admin/secret_field_component.rb +31 -0
- data/app/components/panda/core/admin/sidebar_component.html.erb +160 -0
- data/app/components/panda/core/admin/sidebar_component.rb +55 -0
- data/app/components/panda/core/admin/slideover_component.html.erb +67 -0
- data/app/components/panda/core/admin/slideover_component.rb +31 -70
- data/app/components/panda/core/admin/statistics_component.html.erb +4 -0
- data/app/components/panda/core/admin/statistics_component.rb +6 -8
- data/app/components/panda/core/admin/tab_bar_component.html.erb +48 -0
- data/app/components/panda/core/admin/tab_bar_component.rb +32 -67
- data/app/components/panda/core/admin/table_component.html.erb +82 -0
- data/app/components/panda/core/admin/table_component.rb +54 -87
- data/app/components/panda/core/admin/tag_badge_component.html.erb +7 -0
- data/app/components/panda/core/admin/tag_badge_component.rb +21 -0
- data/app/components/panda/core/admin/tag_component.html.erb +1 -0
- data/app/components/panda/core/admin/tag_component.rb +51 -20
- data/app/components/panda/core/admin/tag_input_component.html.erb +37 -0
- data/app/components/panda/core/admin/tag_input_component.rb +22 -0
- data/app/components/panda/core/admin/tags_panel_component.html.erb +8 -0
- data/app/components/panda/core/admin/tags_panel_component.rb +33 -0
- data/app/components/panda/core/admin/user_activity_component.html.erb +15 -0
- data/app/components/panda/core/admin/user_activity_component.rb +9 -22
- data/app/components/panda/core/admin/user_display_component.html.erb +8 -0
- data/app/components/panda/core/admin/user_display_component.rb +19 -22
- data/app/components/panda/core/base.rb +35 -42
- data/app/components/panda/core/shared/footer_component.html.erb +2 -0
- data/app/components/panda/core/shared/footer_component.rb +11 -0
- data/app/components/panda/core/shared/header_component.html.erb +32 -0
- data/app/components/panda/core/shared/header_component.rb +19 -0
- data/app/constraints/panda/core/admin_constraint.rb +2 -2
- data/app/controllers/concerns/panda/core/admin_authorization.rb +58 -0
- data/app/controllers/concerns/panda/core/authorizable.rb +107 -0
- data/app/controllers/panda/core/admin/base_controller.rb +62 -3
- data/app/controllers/panda/core/admin/editor/search_controller.rb +17 -0
- data/app/controllers/panda/core/admin/feature_flags_controller.rb +35 -0
- data/app/controllers/panda/core/admin/file_categories_controller.rb +84 -0
- data/app/controllers/panda/core/admin/files_controller.rb +230 -0
- data/app/controllers/panda/core/admin/import_sessions_controller.rb +120 -0
- data/app/controllers/panda/core/admin/my_profile/logins_controller.rb +24 -0
- data/app/controllers/panda/core/admin/my_profile_controller.rb +31 -0
- data/app/controllers/panda/core/admin/search_controller.rb +15 -0
- data/app/controllers/panda/core/admin/sessions_controller.rb +84 -10
- data/app/controllers/panda/core/admin/tags_controller.rb +77 -0
- data/app/controllers/panda/core/admin/test_sessions_controller.rb +5 -6
- data/app/controllers/panda/core/admin/users_controller.rb +184 -0
- data/app/controllers/panda/core/application_controller.rb +13 -1
- data/app/helpers/panda/core/active_storage_helper.rb +24 -0
- data/app/helpers/panda/core/feature_flag_helper.rb +11 -0
- data/app/helpers/panda/core/form_helper.rb +15 -0
- data/app/javascript/panda/core/controllers/avatar_upload_controller.js +73 -0
- data/app/javascript/panda/core/controllers/clipboard_controller.js +119 -0
- data/app/javascript/panda/core/controllers/collapsible_item_controller.js +45 -0
- data/app/javascript/panda/core/controllers/custom_select_controller.js +256 -0
- data/app/javascript/panda/core/controllers/datepicker_controller.js +121 -0
- data/app/javascript/panda/core/controllers/daterange_controller.js +193 -0
- data/app/javascript/panda/core/controllers/file_gallery_controller.js +134 -0
- data/app/javascript/panda/core/controllers/file_upload_controller.js +165 -0
- data/app/javascript/panda/core/controllers/global_search_controller.js +184 -0
- data/app/javascript/panda/core/controllers/index.js +36 -0
- data/app/javascript/panda/core/controllers/mobile_sidebar_controller.js +58 -0
- data/app/javascript/panda/core/controllers/navigation_toggle_controller.js +49 -24
- data/app/javascript/panda/core/controllers/row_link_controller.js +27 -0
- data/app/javascript/panda/core/controllers/tag_input_controller.js +183 -0
- data/app/javascript/panda/core/tailwindcss-stimulus-components.js +2 -3
- data/app/javascript/panda/core/vendor/@fortawesome--fontawesome-free@7.2.0.js +8129 -0
- data/app/javascript/panda/core/vendor/@hotwired--turbo.js +7197 -100
- data/app/javascript/panda/core/vendor/@rails--actioncable--src.js +511 -2
- data/app/javascript/panda/core/vendor/@tailwindplus--elements@1.0.22.js +65 -0
- data/app/javascript/panda/core/vendor/cropperjs@2.1.0.js +3 -0
- data/app/javascript/panda/core/vendor/vanilla-calendar-pro.js +2 -0
- data/app/models/concerns/panda/core/has_metadata.rb +164 -0
- data/app/models/concerns/panda/core/importable.rb +79 -0
- data/app/models/concerns/panda/core/searchable.rb +66 -0
- data/app/models/concerns/panda/core/taggable.rb +37 -0
- data/app/models/panda/core/feature_flag.rb +56 -0
- data/app/models/panda/core/file_categorization.rb +14 -0
- data/app/models/panda/core/file_category.rb +45 -0
- data/app/models/panda/core/import_session.rb +79 -0
- data/app/models/panda/core/presence.rb +24 -0
- data/app/models/panda/core/tag.rb +33 -0
- data/app/models/panda/core/tagging.rb +14 -0
- data/app/models/panda/core/user.rb +94 -16
- data/app/models/panda/core/user_activity.rb +42 -0
- data/app/models/panda/core/user_session.rb +35 -0
- data/app/services/panda/core/attach_avatar_service.rb +15 -3
- data/app/services/panda/core/csv_import_service.rb +65 -0
- data/app/services/panda/core/file_categorizer.rb +52 -0
- data/app/services/panda/core/file_parser.rb +76 -0
- data/app/services/panda/core/invite_user_service.rb +44 -0
- data/app/services/panda/core/presence_service.rb +49 -0
- data/app/views/layouts/panda/core/admin.html.erb +6 -76
- data/app/views/layouts/panda/core/admin_simple.html.erb +2 -2
- data/app/views/panda/core/admin/dashboard/_default_content.html.erb +1 -73
- data/app/views/panda/core/admin/dashboard/show.html.erb +12 -15
- data/app/views/panda/core/admin/feature_flags/index.html.erb +56 -0
- data/app/views/panda/core/admin/file_categories/_form.html.erb +20 -0
- data/app/views/panda/core/admin/file_categories/edit.html.erb +5 -0
- data/app/views/panda/core/admin/file_categories/index.html.erb +55 -0
- data/app/views/panda/core/admin/file_categories/new.html.erb +5 -0
- data/app/views/panda/core/admin/files/_file_details.html.erb +156 -0
- data/app/views/panda/core/admin/files/index.html.erb +61 -0
- data/app/views/panda/core/admin/import_sessions/column_map.html.erb +43 -0
- data/app/views/panda/core/admin/import_sessions/index.html.erb +48 -0
- data/app/views/panda/core/admin/import_sessions/new.html.erb +37 -0
- data/app/views/panda/core/admin/import_sessions/preview.html.erb +51 -0
- data/app/views/panda/core/admin/import_sessions/show.html.erb +87 -0
- data/app/views/panda/core/admin/my_profile/edit.html.erb +51 -39
- data/app/views/panda/core/admin/my_profile/logins/show.html.erb +72 -0
- data/app/views/panda/core/admin/sessions/new.html.erb +1 -37
- data/app/views/panda/core/admin/shared/_breadcrumbs.html.erb +1 -18
- data/app/views/panda/core/admin/shared/_sidebar.html.erb +1 -99
- data/app/views/panda/core/admin/shared/_slideover.html.erb +3 -3
- data/app/views/panda/core/admin/tags/_form.html.erb +21 -0
- data/app/views/panda/core/admin/tags/edit.html.erb +4 -0
- data/app/views/panda/core/admin/tags/index.html.erb +41 -0
- data/app/views/panda/core/admin/tags/new.html.erb +4 -0
- data/app/views/panda/core/admin/users/activity.html.erb +90 -0
- data/app/views/panda/core/admin/users/edit.html.erb +48 -0
- data/app/views/panda/core/admin/users/index.html.erb +161 -0
- data/app/views/panda/core/admin/users/sessions.html.erb +103 -0
- data/app/views/panda/core/admin/users/show.html.erb +224 -0
- data/app/views/panda/core/shared/_footer.html.erb +1 -2
- data/app/views/panda/core/shared/_header.html.erb +4 -22
- data/config/brakeman.ignore +68 -31
- data/config/importmap.rb +13 -11
- data/config/routes.rb +49 -2
- data/db/migrate/20260202171614_create_panda_core_file_categories.rb +30 -0
- data/db/migrate/20260203000001_add_user_management_fields_to_panda_core_users.rb +21 -0
- data/db/migrate/20260203000002_create_panda_core_user_activities.rb +24 -0
- data/db/migrate/20260203000003_create_panda_core_user_sessions.rb +25 -0
- data/db/migrate/20260207100000_create_panda_core_presences.rb +21 -0
- data/db/migrate/20260213000001_fix_active_storage_attachments_record_id_type.rb +44 -0
- data/db/migrate/20260217000001_create_panda_core_feature_flags.rb +14 -0
- data/db/migrate/20260303000001_add_metadata_to_panda_core_users.rb +11 -0
- data/db/migrate/20260310000001_create_panda_core_tags.rb +27 -0
- data/db/migrate/20260310000002_create_panda_core_import_sessions.rb +29 -0
- data/lib/generators/panda/core/install_generator.rb +32 -0
- data/lib/generators/panda/core/templates/panda.rb +63 -0
- data/lib/panda/core/asset_loader.rb +5 -2
- data/lib/panda/core/authentication.rb +3 -3
- data/lib/panda/core/configuration.rb +195 -1
- data/lib/panda/core/engine/admin_controller_config.rb +3 -6
- data/lib/panda/core/engine/autoload_config.rb +21 -9
- data/lib/panda/core/engine/omniauth_config.rb +108 -38
- data/lib/panda/core/engine/pending_migrations_check.rb +46 -0
- data/lib/panda/core/engine/sqlite_schema_compatibility.rb +36 -0
- data/lib/panda/core/engine/{phlex_config.rb → view_component_config.rb} +5 -7
- data/lib/panda/core/engine.rb +90 -25
- data/lib/panda/core/middleware.rb +35 -0
- data/lib/panda/core/navigation_registry.rb +455 -0
- data/lib/panda/core/oauth_providers.rb +27 -0
- data/lib/panda/core/permission_registry.rb +89 -0
- data/lib/panda/core/search_registry.rb +69 -0
- data/lib/panda/core/seeds/file_categories.rb +30 -0
- data/lib/panda/core/shared/inflections_config.rb +1 -5
- data/lib/panda/core/testing/rails_helper.rb +87 -0
- data/lib/panda/core/testing/support/authentication_test_helpers.rb +22 -18
- data/lib/panda/core/testing/support/system/cuprite_helpers.rb +4 -4
- data/lib/panda/core/testing/view_component_test_controller.rb +19 -0
- data/lib/panda/core/version.rb +1 -1
- data/lib/panda/core/widget_registry.rb +50 -0
- data/lib/panda/core.rb +17 -8
- data/lib/tasks/panda/core/file_categories.rake +41 -0
- data/public/panda-core-assets/panda-core-0.12.5.css +2 -0
- data/public/panda-core-assets/panda-core-0.13.0.css +2 -0
- data/public/panda-core-assets/panda-core-0.14.0.css +2 -0
- data/public/panda-core-assets/panda-core-0.14.4.css +2 -0
- data/public/panda-core-assets/panda-core.css +2 -2
- data/public/panda-core-assets/vanilla-calendar.css +47 -0
- metadata +203 -26
- data/lib/panda/core/engine/inflections_config.rb +0 -23
|
@@ -1,22 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<%= csrf_meta_tags %>
|
|
6
|
-
<%= csp_meta_tag %>
|
|
7
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@7.1.0/css/all.min.css">
|
|
8
|
-
<%= panda_core_stylesheet %>
|
|
9
|
-
|
|
10
|
-
<!-- ES Module Shims polyfill - must load BEFORE importmap -->
|
|
11
|
-
<script async src="https://ga.jspm.io/npm:es-module-shims@2.6.2/dist/es-module-shims.js"></script>
|
|
12
|
-
|
|
13
|
-
<!-- Panda JavaScript (Core + all registered modules via ModuleRegistry) -->
|
|
14
|
-
<%= panda_core_javascript %>
|
|
15
|
-
|
|
16
|
-
<% if defined?(Panda::CMS) && controller.class.name.start_with?("Panda::CMS") %>
|
|
17
|
-
<%= render "panda/cms/shared/favicons" %>
|
|
18
|
-
<% end %>
|
|
19
|
-
|
|
20
|
-
<%= yield :head %>
|
|
21
|
-
</head>
|
|
22
|
-
<body class="overflow-hidden h-full <%= local_assigns[:body_class] || "" %>" data-environment="<%= Rails.env %>">
|
|
1
|
+
<%= render Panda::Core::Shared::HeaderComponent.new(
|
|
2
|
+
html_class: local_assigns[:html_class] || "",
|
|
3
|
+
body_class: local_assigns[:body_class] || ""
|
|
4
|
+
) %>
|
data/config/brakeman.ignore
CHANGED
|
@@ -1,51 +1,88 @@
|
|
|
1
1
|
{
|
|
2
2
|
"ignored_warnings": [
|
|
3
3
|
{
|
|
4
|
-
"warning_type": "
|
|
5
|
-
"warning_code":
|
|
6
|
-
"fingerprint": "
|
|
7
|
-
"check_name": "
|
|
8
|
-
"message": "
|
|
9
|
-
"file": "lib/panda/core/testing/
|
|
10
|
-
"line":
|
|
11
|
-
"link": "https://brakemanscanner.org/docs/warning_types/
|
|
12
|
-
"code": "
|
|
4
|
+
"warning_type": "Cross-Site Request Forgery",
|
|
5
|
+
"warning_code": 86,
|
|
6
|
+
"fingerprint": "fdf51189b80e32937b18aea1d088b9de2397d9a958f4a961030b37ebeae4e53d",
|
|
7
|
+
"check_name": "ForgerySetting",
|
|
8
|
+
"message": "`protect_from_forgery` should be configured with `with: :exception`",
|
|
9
|
+
"file": "lib/panda/core/testing/view_component_test_controller.rb",
|
|
10
|
+
"line": 7,
|
|
11
|
+
"link": "https://brakemanscanner.org/docs/warning_types/cross-site_request_forgery/",
|
|
12
|
+
"code": "protect_from_forgery(:with => :null_session)",
|
|
13
13
|
"render_path": null,
|
|
14
14
|
"location": {
|
|
15
|
-
"type": "
|
|
16
|
-
"
|
|
17
|
-
"method": "record_video!"
|
|
15
|
+
"type": "controller",
|
|
16
|
+
"controller": "ViewComponentTestController"
|
|
18
17
|
},
|
|
19
|
-
"user_input":
|
|
18
|
+
"user_input": null,
|
|
20
19
|
"confidence": "Medium",
|
|
21
20
|
"cwe_id": [
|
|
22
|
-
|
|
21
|
+
352
|
|
23
22
|
],
|
|
24
|
-
"note": "
|
|
23
|
+
"note": ""
|
|
25
24
|
},
|
|
26
25
|
{
|
|
27
|
-
"warning_type": "
|
|
28
|
-
"warning_code":
|
|
29
|
-
"fingerprint": "
|
|
30
|
-
"check_name": "
|
|
31
|
-
"message": "
|
|
32
|
-
"file": "
|
|
33
|
-
"line":
|
|
34
|
-
"link": "https://brakemanscanner.org/docs/warning_types/
|
|
35
|
-
"code": "
|
|
26
|
+
"warning_type": "Mass Assignment",
|
|
27
|
+
"warning_code": 105,
|
|
28
|
+
"fingerprint": "7b32da2eebb702da28834b0ac77f1a3801b9abb4b09527ce7726070b5d91ee7a",
|
|
29
|
+
"check_name": "PermitAttributes",
|
|
30
|
+
"message": "Potentially dangerous key allowed for mass assignment",
|
|
31
|
+
"file": "app/controllers/panda/core/admin/users_controller.rb",
|
|
32
|
+
"line": 169,
|
|
33
|
+
"link": "https://brakemanscanner.org/docs/warning_types/mass_assignment/",
|
|
34
|
+
"code": "params.require(:user).permit(:name, :email, :admin, :internal)",
|
|
36
35
|
"render_path": null,
|
|
37
36
|
"location": {
|
|
38
37
|
"type": "method",
|
|
39
|
-
"class": "Panda::Core::
|
|
40
|
-
"method": "
|
|
38
|
+
"class": "Panda::Core::Admin::UsersController",
|
|
39
|
+
"method": "user_params"
|
|
41
40
|
},
|
|
42
|
-
"user_input": "
|
|
43
|
-
"confidence": "
|
|
41
|
+
"user_input": ":admin",
|
|
42
|
+
"confidence": "High",
|
|
43
|
+
"cwe_id": [
|
|
44
|
+
915
|
|
45
|
+
],
|
|
46
|
+
"note": "Admin-only controller behind authenticate_admin_user! - only admins can modify user roles and metadata"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"warning_type": "Cross-Site Scripting",
|
|
50
|
+
"warning_code": 2,
|
|
51
|
+
"fingerprint": "46a409fd77a42e7e6db3d8c22a494fa102be16bb04ca613494baf0e3f75710e8",
|
|
52
|
+
"check_name": "CrossSiteScripting",
|
|
53
|
+
"message": "Unescaped parameter value",
|
|
54
|
+
"file": "app/views/panda/core/admin/users/edit.html.erb",
|
|
55
|
+
"line": 41,
|
|
56
|
+
"link": "https://brakemanscanner.org/docs/warning_types/cross-site_scripting/",
|
|
57
|
+
"code": "Panda::Core.config.admin_user_edit_content.call(User.find(params[:id]), f, self)",
|
|
58
|
+
"render_path": null,
|
|
59
|
+
"location": null,
|
|
60
|
+
"user_input": "params[:id]",
|
|
61
|
+
"confidence": "Weak",
|
|
62
|
+
"cwe_id": [
|
|
63
|
+
79
|
|
64
|
+
],
|
|
65
|
+
"note": "Hook content is controlled by the host application developer, not user input. The raw call is intentional to render host-provided HTML."
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"warning_type": "Cross-Site Scripting",
|
|
69
|
+
"warning_code": 2,
|
|
70
|
+
"fingerprint": "f60426d4ca96ba191b9a49da3b27193b2dc00fdcb93574037165d98b3dbab0d4",
|
|
71
|
+
"check_name": "CrossSiteScripting",
|
|
72
|
+
"message": "Unescaped parameter value",
|
|
73
|
+
"file": "app/views/panda/core/admin/users/show.html.erb",
|
|
74
|
+
"line": 36,
|
|
75
|
+
"link": "https://brakemanscanner.org/docs/warning_types/cross-site_scripting/",
|
|
76
|
+
"code": "Panda::Core.config.admin_user_show_content.call(User.find(params[:id]), self)",
|
|
77
|
+
"render_path": null,
|
|
78
|
+
"location": null,
|
|
79
|
+
"user_input": "params[:id]",
|
|
80
|
+
"confidence": "Weak",
|
|
44
81
|
"cwe_id": [
|
|
45
|
-
|
|
82
|
+
79
|
|
46
83
|
],
|
|
47
|
-
"note": "
|
|
84
|
+
"note": "Hook content is controlled by the host application developer, not user input. The raw call is intentional to render host-provided HTML."
|
|
48
85
|
}
|
|
49
86
|
],
|
|
50
|
-
"brakeman_version": "
|
|
87
|
+
"brakeman_version": "8.0.4"
|
|
51
88
|
}
|
data/config/importmap.rb
CHANGED
|
@@ -9,20 +9,22 @@ pin "panda/core/controllers/theme_form_controller", to: "/panda/core/controllers
|
|
|
9
9
|
pin "panda/core/controllers/image_cropper_controller", to: "/panda/core/controllers/image_cropper_controller.js"
|
|
10
10
|
pin "panda/core/tailwindplus-elements", to: "/panda/core/tailwindplus-elements.js"
|
|
11
11
|
|
|
12
|
-
# Base JavaScript dependencies for Panda Core (vendored for reliability)
|
|
12
|
+
# Base JavaScript dependencies for Panda Core (all vendored for reliability)
|
|
13
13
|
pin "@hotwired/stimulus", to: "/panda/core/vendor/@hotwired--stimulus.js", preload: true # @3.2.2
|
|
14
|
-
pin "@hotwired/turbo", to: "/panda/core/vendor/@hotwired--turbo.js", preload: true # @8.0.
|
|
15
|
-
pin "@rails/actioncable/src", to: "/panda/core/vendor/@rails--actioncable--src.js", preload: true # @8.
|
|
14
|
+
pin "@hotwired/turbo", to: "/panda/core/vendor/@hotwired--turbo.js", preload: true # @8.0.23
|
|
15
|
+
pin "@rails/actioncable/src", to: "/panda/core/vendor/@rails--actioncable--src.js", preload: true # @8.1.300
|
|
16
16
|
pin "tailwindcss-stimulus-components", to: "/panda/core/tailwindcss-stimulus-components.js" # @6.1.3
|
|
17
17
|
|
|
18
|
-
# Font Awesome icons (
|
|
19
|
-
pin "@fortawesome/fontawesome-free", to: "
|
|
18
|
+
# Font Awesome icons (vendored)
|
|
19
|
+
pin "@fortawesome/fontawesome-free", to: "/panda/core/vendor/@fortawesome--fontawesome-free@7.2.0.js" # @7.2.0
|
|
20
20
|
|
|
21
|
-
# Tailwind Plus Elements - Vanilla JS interactive components (
|
|
21
|
+
# Tailwind Plus Elements - Vanilla JS interactive components (vendored)
|
|
22
22
|
# Provides: Autocomplete, Command palette, Dialog, Disclosure, Dropdown menu, Popover, Select, Tabs
|
|
23
|
-
|
|
24
|
-
pin "@tailwindplus/elements", to: "https://esm.sh/@tailwindplus/elements@1", preload: false
|
|
23
|
+
pin "@tailwindplus/elements", to: "/panda/core/vendor/@tailwindplus--elements@1.0.22.js", preload: false # @1.0.22
|
|
25
24
|
|
|
26
|
-
# Cropper.js - Image cropping library (
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
# Cropper.js - Image cropping library (vendored)
|
|
26
|
+
# Note: v2.x uses Web Components — no separate CSS file needed
|
|
27
|
+
pin "cropperjs", to: "/panda/core/vendor/cropperjs@2.1.0.js" # @2.1.0
|
|
28
|
+
|
|
29
|
+
# Vanilla Calendar Pro - Date picker library (vendored)
|
|
30
|
+
pin "vanilla-calendar-pro", to: "/panda/core/vendor/vanilla-calendar-pro.js" # @3.1.0
|
data/config/routes.rb
CHANGED
|
@@ -16,17 +16,64 @@ Panda::Core::Engine.routes.draw do
|
|
|
16
16
|
# Dashboard and admin routes - authentication handled by AdminController
|
|
17
17
|
get "/", to: "admin/dashboard#show", as: :root
|
|
18
18
|
|
|
19
|
+
# Global admin search
|
|
20
|
+
get "/search", to: "admin/search#index", as: :search
|
|
21
|
+
|
|
22
|
+
# Editor search endpoint for link-autocomplete
|
|
23
|
+
namespace :editor, module: "admin/editor" do
|
|
24
|
+
get :search, to: "search#index", as: :search
|
|
25
|
+
end
|
|
26
|
+
|
|
19
27
|
# Profile management
|
|
20
|
-
resource :my_profile, only: %i[show edit update], controller: "admin/my_profile", path: "my_profile"
|
|
28
|
+
resource :my_profile, only: %i[show edit update], controller: "admin/my_profile", path: "my_profile" do
|
|
29
|
+
resource :logins, only: [:show], controller: "admin/my_profile/logins"
|
|
30
|
+
end
|
|
21
31
|
|
|
22
32
|
# Settings
|
|
23
33
|
resource :settings, only: [:show], controller: "admin/settings"
|
|
24
34
|
|
|
35
|
+
# User management
|
|
36
|
+
resources :users, only: %i[index show edit update], controller: "admin/users" do
|
|
37
|
+
member do
|
|
38
|
+
patch :enable
|
|
39
|
+
patch :disable
|
|
40
|
+
get :activity
|
|
41
|
+
get :sessions
|
|
42
|
+
delete "sessions/:session_id", action: :revoke_session, as: :revoke_session
|
|
43
|
+
end
|
|
44
|
+
collection do
|
|
45
|
+
post :invite
|
|
46
|
+
post :bulk_action
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# File management
|
|
51
|
+
resources :files, controller: "admin/files"
|
|
52
|
+
|
|
53
|
+
# File category management
|
|
54
|
+
resources :file_categories, only: %i[index new create edit update destroy], controller: "admin/file_categories"
|
|
55
|
+
|
|
56
|
+
# Feature flag management
|
|
57
|
+
resources :feature_flags, only: %i[index update], controller: "admin/feature_flags"
|
|
58
|
+
|
|
59
|
+
# Tags
|
|
60
|
+
resources :tags, only: %i[index new create edit update destroy], controller: "admin/tags"
|
|
61
|
+
|
|
62
|
+
# CSV Import
|
|
63
|
+
resources :import_sessions, only: %i[index new create show], controller: "admin/import_sessions" do
|
|
64
|
+
member do
|
|
65
|
+
get :column_map
|
|
66
|
+
patch :update_mapping
|
|
67
|
+
get :preview
|
|
68
|
+
post :import
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
25
72
|
# Test-only authentication endpoint (available in development and test environments)
|
|
26
73
|
# This bypasses OAuth for faster, more reliable test execution
|
|
27
74
|
# Development: Used by Capybara system tests which run Rails server in development mode
|
|
28
75
|
# Test: Used by controller/request tests
|
|
29
|
-
|
|
76
|
+
if Rails.env.development? || Rails.env.test?
|
|
30
77
|
get "/test_login/:user_id", to: "admin/test_sessions#create", as: :test_login
|
|
31
78
|
post "/test_sessions", to: "admin/test_sessions#create", as: :test_sessions
|
|
32
79
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreatePandaCoreFileCategories < ActiveRecord::Migration[7.1]
|
|
4
|
+
def change
|
|
5
|
+
create_table :panda_core_file_categories, id: :uuid do |t|
|
|
6
|
+
t.string :name, null: false
|
|
7
|
+
t.string :slug, null: false
|
|
8
|
+
t.references :parent, type: :uuid, foreign_key: {to_table: :panda_core_file_categories}
|
|
9
|
+
t.boolean :system, null: false, default: false
|
|
10
|
+
t.string :icon
|
|
11
|
+
t.integer :position, null: false, default: 0
|
|
12
|
+
t.timestamps
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
add_index :panda_core_file_categories, :slug, unique: true
|
|
16
|
+
add_index :panda_core_file_categories, :position
|
|
17
|
+
|
|
18
|
+
create_table :panda_core_file_categorizations, id: :uuid do |t|
|
|
19
|
+
t.references :file_category, null: false, type: :uuid,
|
|
20
|
+
foreign_key: {to_table: :panda_core_file_categories}
|
|
21
|
+
t.bigint :blob_id, null: false
|
|
22
|
+
t.timestamps
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
add_index :panda_core_file_categorizations, %i[file_category_id blob_id],
|
|
26
|
+
unique: true, name: :idx_file_categorizations_on_category_and_blob
|
|
27
|
+
add_index :panda_core_file_categorizations, :blob_id
|
|
28
|
+
add_foreign_key :panda_core_file_categorizations, :active_storage_blobs, column: :blob_id
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddUserManagementFieldsToPandaCoreUsers < ActiveRecord::Migration[8.1]
|
|
4
|
+
def change
|
|
5
|
+
change_table :panda_core_users, bulk: true do |t|
|
|
6
|
+
t.boolean :enabled, default: true, null: false
|
|
7
|
+
t.datetime :last_login_at
|
|
8
|
+
t.string :last_login_ip
|
|
9
|
+
t.integer :login_count, default: 0, null: false
|
|
10
|
+
t.uuid :invited_by_id
|
|
11
|
+
t.string :invitation_token
|
|
12
|
+
t.datetime :invitation_sent_at
|
|
13
|
+
t.datetime :invitation_accepted_at
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
add_index :panda_core_users, :invitation_token, unique: true
|
|
17
|
+
add_index :panda_core_users, :invited_by_id
|
|
18
|
+
add_index :panda_core_users, :enabled
|
|
19
|
+
add_foreign_key :panda_core_users, :panda_core_users, column: :invited_by_id
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreatePandaCoreUserActivities < ActiveRecord::Migration[8.1]
|
|
4
|
+
def change
|
|
5
|
+
create_table :panda_core_user_activities, id: :uuid do |t|
|
|
6
|
+
t.uuid :user_id, null: false
|
|
7
|
+
t.string :action, null: false
|
|
8
|
+
t.string :resource_type
|
|
9
|
+
t.uuid :resource_id
|
|
10
|
+
t.jsonb :metadata, default: {}
|
|
11
|
+
t.string :ip_address
|
|
12
|
+
t.string :user_agent
|
|
13
|
+
|
|
14
|
+
t.timestamps
|
|
15
|
+
|
|
16
|
+
t.index :user_id
|
|
17
|
+
t.index [:resource_type, :resource_id]
|
|
18
|
+
t.index :action
|
|
19
|
+
t.index :created_at
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
add_foreign_key :panda_core_user_activities, :panda_core_users, column: :user_id
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreatePandaCoreUserSessions < ActiveRecord::Migration[8.1]
|
|
4
|
+
def change
|
|
5
|
+
create_table :panda_core_user_sessions, id: :uuid do |t|
|
|
6
|
+
t.uuid :user_id, null: false
|
|
7
|
+
t.string :session_id, null: false
|
|
8
|
+
t.string :ip_address
|
|
9
|
+
t.string :user_agent
|
|
10
|
+
t.datetime :last_active_at
|
|
11
|
+
t.boolean :active, default: true, null: false
|
|
12
|
+
t.datetime :revoked_at
|
|
13
|
+
t.uuid :revoked_by_id
|
|
14
|
+
|
|
15
|
+
t.timestamps
|
|
16
|
+
|
|
17
|
+
t.index :session_id, unique: true
|
|
18
|
+
t.index :user_id
|
|
19
|
+
t.index :active
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
add_foreign_key :panda_core_user_sessions, :panda_core_users, column: :user_id
|
|
23
|
+
add_foreign_key :panda_core_user_sessions, :panda_core_users, column: :revoked_by_id, on_delete: :nullify
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreatePandaCorePresences < ActiveRecord::Migration[8.1]
|
|
4
|
+
def change
|
|
5
|
+
create_table :panda_core_presences, id: :uuid do |t|
|
|
6
|
+
t.string :presenceable_type, null: false
|
|
7
|
+
t.uuid :presenceable_id, null: false
|
|
8
|
+
t.uuid :user_id, null: false
|
|
9
|
+
t.datetime :last_seen_at, null: false
|
|
10
|
+
t.timestamps
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
add_index :panda_core_presences, [:presenceable_type, :presenceable_id, :user_id],
|
|
14
|
+
unique: true, name: "index_unique_presence"
|
|
15
|
+
add_index :panda_core_presences, [:presenceable_type, :presenceable_id],
|
|
16
|
+
name: "index_presences_on_presenceable"
|
|
17
|
+
add_index :panda_core_presences, :user_id
|
|
18
|
+
add_index :panda_core_presences, :last_seen_at
|
|
19
|
+
add_foreign_key :panda_core_presences, :panda_core_users, column: :user_id
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class FixActiveStorageAttachmentsRecordIdType < ActiveRecord::Migration[8.1]
|
|
4
|
+
def up
|
|
5
|
+
return unless table_exists?(:active_storage_attachments)
|
|
6
|
+
|
|
7
|
+
column = columns(:active_storage_attachments).find { |c| c.name == "record_id" }
|
|
8
|
+
return if column.nil? || column.sql_type == "character varying"
|
|
9
|
+
|
|
10
|
+
# Remove orphaned attachments where UUID was silently cast to 0
|
|
11
|
+
execute <<~SQL
|
|
12
|
+
DELETE FROM active_storage_attachments WHERE record_id = 0
|
|
13
|
+
SQL
|
|
14
|
+
|
|
15
|
+
# Drop the unique index before changing the column type
|
|
16
|
+
remove_index :active_storage_attachments,
|
|
17
|
+
name: "index_active_storage_attachments_uniqueness",
|
|
18
|
+
if_exists: true
|
|
19
|
+
|
|
20
|
+
change_column :active_storage_attachments, :record_id, :string, null: false
|
|
21
|
+
|
|
22
|
+
add_index :active_storage_attachments,
|
|
23
|
+
[:record_type, :record_id, :name, :blob_id],
|
|
24
|
+
unique: true,
|
|
25
|
+
name: "index_active_storage_attachments_uniqueness"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def down
|
|
29
|
+
return unless table_exists?(:active_storage_attachments)
|
|
30
|
+
|
|
31
|
+
remove_index :active_storage_attachments,
|
|
32
|
+
name: "index_active_storage_attachments_uniqueness",
|
|
33
|
+
if_exists: true
|
|
34
|
+
|
|
35
|
+
change_column :active_storage_attachments, :record_id, :bigint,
|
|
36
|
+
null: false,
|
|
37
|
+
using: "record_id::bigint"
|
|
38
|
+
|
|
39
|
+
add_index :active_storage_attachments,
|
|
40
|
+
[:record_type, :record_id, :name, :blob_id],
|
|
41
|
+
unique: true,
|
|
42
|
+
name: "index_active_storage_attachments_uniqueness"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreatePandaCoreFeatureFlags < ActiveRecord::Migration[8.1]
|
|
4
|
+
def change
|
|
5
|
+
create_table :panda_core_feature_flags, id: :uuid do |t|
|
|
6
|
+
t.string :key, null: false
|
|
7
|
+
t.boolean :enabled, null: false, default: false
|
|
8
|
+
t.string :description
|
|
9
|
+
t.timestamps
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
add_index :panda_core_feature_flags, :key, unique: true
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddMetadataToPandaCoreUsers < ActiveRecord::Migration[8.1]
|
|
4
|
+
def change
|
|
5
|
+
add_column :panda_core_users, :metadata, :jsonb, default: {}, null: false
|
|
6
|
+
|
|
7
|
+
if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
|
|
8
|
+
add_index :panda_core_users, :metadata, using: :gin, name: "index_panda_core_users_on_metadata"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreatePandaCoreTags < ActiveRecord::Migration[8.1]
|
|
4
|
+
def change
|
|
5
|
+
create_table :panda_core_tags, id: :uuid do |t|
|
|
6
|
+
t.string :tenant_type
|
|
7
|
+
t.string :tenant_id
|
|
8
|
+
t.string :name, null: false
|
|
9
|
+
t.string :colour
|
|
10
|
+
t.integer :taggings_count, default: 0, null: false
|
|
11
|
+
t.timestamps
|
|
12
|
+
|
|
13
|
+
t.index [:tenant_type, :tenant_id]
|
|
14
|
+
t.index [:tenant_type, :tenant_id, :name], unique: true, name: :idx_panda_core_tags_on_tenant_and_name
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
create_table :panda_core_taggings, id: :uuid do |t|
|
|
18
|
+
t.references :tag, null: false, type: :uuid, foreign_key: {to_table: :panda_core_tags}
|
|
19
|
+
t.string :taggable_type, null: false
|
|
20
|
+
t.string :taggable_id, null: false
|
|
21
|
+
t.timestamps
|
|
22
|
+
|
|
23
|
+
t.index [:taggable_type, :taggable_id], name: :idx_panda_core_taggings_on_taggable
|
|
24
|
+
t.index [:tag_id, :taggable_type, :taggable_id], unique: true, name: :idx_panda_core_taggings_unique
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreatePandaCoreImportSessions < ActiveRecord::Migration[8.1]
|
|
4
|
+
def change
|
|
5
|
+
create_table :panda_core_import_sessions, id: :uuid do |t|
|
|
6
|
+
t.string :importable_type, null: false
|
|
7
|
+
t.string :tenant_type
|
|
8
|
+
t.bigint :tenant_id
|
|
9
|
+
t.uuid :user_id, null: false
|
|
10
|
+
t.string :status, null: false, default: "pending"
|
|
11
|
+
t.jsonb :column_mapping, default: {}, null: false
|
|
12
|
+
t.integer :total_rows, default: 0, null: false
|
|
13
|
+
t.integer :processed_rows, default: 0, null: false
|
|
14
|
+
t.integer :imported_count, default: 0, null: false
|
|
15
|
+
t.integer :skipped_count, default: 0, null: false
|
|
16
|
+
t.integer :error_count, default: 0, null: false
|
|
17
|
+
t.jsonb :errors_log, default: [], null: false
|
|
18
|
+
t.datetime :started_at
|
|
19
|
+
t.datetime :completed_at
|
|
20
|
+
t.timestamps
|
|
21
|
+
|
|
22
|
+
t.index [:tenant_type, :tenant_id]
|
|
23
|
+
t.index :status
|
|
24
|
+
t.index :user_id
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
add_foreign_key :panda_core_import_sessions, :panda_core_users, column: :user_id
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Panda
|
|
4
|
+
module Core
|
|
5
|
+
module Generators
|
|
6
|
+
class InstallGenerator < Rails::Generators::Base
|
|
7
|
+
source_root File.expand_path("templates", __dir__)
|
|
8
|
+
|
|
9
|
+
desc "Install Panda Core: create the initializer and copy migrations"
|
|
10
|
+
|
|
11
|
+
def copy_initializer
|
|
12
|
+
template "panda.rb", "config/initializers/panda.rb"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def copy_migrations
|
|
16
|
+
rake "panda_core:install:migrations"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def show_readme
|
|
20
|
+
say ""
|
|
21
|
+
say "Panda Core installed!", :green
|
|
22
|
+
say ""
|
|
23
|
+
say "Next steps:"
|
|
24
|
+
say " 1. Edit config/initializers/panda.rb to configure authentication"
|
|
25
|
+
say " 2. Run: rails db:migrate"
|
|
26
|
+
say " 3. Add gem 'panda-cms' to your Gemfile for CMS functionality"
|
|
27
|
+
say ""
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Panda::Core.configure do |config|
|
|
4
|
+
# Path prefix for admin routes (e.g. "/admin", "/manage")
|
|
5
|
+
config.admin_path = "/admin"
|
|
6
|
+
|
|
7
|
+
# Title shown on the login page
|
|
8
|
+
config.login_page_title = "Admin"
|
|
9
|
+
|
|
10
|
+
# Title shown in the admin navigation bar
|
|
11
|
+
config.admin_title = "<%= Rails.application.class.module_parent_name %> Admin"
|
|
12
|
+
|
|
13
|
+
# Authentication providers
|
|
14
|
+
# Add the corresponding OmniAuth gem for each provider you enable
|
|
15
|
+
# (e.g. omniauth-google-oauth2, omniauth-github, omniauth-microsoft_graph).
|
|
16
|
+
#
|
|
17
|
+
# In development, GitHub OAuth works out of the box with shared dev credentials
|
|
18
|
+
# (restricted to localhost:3000). For production, add your own credentials via
|
|
19
|
+
# `rails credentials:edit`.
|
|
20
|
+
#
|
|
21
|
+
# The "developer" provider is built into OmniAuth and only active in
|
|
22
|
+
# development — it shows a simple form to enter a name and email.
|
|
23
|
+
#
|
|
24
|
+
# config.authentication_providers = {
|
|
25
|
+
# github: {
|
|
26
|
+
# enabled: true,
|
|
27
|
+
# name: "GitHub",
|
|
28
|
+
# client_id: if Rails.env.development?
|
|
29
|
+
# "Ov23liFMGyVvRrpuvyTT" # Shared Panda dev app (localhost:3000 only)
|
|
30
|
+
# else
|
|
31
|
+
# Rails.application.credentials.dig(:github, :client_id)
|
|
32
|
+
# end,
|
|
33
|
+
# client_secret: if Rails.env.development?
|
|
34
|
+
# "394a7024d7dd9c0ee0c8540768331d59d9e22477"
|
|
35
|
+
# else
|
|
36
|
+
# Rails.application.credentials.dig(:github, :client_secret)
|
|
37
|
+
# end
|
|
38
|
+
# },
|
|
39
|
+
# developer: {
|
|
40
|
+
# enabled: true,
|
|
41
|
+
# name: "Developer Login"
|
|
42
|
+
# }
|
|
43
|
+
# }
|
|
44
|
+
|
|
45
|
+
# Session cookie name
|
|
46
|
+
config.session_token_cookie = :panda_session
|
|
47
|
+
|
|
48
|
+
# User model classes (usually left as defaults)
|
|
49
|
+
config.user_class = "Panda::Core::User"
|
|
50
|
+
config.user_identity_class = "Panda::Core::UserIdentity"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Uncomment after adding gem "panda-cms" to your Gemfile:
|
|
54
|
+
# Panda::CMS.configure do |config|
|
|
55
|
+
# # Require login to view the public site
|
|
56
|
+
# config.require_login_to_view = false
|
|
57
|
+
# end
|
|
58
|
+
|
|
59
|
+
# Uncomment after adding gem "panda-editor" to your Gemfile:
|
|
60
|
+
# Panda::Editor.configure do |config|
|
|
61
|
+
# # Additional EditorJS tools to load
|
|
62
|
+
# # config.editor_js_tools = []
|
|
63
|
+
# end
|
|
@@ -161,8 +161,11 @@ module Panda
|
|
|
161
161
|
css_files = Dir[assets_dir.join("panda-core-*.css")].reject { |f| File.symlink?(f) }
|
|
162
162
|
|
|
163
163
|
if css_files.any?
|
|
164
|
-
# Return the
|
|
165
|
-
latest = css_files.max_by { |f|
|
|
164
|
+
# Return the file with the highest semantic version
|
|
165
|
+
latest = css_files.max_by { |f|
|
|
166
|
+
version_str = File.basename(f).match(/panda-core-(.+)\.css/)&.captures&.first || "0"
|
|
167
|
+
Gem::Version.new(version_str)
|
|
168
|
+
}
|
|
166
169
|
return "/panda-core-assets/#{File.basename(latest)}"
|
|
167
170
|
end
|
|
168
171
|
else
|
|
@@ -11,7 +11,7 @@ module Panda
|
|
|
11
11
|
|
|
12
12
|
def current_user
|
|
13
13
|
return @current_user if defined?(@current_user)
|
|
14
|
-
@current_user = User.find_by(id: session[
|
|
14
|
+
@current_user = User.find_by(id: session[Panda::Core::ADMIN_SESSION_KEY]) if session[Panda::Core::ADMIN_SESSION_KEY]
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def require_authentication
|
|
@@ -23,12 +23,12 @@ module Panda
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def sign_in(user)
|
|
26
|
-
session[
|
|
26
|
+
session[Panda::Core::ADMIN_SESSION_KEY] = user.id
|
|
27
27
|
@current_user = user
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def sign_out
|
|
31
|
-
session.delete(
|
|
31
|
+
session.delete(Panda::Core::ADMIN_SESSION_KEY)
|
|
32
32
|
@current_user = nil
|
|
33
33
|
end
|
|
34
34
|
end
|