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.
Files changed (194) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +32 -0
  4. data/Rakefile +32 -0
  5. data/app/assets/config/rails_base/manifest.js +3 -0
  6. data/app/assets/images/rails_base/favicon.ico +0 -0
  7. data/app/assets/javascripts/rails_base/admin.js +2 -0
  8. data/app/assets/javascripts/rails_base/application.js +22 -0
  9. data/app/assets/javascripts/rails_base/cable.js +13 -0
  10. data/app/assets/javascripts/rails_base/mfa_auth.coffee +3 -0
  11. data/app/assets/javascripts/rails_base/secondary_authentication.coffee +3 -0
  12. data/app/assets/javascripts/rails_base/sessions.js +152 -0
  13. data/app/assets/javascripts/rails_base/user_settings.coffee +3 -0
  14. data/app/assets/stylesheets/rails_base/admin.css +4 -0
  15. data/app/assets/stylesheets/rails_base/application.scss +15 -0
  16. data/app/assets/stylesheets/rails_base/mfa_auth.scss +3 -0
  17. data/app/assets/stylesheets/rails_base/scaffolds.scss +84 -0
  18. data/app/assets/stylesheets/rails_base/secondary_authentication.scss +3 -0
  19. data/app/assets/stylesheets/rails_base/user_settings.scss +3 -0
  20. data/app/controllers/rails_base/admin_controller.rb +315 -0
  21. data/app/controllers/rails_base/application_controller.rb +153 -0
  22. data/app/controllers/rails_base/errors_controller.rb +29 -0
  23. data/app/controllers/rails_base/mfa_auth_controller.rb +50 -0
  24. data/app/controllers/rails_base/secondary_authentication_controller.rb +224 -0
  25. data/app/controllers/rails_base/switch_user_controller.rb +29 -0
  26. data/app/controllers/rails_base/user_settings_controller.rb +81 -0
  27. data/app/controllers/rails_base/users/passwords_controller.rb +19 -0
  28. data/app/controllers/rails_base/users/registrations_controller.rb +80 -0
  29. data/app/controllers/rails_base/users/sessions_controller.rb +108 -0
  30. data/app/helpers/rails_base/admin_helper.rb +107 -0
  31. data/app/helpers/rails_base/appearance_helper.rb +58 -0
  32. data/app/helpers/rails_base/application_helper.rb +26 -0
  33. data/app/helpers/rails_base/capture_reference_helper.rb +57 -0
  34. data/app/helpers/rails_base/mfa_auth_helper.rb +2 -0
  35. data/app/helpers/rails_base/secondary_authentication_helper.rb +2 -0
  36. data/app/helpers/rails_base/user_field_validators.rb +108 -0
  37. data/app/helpers/rails_base/user_settings_helper.rb +22 -0
  38. data/app/jobs/rails_base/application_job.rb +10 -0
  39. data/app/jobs/twilio_job.rb +9 -0
  40. data/app/mailers/rails_base/application_mailer.rb +9 -0
  41. data/app/mailers/rails_base/email_verification_mailer.rb +22 -0
  42. data/app/mailers/rails_base/event_mailer.rb +16 -0
  43. data/app/models/admin_action.rb +119 -0
  44. data/app/models/rails_base/application_record.rb +22 -0
  45. data/app/models/rails_base/user_constants.rb +28 -0
  46. data/app/models/secret.rb +37 -0
  47. data/app/models/short_lived_data.rb +132 -0
  48. data/app/models/user.rb +143 -0
  49. data/app/services/rails_base/admin_risky_mfa_send.rb +80 -0
  50. data/app/services/rails_base/admin_update_attribute.rb +100 -0
  51. data/app/services/rails_base/authentication/authenticate_user.rb +28 -0
  52. data/app/services/rails_base/authentication/constants.rb +60 -0
  53. data/app/services/rails_base/authentication/decision_twofa_type.rb +76 -0
  54. data/app/services/rails_base/authentication/destroy_user.rb +45 -0
  55. data/app/services/rails_base/authentication/mfa_set_encrypt_token.rb +32 -0
  56. data/app/services/rails_base/authentication/mfa_validator.rb +88 -0
  57. data/app/services/rails_base/authentication/modify_password.rb +67 -0
  58. data/app/services/rails_base/authentication/send_forgot_password.rb +26 -0
  59. data/app/services/rails_base/authentication/send_login_mfa_to_user.rb +77 -0
  60. data/app/services/rails_base/authentication/send_verification_email.rb +103 -0
  61. data/app/services/rails_base/authentication/session_token_verifier.rb +31 -0
  62. data/app/services/rails_base/authentication/single_sign_on_create.rb +44 -0
  63. data/app/services/rails_base/authentication/single_sign_on_send.rb +101 -0
  64. data/app/services/rails_base/authentication/single_sign_on_verify.rb +42 -0
  65. data/app/services/rails_base/authentication/sso_verify_email.rb +43 -0
  66. data/app/services/rails_base/authentication/update_phone_send_verification.rb +46 -0
  67. data/app/services/rails_base/authentication/verify_forgot_password.rb +46 -0
  68. data/app/services/rails_base/email_change.rb +20 -0
  69. data/app/services/rails_base/encryption.rb +87 -0
  70. data/app/services/rails_base/name_change.rb +71 -0
  71. data/app/services/rails_base/service_base.rb +65 -0
  72. data/app/services/rails_base/service_logging.rb +23 -0
  73. data/app/views/layouts/rails_base/application.html.erb +185 -0
  74. data/app/views/layouts/rails_base/mailer.html.erb +13 -0
  75. data/app/views/layouts/rails_base/mailer.text.erb +1 -0
  76. data/app/views/new.html.erb +4 -0
  77. data/app/views/rails_base/admin/history.html.erb +26 -0
  78. data/app/views/rails_base/admin/index.html.erb +149 -0
  79. data/app/views/rails_base/admin/show_config.html.erb +18 -0
  80. data/app/views/rails_base/devise/confirmations/new.html.erb +16 -0
  81. data/app/views/rails_base/devise/mailer/confirmation_instructions.html.erb +5 -0
  82. data/app/views/rails_base/devise/mailer/email_changed.html.erb +7 -0
  83. data/app/views/rails_base/devise/mailer/password_change.html.erb +3 -0
  84. data/app/views/rails_base/devise/mailer/reset_password_instructions.html.erb +8 -0
  85. data/app/views/rails_base/devise/mailer/unlock_instructions.html.erb +7 -0
  86. data/app/views/rails_base/devise/passwords/edit.html.erb +25 -0
  87. data/app/views/rails_base/devise/passwords/new.html.erb +27 -0
  88. data/app/views/rails_base/devise/registrations/edit.html.erb +43 -0
  89. data/app/views/rails_base/devise/registrations/new.html.erb +123 -0
  90. data/app/views/rails_base/devise/sessions/new.html.erb +4 -0
  91. data/app/views/rails_base/devise/shared/_error_messages.html.erb +15 -0
  92. data/app/views/rails_base/devise/shared/_links.html.erb +25 -0
  93. data/app/views/rails_base/devise/unlocks/new.html.erb +16 -0
  94. data/app/views/rails_base/email_verification_mailer/email_verification.html.erb +25 -0
  95. data/app/views/rails_base/email_verification_mailer/event.html.erb +20 -0
  96. data/app/views/rails_base/email_verification_mailer/forgot_password.html.erb +22 -0
  97. data/app/views/rails_base/errors/internal_error.html.erb +1 -0
  98. data/app/views/rails_base/errors/not_found.html.erb +1 -0
  99. data/app/views/rails_base/errors/unacceptable.html.erb +1 -0
  100. data/app/views/rails_base/event_mailer/event.html.erb +10 -0
  101. data/app/views/rails_base/mfa_auth/mfa_code.html.erb +10 -0
  102. data/app/views/rails_base/secondary_authentication/after_email_login_session_new.html.erb +3 -0
  103. data/app/views/rails_base/secondary_authentication/forgot_password.html.erb +9 -0
  104. data/app/views/rails_base/secondary_authentication/remove_me.html.erb +1 -0
  105. data/app/views/rails_base/secondary_authentication/static.html.erb +5 -0
  106. data/app/views/rails_base/shared/_admin_actions_modal.html.erb +65 -0
  107. data/app/views/rails_base/shared/_admin_config_class.html.erb +52 -0
  108. data/app/views/rails_base/shared/_admin_history.html.erb +86 -0
  109. data/app/views/rails_base/shared/_admin_modify_email.html.erb +78 -0
  110. data/app/views/rails_base/shared/_admin_modify_name.html.erb +107 -0
  111. data/app/views/rails_base/shared/_admin_modify_phone.html.erb +87 -0
  112. data/app/views/rails_base/shared/_admin_modify_text.html.erb +35 -0
  113. data/app/views/rails_base/shared/_admin_risky_change.html.erb +57 -0
  114. data/app/views/rails_base/shared/_admin_risky_mfa.html.erb +74 -0
  115. data/app/views/rails_base/shared/_admin_selector_dropdown.html.erb +70 -0
  116. data/app/views/rails_base/shared/_admin_toggle_button.html.erb +72 -0
  117. data/app/views/rails_base/shared/_admin_warning_alert.html.erb +7 -0
  118. data/app/views/rails_base/shared/_appearance_mode_selector.html.erb +183 -0
  119. data/app/views/rails_base/shared/_custom_form_validation_javascript.html.erb +129 -0
  120. data/app/views/rails_base/shared/_enable_mfa_auth_modal.html.erb +105 -0
  121. data/app/views/rails_base/shared/_error_pages.html.erb +123 -0
  122. data/app/views/rails_base/shared/_logged_in_header.html.erb +123 -0
  123. data/app/views/rails_base/shared/_logged_out_header.html.erb +14 -0
  124. data/app/views/rails_base/shared/_mfa_input_layout.html.erb +5 -0
  125. data/app/views/rails_base/shared/_mfa_input_layout_default.html.erb +97 -0
  126. data/app/views/rails_base/shared/_mfa_input_layout_fallback.html.erb +55 -0
  127. data/app/views/rails_base/shared/_modify_mfa_auth_modal.html.erb +20 -0
  128. data/app/views/rails_base/shared/_password_confirm_javascript.html.erb +71 -0
  129. data/app/views/rails_base/shared/_reset_password_form.html.erb +111 -0
  130. data/app/views/rails_base/shared/_session_create_form.html.erb +32 -0
  131. data/app/views/rails_base/shared/_session_timeout_modal.html.erb +76 -0
  132. data/app/views/rails_base/switch_user/_widget.html.erb +5 -0
  133. data/app/views/rails_base/user_settings/_confirm_destroy_user.html.erb +42 -0
  134. data/app/views/rails_base/user_settings/_destroy_user.html.erb +106 -0
  135. data/app/views/rails_base/user_settings/_modify_name.html.erb +71 -0
  136. data/app/views/rails_base/user_settings/_modify_password.html.erb +101 -0
  137. data/app/views/rails_base/user_settings/_modify_password_update_password.html.erb +2 -0
  138. data/app/views/rails_base/user_settings/index.html.erb +54 -0
  139. data/config/initializers/01_rails_config.rb +19 -0
  140. data/config/initializers/admin_action_helper.rb +88 -0
  141. data/config/initializers/browser.rb +4 -0
  142. data/config/initializers/default_logged_in_headers.rb +23 -0
  143. data/config/initializers/devise.rb +314 -0
  144. data/config/initializers/encryption.rb +2 -0
  145. data/config/initializers/switch_user.rb +58 -0
  146. data/config/initializers/switch_user_helper.rb +29 -0
  147. data/config/locales/devise.en.yml +65 -0
  148. data/config/locales/en.yml +58 -0
  149. data/config/routes.rb +114 -0
  150. data/db/migrate/20210212175453_devise_create_rails_base_users.rb +56 -0
  151. data/db/migrate/20210212190537_create_rails_base_short_lived_data.rb +19 -0
  152. data/db/migrate/20210212192645_create_rails_base_secrets.rb +11 -0
  153. data/db/migrate/20210406015744_create_rails_base_admin_actions.rb +17 -0
  154. data/db/seeds.rb +23 -0
  155. data/lib/link_decision_helper.rb +71 -0
  156. data/lib/rails_base.rb +50 -0
  157. data/lib/rails_base/admin/action_cache.rb +99 -0
  158. data/lib/rails_base/admin/action_helper.rb +134 -0
  159. data/lib/rails_base/admin/default_index_tile.rb +176 -0
  160. data/lib/rails_base/admin/index_tile.rb +186 -0
  161. data/lib/rails_base/config.rb +52 -0
  162. data/lib/rails_base/configuration/active_job.rb +38 -0
  163. data/lib/rails_base/configuration/admin.rb +231 -0
  164. data/lib/rails_base/configuration/app.rb +52 -0
  165. data/lib/rails_base/configuration/appearance.rb +131 -0
  166. data/lib/rails_base/configuration/authentication.rb +37 -0
  167. data/lib/rails_base/configuration/base.rb +209 -0
  168. data/lib/rails_base/configuration/display/background_color.rb +25 -0
  169. data/lib/rails_base/configuration/display/btn_danger.rb +25 -0
  170. data/lib/rails_base/configuration/display/btn_dark.rb +25 -0
  171. data/lib/rails_base/configuration/display/btn_info.rb +25 -0
  172. data/lib/rails_base/configuration/display/btn_light.rb +25 -0
  173. data/lib/rails_base/configuration/display/btn_primary.rb +25 -0
  174. data/lib/rails_base/configuration/display/btn_secondary.rb +25 -0
  175. data/lib/rails_base/configuration/display/btn_success.rb +25 -0
  176. data/lib/rails_base/configuration/display/btn_warning.rb +25 -0
  177. data/lib/rails_base/configuration/display/footer.rb +54 -0
  178. data/lib/rails_base/configuration/display/navbar.rb +25 -0
  179. data/lib/rails_base/configuration/display/table_body.rb +25 -0
  180. data/lib/rails_base/configuration/display/table_header.rb +25 -0
  181. data/lib/rails_base/configuration/display/text.rb +26 -0
  182. data/lib/rails_base/configuration/exceptions_app.rb +25 -0
  183. data/lib/rails_base/configuration/login_behavior.rb +17 -0
  184. data/lib/rails_base/configuration/mailer.rb +116 -0
  185. data/lib/rails_base/configuration/mfa.rb +84 -0
  186. data/lib/rails_base/configuration/owner.rb +17 -0
  187. data/lib/rails_base/configuration/redis.rb +29 -0
  188. data/lib/rails_base/configuration/user.rb +43 -0
  189. data/lib/rails_base/engine.rb +51 -0
  190. data/lib/rails_base/version.rb +10 -0
  191. data/lib/tasks/rails_base_tasks.rake +4 -0
  192. data/lib/twilio_helper.rb +26 -0
  193. data/lib/velocity_limiter.rb +91 -0
  194. 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)