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,20 @@
|
|
1
|
+
class RailsBase::EmailChange < RailsBase::ServiceBase
|
2
|
+
|
3
|
+
delegate :email, to: :context
|
4
|
+
delegate :last_name, to: :context
|
5
|
+
delegate :user, to: :context
|
6
|
+
|
7
|
+
def call
|
8
|
+
context.original_email = user.email
|
9
|
+
user.update_attribute(:email, email)
|
10
|
+
context.new_email = email
|
11
|
+
log(level: :info, msg: "Changed #{user.id} email from: #{context.original_email} to #{email}")
|
12
|
+
rescue StandardError
|
13
|
+
context.fail!(message: 'Unable to update email address. Likely that this email is already taken')
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate!
|
17
|
+
raise "Expected email to be a String. Received #{email.class}" unless email.is_a? String
|
18
|
+
raise "Expected user to be a User. Received #{user.class}" unless user.is_a? User
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
class RailsBase::Encryption
|
4
|
+
SECRET_NAME = 'encryption_service_verifier'
|
5
|
+
extend RailsBase::ServiceLogging
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# for service_logging class override
|
9
|
+
def class_name
|
10
|
+
name
|
11
|
+
end
|
12
|
+
# token = Encryption.encode(value: 'testing Encryption', purpose: :login)
|
13
|
+
def encode(value:, purpose:, expires_in: nil, expires_at: nil, url_safe: false)
|
14
|
+
# expires_in = 5.minutes if purpose==:user_id_ajax
|
15
|
+
params = {}
|
16
|
+
params[:purpose] = purpose if purpose
|
17
|
+
|
18
|
+
params[:expires_at] = expires_at if expires_at
|
19
|
+
|
20
|
+
# expires_in takes precedence
|
21
|
+
if expires_in
|
22
|
+
params[:expires_in] = expires_in
|
23
|
+
params.delete :expires_at if expires_at
|
24
|
+
end
|
25
|
+
|
26
|
+
raise "expires_at && expires_in are both nil" if expires_in.nil? && expires_at.nil?
|
27
|
+
|
28
|
+
log(level: :info, msg: "Encoding [#{value}] with params #{params}")
|
29
|
+
token = verifier.generate(value, params)
|
30
|
+
token = CGI.escape(token) if url_safe
|
31
|
+
token
|
32
|
+
end
|
33
|
+
|
34
|
+
# decoded = Encryption.decode(value: token, purpose: :login)
|
35
|
+
def decode(value:, purpose:, url_safe: false)
|
36
|
+
value = CGI.unescape(value) if url_safe
|
37
|
+
params = {}
|
38
|
+
params[:purpose] = purpose if purpose
|
39
|
+
log(level: :info, msg: "Decoding [#{value}] with params #{params}")
|
40
|
+
# TODO: matt-taylor
|
41
|
+
# Check if the message is valid and untampered with
|
42
|
+
# https://api.rubyonrails.org/classes/ActiveSupport/MessageVerifier.html#method-i-valid_message-3F
|
43
|
+
decoded = verifier.verified(value, params)
|
44
|
+
if decoded.nil?
|
45
|
+
log(level: :warn, msg: "Failed to decode value: value: #{value}, purpose: #{purpose}")
|
46
|
+
end
|
47
|
+
decoded
|
48
|
+
end
|
49
|
+
|
50
|
+
# Encryption.rotate_secret
|
51
|
+
def rotate_secret
|
52
|
+
if old_secret
|
53
|
+
verifier(force: true).rotate(old_secret)
|
54
|
+
else
|
55
|
+
verifier(force: true)
|
56
|
+
end
|
57
|
+
log(level: :info, msg: "Rotating secret for Encryption")
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def verifier(force: false)
|
63
|
+
if force
|
64
|
+
@verifier = ActiveSupport::MessageVerifier.new(next_secret, digest: 'SHA512')
|
65
|
+
end
|
66
|
+
@verifier ||= ActiveSupport::MessageVerifier.new(current_secret, digest: 'SHA512')
|
67
|
+
end
|
68
|
+
|
69
|
+
def old_secret
|
70
|
+
Secret.get_secret_range(name: SECRET_NAME)&.first&.secret
|
71
|
+
end
|
72
|
+
|
73
|
+
def current_secret
|
74
|
+
Secret.get_current_secret(name: SECRET_NAME)&.secret || next_secret
|
75
|
+
end
|
76
|
+
|
77
|
+
def next_secret
|
78
|
+
secret = Secret.update(name: SECRET_NAME, secret: generate_secret)
|
79
|
+
|
80
|
+
secret.secret
|
81
|
+
end
|
82
|
+
|
83
|
+
def generate_secret
|
84
|
+
SecureRandom.hex[0..16]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'velocity_limiter'
|
2
|
+
|
3
|
+
class RailsBase::NameChange < RailsBase::ServiceBase
|
4
|
+
include VelocityLimiter
|
5
|
+
include RailsBase::UserFieldValidators
|
6
|
+
include ActionView::Helpers::DateHelper
|
7
|
+
|
8
|
+
delegate :first_name, to: :context
|
9
|
+
delegate :last_name, to: :context
|
10
|
+
delegate :current_user, to: :context
|
11
|
+
delegate :admin_user_id, to: :context
|
12
|
+
|
13
|
+
def call
|
14
|
+
if admin_user_id
|
15
|
+
log(level: :warn, msg: "ADMIN CHANGE: initiated by user:#{admin_user_id}")
|
16
|
+
else
|
17
|
+
velocity = velocity_limit_reached?
|
18
|
+
if velocity[:reached]
|
19
|
+
context.fail!(message: velocity[:msg])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
original_name = current_user.full_name
|
24
|
+
|
25
|
+
name_validation = validate_full_name?(first_name: first_name, last_name: last_name)
|
26
|
+
|
27
|
+
unless name_validation[:status]
|
28
|
+
errors = name_validation[:errors].values.join('</br>')
|
29
|
+
context.fail!(message: errors)
|
30
|
+
end
|
31
|
+
|
32
|
+
log(level: :info, msg: "Modifying [#{current_user.id}] first name: #{current_user.first_name} -> #{first_name}}")
|
33
|
+
log(level: :info, msg: "Modifying [#{current_user.id}] last name: #{current_user.last_name} -> #{last_name}}")
|
34
|
+
|
35
|
+
if !current_user.update(first_name: first_name, last_name: last_name)
|
36
|
+
context.fail!(message: "Unable to update name. Please try again later")
|
37
|
+
end
|
38
|
+
context.original_name = original_name
|
39
|
+
context.name_change = current_user.reload.full_name
|
40
|
+
|
41
|
+
return if admin_user_id
|
42
|
+
|
43
|
+
RailsBase::EmailVerificationMailer.event(
|
44
|
+
user: current_user,
|
45
|
+
event: "Succesfull name change",
|
46
|
+
msg: "We changed the name on your account from #{original_name} to #{context.name_change}."
|
47
|
+
).deliver_me
|
48
|
+
end
|
49
|
+
|
50
|
+
def velocity_max_in_frame
|
51
|
+
1.hour
|
52
|
+
end
|
53
|
+
|
54
|
+
def velocity_max
|
55
|
+
5
|
56
|
+
end
|
57
|
+
|
58
|
+
def velocity_frame
|
59
|
+
5.hours
|
60
|
+
end
|
61
|
+
|
62
|
+
def cache_key
|
63
|
+
"us.name_change.#{current_user.id}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def validate!
|
67
|
+
raise "Expected first_name to be a String. Received #{first_name.class}" unless first_name.is_a? String
|
68
|
+
raise "Expected last_name to be a String. Received #{last_name.class}" unless last_name.is_a? String
|
69
|
+
raise "Expected current_user to be a User. Received #{current_user.class}" unless current_user.is_a? User
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'interactor'
|
2
|
+
|
3
|
+
class RailsBase::ServiceBase
|
4
|
+
include Interactor
|
5
|
+
include RailsBase::ServiceLogging
|
6
|
+
|
7
|
+
def self.inherited(subclass)
|
8
|
+
# Add the base logging to the subclass.
|
9
|
+
# Since this is done at inheritence time it should always be the first and last hook to run.
|
10
|
+
subclass.around(:service_base_logging)
|
11
|
+
subclass.around(:internal_validate)
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate!
|
15
|
+
# overload from child
|
16
|
+
end
|
17
|
+
|
18
|
+
def internal_validate(interactor)
|
19
|
+
# call validate that is overidden from child
|
20
|
+
begin
|
21
|
+
validate!
|
22
|
+
rescue StandardError => e
|
23
|
+
log(level: :error, msg: "Error during validation. #{e.message}")
|
24
|
+
raise
|
25
|
+
end
|
26
|
+
|
27
|
+
# call interactor
|
28
|
+
interactor.call
|
29
|
+
end
|
30
|
+
|
31
|
+
def service_base_logging(interactor)
|
32
|
+
beginning_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
33
|
+
|
34
|
+
# Pre processing stats
|
35
|
+
log(level: :info, msg: 'Start')
|
36
|
+
|
37
|
+
# Run the job!
|
38
|
+
interactor.call
|
39
|
+
|
40
|
+
# Set status for use in ensure block
|
41
|
+
status = :complete
|
42
|
+
|
43
|
+
# Capture Interactor::Failure for logging purposes, then reraise
|
44
|
+
rescue ::Interactor::Failure
|
45
|
+
# set status for use in ensure block
|
46
|
+
status = :failure
|
47
|
+
|
48
|
+
# Reraise to let the core Interactor handle this
|
49
|
+
raise
|
50
|
+
# Capture exception explicitly to try to logging purposes. Then reraise.
|
51
|
+
rescue ::Exception => e # rubocop:disable Lint/RescueException
|
52
|
+
# set status for use in ensure block
|
53
|
+
status = :error
|
54
|
+
|
55
|
+
# Log error
|
56
|
+
log(level: :error, msg: "Error #{e.class.name}")
|
57
|
+
|
58
|
+
raise
|
59
|
+
ensure
|
60
|
+
# Always log how long it took along with a status
|
61
|
+
finished_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
62
|
+
elapsed = ((finished_time - beginning_time) * 10).round
|
63
|
+
log(level: :info, msg: "Finished with [#{status}]...elapsed #{elapsed}s")
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RailsBase::ServiceLogging
|
2
|
+
def log(level:, msg:)
|
3
|
+
altered_message = "#{log_prefix}: #{msg}"
|
4
|
+
logger.public_send(level, altered_message)
|
5
|
+
end
|
6
|
+
|
7
|
+
def logger
|
8
|
+
con_logger = defined?(context) ? context.loger : nil
|
9
|
+
@logger ||= con_logger || Rails.logger
|
10
|
+
end
|
11
|
+
|
12
|
+
def log_prefix
|
13
|
+
"[#{class_name}-#{service_id}]"
|
14
|
+
end
|
15
|
+
|
16
|
+
def class_name
|
17
|
+
self.class.name
|
18
|
+
end
|
19
|
+
|
20
|
+
def service_id
|
21
|
+
@service_id ||= SecureRandom.alphanumeric(10)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<% if user_signed_in? %>
|
5
|
+
<title><%= RailsBase.config.app.web_name_logged_in(current_user) %></title>
|
6
|
+
<% else %>
|
7
|
+
<title><%= RailsBase.config.app.web_name_logged_out %></title>
|
8
|
+
<% end %>
|
9
|
+
<% unless defined?(@error_page) %>
|
10
|
+
<%= csrf_meta_tags %>
|
11
|
+
<%= csp_meta_tag %>
|
12
|
+
|
13
|
+
<% # dont load turbolinks twice when we render error pages %>
|
14
|
+
<% # casues Uncaught Error: rails-ujs has already been loaded! %>
|
15
|
+
<%= javascript_include_tag 'rails_base/application', 'data-turbolinks-track': 'reload' %>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<%= stylesheet_link_tag 'rails_base/application', media: 'all', 'data-turbolinks-track': 'reload' %>
|
19
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
20
|
+
<link href="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet">
|
21
|
+
<script src="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js"></script>
|
22
|
+
<script src="https://unpkg.com/sticky-table-headers"></script>
|
23
|
+
|
24
|
+
<%=
|
25
|
+
if RailsBase.config.app.favicon_path
|
26
|
+
favicon_link_tag 'rails_base/favicon.ico'
|
27
|
+
end
|
28
|
+
%>
|
29
|
+
</head>
|
30
|
+
|
31
|
+
<body>
|
32
|
+
<script type="text/javascript">
|
33
|
+
// Load at top so available for rest of body oddy
|
34
|
+
function set_cookie(name, value, path ) {
|
35
|
+
path ||= '/'
|
36
|
+
document.cookie = `${name}=${value}; path=${path}`
|
37
|
+
}
|
38
|
+
|
39
|
+
function get_cookie(name) {
|
40
|
+
var cookie = document.cookie
|
41
|
+
return cookie.split('; ').find(row => row.startsWith(`${name}=`)).split('=')[1];
|
42
|
+
}
|
43
|
+
|
44
|
+
function modify_layout(){
|
45
|
+
if(viewport_probable_mobile()){
|
46
|
+
$('#_body_base_container').addClass('p-0')
|
47
|
+
} else {
|
48
|
+
$('#_body_base_container').removeClass('p-0')
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
<% RailsBase::ApplicationController::VIEWPORT_SIZES.each do |name, max_width| %>
|
53
|
+
function viewport_at_least_<%= name %>(){
|
54
|
+
return getViewportWidth() >= <%= max_width || 99_999 %>
|
55
|
+
|
56
|
+
}
|
57
|
+
<% if name == RailsBase::ApplicationController::VIEWPORT_MOBILE_MAX %>
|
58
|
+
<% puts "Rendering #{name} for viewport_probable_mobile" %>
|
59
|
+
|
60
|
+
<% end %>
|
61
|
+
<% end %>
|
62
|
+
|
63
|
+
<%
|
64
|
+
k = RailsBase::ApplicationController::VIEWPORT_MOBILE_MAX
|
65
|
+
size = RailsBase::ApplicationController::VIEWPORT_SIZES[k] || 99_999
|
66
|
+
%>
|
67
|
+
function viewport_probable_mobile(){
|
68
|
+
return getViewportWidth() <= <%= size %>
|
69
|
+
}
|
70
|
+
|
71
|
+
function getViewportWidth() {
|
72
|
+
// https://stackoverflow.com/a/8876069
|
73
|
+
return Math.max(
|
74
|
+
document.documentElement.clientWidth,
|
75
|
+
window.innerWidth || 0
|
76
|
+
)
|
77
|
+
}
|
78
|
+
</script>
|
79
|
+
|
80
|
+
<% rails_base_alert = "alertid-#{(10**10*rand).to_i}" %>
|
81
|
+
<% rails_base_success = "successid-#{(10**10*rand).to_i}"%>
|
82
|
+
<div id='_body_base_container' class="container-fluid" style="overflow-x: hidden !important;">
|
83
|
+
<% if current_user %>
|
84
|
+
<%= render partial: 'rails_base/shared/logged_in_header'%>
|
85
|
+
<% else %>
|
86
|
+
<%= render partial: 'rails_base/shared/logged_out_header'%>
|
87
|
+
<% end %>
|
88
|
+
<% if notice %>
|
89
|
+
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
90
|
+
<%= notice %>
|
91
|
+
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
92
|
+
<span aria-hidden="true">×</span>
|
93
|
+
</button>
|
94
|
+
</div>
|
95
|
+
<% end %>
|
96
|
+
<% if alert %>
|
97
|
+
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
98
|
+
<%= alert %>
|
99
|
+
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
100
|
+
<span aria-hidden="true">×</span>
|
101
|
+
</button>
|
102
|
+
</div>
|
103
|
+
<% end %>
|
104
|
+
<div id='<%= rails_base_success %>' class="alert alert-success alert-dismissible fade show" role="alert" style='display:none'>
|
105
|
+
<div class='text'></div>
|
106
|
+
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
107
|
+
<span aria-hidden="true">×</span>
|
108
|
+
</button>
|
109
|
+
</div>
|
110
|
+
<div id='<%= rails_base_alert %>' class="alert alert-danger alert-dismissible fade show" role="alert" style='display:none'>
|
111
|
+
<div class='text'></div>
|
112
|
+
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
113
|
+
<span aria-hidden="true">×</span>
|
114
|
+
</button>
|
115
|
+
</div>
|
116
|
+
<div class="p-1">
|
117
|
+
<%= yield %>
|
118
|
+
</div>
|
119
|
+
|
120
|
+
<% if RailsBase.appearance.footer.enable? %>
|
121
|
+
<footer id="base-footer" class="text-center">
|
122
|
+
<div class="text-center p-2 <%= appearance_text_class %>">
|
123
|
+
<%= raw RailsBase.appearance.footer.html %>
|
124
|
+
</div>
|
125
|
+
</footer>
|
126
|
+
<% end %>
|
127
|
+
</div>
|
128
|
+
|
129
|
+
<script>
|
130
|
+
modify_layout();
|
131
|
+
function _rails_base_display_success(msg){
|
132
|
+
$('#<%= rails_base_alert %>').hide()
|
133
|
+
$('#<%= rails_base_success %> .text').text(msg)
|
134
|
+
$('#<%= rails_base_success %>').show()
|
135
|
+
};
|
136
|
+
|
137
|
+
function _rails_base_display_alert(msg){
|
138
|
+
$('#<%= rails_base_success %>').hide()
|
139
|
+
$('#<%= rails_base_alert %> .text').text(msg)
|
140
|
+
$('#<%= rails_base_alert %>').show()
|
141
|
+
};
|
142
|
+
|
143
|
+
function _rails_base_hide_displays(){
|
144
|
+
$('#<%= rails_base_alert %>').hide()
|
145
|
+
$('#<%= rails_base_success %>').hide()
|
146
|
+
};
|
147
|
+
|
148
|
+
<%
|
149
|
+
# dont load these when error page happens. The full stack of librarires are not
|
150
|
+
# rendered and jquery/bootstrap are missing
|
151
|
+
%>
|
152
|
+
<% case footer_mode_case %>
|
153
|
+
<% when :sticky %>
|
154
|
+
$('#base-footer').addClass('fixed-bottom')
|
155
|
+
<% when :bottom %>
|
156
|
+
if($('#_body_base_container').height() <= window.innerHeight){
|
157
|
+
$('#base-footer').addClass('fixed-bottom')
|
158
|
+
}
|
159
|
+
<% else %>
|
160
|
+
<% end %>
|
161
|
+
|
162
|
+
<% unless defined?(@error_page) %>
|
163
|
+
$(document).ready(function(){
|
164
|
+
$('[data-toggle="tooltip"]').tooltip();
|
165
|
+
$('.b-tooltip').tooltip();
|
166
|
+
// https://github.com/jmosbech/StickyTableHeaders
|
167
|
+
$('.tableFixHead').stickyTableHeaders();
|
168
|
+
|
169
|
+
// Attempt to set timezone on every request
|
170
|
+
set_cookie('<%= RailsBase::ApplicationController::TIMEZONE_OFFSET_COOKIE %>', new Date().getTimezoneOffset())
|
171
|
+
});
|
172
|
+
<% end %>
|
173
|
+
<% if Rails.env == 'production' %>
|
174
|
+
// Disable console logging
|
175
|
+
console.log = function() {}
|
176
|
+
<% end %>
|
177
|
+
|
178
|
+
function goBack() {
|
179
|
+
window.history.back();
|
180
|
+
}
|
181
|
+
|
182
|
+
$("table select").addClass('w-auto')
|
183
|
+
</script>
|
184
|
+
</body>
|
185
|
+
</html>
|