katalyst-koi 4.19.0 → 4.20.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/builds/koi/admin.css +1 -1
- data/app/components/koi/header/edit_component.rb +1 -1
- data/app/components/koi/tables/cells/link_component.rb +2 -2
- data/app/controllers/admin/admin_users_controller.rb +1 -1
- data/app/controllers/admin/credentials_controller.rb +2 -2
- data/app/controllers/admin/otps_controller.rb +1 -1
- data/app/controllers/admin/sessions_controller.rb +2 -6
- data/app/controllers/admin/tokens_controller.rb +2 -4
- data/app/controllers/admin/url_rewrites_controller.rb +1 -1
- data/app/controllers/admin/well_knowns_controller.rb +1 -1
- data/app/controllers/concerns/koi/controller/is_admin_controller.rb +7 -3
- data/app/controllers/concerns/koi/controller/records_authentication.rb +23 -10
- data/app/controllers/well_knowns_controller.rb +1 -1
- data/app/helpers/koi/date_helper.rb +2 -2
- data/db/migrate/20260501000000_add_last_sign_out_at_to_admin_users.rb +7 -0
- data/lib/generators/koi/admin/admin_generator.rb +1 -1
- data/lib/generators/koi/admin_controller/admin_controller_generator.rb +1 -1
- data/lib/generators/koi/admin_route/admin_route_generator.rb +4 -3
- data/lib/koi/form/builder.rb +2 -2
- data/lib/koi/form/elements/file_element.rb +1 -1
- data/lib/koi/middleware/admin_authentication.rb +32 -4
- metadata +3 -2
|
@@ -52,7 +52,7 @@ module Admin
|
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def destroy
|
|
55
|
-
credential = @admin_user.credentials.find(params
|
|
55
|
+
credential = @admin_user.credentials.find(params.expect(:id))
|
|
56
56
|
credential.destroy!
|
|
57
57
|
|
|
58
58
|
respond_to do |format|
|
|
@@ -68,7 +68,7 @@ module Admin
|
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def set_admin_user
|
|
71
|
-
@admin_user = Admin::User.find(params
|
|
71
|
+
@admin_user = Admin::User.find(params.expect(:admin_user_id))
|
|
72
72
|
|
|
73
73
|
if current_admin == @admin_user
|
|
74
74
|
request.variant = :self
|
|
@@ -35,9 +35,7 @@ module Admin
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def destroy
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
session[:admin_user_id] = nil
|
|
38
|
+
destroy_admin_session!(current_admin_user)
|
|
41
39
|
|
|
42
40
|
redirect_to new_admin_session_path
|
|
43
41
|
end
|
|
@@ -95,9 +93,7 @@ module Admin
|
|
|
95
93
|
end
|
|
96
94
|
|
|
97
95
|
def admin_sign_in(admin_user)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
session[:admin_user_id] = admin_user.id
|
|
96
|
+
create_admin_session!(admin_user)
|
|
101
97
|
|
|
102
98
|
redirect_to(url_from(params[:redirect].presence) || admin_dashboard_path, status: :see_other)
|
|
103
99
|
end
|
|
@@ -22,9 +22,7 @@ module Admin
|
|
|
22
22
|
|
|
23
23
|
def update
|
|
24
24
|
if (@admin_user = Admin::User.find_by_token_for(:password_reset, params[:token]))
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
session[:admin_user_id] = admin_user.id
|
|
25
|
+
create_admin_session!(admin_user)
|
|
28
26
|
|
|
29
27
|
redirect_to admin_admin_user_path(admin_user), status: :see_other, notice: t("koi.auth.token_consumed")
|
|
30
28
|
else
|
|
@@ -35,7 +33,7 @@ module Admin
|
|
|
35
33
|
private
|
|
36
34
|
|
|
37
35
|
def set_admin_user
|
|
38
|
-
@admin_user = Admin::User.find(params
|
|
36
|
+
@admin_user = Admin::User.find(params.expect(:admin_user_id))
|
|
39
37
|
end
|
|
40
38
|
end
|
|
41
39
|
end
|
|
@@ -55,7 +55,7 @@ module Admin
|
|
|
55
55
|
|
|
56
56
|
# Use callbacks to share common setup or constraints between actions.
|
|
57
57
|
def set_well_known
|
|
58
|
-
@well_known = ::WellKnown.find(params
|
|
58
|
+
@well_known = ::WellKnown.find(params.expect(:id))
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
class Collection < Admin::Collection
|
|
@@ -16,7 +16,7 @@ module Koi
|
|
|
16
16
|
include HasAttachments
|
|
17
17
|
include Katalyst::Tables::Backend
|
|
18
18
|
|
|
19
|
-
if (pagy
|
|
19
|
+
if (pagy = "Pagy::Method".safe_constantize)
|
|
20
20
|
include pagy
|
|
21
21
|
elsif (pagy = "Pagy::Backend".safe_constantize)
|
|
22
22
|
# @deprecated Pagy <43
|
|
@@ -49,8 +49,12 @@ module Koi
|
|
|
49
49
|
def authenticate_local_admin
|
|
50
50
|
return if admin_signed_in? || !Rails.env.development?
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
admin_user = Admin::User.where(email: %W[#{ENV.fetch('USER', nil)}@katalyst.com.au admin@katalyst.com.au]).first
|
|
53
|
+
|
|
54
|
+
return unless admin_user
|
|
55
|
+
|
|
56
|
+
session[:admin_user_id] = admin_user.id
|
|
57
|
+
session[:admin_user_signed_in_at] = Time.current.iso8601(6)
|
|
54
58
|
|
|
55
59
|
flash.delete(:redirect) if (redirect = flash[:redirect])
|
|
56
60
|
|
|
@@ -3,33 +3,46 @@
|
|
|
3
3
|
module Koi
|
|
4
4
|
module Controller
|
|
5
5
|
module RecordsAuthentication
|
|
6
|
-
def
|
|
7
|
-
|
|
6
|
+
def create_admin_session!(admin_user)
|
|
7
|
+
sign_in_at = Time.current
|
|
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)
|
|
14
9
|
update_last_sign_in(admin_user)
|
|
15
10
|
|
|
16
|
-
admin_user.current_sign_in_at =
|
|
11
|
+
admin_user.current_sign_in_at = sign_in_at
|
|
17
12
|
admin_user.current_sign_in_ip = request.remote_ip
|
|
18
|
-
admin_user.sign_in_count
|
|
13
|
+
admin_user.sign_in_count += 1
|
|
19
14
|
|
|
20
15
|
admin_user.save!
|
|
16
|
+
|
|
17
|
+
session[:admin_user_id] = admin_user.id
|
|
18
|
+
session[:admin_user_signed_in_at] = sign_in_at.iso8601(6)
|
|
21
19
|
end
|
|
22
20
|
|
|
23
|
-
def
|
|
21
|
+
def destroy_admin_session!(admin_user)
|
|
22
|
+
session[:admin_user_id] = nil
|
|
23
|
+
session[:admin_user_signed_in_at] = nil
|
|
24
|
+
|
|
24
25
|
return unless admin_user
|
|
25
26
|
|
|
27
|
+
sign_out_at = Time.current
|
|
28
|
+
|
|
26
29
|
update_last_sign_in(admin_user)
|
|
27
30
|
|
|
31
|
+
admin_user.last_sign_out_at = sign_out_at
|
|
28
32
|
admin_user.current_sign_in_at = nil
|
|
29
33
|
admin_user.current_sign_in_ip = nil
|
|
30
34
|
|
|
31
35
|
admin_user.save!
|
|
32
36
|
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
|
|
33
46
|
end
|
|
34
47
|
end
|
|
35
48
|
end
|
|
@@ -5,8 +5,8 @@ module Koi
|
|
|
5
5
|
# Returns a string representing the number of days ago or from now.
|
|
6
6
|
# If the date is not 'recent' returns nil.
|
|
7
7
|
def days_ago_in_words(value)
|
|
8
|
-
from_time
|
|
9
|
-
to_time
|
|
8
|
+
from_time = value.to_time
|
|
9
|
+
to_time = Date.current.to_time
|
|
10
10
|
distance_in_days = ((to_time - from_time) / (24.0 * 60.0 * 60.0)).round
|
|
11
11
|
|
|
12
12
|
case distance_in_days
|
|
@@ -15,7 +15,7 @@ module Koi
|
|
|
15
15
|
|
|
16
16
|
hook_for :admin_controller, in: :koi, as: :admin, type: :boolean, default: true do |instance, controller|
|
|
17
17
|
args, opts, config = @_initializer
|
|
18
|
-
opts
|
|
18
|
+
opts ||= {}
|
|
19
19
|
|
|
20
20
|
# setting model_name so that generators will use the controller_class_path
|
|
21
21
|
instance.invoke controller, args, { model_name: instance.name, **opts }, config
|
|
@@ -42,7 +42,7 @@ module Koi
|
|
|
42
42
|
def permitted_params
|
|
43
43
|
attachments, others = attributes_names.partition { |name| attachments?(name) }
|
|
44
44
|
params = others.map { |name| ":#{name}" }
|
|
45
|
-
params
|
|
45
|
+
params += attachments.map { |name| "#{name}: []" }
|
|
46
46
|
params.join(", ")
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -67,9 +67,10 @@ module Koi
|
|
|
67
67
|
in_root do
|
|
68
68
|
if (namespace_match = match_file(route_file, namespace_pattern))
|
|
69
69
|
base_indent, *, existing_block_indent = namespace_match.captures.compact.map(&:length)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
|
|
71
|
+
existing_line_pattern = /^ {,#{existing_block_indent}}\S.+\n?/
|
|
72
|
+
routing_code = rebase_indentation(routing_code, base_indent + 2).gsub(existing_line_pattern, "")
|
|
73
|
+
namespace_pattern = /#{Regexp.escape namespace_match.to_s}/
|
|
73
74
|
end
|
|
74
75
|
|
|
75
76
|
inject_into_file route_file, routing_code, after: namespace_pattern, verbose: true, force: false
|
data/lib/koi/form/builder.rb
CHANGED
|
@@ -41,7 +41,7 @@ module Koi
|
|
|
41
41
|
# @see GOVUKDesignSystemFormBuilder::Builder#govuk_document_field
|
|
42
42
|
def govuk_document_field(attribute_name, hint: {}, **, &)
|
|
43
43
|
if hint.is_a?(Hash)
|
|
44
|
-
max_size
|
|
44
|
+
max_size = hint.fetch(:max_size, Koi.config.document_size_limit)
|
|
45
45
|
hint[:text] ||= t("helpers.hint.default.document", max_size: @template.number_to_human_size(max_size))
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -52,7 +52,7 @@ module Koi
|
|
|
52
52
|
# @see GOVUKDesignSystemFormBuilder::Builder#govuk_image_field
|
|
53
53
|
def govuk_image_field(attribute_name, hint: {}, **, &)
|
|
54
54
|
if hint.is_a?(Hash)
|
|
55
|
-
max_size
|
|
55
|
+
max_size = hint.fetch(:max_size, Koi.config.image_size_limit)
|
|
56
56
|
hint[:text] ||= t("helpers.hint.default.document", max_size: @template.number_to_human_size(max_size))
|
|
57
57
|
end
|
|
58
58
|
|
|
@@ -16,10 +16,11 @@ module Koi
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def admin_call(env)
|
|
19
|
-
request
|
|
20
|
-
session
|
|
19
|
+
request = ActionDispatch::Request.new(env)
|
|
20
|
+
session = ActionDispatch::Request::Session.find(request)
|
|
21
|
+
authenticated = authenticated?(session)
|
|
21
22
|
|
|
22
|
-
if requires_authentication?(request) && !authenticated
|
|
23
|
+
if requires_authentication?(request) && !authenticated
|
|
23
24
|
# Set the redirection path for returning the user to their requested path after login
|
|
24
25
|
if request.get?
|
|
25
26
|
request.flash[:redirect] = request.fullpath
|
|
@@ -39,7 +40,34 @@ module Koi
|
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
def authenticated?(session)
|
|
42
|
-
session[:admin_user_id]
|
|
43
|
+
admin_user = Admin::User.find_by(id: session[:admin_user_id])
|
|
44
|
+
unless admin_user
|
|
45
|
+
clear_admin_session(session)
|
|
46
|
+
return false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
signed_in_at = session_signed_in_at(session)
|
|
50
|
+
if signed_in_at.blank? || session_expired?(admin_user, signed_in_at)
|
|
51
|
+
clear_admin_session(session)
|
|
52
|
+
return false
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
true
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def session_signed_in_at(session)
|
|
59
|
+
Time.zone.parse(session[:admin_user_signed_in_at].to_s)
|
|
60
|
+
rescue ArgumentError
|
|
61
|
+
nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def session_expired?(admin_user, signed_in_at)
|
|
65
|
+
admin_user.last_sign_out_at.present? && signed_in_at < admin_user.last_sign_out_at
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def clear_admin_session(session)
|
|
69
|
+
session.delete(:admin_user_id)
|
|
70
|
+
session.delete(:admin_user_signed_in_at)
|
|
43
71
|
end
|
|
44
72
|
end
|
|
45
73
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: katalyst-koi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.20.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Katalyst Interactive
|
|
@@ -478,6 +478,7 @@ files:
|
|
|
478
478
|
- db/migrate/20231211005214_add_status_code_to_url_rewrites.rb
|
|
479
479
|
- db/migrate/20241214060913_add_otp_secret_to_admin_users.rb
|
|
480
480
|
- db/migrate/20250204060748_create_well_knowns.rb
|
|
481
|
+
- db/migrate/20260501000000_add_last_sign_out_at_to_admin_users.rb
|
|
481
482
|
- db/seeds.rb
|
|
482
483
|
- lib/generators/koi/active_record/active_record_generator.rb
|
|
483
484
|
- lib/generators/koi/admin/USAGE
|
|
@@ -537,7 +538,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
537
538
|
- !ruby/object:Gem::Version
|
|
538
539
|
version: '0'
|
|
539
540
|
requirements: []
|
|
540
|
-
rubygems_version: 4.0.
|
|
541
|
+
rubygems_version: 4.0.10
|
|
541
542
|
specification_version: 4
|
|
542
543
|
summary: Koi CMS admin framework
|
|
543
544
|
test_files: []
|