rails_base 0.51.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +32 -0
- data/Rakefile +32 -0
- data/app/assets/config/rails_base/manifest.js +3 -0
- data/app/assets/images/rails_base/favicon.ico +0 -0
- data/app/assets/javascripts/rails_base/admin.js +2 -0
- data/app/assets/javascripts/rails_base/application.js +22 -0
- data/app/assets/javascripts/rails_base/cable.js +13 -0
- data/app/assets/javascripts/rails_base/mfa_auth.coffee +3 -0
- data/app/assets/javascripts/rails_base/secondary_authentication.coffee +3 -0
- data/app/assets/javascripts/rails_base/sessions.js +152 -0
- data/app/assets/javascripts/rails_base/user_settings.coffee +3 -0
- data/app/assets/stylesheets/rails_base/admin.css +4 -0
- data/app/assets/stylesheets/rails_base/application.scss +15 -0
- data/app/assets/stylesheets/rails_base/mfa_auth.scss +3 -0
- data/app/assets/stylesheets/rails_base/scaffolds.scss +84 -0
- data/app/assets/stylesheets/rails_base/secondary_authentication.scss +3 -0
- data/app/assets/stylesheets/rails_base/user_settings.scss +3 -0
- data/app/controllers/rails_base/admin_controller.rb +315 -0
- data/app/controllers/rails_base/application_controller.rb +153 -0
- data/app/controllers/rails_base/errors_controller.rb +29 -0
- data/app/controllers/rails_base/mfa_auth_controller.rb +50 -0
- data/app/controllers/rails_base/secondary_authentication_controller.rb +224 -0
- data/app/controllers/rails_base/switch_user_controller.rb +29 -0
- data/app/controllers/rails_base/user_settings_controller.rb +81 -0
- data/app/controllers/rails_base/users/passwords_controller.rb +19 -0
- data/app/controllers/rails_base/users/registrations_controller.rb +80 -0
- data/app/controllers/rails_base/users/sessions_controller.rb +108 -0
- data/app/helpers/rails_base/admin_helper.rb +107 -0
- data/app/helpers/rails_base/appearance_helper.rb +58 -0
- data/app/helpers/rails_base/application_helper.rb +26 -0
- data/app/helpers/rails_base/capture_reference_helper.rb +57 -0
- data/app/helpers/rails_base/mfa_auth_helper.rb +2 -0
- data/app/helpers/rails_base/secondary_authentication_helper.rb +2 -0
- data/app/helpers/rails_base/user_field_validators.rb +108 -0
- data/app/helpers/rails_base/user_settings_helper.rb +22 -0
- data/app/jobs/rails_base/application_job.rb +10 -0
- data/app/jobs/twilio_job.rb +9 -0
- data/app/mailers/rails_base/application_mailer.rb +9 -0
- data/app/mailers/rails_base/email_verification_mailer.rb +22 -0
- data/app/mailers/rails_base/event_mailer.rb +16 -0
- data/app/models/admin_action.rb +119 -0
- data/app/models/rails_base/application_record.rb +22 -0
- data/app/models/rails_base/user_constants.rb +28 -0
- data/app/models/secret.rb +37 -0
- data/app/models/short_lived_data.rb +132 -0
- data/app/models/user.rb +143 -0
- data/app/services/rails_base/admin_risky_mfa_send.rb +80 -0
- data/app/services/rails_base/admin_update_attribute.rb +100 -0
- data/app/services/rails_base/authentication/authenticate_user.rb +28 -0
- data/app/services/rails_base/authentication/constants.rb +60 -0
- data/app/services/rails_base/authentication/decision_twofa_type.rb +76 -0
- data/app/services/rails_base/authentication/destroy_user.rb +45 -0
- data/app/services/rails_base/authentication/mfa_set_encrypt_token.rb +32 -0
- data/app/services/rails_base/authentication/mfa_validator.rb +88 -0
- data/app/services/rails_base/authentication/modify_password.rb +67 -0
- data/app/services/rails_base/authentication/send_forgot_password.rb +26 -0
- data/app/services/rails_base/authentication/send_login_mfa_to_user.rb +77 -0
- data/app/services/rails_base/authentication/send_verification_email.rb +103 -0
- data/app/services/rails_base/authentication/session_token_verifier.rb +31 -0
- data/app/services/rails_base/authentication/single_sign_on_create.rb +44 -0
- data/app/services/rails_base/authentication/single_sign_on_send.rb +101 -0
- data/app/services/rails_base/authentication/single_sign_on_verify.rb +42 -0
- data/app/services/rails_base/authentication/sso_verify_email.rb +43 -0
- data/app/services/rails_base/authentication/update_phone_send_verification.rb +46 -0
- data/app/services/rails_base/authentication/verify_forgot_password.rb +46 -0
- data/app/services/rails_base/email_change.rb +20 -0
- data/app/services/rails_base/encryption.rb +87 -0
- data/app/services/rails_base/name_change.rb +71 -0
- data/app/services/rails_base/service_base.rb +65 -0
- data/app/services/rails_base/service_logging.rb +23 -0
- data/app/views/layouts/rails_base/application.html.erb +185 -0
- data/app/views/layouts/rails_base/mailer.html.erb +13 -0
- data/app/views/layouts/rails_base/mailer.text.erb +1 -0
- data/app/views/new.html.erb +4 -0
- data/app/views/rails_base/admin/history.html.erb +26 -0
- data/app/views/rails_base/admin/index.html.erb +149 -0
- data/app/views/rails_base/admin/show_config.html.erb +18 -0
- data/app/views/rails_base/devise/confirmations/new.html.erb +16 -0
- data/app/views/rails_base/devise/mailer/confirmation_instructions.html.erb +5 -0
- data/app/views/rails_base/devise/mailer/email_changed.html.erb +7 -0
- data/app/views/rails_base/devise/mailer/password_change.html.erb +3 -0
- data/app/views/rails_base/devise/mailer/reset_password_instructions.html.erb +8 -0
- data/app/views/rails_base/devise/mailer/unlock_instructions.html.erb +7 -0
- data/app/views/rails_base/devise/passwords/edit.html.erb +25 -0
- data/app/views/rails_base/devise/passwords/new.html.erb +27 -0
- data/app/views/rails_base/devise/registrations/edit.html.erb +43 -0
- data/app/views/rails_base/devise/registrations/new.html.erb +123 -0
- data/app/views/rails_base/devise/sessions/new.html.erb +4 -0
- data/app/views/rails_base/devise/shared/_error_messages.html.erb +15 -0
- data/app/views/rails_base/devise/shared/_links.html.erb +25 -0
- data/app/views/rails_base/devise/unlocks/new.html.erb +16 -0
- data/app/views/rails_base/email_verification_mailer/email_verification.html.erb +25 -0
- data/app/views/rails_base/email_verification_mailer/event.html.erb +20 -0
- data/app/views/rails_base/email_verification_mailer/forgot_password.html.erb +22 -0
- data/app/views/rails_base/errors/internal_error.html.erb +1 -0
- data/app/views/rails_base/errors/not_found.html.erb +1 -0
- data/app/views/rails_base/errors/unacceptable.html.erb +1 -0
- data/app/views/rails_base/event_mailer/event.html.erb +10 -0
- data/app/views/rails_base/mfa_auth/mfa_code.html.erb +10 -0
- data/app/views/rails_base/secondary_authentication/after_email_login_session_new.html.erb +3 -0
- data/app/views/rails_base/secondary_authentication/forgot_password.html.erb +9 -0
- data/app/views/rails_base/secondary_authentication/remove_me.html.erb +1 -0
- data/app/views/rails_base/secondary_authentication/static.html.erb +5 -0
- data/app/views/rails_base/shared/_admin_actions_modal.html.erb +65 -0
- data/app/views/rails_base/shared/_admin_config_class.html.erb +52 -0
- data/app/views/rails_base/shared/_admin_history.html.erb +86 -0
- data/app/views/rails_base/shared/_admin_modify_email.html.erb +78 -0
- data/app/views/rails_base/shared/_admin_modify_name.html.erb +107 -0
- data/app/views/rails_base/shared/_admin_modify_phone.html.erb +87 -0
- data/app/views/rails_base/shared/_admin_modify_text.html.erb +35 -0
- data/app/views/rails_base/shared/_admin_risky_change.html.erb +57 -0
- data/app/views/rails_base/shared/_admin_risky_mfa.html.erb +74 -0
- data/app/views/rails_base/shared/_admin_selector_dropdown.html.erb +70 -0
- data/app/views/rails_base/shared/_admin_toggle_button.html.erb +72 -0
- data/app/views/rails_base/shared/_admin_warning_alert.html.erb +7 -0
- data/app/views/rails_base/shared/_appearance_mode_selector.html.erb +183 -0
- data/app/views/rails_base/shared/_custom_form_validation_javascript.html.erb +129 -0
- data/app/views/rails_base/shared/_enable_mfa_auth_modal.html.erb +105 -0
- data/app/views/rails_base/shared/_error_pages.html.erb +123 -0
- data/app/views/rails_base/shared/_logged_in_header.html.erb +123 -0
- data/app/views/rails_base/shared/_logged_out_header.html.erb +14 -0
- data/app/views/rails_base/shared/_mfa_input_layout.html.erb +5 -0
- data/app/views/rails_base/shared/_mfa_input_layout_default.html.erb +97 -0
- data/app/views/rails_base/shared/_mfa_input_layout_fallback.html.erb +55 -0
- data/app/views/rails_base/shared/_modify_mfa_auth_modal.html.erb +20 -0
- data/app/views/rails_base/shared/_password_confirm_javascript.html.erb +71 -0
- data/app/views/rails_base/shared/_reset_password_form.html.erb +111 -0
- data/app/views/rails_base/shared/_session_create_form.html.erb +32 -0
- data/app/views/rails_base/shared/_session_timeout_modal.html.erb +76 -0
- data/app/views/rails_base/switch_user/_widget.html.erb +5 -0
- data/app/views/rails_base/user_settings/_confirm_destroy_user.html.erb +42 -0
- data/app/views/rails_base/user_settings/_destroy_user.html.erb +106 -0
- data/app/views/rails_base/user_settings/_modify_name.html.erb +71 -0
- data/app/views/rails_base/user_settings/_modify_password.html.erb +101 -0
- data/app/views/rails_base/user_settings/_modify_password_update_password.html.erb +2 -0
- data/app/views/rails_base/user_settings/index.html.erb +54 -0
- data/config/initializers/01_rails_config.rb +19 -0
- data/config/initializers/admin_action_helper.rb +88 -0
- data/config/initializers/browser.rb +4 -0
- data/config/initializers/default_logged_in_headers.rb +23 -0
- data/config/initializers/devise.rb +314 -0
- data/config/initializers/encryption.rb +2 -0
- data/config/initializers/switch_user.rb +58 -0
- data/config/initializers/switch_user_helper.rb +29 -0
- data/config/locales/devise.en.yml +65 -0
- data/config/locales/en.yml +58 -0
- data/config/routes.rb +114 -0
- data/db/migrate/20210212175453_devise_create_rails_base_users.rb +56 -0
- data/db/migrate/20210212190537_create_rails_base_short_lived_data.rb +19 -0
- data/db/migrate/20210212192645_create_rails_base_secrets.rb +11 -0
- data/db/migrate/20210406015744_create_rails_base_admin_actions.rb +17 -0
- data/db/seeds.rb +23 -0
- data/lib/link_decision_helper.rb +71 -0
- data/lib/rails_base.rb +50 -0
- data/lib/rails_base/admin/action_cache.rb +99 -0
- data/lib/rails_base/admin/action_helper.rb +134 -0
- data/lib/rails_base/admin/default_index_tile.rb +176 -0
- data/lib/rails_base/admin/index_tile.rb +186 -0
- data/lib/rails_base/config.rb +52 -0
- data/lib/rails_base/configuration/active_job.rb +38 -0
- data/lib/rails_base/configuration/admin.rb +231 -0
- data/lib/rails_base/configuration/app.rb +52 -0
- data/lib/rails_base/configuration/appearance.rb +131 -0
- data/lib/rails_base/configuration/authentication.rb +37 -0
- data/lib/rails_base/configuration/base.rb +209 -0
- data/lib/rails_base/configuration/display/background_color.rb +25 -0
- data/lib/rails_base/configuration/display/btn_danger.rb +25 -0
- data/lib/rails_base/configuration/display/btn_dark.rb +25 -0
- data/lib/rails_base/configuration/display/btn_info.rb +25 -0
- data/lib/rails_base/configuration/display/btn_light.rb +25 -0
- data/lib/rails_base/configuration/display/btn_primary.rb +25 -0
- data/lib/rails_base/configuration/display/btn_secondary.rb +25 -0
- data/lib/rails_base/configuration/display/btn_success.rb +25 -0
- data/lib/rails_base/configuration/display/btn_warning.rb +25 -0
- data/lib/rails_base/configuration/display/footer.rb +54 -0
- data/lib/rails_base/configuration/display/navbar.rb +25 -0
- data/lib/rails_base/configuration/display/table_body.rb +25 -0
- data/lib/rails_base/configuration/display/table_header.rb +25 -0
- data/lib/rails_base/configuration/display/text.rb +26 -0
- data/lib/rails_base/configuration/exceptions_app.rb +25 -0
- data/lib/rails_base/configuration/login_behavior.rb +17 -0
- data/lib/rails_base/configuration/mailer.rb +116 -0
- data/lib/rails_base/configuration/mfa.rb +84 -0
- data/lib/rails_base/configuration/owner.rb +17 -0
- data/lib/rails_base/configuration/redis.rb +29 -0
- data/lib/rails_base/configuration/user.rb +43 -0
- data/lib/rails_base/engine.rb +51 -0
- data/lib/rails_base/version.rb +10 -0
- data/lib/tasks/rails_base_tasks.rake +4 -0
- data/lib/twilio_helper.rb +26 -0
- data/lib/velocity_limiter.rb +91 -0
- metadata +619 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
class LinkDecisionHelper
|
2
|
+
ALLOWED_TYPES = [
|
3
|
+
NAVBAR_LOGGED_IN = :n_logged_in,
|
4
|
+
NAVBAR_LOGGED_OUT = :n_logged_out
|
5
|
+
]
|
6
|
+
|
7
|
+
DEFAULT_TITLE = 'Default Title'
|
8
|
+
DEFAULT_URL = '/' # root
|
9
|
+
|
10
|
+
class NotOnAllowListError < StandardError; end;
|
11
|
+
|
12
|
+
def self.clear_type!(type:)
|
13
|
+
raise "Unexpected type [#{type}]. Expected #{ALLOWED_TYPES}" unless ALLOWED_TYPES.include?(type)
|
14
|
+
Rails.application.config.public_send("#{type}=", [])
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(title:, url:, type:, display: true, default_type: nil, config: nil, _blank: false)
|
18
|
+
raise NotOnAllowListError, "Unexpected type [#{type}]. Expected #{ALLOWED_TYPES}" unless ALLOWED_TYPES.include?(type)
|
19
|
+
|
20
|
+
@config = config
|
21
|
+
@type = type
|
22
|
+
@url = url
|
23
|
+
@title = title
|
24
|
+
@display = display
|
25
|
+
@_blank = _blank
|
26
|
+
|
27
|
+
if default_type && ALLOWED_TYPES.include?(default_type)
|
28
|
+
assign_default!
|
29
|
+
elsif default_type && !ALLOWED_TYPES.include?(default_type)
|
30
|
+
raise NotOnAllowListError, 'unexpected default value'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def assign!(index: -1)
|
35
|
+
config.public_send(@type).insert(index, self)
|
36
|
+
end
|
37
|
+
|
38
|
+
def url
|
39
|
+
get_value(@url)
|
40
|
+
end
|
41
|
+
|
42
|
+
def title
|
43
|
+
get_value(@title)
|
44
|
+
end
|
45
|
+
|
46
|
+
def blank?
|
47
|
+
@_blank
|
48
|
+
end
|
49
|
+
|
50
|
+
def display?(current_user)
|
51
|
+
get_value(@display, current_user)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def get_value(thing, *args)
|
57
|
+
thing.is_a?(Proc) ? thing.call(*args) : thing
|
58
|
+
end
|
59
|
+
|
60
|
+
def assign_default!
|
61
|
+
case @type
|
62
|
+
when NAVBAR_LOGGED_IN
|
63
|
+
@url = DEFAULT_URL
|
64
|
+
@title = DEFAULT_TITLE
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def config
|
69
|
+
@config ||= Rails.application.config
|
70
|
+
end
|
71
|
+
end
|
data/lib/rails_base.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require "rails_base/engine"
|
2
|
+
|
3
|
+
# explicitly require gems that provide assets
|
4
|
+
# when engine loads, this adds assets to Main apps ssets pipeline
|
5
|
+
# (Only a problem for lazy loaded non prod ENVs)
|
6
|
+
require 'jquery_mask_rails'
|
7
|
+
require 'allow_numeric'
|
8
|
+
require 'jquery-rails'
|
9
|
+
require 'coffee-rails'
|
10
|
+
require 'turbolinks'
|
11
|
+
require 'popper_js'
|
12
|
+
require 'bootstrap'
|
13
|
+
require 'sassc-rails'
|
14
|
+
require 'switch_user'
|
15
|
+
|
16
|
+
require 'rails_base/admin/action_cache'
|
17
|
+
require 'rails_base/config'
|
18
|
+
|
19
|
+
module RailsBase
|
20
|
+
def self.url_routes
|
21
|
+
Rails.application.routes.url_helpers
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.route_exist?(path)
|
25
|
+
Rails.application.routes.recognize_path(path)
|
26
|
+
true
|
27
|
+
rescue StandardError, ActionController::RoutingError
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.configure(&block)
|
32
|
+
yield(config) if block_given?
|
33
|
+
|
34
|
+
config.validate_configs!
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.config
|
38
|
+
@config ||= RailsBase::Config.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.appearance
|
42
|
+
@appearance ||= config.appearance
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.reset_config!
|
46
|
+
config.reset_config!
|
47
|
+
end
|
48
|
+
|
49
|
+
AdminStruct = Struct.new(:original_attribute, :new_attribute, :user)
|
50
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'redis'
|
2
|
+
require 'redis-namespace'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module RailsBase::Admin
|
6
|
+
class ActionCache
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
KEY_BASE = 'aac_user'
|
10
|
+
LAST_VIEWED_BASE = 'lv'
|
11
|
+
LV_TTL = 150.days
|
12
|
+
TTL_FOR_CACHE = 60.days
|
13
|
+
VALID_TIME_OBJECT = [Time, DateTime, ActiveSupport::TimeWithZone]
|
14
|
+
|
15
|
+
attr_reader :redis
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
url = RailsBase.config.redis.admin_action
|
19
|
+
namespace = RailsBase.config.redis.admin_action_namespace
|
20
|
+
client = Redis.new(url: url)
|
21
|
+
@redis = Redis::Namespace.new(namespace, redis_url: client)
|
22
|
+
@logger = Rails.logger
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_action(user:, msg:, occured:)
|
26
|
+
validate!(user, msg, occured)
|
27
|
+
|
28
|
+
score = occured.to_f
|
29
|
+
@logger.info { "Adding Redis Cache Admin actions for #{key(user)}" }
|
30
|
+
|
31
|
+
redis.zadd(key(user), score, msg)
|
32
|
+
redis.expire(key(user), TTL_FOR_CACHE.to_i)
|
33
|
+
end
|
34
|
+
|
35
|
+
def actions_since(user:, alltime: false, time: nil)
|
36
|
+
score =
|
37
|
+
if alltime
|
38
|
+
0
|
39
|
+
else
|
40
|
+
valid_time!(time)
|
41
|
+
score = time.to_f
|
42
|
+
end
|
43
|
+
|
44
|
+
validate_user!(user)
|
45
|
+
max_score = Time.now.to_f
|
46
|
+
@logger.info { "Retrieving Redis Cache Admin actions for #{key(user)} since #{time}" }
|
47
|
+
|
48
|
+
redis.zrangebyscore(key(user), score, max_score, with_scores: true)
|
49
|
+
end
|
50
|
+
|
51
|
+
def delete_actions_since!(user:, time:)
|
52
|
+
valid_time!(time)
|
53
|
+
validate_user!(user)
|
54
|
+
|
55
|
+
score = time.to_f
|
56
|
+
redis.zremrangebyscore(key(user), 0, score)
|
57
|
+
@logger.info { "Deleted Redis Cache Admin actions for #{key(user)}" }
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
def update_last_viewed(user:, time: Time.zone.now)
|
62
|
+
valid_time!(time)
|
63
|
+
validate_user!(user)
|
64
|
+
|
65
|
+
redis.set(key_last_viewed(user), time.to_f, ex: LV_TTL)
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_last_viewed(user:)
|
69
|
+
validate_user!(user)
|
70
|
+
|
71
|
+
redis.get(key_last_viewed(user))
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def validate!(user, msg, occured)
|
77
|
+
raise ArgumentError, 'Expected msg to be a string' unless msg.is_a?(String)
|
78
|
+
|
79
|
+
validate_user!(user)
|
80
|
+
valid_time!(occured)
|
81
|
+
end
|
82
|
+
|
83
|
+
def validate_user!(user)
|
84
|
+
raise ArgumentError, 'Expected user to respond to `id`' unless user.respond_to?('id')
|
85
|
+
end
|
86
|
+
|
87
|
+
def valid_time!(time)
|
88
|
+
raise ArgumentError, "Expected occured to be a #{VALID_TIME_OBJECT.join(' or ')}" unless VALID_TIME_OBJECT.include?(time.class)
|
89
|
+
end
|
90
|
+
|
91
|
+
def key_last_viewed(user)
|
92
|
+
"#{key(user)}:#{LAST_VIEWED_BASE}"
|
93
|
+
end
|
94
|
+
|
95
|
+
def key(user)
|
96
|
+
"#{KEY_BASE}:#{user.id}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module RailsBase::Admin
|
2
|
+
class ActionHelper
|
3
|
+
ACTIONS_KEY = "___all_actions_#{(rand*10**10).to_i}___"
|
4
|
+
CONTROLLER_ACTIONS_KEY = "___all_controller_actions__#{(rand*10**10).to_i}___"
|
5
|
+
DEFAULT_ALLOWED_KLASSES = [ApplicationController, RailsBase::ApplicationController, ::SwitchUserController]
|
6
|
+
class << self
|
7
|
+
def allowed_inherited_klasses
|
8
|
+
DEFAULT_ALLOWED_KLASSES + (@allowed_klasses || [])
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_inherited_klasses(klass)
|
12
|
+
@allowed_klasses ||= []
|
13
|
+
@allowed_klasses << klass
|
14
|
+
end
|
15
|
+
|
16
|
+
def clear_inherited_klasses!
|
17
|
+
@allowed_klasses = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def add(instance)
|
21
|
+
@actions ||= {}
|
22
|
+
@all_actions ||= []
|
23
|
+
@default_actions ||= []
|
24
|
+
|
25
|
+
@all_actions << [instance]
|
26
|
+
@default_actions << [instance]
|
27
|
+
|
28
|
+
controller = instance.controller
|
29
|
+
action = instance.action
|
30
|
+
if controller.nil?
|
31
|
+
@actions[ACTIONS_KEY] ||= []
|
32
|
+
@actions[ACTIONS_KEY] << instance
|
33
|
+
return
|
34
|
+
end
|
35
|
+
|
36
|
+
@actions[controller.to_s] ||= {}
|
37
|
+
|
38
|
+
if action
|
39
|
+
@actions[controller.to_s][action.to_s] ||= []
|
40
|
+
@actions[controller.to_s][action.to_s] << instance
|
41
|
+
else
|
42
|
+
@actions[controller.to_s][CONTROLLER_ACTIONS_KEY] ||= []
|
43
|
+
@actions[controller.to_s][CONTROLLER_ACTIONS_KEY] << instance
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def actions
|
48
|
+
@actions
|
49
|
+
end
|
50
|
+
|
51
|
+
def reset!
|
52
|
+
@actions = nil
|
53
|
+
@all_actions = nil
|
54
|
+
@default_actions.each { |instance| add(instance) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class InvalidControllerError < StandardError; end;
|
59
|
+
class InvalidActionError < StandardError; end;
|
60
|
+
class InvalidTitleError < StandardError; end;
|
61
|
+
|
62
|
+
attr_accessor :controller, :action, :proc, :title, :default
|
63
|
+
# controller is the controller class inherited by RailsBase::ApplicationController
|
64
|
+
# action is the method name on the controller
|
65
|
+
# title should be the AdminAction.action
|
66
|
+
# if proc available,
|
67
|
+
# => |session, admin_user, user, title, struct|
|
68
|
+
# => RailsBase::AdminStruct has methods original_attribute and new_attribute
|
69
|
+
# => Expected return
|
70
|
+
# => { admin_user, user, action, original_attribute, new_attribute, change_to }
|
71
|
+
def initialize(controller: nil, action: nil, title: nil, default: false, proc: nil)
|
72
|
+
@controller = controller
|
73
|
+
@action = action
|
74
|
+
@title = title
|
75
|
+
@proc = proc
|
76
|
+
valid_controller!
|
77
|
+
valid_action!
|
78
|
+
valid_title!
|
79
|
+
end
|
80
|
+
|
81
|
+
def add!
|
82
|
+
self.class.add(self)
|
83
|
+
end
|
84
|
+
|
85
|
+
def call(req:, params:, admin_user:, user:, struct: nil)
|
86
|
+
# byebug
|
87
|
+
if proc
|
88
|
+
action_params = proc.call(req, params, admin_user, user, title, struct)
|
89
|
+
return if action_params.nil?
|
90
|
+
|
91
|
+
AdminAction.action(action_params)
|
92
|
+
else
|
93
|
+
default_call(request: request, admin_user: admin_user, user: user, struct: struct)
|
94
|
+
end
|
95
|
+
rescue StandardError => e
|
96
|
+
Rails.logger.error(e.message)
|
97
|
+
Rails.logger.error(e.backtrace)
|
98
|
+
Rails.logger.error("Trapping Error from AdminActionHelper.")
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def default_call(session:, admin_user:, user:, struct: nil)
|
104
|
+
action_params = {
|
105
|
+
admin_user: admin_user,
|
106
|
+
user: user,
|
107
|
+
action: title,
|
108
|
+
change_from: struct&.original_attribute,
|
109
|
+
change_to: struct&.new_attribute,
|
110
|
+
}
|
111
|
+
AdminAction.action(action_params)
|
112
|
+
end
|
113
|
+
|
114
|
+
def valid_controller!
|
115
|
+
return if self.class.allowed_inherited_klasses.include?(controller.superclass)
|
116
|
+
|
117
|
+
raise InvalidControllerError, "@controller does not inherit #{self.class.allowed_inherited_klasses}"
|
118
|
+
end
|
119
|
+
|
120
|
+
def valid_action!
|
121
|
+
return if action.nil?
|
122
|
+
return if controller.instance_methods.map(&:to_s).include?(action.to_s)
|
123
|
+
|
124
|
+
puts controller.instance_methods
|
125
|
+
raise InvalidActionError, "#{controller} does not respond to #{action}"
|
126
|
+
end
|
127
|
+
|
128
|
+
def valid_title!
|
129
|
+
return unless title.nil? && proc.nil?
|
130
|
+
|
131
|
+
raise InvalidTitleError, "Missing title and proc. 1 or the other needs to be present"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'rails_base/admin/index_tile'
|
2
|
+
|
3
|
+
# ID Tile
|
4
|
+
params = {
|
5
|
+
type: :plain,
|
6
|
+
value: ->(user) { user.id },
|
7
|
+
insert: 0, # optional value default is to push it to the end of the array ORDER MATTERS
|
8
|
+
name: 'user_id', # name to be amended to html id
|
9
|
+
col_name: 'User Id', # Expected to be the column header name
|
10
|
+
}
|
11
|
+
|
12
|
+
instance = RailsBase::Admin::IndexTile.new(**params)
|
13
|
+
RailsBase::Admin::IndexTile.add(instance)
|
14
|
+
|
15
|
+
# Name Tile
|
16
|
+
params = {
|
17
|
+
type: :text,
|
18
|
+
value: ->(user) { user.full_name },
|
19
|
+
insert: 1, # optional value default is to push it to the end of the array ORDER MATTERS
|
20
|
+
name: 'full_name', # name to be amended to html id
|
21
|
+
col_name: 'Full Name', # Expected to be the column header name
|
22
|
+
partial: 'rails_base/shared/admin_modify_name',
|
23
|
+
min_width: 220,
|
24
|
+
disabled: -> (user, admin_user) { !RailsBase.config.admin.name_tile_users.call(admin_user) },
|
25
|
+
disabled_msg: -> (user, admin_user) { 'Your admin user does not have permissions' }
|
26
|
+
}
|
27
|
+
instance = RailsBase::Admin::IndexTile.new(**params)
|
28
|
+
RailsBase::Admin::IndexTile.add(instance)
|
29
|
+
|
30
|
+
# Active Tile
|
31
|
+
params = {
|
32
|
+
type: :toggle,
|
33
|
+
value: ->(user) { user.active },
|
34
|
+
on: 'Active',
|
35
|
+
off: 'Inactive',
|
36
|
+
name: 'active', # name to be amended to html id
|
37
|
+
col_name: 'Active User', # Expected to be the column header name
|
38
|
+
disabled: -> (user, admin_user) { user == admin_user || !RailsBase.config.admin.email_tile_users.call(admin_user) },
|
39
|
+
disabled_msg: -> (user, admin_user) { 'Your admin user does not have permissions' }
|
40
|
+
}
|
41
|
+
instance = RailsBase::Admin::IndexTile.new(**params)
|
42
|
+
RailsBase::Admin::IndexTile.add(instance)
|
43
|
+
|
44
|
+
# Email Tile
|
45
|
+
params = {
|
46
|
+
type: :risky,
|
47
|
+
value: ->(user) { user.email },
|
48
|
+
insert: 2, # optional value default is to push it to the end of the array ORDER MATTERS
|
49
|
+
name: :email, # name to be amended to html id
|
50
|
+
col_name: 'Email', # Expected to be the column header name
|
51
|
+
min_width: 220,
|
52
|
+
disabled: -> (user, admin_user) { !RailsBase.config.admin.email_validate_tile_users.call(admin_user) },
|
53
|
+
disabled_msg: -> (user, admin_user) { 'Your admin user does not have permissions' }
|
54
|
+
}
|
55
|
+
instance = RailsBase::Admin::IndexTile.new(**params)
|
56
|
+
RailsBase::Admin::IndexTile.add(instance)
|
57
|
+
|
58
|
+
# Email Validated Tile
|
59
|
+
params = {
|
60
|
+
type: :toggle,
|
61
|
+
value: ->(user) { user.email_validated },
|
62
|
+
on: 'Valid',
|
63
|
+
off: 'Invalid',
|
64
|
+
name: 'email_validated', # name to be amended to html id
|
65
|
+
col_name: 'Email Validated?', # Expected to be the column header name
|
66
|
+
disabled: -> (user, admin_user) { !RailsBase.config.admin.email_tile_users.call(admin_user) },
|
67
|
+
disabled_msg: -> (user, admin_user) { 'Your admin user does not have permissions' }
|
68
|
+
}
|
69
|
+
instance = RailsBase::Admin::IndexTile.new(**params)
|
70
|
+
RailsBase::Admin::IndexTile.add(instance)
|
71
|
+
|
72
|
+
# phone_number Tile
|
73
|
+
params = {
|
74
|
+
type: :risky,
|
75
|
+
value: ->(user) { user.phone_number },
|
76
|
+
name: :phone_number, # name to be amended to html id
|
77
|
+
col_name: 'Phone Number', # Expected to be the column header name
|
78
|
+
min_width: 180,
|
79
|
+
disabled: -> (user, admin_user) { !RailsBase.config.admin.phone_tile_users.call(admin_user) },
|
80
|
+
disabled_msg: -> (user, admin_user) { 'Your admin user does not have permissions' }
|
81
|
+
|
82
|
+
}
|
83
|
+
instance = RailsBase::Admin::IndexTile.new(**params)
|
84
|
+
RailsBase::Admin::IndexTile.add(instance)
|
85
|
+
|
86
|
+
# Mfa Enabled Validated Tile
|
87
|
+
params = {
|
88
|
+
type: :toggle,
|
89
|
+
value: ->(user) { user.mfa_enabled },
|
90
|
+
on: 'Enabled',
|
91
|
+
off: 'Disabled',
|
92
|
+
name: 'mfa_enabled', # name to be amended to html id
|
93
|
+
col_name: 'MFA Enabled?', # Expected to be the column header name
|
94
|
+
disabled: -> (user, admin_user) { !RailsBase.config.admin.mfa_tile_users.call(admin_user) },
|
95
|
+
disabled_msg: -> (user, admin_user) { 'Your admin user does not have permissions' },
|
96
|
+
min_width: 220,
|
97
|
+
}
|
98
|
+
instance = RailsBase::Admin::IndexTile.new(**params)
|
99
|
+
RailsBase::Admin::IndexTile.add(instance)
|
100
|
+
|
101
|
+
|
102
|
+
# Admin Type Tile
|
103
|
+
params = {
|
104
|
+
type: :selector,
|
105
|
+
value: ->(user) { user.admin },
|
106
|
+
name: 'admin', # name to be amended to html id
|
107
|
+
col_name: 'Admin Type', # Expected to be the column header name
|
108
|
+
selector: -> (user) { RailsBase.config.admin.admin_types },
|
109
|
+
disabled: -> (user, admin_user) { user == admin_user || !RailsBase.config.admin.admin_type_tile_users.call(admin_user) },
|
110
|
+
disabled_msg: -> (user, admin_user) { 'Unable to complete action.' }
|
111
|
+
}
|
112
|
+
instance = RailsBase::Admin::IndexTile.new(**params)
|
113
|
+
RailsBase::Admin::IndexTile.add(instance)
|
114
|
+
|
115
|
+
|
116
|
+
selector_array = Proc.new do |user|
|
117
|
+
base = [RailsBase.config.user.class::USER_DEFINED_KEY, RailsBase.config.user.class::USER_DEFINED_ZONE[RailsBase.config.user.class::USER_DEFINED_KEY].call(user)]
|
118
|
+
RailsBase.config.user.class::ACTIVE_SUPPORT_MAPPING.each do |k,v|
|
119
|
+
base << [k, v.call]
|
120
|
+
end
|
121
|
+
base
|
122
|
+
end
|
123
|
+
|
124
|
+
# Users Timezone
|
125
|
+
params = {
|
126
|
+
type: :selector,
|
127
|
+
value: ->(user) { user.last_known_timezone || RailsBase.config.user.user_timezone(user) },
|
128
|
+
name: 'last_known_timezone', # name to be amended to html id
|
129
|
+
col_name: 'Timezone', # Expected to be the column header name
|
130
|
+
selector: -> (user) { selector_array.call(user) },
|
131
|
+
disabled: -> (user, admin_user) { RailsBase.config.user.tz_user_defined? || !RailsBase.config.admin.modify_timezone_tile_users.call(admin_user) },
|
132
|
+
disabled_msg: -> (user, admin_user) { RailsBase.config.user.tz_user_defined? ? 'User Defined TZ is enabled in config. Cant change TZ.' : 'Unable to perform action' }
|
133
|
+
}
|
134
|
+
instance = RailsBase::Admin::IndexTile.new(**params)
|
135
|
+
RailsBase::Admin::IndexTile.add(instance)
|
136
|
+
|
137
|
+
# Last logged in
|
138
|
+
params = {
|
139
|
+
type: :plain,
|
140
|
+
value: ->(user) { user.last_sign_in_at&.to_formatted_s(:rfc822) || 'Never' },
|
141
|
+
name: 'logged_in_last', # name to be amended to html id
|
142
|
+
col_name: 'Last Logged In', # Expected to be the column header name
|
143
|
+
}
|
144
|
+
instance = RailsBase::Admin::IndexTile.new(**params)
|
145
|
+
RailsBase::Admin::IndexTile.add(instance)
|
146
|
+
|
147
|
+
|
148
|
+
# Impersonation Tile
|
149
|
+
params = {
|
150
|
+
type: :button,
|
151
|
+
value: ->(_user) { },
|
152
|
+
name: 'impersonate', # name to be amended to html id
|
153
|
+
col_name: 'Impersonate', # Expected to be the column header name
|
154
|
+
method: :post,
|
155
|
+
color: 'warning',
|
156
|
+
disabled: ->(user, admin_user) { !RailsBase.config.admin.impersonate_tile_users.call(admin_user) },
|
157
|
+
disabled_msg: ->(user, admin_user) { 'Your Admin User is not permitted to impersonate Users' },
|
158
|
+
url: ->(user) { RailsBase.url_routes.switch_user_path(scope_identifier: "user_#{user.id}") }
|
159
|
+
}
|
160
|
+
instance = RailsBase::Admin::IndexTile.new(**params)
|
161
|
+
RailsBase::Admin::IndexTile.add(instance)
|
162
|
+
|
163
|
+
# SSO send Tile
|
164
|
+
params = {
|
165
|
+
type: :button,
|
166
|
+
value: ->(_user) { },
|
167
|
+
name: 'sso_send', # name to be amended to html id
|
168
|
+
col_name: 'Send SSO', # Expected to be the column header name
|
169
|
+
method: :post,
|
170
|
+
color: 'warning',
|
171
|
+
disabled: ->(user, admin_user) { !RailsBase.config.admin.sso_tile_users.call(admin_user) },
|
172
|
+
disabled_msg: ->(user, admin_user) { 'Your Admin User is not permitted to send SSO' },
|
173
|
+
url: ->(user) { RailsBase.url_routes.admin_sso_send_path(id: user.id) }
|
174
|
+
}
|
175
|
+
instance = RailsBase::Admin::IndexTile.new(**params)
|
176
|
+
RailsBase::Admin::IndexTile.add(instance)
|