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,186 @@
1
+ require RailsBase::Engine.root.join('app', 'helpers', 'rails_base', 'admin_helper.rb')
2
+
3
+ module RailsBase::Admin
4
+ class IndexTile
5
+ include RailsBase::AdminHelper
6
+ attr_accessor :type, :name, :value, :col_name, :insert, :on, :off, :disabled, :disabled_msg, :selector, :partial , :link , :min_width , :url, :method , :color
7
+ MODIFY_TYPES = [
8
+ RISKY = { type: :risky },
9
+ TOGGLE = { type: :toggle, expects: { on: 'String', off: 'String' } },
10
+ SELECTOR = { type: :selector, expects: { selector: 'Proc' } },
11
+ TEXT = { type: :text, expects: { partial: 'String' } },
12
+ BUTTON = { type: :button, expects: { url: 'Proc', method: 'Symbol', color: 'String' } },
13
+ PLAIN = { type: :plain },
14
+ ]
15
+
16
+ VALID_METHODS = [:get, :post, :delete, :patch, :put]
17
+ # Input params
18
+ # type: Symbol
19
+ # => values: MODIFY_TYPES.map{|s| s[:type]}
20
+ # => what: This is the type of index self will be
21
+ #
22
+ # name: Symbol
23
+ # => values: <Anything>
24
+ # => what: Used as the `id` for html. when risky, expected it is a key in RailsBase::AdminController::SECOND_MODAL_MAPPING
25
+ #
26
+ # value: Proc
27
+ # => values: Proc that takes a user as an argument ex: ->(current_user) { user.full_name }
28
+ # => what: Value returned from proc will be value displayed table grid
29
+ #
30
+ # display: Proc
31
+ # => values: Proc that takes a user as an argument ex: ->(current_user) { user.full_name }
32
+ # => what: Boolean returned from proc will allow the element to be changeable
33
+ #
34
+ # col_name: String
35
+ # => values: Short String
36
+ # => what: Value for the Column header
37
+ #
38
+ # insert: Integer
39
+ # => values: Expected to be an integer
40
+ # => what: Column number in the admin view index table
41
+ #
42
+ # on: String
43
+ # => values: 1 word for a toggle switch
44
+ # => what: When toggle is on, this is displayed
45
+ #
46
+ # off: String
47
+ # => values: 1 word for a toggle switch
48
+ # => what: When toggle is off, this is displayed
49
+ #
50
+ # partial: String
51
+ # => values: Path to partial
52
+ # => what: Partial that will get loaded. At present, only for TEXT type
53
+ #
54
+ # url: Proc
55
+ # => values: Given a user, Proc that dynamically assigns url based on the user
56
+ # => what: ->(user) { Rails.application.url_routes.root_path }
57
+ #
58
+ # min_width: Integer
59
+ # => values: nil || > 0
60
+ # => what: Min width for the given table column. When nil passed, none will be set
61
+ #
62
+ # method: Symbol
63
+ # => values: [:get, :post, :delete, :patch, :put]
64
+ # => what: Min width for the given table column. When nil passed, none will be set. Used for Button
65
+ #
66
+ # method: String
67
+ # => values: [:get, :post, :delete, :patch, :put]
68
+ # => what: Min width for the given table column. When nil passed, none will be set. Used for Button
69
+ #
70
+ # selector: Array
71
+ # => values: [:get, :post, :delete, :patch, :put]
72
+ # => what: Min width for the given table column. When nil passed, none will be set. Used for Button
73
+ #
74
+ # selected: String
75
+ # => values: [:get, :post, :delete, :patch, :put]
76
+ # => what: Min width for the given table column. When nil passed, none will be set. Used for Button
77
+
78
+ def self.add(instance)
79
+ @default ||= []
80
+ @default.insert(instance.insert, instance)
81
+ end
82
+
83
+ def self.defaults
84
+ @default
85
+ end
86
+
87
+ def initialize(type:, name:, value:, col_name:, disabled: nil, disabled_msg: nil, insert: nil, on: nil, off: nil, selector: [], partial: nil, url: nil, min_width: nil, method: nil, color: 'warning')
88
+ @type = type
89
+ @name = name
90
+ @value = value
91
+ @col_name = col_name
92
+ @insert = insert.is_a?(Integer) ? insert : -1
93
+ @on = on
94
+ @off = off
95
+ @partial = partial
96
+ @min_width = min_width&.to_i rescue nil
97
+ @disabled = disabled
98
+ @disabled_msg = disabled_msg
99
+ @selector = selector
100
+ @method = method
101
+ @url = url
102
+ @color = color
103
+
104
+ validate!
105
+ validate_expects!
106
+ validate_risky!
107
+ validate_method!
108
+ validate_disabled!
109
+ validate_disabled_msg!
110
+ end
111
+
112
+ def description
113
+ "#{type} for #{name}"
114
+ end
115
+
116
+ def is_toggle?
117
+ type == TOGGLE[:type]
118
+ end
119
+
120
+ def is_selector?
121
+ type == SELECTOR[:type]
122
+ end
123
+
124
+ def is_risky?
125
+ type == RISKY[:type]
126
+ end
127
+
128
+ def is_text?
129
+ type == TEXT[:type]
130
+ end
131
+
132
+ def is_button?
133
+ type == BUTTON[:type]
134
+ end
135
+
136
+ private
137
+
138
+ def validate!
139
+ types = MODIFY_TYPES.map{|s| s[:type]}
140
+ raise ArgumentError, "Expected type to be in [#{types}]" unless types.include? type
141
+ raise ArgumentError, "Expected value to be a proc" unless value.is_a? Proc
142
+ end
143
+
144
+ def validate_disabled!
145
+ return if disabled.nil?
146
+ return if disabled.is_a?(Proc)
147
+
148
+ raise ArgumentError, 'Expected disabled to be a Proc'
149
+ end
150
+
151
+ def validate_disabled_msg!
152
+ return if disabled.nil?
153
+ return unless disabled_msg.nil?
154
+
155
+ raise ArgumentError, 'Expected `disabled_msg` to be present'
156
+ end
157
+
158
+ def validate_expects!
159
+ type_object = MODIFY_TYPES.find { |s| s[:type] == type }
160
+
161
+ return if type_object[:expects].nil?
162
+
163
+ type_object[:expects].each do |k, v|
164
+ val = public_send(k)
165
+ raise ArgumentError, "Expected [#{val}] to be a #{v.constantize}" unless val.is_a? v.constantize
166
+ end
167
+ end
168
+
169
+ def validate_risky!
170
+ return unless is_risky?
171
+ return if SECOND_MODAL_MAPPING.keys.include?(name)
172
+
173
+ keys = SECOND_MODAL_MAPPING.keys
174
+ msg = "Unable to use name #{name}. Expected to be defined in #{keys}" \
175
+ "RailsBase::AdminController::SECOND_MODAL_MAPPING"
176
+ raise ArgumentError, msg
177
+ end
178
+
179
+
180
+ def validate_method!
181
+ return if method.nil?
182
+
183
+ raise ArgumentError, "Unexpected method. Received: #{method}. Expected [#{VALID_METHODS}]" unless VALID_METHODS.include? method
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,52 @@
1
+ require 'rails_base/configuration/admin'
2
+ require 'rails_base/configuration/mfa'
3
+ require 'rails_base/configuration/authentication'
4
+ require 'rails_base/configuration/redis'
5
+ require 'rails_base/configuration/owner'
6
+ require 'rails_base/configuration/mailer'
7
+ require 'rails_base/configuration/exceptions_app'
8
+ require 'rails_base/configuration/app'
9
+ require 'rails_base/configuration/appearance'
10
+ require 'rails_base/configuration/user'
11
+ require 'rails_base/configuration/login_behavior'
12
+ require 'rails_base/configuration/active_job'
13
+
14
+ module RailsBase
15
+ class Config
16
+ VARIABLES = {
17
+ admin: nil,
18
+ mfa: nil,
19
+ auth: :authentication,
20
+ redis: nil,
21
+ owner: nil,
22
+ mailer: nil,
23
+ exceptions_app: nil,
24
+ app: nil,
25
+ appearance: nil,
26
+ user: nil,
27
+ active_job: nil,
28
+ login_behavior: nil
29
+ }
30
+ attr_reader *VARIABLES.keys
31
+
32
+ def initialize
33
+ VARIABLES.each do |variable, override|
34
+ klass_name = (override || variable).to_s.camelize
35
+ klass = "RailsBase::Configuration::#{klass_name}".constantize
36
+ instance_variable_set(:"@#{variable}", klass.new)
37
+ end
38
+ end
39
+
40
+ def validate_configs!
41
+ VARIABLES.keys.each do |var|
42
+ send(var).validate!
43
+ end
44
+ end
45
+
46
+ def reset_config!
47
+ VARIABLES.keys.each do |var|
48
+ send(var).assign_default_values!
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,38 @@
1
+ module RailsBase
2
+ module Configuration
3
+ class ActiveJob < Base
4
+ ACTIVE_JOB_PROC = Proc.new do |val, instance|
5
+ if val.is_a?(Symbol)
6
+ begin
7
+ ::ActiveJob::QueueAdapters.lookup(val)
8
+ Rails.configuration.active_job.queue_adapter = val.to_sym
9
+ rescue StandardError => e
10
+ raise ArgumentError, "config.app.active_job_adapter=#{val} is not a defined active job"
11
+ end
12
+ end
13
+ end
14
+
15
+ DEFAULT_VALUES = {
16
+ enable_ui: {
17
+ type: :boolean,
18
+ default: true,
19
+ description: 'All ActiveJob UI. To be used downstream'
20
+ },
21
+ view_ui: {
22
+ type: :proc,
23
+ default: ->(user) { user.at_least_owner? },
24
+ dependents: [ -> (i) { i.enable_ui? }],
25
+ description: 'All users to view ActiveJob UI. To be used downstream'
26
+ },
27
+ adapter: {
28
+ type: :symbol_class,
29
+ default: ENV['USE_SIDEKIQ']=='true' ? :sidekiq : :inline,
30
+ on_assignment: ACTIVE_JOB_PROC,
31
+ description: 'Active job adapter. This expects a symbol or a class that inherits from ActiveJob::QueueAdapters'
32
+ },
33
+ }
34
+
35
+ attr_accessor *DEFAULT_VALUES.keys
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,231 @@
1
+ require 'rails_base/configuration/base'
2
+ require 'rails_base/admin/index_tile'
3
+ require 'rails_base/admin/default_index_tile'
4
+ require RailsBase::Engine.root.join('app', 'models', 'rails_base', 'user_constants.rb')
5
+
6
+ module RailsBase
7
+ module Configuration
8
+ class Admin < Base
9
+
10
+ include RailsBase::UserConstants
11
+
12
+ ADMIN_TYPE_PROC = Proc.new do |hash|
13
+ RailsBase.config.admin.admin_types.map do |type|
14
+ {
15
+ filter: "Admin Type: #{type}",
16
+ proc: ->(user, admin_user) { user.public_send("admin_#{type}?") },
17
+ id: "#{hash[:id]}_#{type}",
18
+ }
19
+ end
20
+ end
21
+
22
+ DEFAULT_ADMIN_TYPE = {
23
+ filter: '',
24
+ id: "admin",
25
+ proc: ->(_user, _admin_user) { },
26
+ replace: ADMIN_TYPE_PROC,
27
+ }
28
+
29
+ DEFAULT_ADMIN_SELF = {
30
+ filter: 'My User',
31
+ id: 'my_admin_user',
32
+ proc: ->(user, admin_user) { user == admin_user }
33
+ }
34
+
35
+ DEFAULT_ADMIN_ACTIVE = {
36
+ filter: 'Active Users',
37
+ id: 'active_users',
38
+ proc: ->(user, admin_user) { user.active? }
39
+ }
40
+
41
+ DEFAULT_EMAIL_VALIDATED = {
42
+ filter: 'Email Validated',
43
+ id: 'email_validated',
44
+ proc: ->(user, admin_user) { user.email_validated? }
45
+ }
46
+
47
+ DEFAULT_MFA_ENABLED = {
48
+ filter: 'MFA Enabled',
49
+ id: 'mfa_enabled',
50
+ proc: ->(user, admin_user) { user.mfa_enabled? }
51
+ }
52
+
53
+ DEFAULT_PAGE_FILTER = [DEFAULT_ADMIN_TYPE, DEFAULT_ADMIN_SELF, DEFAULT_ADMIN_ACTIVE, DEFAULT_EMAIL_VALIDATED, DEFAULT_MFA_ENABLED].flatten
54
+ DEFAULT_VALUES = {
55
+ enable: {
56
+ type: :boolean,
57
+ default: true,
58
+ description: 'Enable Admin capabilities'
59
+ },
60
+ admin_types: {
61
+ type: :array,
62
+ klass_type: [Symbol],
63
+ default: ADMIN_ENUMS,
64
+ on_assignment: ->(val, instance) { instance._assert_admin_type },
65
+ description: 'List of admin types. Assignment order is important. Note: :none gets prepended as this is default. Note: :owner, gets appended to this array as the last, highest priority',
66
+ decipher: ->(thing) { thing },
67
+ },
68
+ default_admin_type: {
69
+ type: :values,
70
+ expect_values: ->(instance) { instance.admin_types },
71
+ default: ADMIN_ROLE_NONE,
72
+ description: 'Starting value for new users. Dependent on `admin_types` values',
73
+ decipher: ->(thing) { thing },
74
+ },
75
+ enable_history: {
76
+ type: :boolean,
77
+ default: true,
78
+ dependents: [ -> (i) { i.enable? } ],
79
+ description: 'Enable Users to view history'
80
+ },
81
+ view_admin_page: {
82
+ type: :proc,
83
+ default: ->(user) { user.active && user.at_least_view_only? },
84
+ dependents: [ -> (i) { i.enable? } ],
85
+ description: 'Users that can view admin index'
86
+ },
87
+ enable_history_by_user: {
88
+ type: :proc,
89
+ default: ->(user) { true },
90
+ dependents: [ -> (i) { i.enable_history? }, -> (i) { i.enable? } ],
91
+ description: 'Users that can view history page',
92
+ },
93
+ enable_actions: {
94
+ type: :boolean,
95
+ default: true,
96
+ dependents: [ -> (i) { i.enable? } ],
97
+ description: 'Enable history of admin actions',
98
+ },
99
+ admin_page_tiles: {
100
+ type: :array,
101
+ klass_type: [RailsBase::Admin::IndexTile],
102
+ default: RailsBase::Admin::IndexTile.defaults,
103
+ decipher: ->(thing) { thing.description },
104
+ description: 'List of tiles on admin page',
105
+ },
106
+ # Next value is dependent on admin_types. Must be defined after
107
+ admin_page_filter: {
108
+ type: :array,
109
+ # klass_type: [Array],
110
+ on_assignment: ->(val, instance) { instance._admin_type_replace_proc },
111
+ default: DEFAULT_PAGE_FILTER,
112
+ description: 'List of filters on admin page.',
113
+ decipher: ->(thing) { thing[:filter] },
114
+ },
115
+ enable_sso_tile: {
116
+ type: :boolean,
117
+ default: true,
118
+ dependents: [ -> (i) { i.enable? } ],
119
+ description: 'Display SSO tile on admin page',
120
+ },
121
+ sso_tile_users: {
122
+ type: :proc,
123
+ default: ->(user) { user.active && user.at_least_super? },
124
+ dependents: [ -> (i) { i.enable_sso_tile? } ],
125
+ description: 'List of users that can use SSO on admin page',
126
+ },
127
+ impersonate_tile_users: {
128
+ type: :proc,
129
+ default: ->(user) { user.active && user.at_least_super? },
130
+ description: 'List of users that can use impersonation on admin page',
131
+ },
132
+ admin_type_tile_users: {
133
+ type: :proc,
134
+ default: ->(user) { user.active && user.at_least_owner? },
135
+ description: 'List of users that can change other users admin',
136
+ },
137
+ mfa_tile_users: {
138
+ type: :proc,
139
+ default: ->(user) { user.active && user.at_least_super? },
140
+ description: 'List of users that can change MFA on admin page',
141
+ },
142
+ phone_tile_users: {
143
+ type: :proc,
144
+ default: ->(user) { user.active && user.at_least_super? },
145
+ description: 'List of users that can change users phone number on admin page',
146
+ },
147
+ email_tile_users: {
148
+ type: :proc,
149
+ default: ->(user) { user.active && user.at_least_super? },
150
+ description: 'List of users that can change users email on admin page',
151
+ },
152
+ email_validate_tile_users: {
153
+ type: :proc,
154
+ default: ->(user) { user.active && user.at_least_super? },
155
+ description: 'List of users that can change email validated on admin page',
156
+ },
157
+ name_tile_users: {
158
+ type: :proc,
159
+ default: ->(user) { user.active && user.at_least_super? },
160
+ description: 'List of users that can change users name on admin page',
161
+ },
162
+ active_tile_users: {
163
+ type: :proc,
164
+ default: ->(user) { user.active && user.at_least_super? },
165
+ description: 'List of users that can change active on admin page',
166
+ },
167
+ modify_timezone_tile_users: {
168
+ type: :proc,
169
+ default: ->(user) { user.active && user.at_least_super? },
170
+ description: 'List of users that can change the timezone for a given user',
171
+ },
172
+ config_page: {
173
+ type: :proc,
174
+ default: ->(user) { user.active && user.at_least_super? },
175
+ description: 'List of users that can view the configuration page',
176
+ },
177
+ admin_velocity_max: {
178
+ type: :integer,
179
+ default: ENV.fetch('ADMIN_VELOCITY_MAX', 20).to_i,
180
+ description: 'Max number of risky changes an admin can make in a given window',
181
+ },
182
+ admin_velocity_max_in_frame: {
183
+ type: :duration,
184
+ default: ENV.fetch('ADMIN_VELOCITY_MAX_IN_FRAME', 1).to_i.hours,
185
+ description: 'Sliding window for admin_velocity_max',
186
+
187
+ },
188
+ admin_velocity_frame: {
189
+ type: :duration,
190
+ default: ENV.fetch('ADMIN_VELOCITY_FRAME', 5).to_i.hours,
191
+ description: 'Debug purposes. How long to keep admin_velocity_max attempts',
192
+ },
193
+ }
194
+
195
+ attr_accessor *DEFAULT_VALUES.keys
196
+
197
+ def _assert_admin_type
198
+ admin_types.delete(ADMIN_ROLE_OWNER)
199
+ admin_types.delete(ADMIN_ROLE_NONE)
200
+ admin_types << ADMIN_ROLE_OWNER
201
+ admin_types.prepend ADMIN_ROLE_NONE
202
+ convenience_methods
203
+ end
204
+
205
+ def _admin_type_replace_proc
206
+ admin_page_filter.each_with_index do |value, index|
207
+ next unless value[:replace].present?
208
+
209
+ admin_page_filter[index] = ADMIN_TYPE_PROC.call(value)
210
+ end
211
+ admin_page_filter.flatten!
212
+ end
213
+
214
+ private
215
+
216
+ def convenience_methods
217
+ # defines instance methods like
218
+ # user.at_least_super?
219
+ # user.at_least_owner?
220
+ # user.admin_super!
221
+ # user.admin_owner!
222
+ # User.admin_owner
223
+ # User.admin_owners
224
+ # This is 100% dependent upon keeping `admin_types` in order of precedence
225
+ admin_types.each do |type|
226
+ ::User._def_admin_convenience_method!(admin_method: type)
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end