katalyst-koi 4.20.1 → 5.0.0.alpha.1
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/app/assets/images/koi/icons/add.svg +3 -0
- data/app/assets/images/koi/icons/close.svg +1 -0
- data/app/assets/images/koi/koi.png +0 -0
- data/app/assets/javascripts/koi/controllers/file_field_controller.js +2 -2
- data/app/assets/javascripts/koi/controllers/index.js +0 -3
- data/app/assets/javascripts/koi/controllers/koi/modal_controller.js +40 -0
- data/app/assets/javascripts/koi/controllers/navigation_controller.js +14 -21
- data/app/assets/javascripts/koi/controllers/webauthn_authentication_controller.js +12 -13
- data/app/assets/javascripts/koi/controllers/webauthn_registration_controller.js +11 -10
- data/app/assets/stylesheets/koi/blocks/actions.css +8 -0
- data/app/assets/stylesheets/koi/blocks/application-header.css +15 -0
- data/app/assets/stylesheets/koi/blocks/application-navigation.css +54 -0
- data/app/assets/stylesheets/koi/blocks/button.css +90 -0
- data/app/assets/stylesheets/koi/blocks/flash.css +19 -0
- data/app/assets/stylesheets/koi/blocks/icon.css +15 -0
- data/app/assets/stylesheets/koi/blocks/index.css +13 -0
- data/app/assets/stylesheets/koi/blocks/modal.css +26 -0
- data/app/assets/stylesheets/koi/blocks/navigation.css +23 -0
- data/app/assets/stylesheets/koi/blocks/page-header.css +31 -0
- data/app/assets/stylesheets/koi/blocks/pagy.css +82 -0
- data/app/assets/stylesheets/koi/blocks/prose.css +37 -0
- data/app/assets/stylesheets/koi/blocks/tables/index.css +4 -0
- data/app/assets/stylesheets/koi/{components/_query.scss → blocks/tables/query.css} +13 -13
- data/app/assets/stylesheets/koi/{base/_tables.scss → blocks/tables/table.css} +11 -59
- data/app/assets/stylesheets/koi/compositions/cover.css +17 -0
- data/app/assets/stylesheets/koi/{base/_flow.scss → compositions/flow.css} +1 -1
- data/app/assets/stylesheets/koi/compositions/index.css +4 -0
- data/app/assets/stylesheets/koi/compositions/wrapper.css +11 -0
- data/app/assets/stylesheets/koi/forms/caption.css +22 -0
- data/app/assets/stylesheets/koi/forms/checkboxes.css +153 -0
- data/app/assets/stylesheets/koi/forms/date-input.css +12 -0
- data/app/assets/stylesheets/koi/{components/_document-field.scss → forms/document-field.css} +20 -15
- data/app/assets/stylesheets/koi/forms/errors.css +38 -0
- data/app/assets/stylesheets/koi/forms/fieldset.css +73 -0
- data/app/assets/stylesheets/koi/forms/file-upload.css +20 -0
- data/app/assets/stylesheets/koi/forms/form-group.css +19 -0
- data/app/assets/stylesheets/koi/forms/hint.css +11 -0
- data/app/assets/stylesheets/koi/forms/image-field.css +96 -0
- data/app/assets/stylesheets/koi/forms/index.css +44 -0
- data/app/assets/stylesheets/koi/forms/input.css +194 -0
- data/app/assets/stylesheets/koi/forms/label.css +43 -0
- data/app/assets/stylesheets/koi/forms/password.css +18 -0
- data/app/assets/stylesheets/koi/forms/radios.css +162 -0
- data/app/assets/stylesheets/koi/forms/select.css +18 -0
- data/app/assets/stylesheets/koi/forms/textarea.css +3 -0
- data/app/assets/stylesheets/koi/forms/trix.css +33 -0
- data/app/assets/stylesheets/koi/global/fonts.css +22 -0
- data/app/assets/stylesheets/koi/global/global-styles.css +297 -0
- data/app/assets/stylesheets/koi/global/reset.css +98 -0
- data/app/assets/stylesheets/koi/global/variables.css +97 -0
- data/app/assets/stylesheets/koi/icons.css +14 -0
- data/app/assets/stylesheets/koi/{admin.scss → index.css} +16 -7
- data/app/assets/stylesheets/koi/login.css +26 -0
- data/app/assets/stylesheets/koi/themes/_index.scss +0 -1
- data/app/assets/stylesheets/koi/utilities/index.css +1 -0
- data/app/assets/stylesheets/koi/utilities/visually-hidden.css +18 -0
- data/app/components/concerns/koi/tables/cells.rb +3 -3
- data/app/components/koi/header/edit_component.rb +1 -1
- data/app/components/koi/header_component.html.erb +12 -11
- data/app/components/koi/header_component.rb +2 -0
- data/app/components/koi/table_component.rb +8 -0
- data/app/components/koi/tables/cells/link_component.rb +2 -2
- data/app/controllers/admin/admin_users_controller.rb +26 -20
- data/app/controllers/admin/application_controller.rb +1 -3
- data/app/controllers/admin/caches_controller.rb +1 -1
- data/app/controllers/admin/credentials_controller.rb +19 -15
- data/app/controllers/admin/otps_controller.rb +16 -14
- data/app/controllers/admin/sessions_controller.rb +18 -3
- data/app/controllers/admin/tokens_controller.rb +4 -2
- data/app/controllers/admin/url_rewrites_controller.rb +19 -17
- data/app/controllers/admin/well_knowns_controller.rb +20 -18
- data/app/controllers/concerns/koi/controller/records_authentication.rb +10 -23
- data/app/controllers/concerns/koi/controller.rb +25 -4
- data/app/controllers/well_knowns_controller.rb +1 -1
- data/app/helpers/koi/form_helper.rb +18 -0
- data/app/helpers/koi/header_helper.rb +122 -0
- data/app/helpers/koi/index_actions_helper.rb +3 -2
- data/app/helpers/koi/modal_helper.rb +71 -0
- data/app/models/admin/user.rb +7 -1
- data/app/models/url_rewrite.rb +1 -9
- data/app/views/admin/admin_users/_form.html+self.erb +8 -0
- data/app/views/admin/admin_users/_form.html.erb +8 -0
- data/app/views/admin/admin_users/archived.html.erb +7 -4
- data/app/views/admin/admin_users/edit.html+self.erb +12 -0
- data/app/views/admin/admin_users/edit.html.erb +13 -8
- data/app/views/admin/admin_users/index.html.erb +10 -5
- data/app/views/admin/admin_users/new.html.erb +8 -8
- data/app/views/admin/admin_users/show.html+self.erb +26 -14
- data/app/views/admin/admin_users/show.html.erb +22 -20
- data/app/views/admin/credentials/_credentials.html+self.erb +8 -6
- data/app/views/admin/credentials/_credentials.html.erb +3 -1
- data/app/views/admin/credentials/create.turbo_stream.erb +4 -3
- data/app/views/admin/credentials/destroy.turbo_stream.erb +4 -2
- data/app/views/admin/credentials/new.html.erb +42 -36
- data/app/views/admin/dashboards/show.html.erb +13 -1
- data/app/views/admin/otps/_form.html.erb +7 -7
- data/app/views/admin/otps/create.turbo_stream.erb +3 -3
- data/app/views/admin/otps/new.html.erb +5 -3
- data/app/views/admin/sessions/new.html.erb +2 -3
- data/app/views/admin/sessions/otp.html.erb +1 -3
- data/app/views/admin/sessions/password.html.erb +1 -3
- data/app/views/admin/tokens/show.html.erb +4 -6
- data/app/views/admin/url_rewrites/_form.html.erb +9 -0
- data/app/views/admin/url_rewrites/edit.html.erb +13 -9
- data/app/views/admin/url_rewrites/index.html.erb +10 -7
- data/app/views/admin/url_rewrites/new.html.erb +8 -8
- data/app/views/admin/url_rewrites/show.html.erb +17 -12
- data/app/views/admin/well_knowns/_form.html.erb +9 -0
- data/app/views/admin/well_knowns/edit.html.erb +13 -9
- data/app/views/admin/well_knowns/index.html.erb +8 -5
- data/app/views/admin/well_knowns/new.html.erb +8 -8
- data/app/views/admin/well_knowns/show.html.erb +14 -13
- data/app/views/katalyst/content/asides/_aside.html+form.erb +6 -4
- data/app/views/katalyst/content/columns/_column.html+form.erb +5 -3
- data/app/views/katalyst/content/contents/_content.html+form.erb +8 -6
- data/app/views/katalyst/content/figures/_figure.html+form.erb +8 -5
- data/app/views/katalyst/content/groups/_group.html+form.erb +5 -3
- data/app/views/katalyst/content/items/_item.html+form.erb +5 -3
- data/app/views/katalyst/content/sections/_section.html+form.erb +5 -3
- data/app/views/katalyst/content/tables/_table.html+form.erb +16 -11
- data/app/views/katalyst/navigation/items/_button.html.erb +6 -12
- data/app/views/katalyst/navigation/items/_heading.html.erb +3 -10
- data/app/views/katalyst/navigation/items/_link.html.erb +6 -11
- data/app/views/katalyst/navigation/menus/edit.html.erb +10 -6
- data/app/views/katalyst/navigation/menus/index.html.erb +4 -2
- data/app/views/katalyst/navigation/menus/new.html.erb +5 -3
- data/app/views/katalyst/navigation/menus/show.html.erb +8 -7
- data/app/views/layouts/koi/_application_header.html.erb +20 -0
- data/app/views/layouts/koi/_application_navigation.html.erb +34 -0
- data/app/views/layouts/koi/_flash.html.erb +6 -3
- data/app/views/layouts/koi/_navigation_header.html.erb +0 -2
- data/app/views/layouts/koi/application.html.erb +22 -27
- data/app/views/layouts/koi/frame.html.erb +1 -3
- data/app/views/layouts/koi/login.html.erb +12 -5
- data/config/importmap.rb +1 -0
- data/config/locales/koi.en.yml +9 -1
- data/config/locales/pagy.en.yml +11 -0
- data/config/routes.rb +1 -1
- data/lib/generators/koi/admin/admin_generator.rb +4 -13
- data/lib/generators/koi/admin_controller/admin_controller_generator.rb +7 -17
- data/lib/generators/koi/admin_controller/templates/controller.rb.tt +82 -18
- data/lib/generators/koi/admin_controller/templates/controller_spec.rb.tt +113 -47
- data/lib/generators/koi/admin_route/admin_route_generator.rb +63 -10
- data/lib/generators/koi/admin_views/USAGE +18 -7
- data/lib/generators/koi/admin_views/admin_views_generator.rb +19 -11
- data/lib/generators/koi/admin_views/templates/_form.html.erb.tt +8 -0
- data/lib/generators/koi/admin_views/templates/archived.html.erb.tt +33 -0
- data/lib/generators/koi/admin_views/templates/edit.html.erb.tt +17 -9
- data/lib/generators/koi/admin_views/templates/index.html.erb.tt +31 -3
- data/lib/generators/koi/admin_views/templates/new.html.erb.tt +8 -8
- data/lib/generators/koi/admin_views/templates/show.html.erb.tt +15 -18
- data/lib/generators/koi/helpers/attribute_helpers.rb +147 -0
- data/lib/generators/koi/helpers/attribute_types.rb +218 -0
- data/lib/generators/koi/helpers/resource_helpers.rb +121 -0
- data/lib/generators/koi/{active_record/active_record_generator.rb → model/model_generator.rb} +1 -1
- data/lib/koi/config.rb +3 -1
- data/lib/koi/engine.rb +1 -15
- data/lib/koi/form/builder.rb +6 -6
- data/lib/koi/form/content.rb +55 -0
- data/lib/koi/form/elements/document.rb +1 -1
- data/lib/koi/form/elements/file_element.rb +1 -1
- data/lib/koi/form/elements/image.rb +1 -1
- data/lib/koi/form_builder.rb +1 -0
- data/lib/koi/menu.rb +14 -1
- data/lib/koi/middleware/admin_authentication.rb +4 -32
- data/spec/factories/admins.rb +1 -1
- metadata +93 -109
- data/app/assets/builds/katalyst/koi.esm.js +0 -518
- data/app/assets/builds/katalyst/koi.js +0 -518
- data/app/assets/builds/katalyst/koi.min.js +0 -2
- data/app/assets/builds/katalyst/koi.min.js.map +0 -1
- data/app/assets/builds/koi/admin.css +0 -1
- data/app/assets/stylesheets/koi/base/_button.scss +0 -122
- data/app/assets/stylesheets/koi/base/_icon.scss +0 -29
- data/app/assets/stylesheets/koi/base/_index.scss +0 -21
- data/app/assets/stylesheets/koi/base/_input.scss +0 -19
- data/app/assets/stylesheets/koi/base/_link.scss +0 -26
- data/app/assets/stylesheets/koi/base/_list.scss +0 -11
- data/app/assets/stylesheets/koi/base/_typography.scss +0 -160
- data/app/assets/stylesheets/koi/components/_actions-group.scss +0 -7
- data/app/assets/stylesheets/koi/components/_image-field.scss +0 -95
- data/app/assets/stylesheets/koi/components/_index.scss +0 -9
- data/app/assets/stylesheets/koi/components/_pagy.scss +0 -30
- data/app/assets/stylesheets/koi/components/_summary-list.scss +0 -40
- data/app/assets/stylesheets/koi/layouts/_banner.scss +0 -7
- data/app/assets/stylesheets/koi/layouts/_content.scss +0 -40
- data/app/assets/stylesheets/koi/layouts/_flash.scss +0 -41
- data/app/assets/stylesheets/koi/layouts/_header.scss +0 -61
- data/app/assets/stylesheets/koi/layouts/_index.scss +0 -48
- data/app/assets/stylesheets/koi/layouts/_main.scss +0 -23
- data/app/assets/stylesheets/koi/layouts/_navigation.scss +0 -180
- data/app/assets/stylesheets/koi/layouts/_stack.scss +0 -13
- data/app/assets/stylesheets/koi/pages/_index.scss +0 -1
- data/app/assets/stylesheets/koi/pages/_login.scss +0 -46
- data/app/assets/stylesheets/koi/themes/_govuk.scss +0 -59
- data/app/assets/stylesheets/koi/themes/_kpop.scss +0 -5
- data/app/assets/stylesheets/koi/utils/_breakpoints.scss +0 -13
- data/app/assets/stylesheets/koi/utils/_hide.scss +0 -11
- data/app/assets/stylesheets/koi/utils/_index.scss +0 -2
- data/app/assets/stylesheets/koi/utils/_typography.scss +0 -42
- data/app/components/koi/content/editor/item_form_component.html.erb +0 -11
- data/app/components/koi/content/editor/item_form_component.rb +0 -94
- data/app/components/koi/summary_list/attachment_component.rb +0 -47
- data/app/components/koi/summary_list/base.rb +0 -59
- data/app/components/koi/summary_list/boolean_component.rb +0 -15
- data/app/components/koi/summary_list/date_component.rb +0 -17
- data/app/components/koi/summary_list/datetime_component.rb +0 -17
- data/app/components/koi/summary_list/item_component.rb +0 -26
- data/app/components/koi/summary_list/number_component.rb +0 -21
- data/app/components/koi/summary_list/rich_text_component.rb +0 -8
- data/app/components/koi/summary_list/text_component.rb +0 -8
- data/app/components/koi/summary_list_component.html.erb +0 -5
- data/app/components/koi/summary_list_component.rb +0 -75
- data/app/controllers/concerns/koi/controller/is_admin_controller.rb +0 -77
- data/app/helpers/koi/application_helper.rb +0 -7
- data/app/helpers/koi/date_helper.rb +0 -26
- data/app/helpers/koi/definition_list_helper.rb +0 -10
- data/app/views/admin/admin_users/_fields.html+self.erb +0 -3
- data/app/views/admin/admin_users/_fields.html.erb +0 -3
- data/app/views/admin/url_rewrites/_fields.html.erb +0 -4
- data/app/views/admin/well_knowns/_fields.html.erb +0 -6
- data/app/views/layouts/koi/_environment.html.erb +0 -4
- data/app/views/layouts/koi/_header.html.erb +0 -11
- data/app/views/layouts/koi/_navigation.html.erb +0 -23
- data/app/views/layouts/koi/_navigation_collapse.html.erb +0 -3
- data/config/initializers/dartsass.rb +0 -10
- data/config/locales/pagy/en.yml +0 -24
- data/db/migrate/20260501000000_add_last_sign_out_at_to_admin_users.rb +0 -7
- data/lib/generators/koi/admin_views/templates/_fields.html.erb.tt +0 -3
- data/lib/generators/koi/helpers/admin_generator_attributes.rb +0 -66
- data/lib/koi/extensions/dartsass.rb +0 -23
- /data/app/assets/stylesheets/koi/{components/_clipboard.scss → blocks/clipboard.css} +0 -0
- /data/app/assets/stylesheets/koi/{components/_index-actions.scss → blocks/index-actions.css} +0 -0
- /data/app/assets/stylesheets/koi/{components/_toolbar.scss → blocks/toolbar.css} +0 -0
- /data/app/assets/stylesheets/koi/{base/_repel.scss → compositions/repel.css} +0 -0
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module Admin
|
|
4
4
|
class AdminUsersController < ApplicationController
|
|
5
|
-
before_action :
|
|
5
|
+
before_action :set_admin_user, only: %i[show edit update destroy]
|
|
6
6
|
|
|
7
|
-
attr_reader :
|
|
7
|
+
attr_reader :admin_user
|
|
8
8
|
|
|
9
9
|
def index
|
|
10
10
|
collection = Collection.new.with_params(params).apply(Admin::User.strict_loading)
|
|
@@ -19,65 +19,71 @@ module Admin
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def show
|
|
22
|
-
render
|
|
22
|
+
render locals: { admin_user: }
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def new
|
|
26
|
-
@
|
|
26
|
+
@admin_user = Admin::User.new
|
|
27
27
|
|
|
28
|
-
render
|
|
28
|
+
render locals: { admin_user: }
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def edit
|
|
32
|
-
render :edit, locals: {
|
|
32
|
+
render :edit, locals: { admin_user: }
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def create
|
|
36
|
-
|
|
36
|
+
admin_user = Admin::User.new(admin_user_params)
|
|
37
37
|
|
|
38
|
-
if
|
|
39
|
-
redirect_to admin_admin_user_path(
|
|
38
|
+
if admin_user.save
|
|
39
|
+
redirect_to admin_admin_user_path(admin_user)
|
|
40
40
|
else
|
|
41
|
-
render :new, locals: {
|
|
41
|
+
render :new, locals: { admin_user: }, status: :unprocessable_content
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def update
|
|
46
|
-
if
|
|
46
|
+
if admin_user.update(admin_user_params)
|
|
47
47
|
redirect_to action: :show
|
|
48
48
|
else
|
|
49
|
-
render :edit, locals: {
|
|
49
|
+
render :edit, locals: { admin_user: }, status: :unprocessable_content
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def archive
|
|
54
54
|
Admin::User.where(id: params[:id]).where.not(id: current_admin.id).each(&:archive!)
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
redirect_back(fallback_location: admin_admin_users_path, status: :see_other)
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def restore
|
|
60
60
|
Admin::User.archived.where(id: params[:id]).each(&:restore!)
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
redirect_back(fallback_location: admin_admin_users_path, status: :see_other)
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
def destroy
|
|
66
|
-
|
|
66
|
+
if admin_user.archived?
|
|
67
|
+
admin_user.destroy!
|
|
67
68
|
|
|
68
|
-
|
|
69
|
+
redirect_to admin_admin_users_path
|
|
70
|
+
else
|
|
71
|
+
admin_user.archive!
|
|
72
|
+
|
|
73
|
+
redirect_back_or_to(admin_admin_user_path(admin_user), status: :see_other)
|
|
74
|
+
end
|
|
69
75
|
end
|
|
70
76
|
|
|
71
77
|
private
|
|
72
78
|
|
|
73
|
-
def
|
|
74
|
-
@
|
|
79
|
+
def set_admin_user
|
|
80
|
+
@admin_user = Admin::User.with_archived.find(params[:id])
|
|
75
81
|
|
|
76
|
-
request.variant << :self if
|
|
82
|
+
request.variant << :self if admin_user == current_admin_user
|
|
77
83
|
end
|
|
78
84
|
|
|
79
85
|
def admin_user_params
|
|
80
|
-
params.expect(
|
|
86
|
+
params.expect(admin_user: %i[name email password archived])
|
|
81
87
|
end
|
|
82
88
|
|
|
83
89
|
class Collection < Admin::Collection
|
|
@@ -6,25 +6,29 @@ module Admin
|
|
|
6
6
|
|
|
7
7
|
before_action :set_admin_user
|
|
8
8
|
|
|
9
|
+
attr_reader :admin_user
|
|
10
|
+
|
|
9
11
|
def new
|
|
10
|
-
unless
|
|
11
|
-
|
|
12
|
+
unless admin_user.webauthn_id
|
|
13
|
+
admin_user.update!(webauthn_id: WebAuthn.generate_user_id)
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
options = webauthn_relying_party.options_for_registration(
|
|
15
17
|
user: {
|
|
16
|
-
id:
|
|
17
|
-
name:
|
|
18
|
-
display_name:
|
|
18
|
+
id: admin_user.webauthn_id,
|
|
19
|
+
name: admin_user.email,
|
|
20
|
+
display_name: admin_user.name,
|
|
19
21
|
},
|
|
20
|
-
exclude:
|
|
22
|
+
exclude: admin_user.credentials.map(&:external_id),
|
|
21
23
|
)
|
|
22
24
|
|
|
23
25
|
# Store the newly generated challenge somewhere so you can have it
|
|
24
26
|
# for the verification phase.
|
|
25
27
|
session[:creation_challenge] = options.challenge
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
credential = admin_user.credentials.new
|
|
30
|
+
|
|
31
|
+
render locals: { admin_user:, credential:, options: }
|
|
28
32
|
end
|
|
29
33
|
|
|
30
34
|
def create
|
|
@@ -35,7 +39,7 @@ module Admin
|
|
|
35
39
|
session.delete(:creation_challenge),
|
|
36
40
|
)
|
|
37
41
|
|
|
38
|
-
credential =
|
|
42
|
+
credential = admin_user.credentials.find_or_initialize_by(
|
|
39
43
|
external_id: webauthn_credential.id,
|
|
40
44
|
)
|
|
41
45
|
|
|
@@ -46,18 +50,18 @@ module Admin
|
|
|
46
50
|
)
|
|
47
51
|
|
|
48
52
|
respond_to do |format|
|
|
49
|
-
format.html { redirect_to admin_admin_user_path(
|
|
50
|
-
format.turbo_stream { render locals: {
|
|
53
|
+
format.html { redirect_to admin_admin_user_path(admin_user), status: :see_other }
|
|
54
|
+
format.turbo_stream { render locals: { admin_user: } }
|
|
51
55
|
end
|
|
52
56
|
end
|
|
53
57
|
|
|
54
58
|
def destroy
|
|
55
|
-
credential =
|
|
59
|
+
credential = admin_user.credentials.find(params[:id])
|
|
56
60
|
credential.destroy!
|
|
57
61
|
|
|
58
62
|
respond_to do |format|
|
|
59
|
-
format.html { redirect_to admin_admin_user_path(
|
|
60
|
-
format.turbo_stream { render locals: {
|
|
63
|
+
format.html { redirect_to admin_admin_user_path(admin_user), status: :see_other }
|
|
64
|
+
format.turbo_stream { render locals: { admin_user: } }
|
|
61
65
|
end
|
|
62
66
|
end
|
|
63
67
|
|
|
@@ -68,9 +72,9 @@ module Admin
|
|
|
68
72
|
end
|
|
69
73
|
|
|
70
74
|
def set_admin_user
|
|
71
|
-
@admin_user = Admin::User.find(params
|
|
75
|
+
@admin_user = Admin::User.find(params[:admin_user_id])
|
|
72
76
|
|
|
73
|
-
if current_admin ==
|
|
77
|
+
if current_admin == admin_user
|
|
74
78
|
request.variant = :self
|
|
75
79
|
else
|
|
76
80
|
head(:forbidden)
|
|
@@ -4,45 +4,47 @@ module Admin
|
|
|
4
4
|
class OtpsController < ApplicationController
|
|
5
5
|
before_action :set_admin_user
|
|
6
6
|
|
|
7
|
+
attr_reader :admin_user
|
|
8
|
+
|
|
7
9
|
def new
|
|
8
|
-
|
|
10
|
+
admin_user.otp_secret = ROTP::Base32.random
|
|
9
11
|
|
|
10
|
-
render :new, locals: {
|
|
12
|
+
render :new, locals: { admin_user: }
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
def create
|
|
14
|
-
|
|
16
|
+
admin_user.otp_secret = otp_params[:otp_secret]
|
|
15
17
|
|
|
16
|
-
if
|
|
17
|
-
|
|
18
|
+
if admin_user.otp.verify(otp_params[:token])
|
|
19
|
+
admin_user.save
|
|
18
20
|
|
|
19
|
-
redirect_to admin_admin_user_path(
|
|
21
|
+
redirect_to admin_admin_user_path(admin_user), status: :see_other
|
|
20
22
|
else
|
|
21
|
-
|
|
23
|
+
admin_user.errors.add(:token, :invalid)
|
|
22
24
|
|
|
23
25
|
respond_to do |format|
|
|
24
|
-
format.html { redirect_to admin_admin_user_path(
|
|
25
|
-
format.turbo_stream { render locals: {
|
|
26
|
+
format.html { redirect_to admin_admin_user_path(admin_user), status: :see_other }
|
|
27
|
+
format.turbo_stream { render locals: { admin_user: }, status: :unprocessable_entity }
|
|
26
28
|
end
|
|
27
29
|
end
|
|
28
30
|
end
|
|
29
31
|
|
|
30
32
|
def destroy
|
|
31
|
-
|
|
33
|
+
admin_user.update!(otp_secret: nil)
|
|
32
34
|
|
|
33
|
-
redirect_to admin_admin_user_path(
|
|
35
|
+
redirect_to admin_admin_user_path(admin_user), status: :see_other
|
|
34
36
|
end
|
|
35
37
|
|
|
36
38
|
private
|
|
37
39
|
|
|
38
40
|
def otp_params
|
|
39
|
-
params.expect(
|
|
41
|
+
params.expect(admin_user: %i[otp_secret token])
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
def set_admin_user
|
|
43
|
-
@admin_user = Admin::User.find(params
|
|
45
|
+
@admin_user = Admin::User.find(params[:admin_user_id])
|
|
44
46
|
|
|
45
|
-
if current_admin ==
|
|
47
|
+
if current_admin == admin_user
|
|
46
48
|
request.variant = :self
|
|
47
49
|
else
|
|
48
50
|
head(:forbidden)
|
|
@@ -6,7 +6,7 @@ module Admin
|
|
|
6
6
|
include Koi::Controller::RecordsAuthentication
|
|
7
7
|
|
|
8
8
|
before_action :redirect_authenticated, only: %i[new], if: :admin_signed_in?
|
|
9
|
-
before_action :authenticate_local_admin, only: %i[new], if:
|
|
9
|
+
before_action :authenticate_local_admin, only: %i[new], if: -> { Koi.config.authenticate_local_admins? }
|
|
10
10
|
|
|
11
11
|
layout "koi/login"
|
|
12
12
|
|
|
@@ -35,7 +35,9 @@ module Admin
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def destroy
|
|
38
|
-
|
|
38
|
+
record_sign_out!(current_admin_user)
|
|
39
|
+
|
|
40
|
+
session[:admin_user_id] = nil
|
|
39
41
|
|
|
40
42
|
redirect_to new_admin_session_path
|
|
41
43
|
end
|
|
@@ -92,8 +94,21 @@ module Admin
|
|
|
92
94
|
redirect_to(admin_dashboard_path, status: :see_other)
|
|
93
95
|
end
|
|
94
96
|
|
|
97
|
+
def authenticate_local_admin
|
|
98
|
+
return if admin_signed_in? || !Rails.env.development?
|
|
99
|
+
|
|
100
|
+
session[:admin_user_id] =
|
|
101
|
+
Admin::User.where(email: %W[#{ENV.fetch('USER', nil)}@katalyst.com.au admin@katalyst.com.au]).first&.id
|
|
102
|
+
|
|
103
|
+
flash.delete(:redirect) if (redirect = flash[:redirect])
|
|
104
|
+
|
|
105
|
+
redirect_to(redirect || admin_dashboard_path, status: :see_other)
|
|
106
|
+
end
|
|
107
|
+
|
|
95
108
|
def admin_sign_in(admin_user)
|
|
96
|
-
|
|
109
|
+
record_sign_in!(admin_user)
|
|
110
|
+
|
|
111
|
+
session[:admin_user_id] = admin_user.id
|
|
97
112
|
|
|
98
113
|
redirect_to(url_from(params[:redirect].presence) || admin_dashboard_path, status: :see_other)
|
|
99
114
|
end
|
|
@@ -22,7 +22,9 @@ module Admin
|
|
|
22
22
|
|
|
23
23
|
def update
|
|
24
24
|
if (@admin_user = Admin::User.find_by_token_for(:password_reset, params[:token]))
|
|
25
|
-
|
|
25
|
+
record_sign_in!(admin_user)
|
|
26
|
+
|
|
27
|
+
session[:admin_user_id] = admin_user.id
|
|
26
28
|
|
|
27
29
|
redirect_to admin_admin_user_path(admin_user), status: :see_other, notice: t("koi.auth.token_consumed")
|
|
28
30
|
else
|
|
@@ -33,7 +35,7 @@ module Admin
|
|
|
33
35
|
private
|
|
34
36
|
|
|
35
37
|
def set_admin_user
|
|
36
|
-
@admin_user = Admin::User.find(params
|
|
38
|
+
@admin_user = Admin::User.find(params[:admin_user_id])
|
|
37
39
|
end
|
|
38
40
|
end
|
|
39
41
|
end
|
|
@@ -4,68 +4,70 @@ module Admin
|
|
|
4
4
|
class UrlRewritesController < ApplicationController
|
|
5
5
|
before_action :set_url_rewrite, only: %i[show edit update destroy]
|
|
6
6
|
|
|
7
|
+
attr_reader :collection, :url_rewrite
|
|
8
|
+
|
|
7
9
|
def index
|
|
8
|
-
collection = Collection.new.with_params(params).apply(UrlRewrite.strict_loading)
|
|
10
|
+
@collection = Collection.new.with_params(params).apply(UrlRewrite.strict_loading.all)
|
|
9
11
|
|
|
10
12
|
render locals: { collection: }
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
def show
|
|
14
|
-
render
|
|
16
|
+
render locals: { url_rewrite: }
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
def new
|
|
18
20
|
@url_rewrite = UrlRewrite.new
|
|
19
|
-
|
|
21
|
+
|
|
22
|
+
render locals: { url_rewrite: }
|
|
20
23
|
end
|
|
21
24
|
|
|
22
25
|
def edit
|
|
23
|
-
render
|
|
26
|
+
render locals: { url_rewrite: }
|
|
24
27
|
end
|
|
25
28
|
|
|
26
29
|
def create
|
|
27
30
|
@url_rewrite = UrlRewrite.new(url_rewrite_params)
|
|
28
31
|
|
|
29
32
|
if @url_rewrite.save
|
|
30
|
-
redirect_to admin_url_rewrite_path(
|
|
33
|
+
redirect_to admin_url_rewrite_path(url_rewrite), status: :see_other
|
|
31
34
|
else
|
|
32
|
-
render :new,
|
|
35
|
+
render :new, locals: { url_rewrite: }, status: :unprocessable_content
|
|
33
36
|
end
|
|
34
37
|
end
|
|
35
38
|
|
|
36
39
|
def update
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if @url_rewrite.save
|
|
40
|
-
redirect_to admin_url_rewrite_path(@url_rewrite)
|
|
40
|
+
if url_rewrite.update(url_rewrite_params)
|
|
41
|
+
redirect_to admin_url_rewrite_path(url_rewrite), status: :see_other
|
|
41
42
|
else
|
|
42
|
-
render :edit,
|
|
43
|
+
render :edit, locals: { url_rewrite: }, status: :unprocessable_content
|
|
43
44
|
end
|
|
44
45
|
end
|
|
45
46
|
|
|
46
47
|
def destroy
|
|
47
48
|
@url_rewrite.destroy!
|
|
48
49
|
|
|
49
|
-
redirect_to admin_url_rewrites_path
|
|
50
|
+
redirect_to admin_url_rewrites_path, status: :see_other
|
|
50
51
|
end
|
|
51
52
|
|
|
52
53
|
private
|
|
53
54
|
|
|
54
|
-
def
|
|
55
|
-
|
|
55
|
+
def set_url_rewrite
|
|
56
|
+
@url_rewrite = ::UrlRewrite.find(params[:id])
|
|
56
57
|
end
|
|
57
58
|
|
|
58
|
-
def
|
|
59
|
-
|
|
59
|
+
def url_rewrite_params
|
|
60
|
+
params.expect(url_rewrite: %i[from to active status_code])
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
class Collection < Admin::Collection
|
|
63
|
-
config.sorting =
|
|
64
|
+
config.sorting = :from
|
|
64
65
|
config.paginate = true
|
|
65
66
|
|
|
66
67
|
attribute :from, :string
|
|
67
68
|
attribute :to, :string
|
|
68
69
|
attribute :active, :boolean
|
|
70
|
+
attribute :status_code, :enum
|
|
69
71
|
end
|
|
70
72
|
end
|
|
71
73
|
end
|
|
@@ -4,58 +4,60 @@ module Admin
|
|
|
4
4
|
class WellKnownsController < ApplicationController
|
|
5
5
|
before_action :set_well_known, only: %i[show edit update destroy]
|
|
6
6
|
|
|
7
|
+
attr_reader :collection, :well_known
|
|
8
|
+
|
|
7
9
|
def index
|
|
8
|
-
collection = Collection.new.with_params(params).apply(
|
|
10
|
+
@collection = Collection.new.with_params(params).apply(WellKnown.strict_loading.all)
|
|
9
11
|
|
|
10
12
|
render locals: { collection: }
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
def show
|
|
14
|
-
render locals: { well_known:
|
|
16
|
+
render locals: { well_known: }
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
def new
|
|
18
|
-
|
|
20
|
+
@well_known = WellKnown.new
|
|
21
|
+
|
|
22
|
+
render locals: { well_known: }
|
|
19
23
|
end
|
|
20
24
|
|
|
21
25
|
def edit
|
|
22
|
-
render locals: { well_known:
|
|
26
|
+
render locals: { well_known: }
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
def create
|
|
26
|
-
@well_known =
|
|
30
|
+
@well_known = WellKnown.new(well_known_params)
|
|
27
31
|
|
|
28
32
|
if @well_known.save
|
|
29
|
-
redirect_to
|
|
33
|
+
redirect_to admin_well_known_path(well_known), status: :see_other
|
|
30
34
|
else
|
|
31
|
-
render :new, locals: { well_known:
|
|
35
|
+
render :new, locals: { well_known: }, status: :unprocessable_content
|
|
32
36
|
end
|
|
33
37
|
end
|
|
34
38
|
|
|
35
39
|
def update
|
|
36
|
-
if
|
|
37
|
-
redirect_to
|
|
40
|
+
if well_known.update(well_known_params)
|
|
41
|
+
redirect_to admin_well_known_path(well_known), status: :see_other
|
|
38
42
|
else
|
|
39
|
-
render :edit, locals: { well_known:
|
|
43
|
+
render :edit, locals: { well_known: }, status: :unprocessable_content
|
|
40
44
|
end
|
|
41
45
|
end
|
|
42
46
|
|
|
43
47
|
def destroy
|
|
44
48
|
@well_known.destroy!
|
|
45
49
|
|
|
46
|
-
redirect_to
|
|
50
|
+
redirect_to admin_well_knowns_path, status: :see_other
|
|
47
51
|
end
|
|
48
52
|
|
|
49
53
|
private
|
|
50
54
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
params.expect(well_known: %i[name purpose content_type content])
|
|
55
|
+
def set_well_known
|
|
56
|
+
@well_known = ::WellKnown.find(params[:id])
|
|
54
57
|
end
|
|
55
58
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
@well_known = ::WellKnown.find(params.expect(:id))
|
|
59
|
+
def well_known_params
|
|
60
|
+
params.expect(well_known: %i[name purpose content_type content])
|
|
59
61
|
end
|
|
60
62
|
|
|
61
63
|
class Collection < Admin::Collection
|
|
@@ -64,7 +66,7 @@ module Admin
|
|
|
64
66
|
|
|
65
67
|
attribute :name, :string
|
|
66
68
|
attribute :purpose, :string
|
|
67
|
-
attribute :content_type, :
|
|
69
|
+
attribute :content_type, :enum
|
|
68
70
|
attribute :content, :string
|
|
69
71
|
end
|
|
70
72
|
end
|
|
@@ -3,46 +3,33 @@
|
|
|
3
3
|
module Koi
|
|
4
4
|
module Controller
|
|
5
5
|
module RecordsAuthentication
|
|
6
|
-
def
|
|
7
|
-
|
|
6
|
+
def update_last_sign_in(admin_user)
|
|
7
|
+
return if admin_user.current_sign_in_at.blank?
|
|
8
8
|
|
|
9
|
+
admin_user.last_sign_in_at = admin_user.current_sign_in_at
|
|
10
|
+
admin_user.last_sign_in_ip = admin_user.current_sign_in_ip
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def record_sign_in!(admin_user)
|
|
9
14
|
update_last_sign_in(admin_user)
|
|
10
15
|
|
|
11
|
-
admin_user.current_sign_in_at =
|
|
16
|
+
admin_user.current_sign_in_at = Time.current
|
|
12
17
|
admin_user.current_sign_in_ip = request.remote_ip
|
|
13
|
-
admin_user.sign_in_count
|
|
18
|
+
admin_user.sign_in_count += 1
|
|
14
19
|
|
|
15
20
|
admin_user.save!
|
|
16
|
-
|
|
17
|
-
session[:admin_user_id] = admin_user.id
|
|
18
|
-
session[:admin_user_signed_in_at] = sign_in_at.iso8601(6)
|
|
19
21
|
end
|
|
20
22
|
|
|
21
|
-
def
|
|
22
|
-
session[:admin_user_id] = nil
|
|
23
|
-
session[:admin_user_signed_in_at] = nil
|
|
24
|
-
|
|
23
|
+
def record_sign_out!(admin_user)
|
|
25
24
|
return unless admin_user
|
|
26
25
|
|
|
27
|
-
sign_out_at = Time.current
|
|
28
|
-
|
|
29
26
|
update_last_sign_in(admin_user)
|
|
30
27
|
|
|
31
|
-
admin_user.last_sign_out_at = sign_out_at
|
|
32
28
|
admin_user.current_sign_in_at = nil
|
|
33
29
|
admin_user.current_sign_in_ip = nil
|
|
34
30
|
|
|
35
31
|
admin_user.save!
|
|
36
32
|
end
|
|
37
|
-
|
|
38
|
-
private
|
|
39
|
-
|
|
40
|
-
def update_last_sign_in(admin_user)
|
|
41
|
-
return if admin_user.current_sign_in_at.blank?
|
|
42
|
-
|
|
43
|
-
admin_user.last_sign_in_at = admin_user.current_sign_in_at
|
|
44
|
-
admin_user.last_sign_in_ip = admin_user.current_sign_in_ip
|
|
45
|
-
end
|
|
46
33
|
end
|
|
47
34
|
end
|
|
48
35
|
end
|
|
@@ -5,12 +5,33 @@ module Koi
|
|
|
5
5
|
extend ActiveSupport::Concern
|
|
6
6
|
|
|
7
7
|
included do
|
|
8
|
-
include
|
|
8
|
+
include HasAdminUsers
|
|
9
|
+
include HasAttachments
|
|
10
|
+
include Katalyst::Tables::Backend
|
|
11
|
+
include ::Pagy::Backend
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
default_form_builder "Koi::FormBuilder"
|
|
14
|
+
default_table_component "Koi::TableComponent"
|
|
15
|
+
default_table_query_component "Koi::TableQueryComponent"
|
|
16
|
+
default_summary_table_component "Koi::SummaryTableComponent"
|
|
11
17
|
|
|
12
|
-
|
|
13
|
-
helper
|
|
18
|
+
# Dependency helpers
|
|
19
|
+
helper Katalyst::GOVUK::Formbuilder::Frontend
|
|
20
|
+
helper Katalyst::Navigation::FrontendHelper
|
|
21
|
+
helper Katalyst::Tables::Frontend
|
|
22
|
+
helper ::Pagy::Frontend
|
|
23
|
+
|
|
24
|
+
# Koi Helpers
|
|
25
|
+
helper FormHelper
|
|
26
|
+
helper HeaderHelper
|
|
27
|
+
helper Pagy::Frontend
|
|
28
|
+
|
|
29
|
+
# @deprecated to be removed in Koi 5
|
|
30
|
+
helper IndexActionsHelper
|
|
31
|
+
|
|
32
|
+
layout -> { turbo_frame_request? ? "koi/frame" : "koi/application" }
|
|
33
|
+
|
|
34
|
+
protect_from_forgery with: :exception
|
|
14
35
|
end
|
|
15
36
|
end
|
|
16
37
|
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Koi
|
|
4
|
+
module FormHelper
|
|
5
|
+
# Ensure that admin forms use `admin_` path helpers.
|
|
6
|
+
def form_with(model: false, url: nil, format: nil, **, &)
|
|
7
|
+
if model && (url != false)
|
|
8
|
+
url ||= if format.nil?
|
|
9
|
+
polymorphic_path([:admin, model], {})
|
|
10
|
+
else
|
|
11
|
+
polymorphic_path([:admin, model], format: format)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|