pages_core 3.13.0 → 3.15.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/VERSION +1 -1
- data/app/assets/builds/pages_core/admin-dist.js +19 -8
- data/app/assets/builds/pages_core/admin-dist.js.map +4 -4
- data/app/assets/builds/pages_core/admin.css +704 -388
- data/app/assets/fonts/Inter-Black.woff2 +0 -0
- data/app/assets/fonts/Inter-BlackItalic.woff2 +0 -0
- data/app/assets/fonts/Inter-Bold.woff2 +0 -0
- data/app/assets/fonts/Inter-BoldItalic.woff2 +0 -0
- data/app/assets/fonts/Inter-ExtraBold.woff2 +0 -0
- data/app/assets/fonts/Inter-ExtraBoldItalic.woff2 +0 -0
- data/app/assets/fonts/Inter-ExtraLight.woff2 +0 -0
- data/app/assets/fonts/Inter-ExtraLightItalic.woff2 +0 -0
- data/app/assets/fonts/Inter-Italic.woff2 +0 -0
- data/app/assets/fonts/Inter-Light.woff2 +0 -0
- data/app/assets/fonts/Inter-LightItalic.woff2 +0 -0
- data/app/assets/fonts/Inter-Medium.woff2 +0 -0
- data/app/assets/fonts/Inter-MediumItalic.woff2 +0 -0
- data/app/assets/fonts/Inter-Regular.woff2 +0 -0
- data/app/assets/fonts/Inter-SemiBold.woff2 +0 -0
- data/app/assets/fonts/Inter-SemiBoldItalic.woff2 +0 -0
- data/app/assets/fonts/Inter-Thin.woff2 +0 -0
- data/app/assets/fonts/Inter-ThinItalic.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-Black.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-BlackItalic.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-Bold.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-BoldItalic.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-ExtraBold.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-ExtraBoldItalic.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-ExtraLight.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-ExtraLightItalic.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-Italic.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-Light.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-LightItalic.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-Medium.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-MediumItalic.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-Regular.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-SemiBold.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-SemiBoldItalic.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-Thin.woff2 +0 -0
- data/app/assets/fonts/InterDisplay-ThinItalic.woff2 +0 -0
- data/app/assets/fonts/InterVariable-Italic.woff2 +0 -0
- data/app/assets/fonts/InterVariable.woff2 +0 -0
- data/app/assets/stylesheets/pages_core/admin/components/archive.css +1 -1
- data/app/assets/stylesheets/pages_core/admin/components/attachments.css +22 -34
- data/app/assets/stylesheets/pages_core/admin/components/base.css +1 -68
- data/app/assets/stylesheets/pages_core/admin/components/forms.css +107 -48
- data/app/assets/stylesheets/pages_core/admin/components/header.css +56 -58
- data/app/assets/stylesheets/pages_core/admin/components/image_editor.css +35 -24
- data/app/assets/stylesheets/pages_core/admin/components/image_grid.css +28 -27
- data/app/assets/stylesheets/pages_core/admin/components/image_uploader.css +5 -5
- data/app/assets/stylesheets/pages_core/admin/components/layout.css +7 -1
- data/app/assets/stylesheets/pages_core/admin/components/list_table.css +24 -15
- data/app/assets/stylesheets/pages_core/admin/components/page_tree.css +63 -104
- data/app/assets/stylesheets/pages_core/admin/components/pagination.css +12 -13
- data/app/assets/stylesheets/pages_core/admin/components/search.css +1 -16
- data/app/assets/stylesheets/pages_core/admin/components/sidebar.css +5 -11
- data/app/assets/stylesheets/pages_core/admin/components/tag_editor.css +22 -36
- data/app/assets/stylesheets/pages_core/admin/components/toast.css +1 -2
- data/app/assets/stylesheets/pages_core/admin/components/toolbar.css +10 -10
- data/app/assets/stylesheets/pages_core/admin/components/totp.css +26 -0
- data/app/assets/stylesheets/pages_core/admin/controllers/pages.css +37 -51
- data/app/assets/stylesheets/pages_core/admin/global/fonts.css +271 -0
- data/app/assets/stylesheets/pages_core/admin/global/typography.css +109 -0
- data/app/assets/stylesheets/pages_core/admin/vars.css +1 -3
- data/app/assets/stylesheets/pages_core/admin.postcss.css +1 -0
- data/app/controllers/admin/account_recoveries_controller.rb +87 -0
- data/app/controllers/admin/invites_controller.rb +3 -2
- data/app/controllers/admin/otp_secrets_controller.rb +45 -0
- data/app/controllers/admin/pages_controller.rb +22 -42
- data/app/controllers/admin/recovery_codes_controller.rb +32 -0
- data/app/controllers/admin/sessions_controller.rb +65 -0
- data/app/controllers/admin/users_controller.rb +2 -8
- data/app/controllers/concerns/pages_core/authentication.rb +12 -10
- data/app/controllers/concerns/pages_core/error_reporting.rb +1 -1
- data/app/controllers/concerns/pages_core/page_parameters.rb +29 -0
- data/app/controllers/concerns/pages_core/policies_helper.rb +1 -1
- data/app/controllers/concerns/pages_core/preview_pages_controller.rb +20 -20
- data/app/controllers/pages_core/admin_controller.rb +1 -3
- data/app/controllers/pages_core/frontend/pages_controller.rb +2 -6
- data/app/formatters/pages_core/html_formatter.rb +2 -4
- data/app/helpers/admin/menu_helper.rb +5 -4
- data/app/helpers/admin/pages_helper.rb +1 -21
- data/app/helpers/pages_core/admin/admin_helper.rb +13 -3
- data/app/helpers/pages_core/admin/content_tabs_helper.rb +1 -2
- data/app/helpers/pages_core/admin/labelled_field_helper.rb +1 -1
- data/app/helpers/pages_core/frontend_helper.rb +1 -1
- data/app/helpers/pages_core/images_helper.rb +10 -8
- data/app/helpers/pages_core/labelled_form_builder.rb +2 -7
- data/app/helpers/pages_core/page_path_helper.rb +1 -1
- data/app/javascript/components/Attachments/Attachment.tsx +20 -18
- data/app/javascript/components/Attachments/AttachmentEditor.tsx +11 -9
- data/app/javascript/components/{Attachments.jsx → Attachments/List.tsx} +58 -63
- data/app/javascript/components/Attachments/useAttachments.ts +15 -0
- data/app/javascript/components/Attachments.tsx +14 -0
- data/app/javascript/components/DateRangeSelect.tsx +105 -0
- data/app/javascript/components/DateTimeSelect.tsx +136 -0
- data/app/javascript/components/EditableImage.tsx +11 -9
- data/app/javascript/components/FileUploadButton.tsx +7 -7
- data/app/javascript/components/ImageCropper/FocalPoint.tsx +9 -12
- data/app/javascript/components/ImageCropper/Image.tsx +10 -8
- data/app/javascript/components/ImageCropper/Toolbar.tsx +11 -12
- data/app/javascript/components/ImageCropper/useCrop.ts +24 -53
- data/app/javascript/components/ImageCropper.tsx +10 -15
- data/app/javascript/components/ImageEditor/Form.tsx +12 -8
- data/app/javascript/components/ImageEditor.tsx +12 -7
- data/app/javascript/components/ImageGrid/DragElement.tsx +9 -12
- data/app/javascript/components/{ImageGrid.jsx → ImageGrid/Grid.tsx} +62 -71
- data/app/javascript/components/ImageGrid/GridImage.tsx +22 -23
- data/app/javascript/components/ImageGrid/Placeholder.tsx +2 -2
- data/app/javascript/components/ImageGrid/useImageGrid.ts +26 -0
- data/app/javascript/components/ImageGrid.tsx +15 -0
- data/app/javascript/components/ImageUploader.tsx +35 -22
- data/app/javascript/components/LabelledField.tsx +34 -0
- data/app/javascript/components/Modal.tsx +2 -2
- data/app/javascript/components/PageForm/Block.tsx +81 -0
- data/app/javascript/components/PageForm/Content.tsx +54 -0
- data/app/javascript/components/PageForm/Dates.tsx +66 -0
- data/app/javascript/components/PageForm/Files.tsx +28 -0
- data/app/javascript/components/PageForm/Form.tsx +41 -0
- data/app/javascript/components/PageForm/Images.tsx +28 -0
- data/app/javascript/components/PageForm/LocaleLinks.tsx +36 -0
- data/app/javascript/components/PageForm/Metadata.tsx +67 -0
- data/app/javascript/components/PageForm/Options.tsx +180 -0
- data/app/javascript/components/PageForm/PageDescription.tsx +48 -0
- data/app/javascript/components/PageForm/PathSegment.tsx +65 -0
- data/app/javascript/components/PageForm/TabPanel.tsx +21 -0
- data/app/javascript/components/PageForm/Tabs.tsx +33 -0
- data/app/javascript/components/PageForm/UnconfiguredContent.tsx +42 -0
- data/app/javascript/components/PageForm/pageParams.ts +95 -0
- data/app/javascript/components/PageForm/preview.ts +23 -0
- data/app/javascript/components/PageForm/usePage.ts +169 -0
- data/app/javascript/components/PageForm/useTabs.ts +46 -0
- data/app/javascript/components/PageForm.tsx +163 -0
- data/app/javascript/components/PageImages.tsx +7 -9
- data/app/javascript/components/PageTree/Draggable.tsx +40 -39
- data/app/javascript/components/PageTree/Node.tsx +62 -56
- data/app/javascript/components/PageTree/PageName.tsx +28 -0
- data/app/javascript/components/PageTree.tsx +65 -53
- data/app/javascript/components/{RichTextArea.jsx → RichTextArea.tsx} +98 -79
- data/app/javascript/components/RichTextToolbarButton.tsx +4 -6
- data/app/javascript/components/TagEditor/AddTagForm.tsx +19 -12
- data/app/javascript/components/TagEditor/Editor.tsx +32 -0
- data/app/javascript/components/TagEditor/Tag.tsx +6 -4
- data/app/javascript/components/TagEditor/useTags.ts +58 -0
- data/app/javascript/components/TagEditor.tsx +8 -58
- data/app/javascript/components/Toast.tsx +3 -3
- data/app/javascript/components/drag/draggedOrder.ts +22 -14
- data/app/javascript/components/drag/useDragCollection.ts +35 -30
- data/app/javascript/components/drag/useDragUploader.ts +32 -21
- data/app/javascript/components/drag/useDraggable.ts +7 -6
- data/app/javascript/components/drag.ts +0 -1
- data/app/javascript/components.ts +1 -3
- data/app/javascript/features/RichText.tsx +2 -3
- data/app/javascript/features/contentTabs.ts +79 -0
- data/app/javascript/index.ts +5 -14
- data/app/javascript/lib/Tree.ts +31 -45
- data/app/javascript/lib/request.ts +11 -11
- data/app/javascript/stores/useToastStore.ts +1 -1
- data/app/javascript/types/Attachments.ts +29 -0
- data/app/javascript/types/Crop.ts +36 -0
- data/app/javascript/types/Drag.ts +34 -0
- data/app/javascript/types/Images.ts +47 -0
- data/app/javascript/types/PageEditor.ts +26 -0
- data/app/javascript/types/Pages.ts +75 -0
- data/app/javascript/types/Tags.ts +9 -0
- data/app/javascript/types/Template.ts +24 -0
- data/app/javascript/types/Trees.ts +19 -0
- data/app/javascript/types.ts +2 -25
- data/app/mailers/admin_mailer.rb +2 -2
- data/app/models/attachment.rb +1 -1
- data/app/models/concerns/pages_core/authenticable_user.rb +63 -0
- data/app/models/concerns/pages_core/emailable.rb +16 -0
- data/app/models/concerns/pages_core/page_model/templateable.rb +2 -16
- data/app/models/invite.rb +2 -6
- data/app/models/otp_secret.rb +101 -0
- data/app/models/page.rb +0 -3
- data/app/models/user.rb +2 -68
- data/app/policies/page_policy.rb +6 -2
- data/app/policies/user_policy.rb +4 -0
- data/app/resources/admin/page_resource.rb +95 -0
- data/app/resources/admin/page_tree_resource.rb +27 -0
- data/app/resources/admin/template_configuration_resource.rb +50 -0
- data/app/views/admin/account_recoveries/new.html.erb +22 -0
- data/app/views/admin/account_recoveries/show.html.erb +37 -0
- data/app/views/admin/invites/show.html.erb +1 -1
- data/app/views/admin/news/_sidebar.html.erb +2 -4
- data/app/views/admin/news/index.html.erb +0 -1
- data/app/views/admin/otp_secrets/create.html.erb +7 -0
- data/app/views/admin/otp_secrets/new.html.erb +60 -0
- data/app/views/admin/pages/_form.html.erb +10 -30
- data/app/views/admin/pages/_search_bar.html.erb +1 -1
- data/app/views/admin/pages/edit.html.erb +1 -57
- data/app/views/admin/pages/index.html.erb +1 -1
- data/app/views/admin/pages/new.html.erb +1 -44
- data/app/views/admin/recovery_codes/_codes.html.erb +14 -0
- data/app/views/admin/recovery_codes/create.html.erb +7 -0
- data/app/views/admin/recovery_codes/new.html.erb +11 -0
- data/app/views/admin/sessions/_otp_form.html.erb +13 -0
- data/app/views/admin/sessions/new.html.erb +31 -0
- data/app/views/admin/sessions/verify_otp.html.erb +19 -0
- data/app/views/admin/users/_access_control.html.erb +5 -1
- data/app/views/admin/users/_list.html.erb +12 -7
- data/app/views/admin/users/edit.html.erb +31 -1
- data/app/views/admin/users/new.html.erb +1 -1
- data/app/views/admin_mailer/account_recovery.text.erb +10 -0
- data/app/views/layouts/admin/_header.html.erb +3 -5
- data/app/views/layouts/admin/_page_header.html.erb +1 -2
- data/app/views/layouts/admin/_toast.html.erb +12 -0
- data/app/views/layouts/admin.html.erb +2 -2
- data/config/locales/en.yml +11 -7
- data/config/routes.rb +13 -12
- data/db/migrate/20240126160700_add_2fa_fields.rb +26 -0
- data/db/migrate/20240129201300_remove_password_reset_tokens.rb +13 -0
- data/db/migrate/20240131140700_change_email_to_citext.rb +18 -0
- data/db/migrate/20240201160700_remove_persistent_data.rb +7 -0
- data/db/migrate/20240508145300_remove_categories.rb +21 -0
- data/lib/pages_core/configuration/base.rb +2 -2
- data/lib/pages_core/templates/configuration.rb +1 -1
- data/lib/pages_core/templates/configuration_proxy.rb +2 -2
- data/lib/pages_core/templates/template_configuration.rb +11 -1
- data/lib/pages_core/templates.rb +6 -4
- data/lib/pages_core/version.rb +1 -1
- data/lib/pages_core.rb +6 -0
- data/lib/rails/generators/pages_core/frontend/templates/javascript/lib/gridOverlay.ts +6 -7
- data/lib/rails/generators/pages_core/frontend/templates/javascript/lib/responsiveEmbeds.ts +17 -12
- data/lib/rails/generators/pages_core/rspec/rspec_generator.rb +0 -2
- data/lib/rails/generators/pages_core/rspec/templates/rails_helper.rb +3 -4
- metadata +143 -35
- data/app/assets/stylesheets/pages_core/admin/components/login.css +0 -33
- data/app/controllers/admin/categories_controller.rb +0 -56
- data/app/controllers/admin/password_resets_controller.rb +0 -85
- data/app/controllers/concerns/pages_core/admin/persistent_params.rb +0 -75
- data/app/controllers/sessions_controller.rb +0 -27
- data/app/helpers/pages_core/admin/page_blocks_helper.rb +0 -66
- data/app/helpers/pages_core/admin/page_json_helper.rb +0 -23
- data/app/javascript/components/DateRangeSelect.jsx +0 -225
- data/app/javascript/components/PageDates.jsx +0 -73
- data/app/javascript/components/PageFiles.jsx +0 -25
- data/app/javascript/components/PageTree/types.ts +0 -15
- data/app/javascript/components/drag/types.ts +0 -28
- data/app/javascript/controllers/EditPageController.ts +0 -22
- data/app/javascript/controllers/LoginController.ts +0 -32
- data/app/javascript/controllers/MainController.ts +0 -74
- data/app/javascript/controllers/PageOptionsController.js +0 -67
- data/app/models/category.rb +0 -22
- data/app/models/page_category.rb +0 -6
- data/app/models/password_reset_token.rb +0 -34
- data/app/views/admin/pages/_edit_content.html.erb +0 -19
- data/app/views/admin/pages/_edit_files.html.erb +0 -4
- data/app/views/admin/pages/_edit_images.html.erb +0 -4
- data/app/views/admin/pages/_edit_metadata.html.erb +0 -35
- data/app/views/admin/pages/_edit_options.html.erb +0 -91
- data/app/views/admin/password_resets/show.html.erb +0 -21
- data/app/views/admin/users/login.html.erb +0 -65
- data/app/views/admin_mailer/password_reset.text.erb +0 -11
- data/lib/rails/generators/pages_core/rspec/templates/mailer_macros.rb +0 -11
@@ -62,11 +62,12 @@ module Admin
|
|
62
62
|
return if @invite && secure_compare(@invite.token, params[:token])
|
63
63
|
|
64
64
|
flash[:notice] = t("pages_core.invite_expired")
|
65
|
-
redirect_to(
|
65
|
+
redirect_to(admin_login_url)
|
66
66
|
end
|
67
67
|
|
68
68
|
def user_params
|
69
|
-
params.require(:user)
|
69
|
+
params.require(:user)
|
70
|
+
.permit(:name, :email, :password, :password_confirmation)
|
70
71
|
end
|
71
72
|
|
72
73
|
def invite_params
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Admin
|
4
|
+
class OtpSecretsController < Admin::AdminController
|
5
|
+
before_action :require_otp_disabled, only: %i[new create]
|
6
|
+
before_action :find_otp_secret
|
7
|
+
|
8
|
+
def new
|
9
|
+
@otp_secret.generate
|
10
|
+
end
|
11
|
+
|
12
|
+
def create
|
13
|
+
if @otp_secret.verify(otp_secret_params)
|
14
|
+
@recovery_codes = @otp_secret.generate_recovery_codes
|
15
|
+
@otp_secret.enable!(@recovery_codes)
|
16
|
+
else
|
17
|
+
flash[:error] = t("pages_core.otp.invalid_code")
|
18
|
+
redirect_to new_admin_otp_secret_path
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def destroy
|
23
|
+
@otp_secret.disable!
|
24
|
+
flash[:notice] = t("pages_core.otp.disabled")
|
25
|
+
redirect_to edit_admin_user_path(current_user)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def find_otp_secret
|
31
|
+
@otp_secret = OtpSecret.new(current_user)
|
32
|
+
end
|
33
|
+
|
34
|
+
def otp_secret_params
|
35
|
+
params.permit(:signed_message, :otp)
|
36
|
+
end
|
37
|
+
|
38
|
+
def require_otp_disabled
|
39
|
+
return unless current_user.otp_enabled?
|
40
|
+
|
41
|
+
flash[:notice] = t("pages_core.otp.already_enabled")
|
42
|
+
redirect_to edit_admin_user_path(current_user)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -2,9 +2,8 @@
|
|
2
2
|
|
3
3
|
module Admin
|
4
4
|
class PagesController < Admin::AdminController
|
5
|
-
include PagesCore::
|
5
|
+
include PagesCore::PageParameters
|
6
6
|
|
7
|
-
before_action :find_categories
|
8
7
|
before_action :find_page, only: %i[show edit update destroy move]
|
9
8
|
|
10
9
|
require_authorization
|
@@ -39,26 +38,26 @@ module Admin
|
|
39
38
|
def edit; end
|
40
39
|
|
41
40
|
def create
|
42
|
-
@page = build_page(content_locale, page_params
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
@page = build_page(content_locale, page_params).tap(&:save)
|
42
|
+
|
43
|
+
respond_with_page(@page) do
|
44
|
+
if @page.valid?
|
46
45
|
redirect_to(edit_admin_page_url(content_locale, @page))
|
46
|
+
else
|
47
|
+
render action: :new
|
47
48
|
end
|
48
|
-
else
|
49
|
-
render action: :new
|
50
49
|
end
|
51
50
|
end
|
52
51
|
|
53
52
|
def update
|
54
|
-
|
55
|
-
|
56
|
-
|
53
|
+
@page.update(page_params)
|
54
|
+
respond_with_page(@page) do
|
55
|
+
if @page.valid?
|
57
56
|
flash[:notice] = t("pages_core.changes_saved")
|
58
57
|
redirect_to edit_admin_page_url(content_locale, @page)
|
58
|
+
else
|
59
|
+
render action: :edit
|
59
60
|
end
|
60
|
-
else
|
61
|
-
render action: :edit
|
62
61
|
end
|
63
62
|
end
|
64
63
|
|
@@ -75,53 +74,34 @@ module Admin
|
|
75
74
|
|
76
75
|
private
|
77
76
|
|
78
|
-
def build_page(locale, attributes = nil
|
77
|
+
def build_page(locale, attributes = nil)
|
79
78
|
Page.new.localize(locale).tap do |page|
|
80
79
|
page.author = default_author || current_user
|
81
80
|
page.attributes = attributes if attributes
|
82
|
-
page.categories = categories if categories
|
83
81
|
end
|
84
82
|
end
|
85
83
|
|
86
84
|
def default_author
|
87
|
-
User.
|
88
|
-
end
|
89
|
-
|
90
|
-
def page_attributes
|
91
|
-
%i[template user_id status feed_enabled published_at redirect_to
|
92
|
-
image_link news_page unique_name pinned parent_page_id serialized_tags
|
93
|
-
meta_image_id starts_at ends_at all_day image_id path_segment
|
94
|
-
meta_title meta_description open_graph_title open_graph_description]
|
85
|
+
User.find_by(email: PagesCore.config.default_author)
|
95
86
|
end
|
96
87
|
|
97
88
|
def page_params
|
98
|
-
params.require(:page).permit(
|
99
|
-
PagesCore::Templates::TemplateConfiguration.all_blocks +
|
100
|
-
page_attributes,
|
101
|
-
page_images_attributes: %i[id position image_id primary _destroy],
|
102
|
-
page_files_attributes: %i[id position attachment_id _destroy]
|
103
|
-
)
|
104
|
-
end
|
105
|
-
|
106
|
-
def param_categories
|
107
|
-
return [] unless params[:category]
|
108
|
-
|
109
|
-
params.permit(category: {})[:category].to_hash
|
110
|
-
.map { |id, _| Category.find(id) }
|
89
|
+
params.require(:page).permit(page_content_attributes)
|
111
90
|
end
|
112
91
|
|
113
92
|
def find_page
|
114
93
|
@page = Page.find(params[:id]).localize(content_locale)
|
115
94
|
end
|
116
95
|
|
117
|
-
def find_categories
|
118
|
-
@categories = Category.order("name")
|
119
|
-
end
|
120
|
-
|
121
96
|
def respond_with_page(page, &block)
|
122
97
|
respond_to do |format|
|
123
|
-
format.html
|
124
|
-
format.json
|
98
|
+
format.html(&block)
|
99
|
+
format.json do
|
100
|
+
render json: ::Admin::PageResource.new(
|
101
|
+
page,
|
102
|
+
params: { user: current_user }
|
103
|
+
)
|
104
|
+
end
|
125
105
|
end
|
126
106
|
end
|
127
107
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Admin
|
4
|
+
class RecoveryCodesController < Admin::AdminController
|
5
|
+
before_action :require_otp_enabled
|
6
|
+
before_action :find_otp_secret
|
7
|
+
|
8
|
+
def new; end
|
9
|
+
|
10
|
+
def create
|
11
|
+
if @otp_secret.validate_otp!(params[:otp])
|
12
|
+
@recovery_codes = @otp_secret.regenerate_recovery_codes!
|
13
|
+
else
|
14
|
+
flash[:error] = t("pages_core.otp.invalid_code")
|
15
|
+
redirect_to new_admin_recovery_codes_path
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def find_otp_secret
|
22
|
+
@otp_secret = OtpSecret.new(current_user)
|
23
|
+
end
|
24
|
+
|
25
|
+
def require_otp_enabled
|
26
|
+
return if current_user.otp_enabled?
|
27
|
+
|
28
|
+
flash[:notice] = t("pages_core.otp.required")
|
29
|
+
redirect_to edit_admin_user_path(current_user)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Admin
|
4
|
+
class SessionsController < Admin::AdminController
|
5
|
+
before_action :require_authentication, only: %i[destroy]
|
6
|
+
before_action :find_user, only: %i[create]
|
7
|
+
before_action :find_signed_user, only: %i[verify_otp]
|
8
|
+
before_action :require_user, only: %i[create verify_otp]
|
9
|
+
|
10
|
+
def new
|
11
|
+
redirect_to admin_default_url if logged_in?
|
12
|
+
end
|
13
|
+
|
14
|
+
def create
|
15
|
+
if @user.otp_enabled?
|
16
|
+
@signed_user_id = message_verifier.generate(
|
17
|
+
@user.id, expires_in: 1.hour
|
18
|
+
)
|
19
|
+
render template: "admin/sessions/verify_otp"
|
20
|
+
else
|
21
|
+
authenticate!(@user)
|
22
|
+
redirect_to admin_default_url
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def destroy
|
27
|
+
flash[:notice] = t("pages_core.logged_out")
|
28
|
+
deauthenticate!
|
29
|
+
redirect_to admin_login_url
|
30
|
+
end
|
31
|
+
|
32
|
+
def verify_otp
|
33
|
+
@otp_secret = OtpSecret.new(@user)
|
34
|
+
if @otp_secret.validate_otp!(params[:otp])
|
35
|
+
authenticate!(@user)
|
36
|
+
redirect_to admin_default_url
|
37
|
+
else
|
38
|
+
flash[:notice] = t("pages_core.otp.invalid_code")
|
39
|
+
render template: "admin/sessions/verify_otp"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def find_signed_user
|
46
|
+
@signed_user_id = params[:signed_user_id]
|
47
|
+
@user = User.find(message_verifier.verify(@signed_user_id))
|
48
|
+
end
|
49
|
+
|
50
|
+
def find_user
|
51
|
+
@user = User.authenticate(params[:email], password: params[:password])
|
52
|
+
end
|
53
|
+
|
54
|
+
def message_verifier
|
55
|
+
Rails.application.message_verifier(:session)
|
56
|
+
end
|
57
|
+
|
58
|
+
def require_user
|
59
|
+
return if @user
|
60
|
+
|
61
|
+
flash[:notice] = t("pages_core.invalid_login")
|
62
|
+
redirect_to admin_login_url
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Admin
|
4
4
|
class UsersController < Admin::AdminController
|
5
|
-
before_action :require_authentication, except: %i[new create
|
5
|
+
before_action :require_authentication, except: %i[new create]
|
6
6
|
before_action :require_no_users, only: %i[new create]
|
7
7
|
before_action(
|
8
8
|
:find_user,
|
@@ -19,12 +19,6 @@ module Admin
|
|
19
19
|
@invites = []
|
20
20
|
end
|
21
21
|
|
22
|
-
def login
|
23
|
-
return unless logged_in?
|
24
|
-
|
25
|
-
redirect_to admin_default_url
|
26
|
-
end
|
27
|
-
|
28
22
|
def show; end
|
29
23
|
|
30
24
|
def new
|
@@ -81,7 +75,7 @@ module Admin
|
|
81
75
|
{ role_names: [] }]
|
82
76
|
end
|
83
77
|
if User.none? || (@user && policy(@user).change_password?)
|
84
|
-
permitted_params += %i[password
|
78
|
+
permitted_params += %i[password password_confirmation]
|
85
79
|
end
|
86
80
|
params.require(:user).permit(permitted_params)
|
87
81
|
end
|
@@ -35,20 +35,22 @@ module PagesCore
|
|
35
35
|
@current_user = user
|
36
36
|
end
|
37
37
|
|
38
|
-
def
|
39
|
-
|
40
|
-
user = User.where(id: session[:current_user_id]).first
|
41
|
-
end
|
42
|
-
|
43
|
-
return unless user&.can_login?
|
38
|
+
def finalize_authenticated_session
|
39
|
+
return unless logged_in?
|
44
40
|
|
45
|
-
|
41
|
+
session[:current_user] =
|
42
|
+
{ id: current_user.id, token: current_user.session_token }
|
46
43
|
end
|
47
44
|
|
48
|
-
def
|
49
|
-
|
45
|
+
def start_authenticated_session
|
46
|
+
user_session = session.fetch(:current_user, nil)&.symbolize_keys
|
47
|
+
|
48
|
+
return unless user_session
|
50
49
|
|
51
|
-
|
50
|
+
user = User.find_by(id: user_session[:id])
|
51
|
+
return unless user && user.session_token == user_session[:token]
|
52
|
+
|
53
|
+
authenticated(user)
|
52
54
|
end
|
53
55
|
end
|
54
56
|
end
|
@@ -11,7 +11,7 @@ module PagesCore
|
|
11
11
|
protected
|
12
12
|
|
13
13
|
def configure_sentry_scope
|
14
|
-
return if Rails.env.test? || !Object.const_defined?(
|
14
|
+
return if Rails.env.test? || !Object.const_defined?(:Sentry)
|
15
15
|
|
16
16
|
Sentry.set_context("params", params.to_unsafe_h)
|
17
17
|
Sentry.set_tags(locale: params[:locale] || I18n.default_locale.to_s)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PagesCore
|
4
|
+
module PageParameters
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def page_attachment_attributes
|
8
|
+
{ page_images_attributes: %i[id position image_id primary _destroy],
|
9
|
+
page_files_attributes: %i[id position attachment_id _destroy] }
|
10
|
+
end
|
11
|
+
|
12
|
+
def page_content_attributes
|
13
|
+
locales = PagesCore.config.locales&.keys || [I18n.default_locale]
|
14
|
+
[page_static_attributes,
|
15
|
+
PagesCore::Templates::TemplateConfiguration.all_blocks,
|
16
|
+
:path_segment,
|
17
|
+
(PagesCore::Templates::TemplateConfiguration
|
18
|
+
.localized_blocks + %i[path_segment])
|
19
|
+
.index_with { locales },
|
20
|
+
page_attachment_attributes]
|
21
|
+
end
|
22
|
+
|
23
|
+
def page_static_attributes
|
24
|
+
%i[template user_id status feed_enabled published_at redirect_to
|
25
|
+
news_page unique_name pinned parent_page_id serialized_tags
|
26
|
+
meta_image_id starts_at ends_at all_day]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -3,11 +3,27 @@
|
|
3
3
|
module PagesCore
|
4
4
|
module PreviewPagesController
|
5
5
|
extend ActiveSupport::Concern
|
6
|
+
include PagesCore::PageParameters
|
7
|
+
|
8
|
+
included do
|
9
|
+
before_action :disable_xss_protection, only: %i[preview]
|
10
|
+
end
|
6
11
|
|
7
12
|
def preview?
|
8
13
|
@preview || false
|
9
14
|
end
|
10
15
|
|
16
|
+
def preview
|
17
|
+
render_error 403 unless logged_in?
|
18
|
+
|
19
|
+
@preview = true
|
20
|
+
@page = Page.find_by(id: params[:page_id]) || Page.new
|
21
|
+
@page.readonly!
|
22
|
+
@page.assign_attributes(preview_page_params)
|
23
|
+
|
24
|
+
render_page
|
25
|
+
end
|
26
|
+
|
11
27
|
private
|
12
28
|
|
13
29
|
def disable_xss_protection
|
@@ -17,31 +33,15 @@ module PagesCore
|
|
17
33
|
response.headers["X-XSS-Protection"] = "0"
|
18
34
|
end
|
19
35
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
def page_params
|
27
|
-
params.require(:page).permit(
|
28
|
-
Page.localized_attributes + permitted_page_attributes
|
29
|
-
)
|
30
|
-
end
|
31
|
-
|
32
|
-
def preview_page(page)
|
33
|
-
redirect_to(page_url(content_locale, page)) && return unless logged_in?
|
34
|
-
|
35
|
-
disable_xss_protection
|
36
|
-
|
37
|
-
@preview = true
|
38
|
-
page.attributes = page_params.merge(
|
36
|
+
def preview_page_params
|
37
|
+
ActionController::Parameters.new(
|
38
|
+
JSON.parse(params.require(:preview_page))
|
39
|
+
).permit(:id, page_content_attributes).merge(
|
39
40
|
status: 2,
|
40
41
|
published_at: Time.zone.now,
|
41
42
|
locale: content_locale,
|
42
43
|
redirect_to: nil
|
43
44
|
)
|
44
|
-
render_page
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
@@ -4,8 +4,6 @@
|
|
4
4
|
# authorization and other common code for the Admin set of controllers.
|
5
5
|
module PagesCore
|
6
6
|
class AdminController < ::ApplicationController
|
7
|
-
include PagesCore::Admin::PersistentParams
|
8
|
-
|
9
7
|
protect_from_forgery with: :exception
|
10
8
|
|
11
9
|
before_action :set_i18n_locale
|
@@ -48,7 +46,7 @@ module PagesCore
|
|
48
46
|
if User.count < 1
|
49
47
|
redirect_to(new_admin_user_url)
|
50
48
|
else
|
51
|
-
redirect_to(
|
49
|
+
redirect_to(admin_login_url)
|
52
50
|
end
|
53
51
|
end
|
54
52
|
|
@@ -12,8 +12,8 @@ module PagesCore
|
|
12
12
|
|
13
13
|
before_action :load_root_pages
|
14
14
|
before_action :find_page_by_path, only: [:show]
|
15
|
-
before_action :find_page, only: %i[show
|
16
|
-
before_action :require_page, only: %i[show
|
15
|
+
before_action :find_page, only: %i[show]
|
16
|
+
before_action :require_page, only: %i[show]
|
17
17
|
before_action :canonicalize_url, only: [:show]
|
18
18
|
static_cache :index, :show
|
19
19
|
|
@@ -27,10 +27,6 @@ module PagesCore
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
def preview
|
31
|
-
preview_page(@page)
|
32
|
-
end
|
33
|
-
|
34
30
|
def show
|
35
31
|
respond_to do |format|
|
36
32
|
format.html { render_published_page(@page) }
|
@@ -38,8 +38,7 @@ module PagesCore
|
|
38
38
|
def find_attachments(str)
|
39
39
|
str.match(attachment_expression)[1]
|
40
40
|
.split(",")
|
41
|
-
.
|
42
|
-
.compact
|
41
|
+
.filter_map { |id| find_attachment(id) }
|
43
42
|
end
|
44
43
|
|
45
44
|
def find_file(id)
|
@@ -51,8 +50,7 @@ module PagesCore
|
|
51
50
|
def find_files(str)
|
52
51
|
str.match(file_expression)[1]
|
53
52
|
.split(",")
|
54
|
-
.
|
55
|
-
.compact
|
53
|
+
.filter_map { |id| find_file(id) }
|
56
54
|
end
|
57
55
|
|
58
56
|
def fix_markup(str)
|
@@ -5,12 +5,13 @@ module Admin
|
|
5
5
|
include PagesCore::LocalesHelper
|
6
6
|
|
7
7
|
def header_tabs(group)
|
8
|
+
return unless menu_items_for(group).any?
|
9
|
+
|
8
10
|
tag.ul(class: group.to_s) do
|
9
11
|
safe_join(menu_items_for(group).map do |item|
|
10
12
|
tag.li do
|
11
13
|
path = instance_eval(&item.path)
|
12
|
-
link_to(item.label,
|
13
|
-
path,
|
14
|
+
link_to(item.label, path,
|
14
15
|
class: (current_menu_item?(item) ? "current" : ""))
|
15
16
|
end
|
16
17
|
end)
|
@@ -24,9 +25,9 @@ module Admin
|
|
24
25
|
.select { |_, routing| routing[:controller] == params[:controller] }
|
25
26
|
end
|
26
27
|
|
27
|
-
def find_menu_candidate(&
|
28
|
+
def find_menu_candidate(&)
|
28
29
|
menu_item_candidates
|
29
|
-
.select
|
30
|
+
.select(&)
|
30
31
|
.try(&:first)
|
31
32
|
.try(&:first)
|
32
33
|
end
|
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
module Admin
|
4
4
|
module PagesHelper
|
5
|
-
include PagesCore::Admin::PageBlocksHelper
|
6
|
-
|
7
5
|
def autopublish_notice(page)
|
8
6
|
return unless page.autopublish?
|
9
7
|
|
@@ -13,22 +11,8 @@ module Admin
|
|
13
11
|
end
|
14
12
|
end
|
15
13
|
|
16
|
-
def available_templates_for_select
|
17
|
-
PagesCore::Templates.names.collect do |template|
|
18
|
-
if template == "index"
|
19
|
-
["[Default]", "index"]
|
20
|
-
else
|
21
|
-
[template.humanize, template]
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def file_embed_code(file)
|
27
|
-
"[file:#{file.id}]"
|
28
|
-
end
|
29
|
-
|
30
14
|
def news_section_name(page, news_pages)
|
31
|
-
if news_pages.
|
15
|
+
if news_pages.count { |p| p.name == page.name } > 1
|
32
16
|
page_name(page, include_parents: true)
|
33
17
|
else
|
34
18
|
page_name(page)
|
@@ -83,10 +67,6 @@ module Admin
|
|
83
67
|
|
84
68
|
private
|
85
69
|
|
86
|
-
def nested_array?(array)
|
87
|
-
array.present? && array.first.is_a?(Array)
|
88
|
-
end
|
89
|
-
|
90
70
|
def page_name_with_fallback(page)
|
91
71
|
if page.name?
|
92
72
|
page.name.to_s
|
@@ -7,7 +7,6 @@ module PagesCore
|
|
7
7
|
include PagesCore::Admin::DateRangeHelper
|
8
8
|
include PagesCore::Admin::ImageUploadsHelper
|
9
9
|
include PagesCore::Admin::LocalesHelper
|
10
|
-
include PagesCore::Admin::PageJsonHelper
|
11
10
|
include PagesCore::Admin::LabelledFieldHelper
|
12
11
|
include PagesCore::Admin::TagEditorHelper
|
13
12
|
|
@@ -18,12 +17,12 @@ module PagesCore
|
|
18
17
|
value: content))
|
19
18
|
end
|
20
19
|
|
21
|
-
def locale_links
|
20
|
+
def locale_links
|
22
21
|
return unless PagesCore.config.localizations?
|
23
22
|
|
24
23
|
safe_join(
|
25
24
|
PagesCore.config.locales.map do |locale, name|
|
26
|
-
link_to(name,
|
25
|
+
link_to(name, yield(locale),
|
27
26
|
class: ("current" if locale == params[:locale].to_sym))
|
28
27
|
end
|
29
28
|
)
|
@@ -33,6 +32,17 @@ module PagesCore
|
|
33
32
|
%w[January February March April May June July August September October
|
34
33
|
November December][month - 1]
|
35
34
|
end
|
35
|
+
|
36
|
+
def qr_code(url)
|
37
|
+
ActiveSupport::SafeBuffer.new(
|
38
|
+
RQRCode::QRCode.new(url)
|
39
|
+
.as_svg({ color: "000",
|
40
|
+
shape_rendering: "crispEdges",
|
41
|
+
module_size: 10,
|
42
|
+
use_path: true,
|
43
|
+
viewbox: true })
|
44
|
+
)
|
45
|
+
end
|
36
46
|
end
|
37
47
|
end
|
38
48
|
end
|