trusty-cms 7.0.28 → 7.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/Gemfile.lock +15 -1
- data/INSTALL.md +21 -3
- data/README.md +0 -1
- data/app/assets/stylesheets/admin/modules/_buttons.scss +4 -1
- data/app/assets/stylesheets/admin/partials/_forms.scss +4 -0
- data/app/controllers/admin/security_controller.rb +78 -0
- data/app/controllers/admin/sessions_controller.rb +43 -0
- data/app/controllers/admin/two_factor_controller.rb +42 -0
- data/app/controllers/admin/users_controller.rb +9 -0
- data/app/controllers/application_controller.rb +7 -0
- data/app/models/standard_tags.rb +0 -16
- data/app/models/trusty_cms/config.rb +0 -4
- data/app/models/user.rb +1 -1
- data/app/views/admin/configuration/edit.html.haml +0 -7
- data/app/views/admin/configuration/show.html.haml +21 -12
- data/app/views/admin/preferences/edit.html.haml +1 -4
- data/app/views/admin/security/edit.html.haml +57 -0
- data/app/views/{devise → admin}/sessions/new.html.haml +5 -5
- data/app/views/admin/two_factor/show.html.haml +14 -0
- data/app/views/admin/users/_form.html.haml +0 -3
- data/app/views/admin/users/index.html.haml +22 -1
- data/app/views/devise/passwords/edit.html.haml +2 -4
- data/config/initializers/active_record_encryption.rb +5 -0
- data/config/initializers/devise.rb +4 -0
- data/config/initializers/trusty_cms_config.rb +0 -1
- data/config/locales/en.yml +30 -5
- data/config/routes.rb +9 -6
- data/db/migrate/20250502162215_add_devise_two_factor_to_admins.rb +7 -0
- data/lib/generators/trusty_cms/templates/application.rb.erb +1 -1
- data/lib/trusty_cms/admin_ui.rb +12 -7
- data/lib/trusty_cms/engine.rb +0 -3
- data/lib/trusty_cms/version.rb +1 -1
- data/package.json +1 -1
- data/spec/dummy/config/application.rb +1 -1
- data/spec/dummy/config/initializers/trusty_cms_config.rb +0 -1
- data/trusty_cms.gemspec +2 -0
- data/yarn.lock +4 -4
- metadata +38 -18
- data/app/assets/javascripts/rad_social/jquery.validate.min.js +0 -4
- data/app/assets/javascripts/rad_social/rad_ajax_form.js +0 -82
- data/app/assets/javascripts/rad_social/rad_email.js +0 -5
- data/app/assets/javascripts/rad_social/rad_email_form.js +0 -80
- data/app/assets/javascripts/rad_social/rad_email_validator.js +0 -47
- data/app/assets/javascripts/rad_social/rad_widget.js +0 -20
- data/app/assets/stylesheets/rad_social/rad_screen.scss +0 -141
- data/app/controllers/social_mailer_controller.rb +0 -26
- data/app/helpers/rad_social_helper.rb +0 -20
- data/app/mailers/rad_social_mailer.rb +0 -25
- data/app/views/admin/users/_password_fields.html.haml +0 -18
- data/app/views/rad_social_mailer/social_mail.html.haml +0 -5
- data/app/views/rad_social_mailer/social_mail_form.html.haml +0 -39
- data/app/views/widget/_email_form.html.haml +0 -20
- data/app/views/widget/_horizontal_widget.html.haml +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ef6650284d438676ef388a1b002d3ff0acfe81dc068bcfafa9e1cb2814749f9
|
4
|
+
data.tar.gz: e6a980c1afa8435a04314a5b43b6788ecc4f743e9c7c32015245e15e0c8c0804
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33d9139d690d376c8d4547b3d8c20cec750671050a9aa9378a197c3c28ab79cb04fda4403b17f2da86bdad23c5699d3dfdeef5f16db1469ad17c546464df89b8
|
7
|
+
data.tar.gz: f728eb8f4da2af5477ba994c9ccad2d5ac46620f0893295734a66035601c2317dc750985ec3b9d52518c786eebd1f5056a4f8dd301cb2beb4001f82e7d96835c
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
trusty-cms (7.0.
|
4
|
+
trusty-cms (7.0.30)
|
5
5
|
RedCloth (= 4.3.3)
|
6
6
|
activestorage-validator
|
7
7
|
acts_as_list (>= 0.9.5, < 1.3.0)
|
@@ -11,6 +11,7 @@ PATH
|
|
11
11
|
ckeditor (>= 4.2.2, < 4.4.0)
|
12
12
|
delocalize (>= 0.2, < 2.0)
|
13
13
|
devise
|
14
|
+
devise-two-factor
|
14
15
|
drb
|
15
16
|
execjs (~> 2.7)
|
16
17
|
haml (>= 5.0, < 6.0)
|
@@ -32,6 +33,7 @@ PATH
|
|
32
33
|
ransack (~> 4.2.1)
|
33
34
|
rdoc (>= 5.1, < 7.0)
|
34
35
|
roadie-rails
|
36
|
+
rqrcode
|
35
37
|
sass-rails
|
36
38
|
stringex (>= 2.7.1, < 2.9.0)
|
37
39
|
tzinfo (>= 1.2.3, < 2.1.0)
|
@@ -133,6 +135,7 @@ GEM
|
|
133
135
|
xpath (~> 3.2)
|
134
136
|
childprocess (5.1.0)
|
135
137
|
logger (~> 1.5)
|
138
|
+
chunky_png (1.4.0)
|
136
139
|
ckeditor (4.3.0)
|
137
140
|
orm_adapter (~> 0.5.0)
|
138
141
|
terrapin
|
@@ -159,6 +162,11 @@ GEM
|
|
159
162
|
railties (>= 4.1.0)
|
160
163
|
responders
|
161
164
|
warden (~> 1.2.3)
|
165
|
+
devise-two-factor (6.1.0)
|
166
|
+
activesupport (>= 7.0, < 8.1)
|
167
|
+
devise (~> 4.0)
|
168
|
+
railties (>= 7.0, < 8.1)
|
169
|
+
rotp (~> 6.0)
|
162
170
|
diff-lcs (1.5.1)
|
163
171
|
docile (1.4.1)
|
164
172
|
drb (2.2.1)
|
@@ -346,6 +354,11 @@ GEM
|
|
346
354
|
roadie-rails (3.3.0)
|
347
355
|
railties (>= 5.1, < 8.1)
|
348
356
|
roadie (~> 5.0)
|
357
|
+
rotp (6.3.0)
|
358
|
+
rqrcode (3.1.0)
|
359
|
+
chunky_png (~> 1.0)
|
360
|
+
rqrcode_core (~> 2.0)
|
361
|
+
rqrcode_core (2.0.0)
|
349
362
|
rspec-core (3.13.2)
|
350
363
|
rspec-support (~> 3.13.0)
|
351
364
|
rspec-expectations (3.13.3)
|
@@ -430,6 +443,7 @@ DEPENDENCIES
|
|
430
443
|
activestorage-validator
|
431
444
|
acts_as_list
|
432
445
|
database_cleaner
|
446
|
+
devise-two-factor
|
433
447
|
factory_bot_rails (= 6.4.4)
|
434
448
|
file_validators
|
435
449
|
launchy (~> 3.0.1)
|
data/INSTALL.md
CHANGED
@@ -6,8 +6,9 @@ From within the directory containing your TrustyCMS instance:
|
|
6
6
|
|
7
7
|
2. Add the following gems to your Gemfile:
|
8
8
|
|
9
|
-
- gem 'trusty-cms'
|
10
|
-
- gem 'rails-observers'
|
9
|
+
- gem 'trusty-cms'
|
10
|
+
- gem 'rails-observers'
|
11
|
+
- gem 'devise-two-factor'
|
11
12
|
|
12
13
|
3. Run `bundle install`
|
13
14
|
|
@@ -20,5 +21,22 @@ From within the directory containing your TrustyCMS instance:
|
|
20
21
|
|
21
22
|
7. Add utf8 encoding to your db.yml
|
22
23
|
|
23
|
-
8.
|
24
|
+
8. Set up encryption keys required for Rails’ native encryption (used by features like two-factor authentication):
|
25
|
+
|
26
|
+
- Run the encryption initializer command:
|
27
|
+
|
28
|
+
```bash
|
29
|
+
./bin/rails db:encryption:init
|
30
|
+
```
|
31
|
+
|
32
|
+
- This will output three secrets. Copy the values and set them as environment variables in your preferred environment file (e.g., `.env`, `.env.development`, or via system environment settings):
|
33
|
+
|
34
|
+
```env
|
35
|
+
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY
|
36
|
+
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY
|
37
|
+
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT
|
38
|
+
```
|
39
|
+
- **Important**: Use different keys for each environment (development, test, production) unless two environments (e.g., development and staging) share a database — in that case, they **must** use the same keys.
|
40
|
+
|
41
|
+
9. Run `bundle exec rake db:setup`, `bundle exec rake trusty_cms:install:migrations`, then
|
24
42
|
`bundle exec rake db:bootstrap`.
|
data/README.md
CHANGED
@@ -26,7 +26,6 @@ TrustyCMS features:
|
|
26
26
|
* An advanced plugin system
|
27
27
|
* Asset management & searching
|
28
28
|
* Serve multiple sites (domains) from a single instance
|
29
|
-
* Social sharing buttons
|
30
29
|
* Reusable bits of content (Snippets)
|
31
30
|
* Allows Rails controllers/actions to use Trusty CMS layouts as their "layout"
|
32
31
|
* Operates in two modes: dev and production depending on the URL
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'rqrcode'
|
2
|
+
|
3
|
+
class Admin::SecurityController < ApplicationController
|
4
|
+
before_action :authenticate_user!
|
5
|
+
before_action :set_user
|
6
|
+
before_action :set_template_names
|
7
|
+
before_action :ensure_otp_secret, only: %i[show edit]
|
8
|
+
before_action :set_two_factor_variables, only: %i[show edit]
|
9
|
+
|
10
|
+
def show
|
11
|
+
set_standard_body_style
|
12
|
+
render :edit
|
13
|
+
end
|
14
|
+
|
15
|
+
def edit
|
16
|
+
render
|
17
|
+
end
|
18
|
+
|
19
|
+
def update
|
20
|
+
if @user.update(security_params)
|
21
|
+
sign_out(@user)
|
22
|
+
redirect_to new_user_session_path, notice: t('security_controller.password_updated')
|
23
|
+
else
|
24
|
+
flash[:error] = t('security_controller.error_updating_password')
|
25
|
+
render :edit
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def verify_two_factor
|
30
|
+
if @user.validate_and_consume_otp!(params[:otp_attempt])
|
31
|
+
@user.update!(otp_required_for_login: true)
|
32
|
+
redirect_to admin_security_path, notice: t('security_controller.two_factor_enabled')
|
33
|
+
else
|
34
|
+
flash[:error] = t('security_controller.two_factor_invalid_code')
|
35
|
+
redirect_to admin_security_path
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def disable_two_factor
|
40
|
+
if @user.update(otp_required_for_login: false, otp_secret: nil)
|
41
|
+
redirect_to admin_security_path, notice: t('security_controller.two_factor_disabled')
|
42
|
+
else
|
43
|
+
flash[:error] = t('security_controller.two_factor_disabled_error')
|
44
|
+
redirect_to admin_security_path
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def set_user
|
51
|
+
@user = current_user
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_template_names
|
55
|
+
@controller_name = 'user'
|
56
|
+
@template_name = 'security'
|
57
|
+
end
|
58
|
+
|
59
|
+
def ensure_otp_secret
|
60
|
+
return if @user.otp_secret.present?
|
61
|
+
|
62
|
+
@user.update!(otp_secret: User.generate_otp_secret)
|
63
|
+
end
|
64
|
+
|
65
|
+
def set_two_factor_variables
|
66
|
+
@two_factor_enabled = @user.otp_required_for_login
|
67
|
+
|
68
|
+
return if @two_factor_enabled
|
69
|
+
|
70
|
+
otp_uri = @user.otp_provisioning_uri(@user.email, issuer: 'TrustyCMS')
|
71
|
+
qr = RQRCode::QRCode.new(otp_uri)
|
72
|
+
@qr_png_data = qr.as_png(size: 200).to_data_url
|
73
|
+
end
|
74
|
+
|
75
|
+
def security_params
|
76
|
+
params.require(:user).permit(:password, :password_confirmation)
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class Admin::SessionsController < Devise::SessionsController
|
2
|
+
def create
|
3
|
+
user = find_user
|
4
|
+
|
5
|
+
if authenticated?(user)
|
6
|
+
handle_successful_authentication(user)
|
7
|
+
else
|
8
|
+
handle_failed_authentication
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def find_user
|
15
|
+
User.find_by(email: params[:user][:email])
|
16
|
+
end
|
17
|
+
|
18
|
+
def authenticated?(user)
|
19
|
+
user&.valid_password?(params[:user][:password])
|
20
|
+
end
|
21
|
+
|
22
|
+
def handle_successful_authentication(user)
|
23
|
+
if user.otp_required_for_login
|
24
|
+
start_two_factor_session(user)
|
25
|
+
redirect_to admin_two_factor_path
|
26
|
+
else
|
27
|
+
sign_in(:user, user)
|
28
|
+
redirect_to after_sign_in_path_for(user)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def handle_failed_authentication
|
33
|
+
self.resource = resource_class.new(sign_in_params)
|
34
|
+
clean_up_passwords(resource)
|
35
|
+
flash.now[:alert] = t('invalid_email_or_password')
|
36
|
+
render :new
|
37
|
+
end
|
38
|
+
|
39
|
+
def start_two_factor_session(user)
|
40
|
+
session[:pre_2fa_user_id] = user.id
|
41
|
+
session[:pre_2fa_started_at] = Time.current.to_i
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Admin::TwoFactorController < ApplicationController
|
2
|
+
skip_before_action :authenticate_user!
|
3
|
+
before_action :load_pre_2fa_user
|
4
|
+
|
5
|
+
MAX_2FA_SESSION_DURATION = 5.minutes.freeze
|
6
|
+
|
7
|
+
def show; end
|
8
|
+
|
9
|
+
def create
|
10
|
+
if @user.validate_and_consume_otp!(params[:otp_attempt])
|
11
|
+
session.delete(:pre_2fa_user_id)
|
12
|
+
session.delete(:pre_2fa_started_at)
|
13
|
+
sign_in(:user, @user)
|
14
|
+
redirect_to after_sign_in_path_for(@user)
|
15
|
+
else
|
16
|
+
reset_session
|
17
|
+
redirect_to new_user_session_path, alert: t('two_factor_controller.invalid_code')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def load_pre_2fa_user
|
24
|
+
if current_user
|
25
|
+
redirect_to after_sign_in_path_for(current_user) and return
|
26
|
+
end
|
27
|
+
|
28
|
+
@user = User.find_by(id: session[:pre_2fa_user_id])
|
29
|
+
|
30
|
+
if !@user&.otp_required_for_login || session_expired?
|
31
|
+
reset_session
|
32
|
+
redirect_to new_user_session_path, alert: t('two_factor_controller.session_expired')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def session_expired?
|
37
|
+
started_at = session[:pre_2fa_started_at]
|
38
|
+
return true unless started_at
|
39
|
+
|
40
|
+
Time.current.to_i - started_at > MAX_2FA_SESSION_DURATION
|
41
|
+
end
|
42
|
+
end
|
@@ -45,6 +45,15 @@ class Admin::UsersController < Admin::ResourceController
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
def disable_2fa
|
49
|
+
user = User.find(params[:id])
|
50
|
+
user.update(
|
51
|
+
otp_required_for_login: false,
|
52
|
+
otp_secret: nil,
|
53
|
+
)
|
54
|
+
redirect_to admin_users_path
|
55
|
+
end
|
56
|
+
|
48
57
|
private
|
49
58
|
|
50
59
|
def user_params
|
@@ -6,6 +6,7 @@ class ApplicationController < ActionController::Base
|
|
6
6
|
|
7
7
|
protect_from_forgery with: :exception
|
8
8
|
before_action :authenticate_user!
|
9
|
+
before_action :configure_permitted_parameters, if: :devise_controller?
|
9
10
|
before_action :set_timezone
|
10
11
|
before_action :set_user_locale
|
11
12
|
before_action :set_javascripts_and_stylesheets
|
@@ -44,6 +45,12 @@ class ApplicationController < ActionController::Base
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
48
|
+
protected
|
49
|
+
|
50
|
+
def configure_permitted_parameters
|
51
|
+
devise_parameter_sanitizer.permit(:sign_in, keys: [:otp_attempt])
|
52
|
+
end
|
53
|
+
|
47
54
|
private
|
48
55
|
|
49
56
|
def set_mailer
|
data/app/models/standard_tags.rb
CHANGED
@@ -931,22 +931,6 @@ module StandardTags
|
|
931
931
|
end
|
932
932
|
end
|
933
933
|
|
934
|
-
desc 'Widget of sharing icons'
|
935
|
-
tag 'rad_share_widget' do |tag|
|
936
|
-
attributes = tag.attr.to_options
|
937
|
-
url = attributes[:url].nil? ? request.url : attributes[:url]
|
938
|
-
message = attributes[:message].nil? ? "Check out #{tag.locals.page.title}." : attributes[:message]
|
939
|
-
email_subject = attributes[:email_subject].nil? ? tag.locals.page.title : attributes[:email_subject]
|
940
|
-
email_message = attributes[:email_message].nil? ? "I thought you might be interested in this: #{url}" : "#{attributes[:email_message]} #{url}"
|
941
|
-
email_action_url = attributes[:email_action_url].nil? ? '/rad_social/mail' : attributes[:email_action_url]
|
942
|
-
request.env['action_controller.instance'].render_to_string partial: 'widget/horizontal_widget',
|
943
|
-
locals: { url: url,
|
944
|
-
message: message,
|
945
|
-
email_subject: email_subject,
|
946
|
-
email_message: email_message,
|
947
|
-
email_action_url: email_action_url }
|
948
|
-
end
|
949
|
-
|
950
934
|
private
|
951
935
|
|
952
936
|
def render_children_with_pagination(tag, opts = {})
|
@@ -145,10 +145,6 @@ module TrustyCms
|
|
145
145
|
@default_settings ||= %w{defaults.locale defaults.page.filter defaults.page.parts defaults.page.fields defaults.page.status}
|
146
146
|
end
|
147
147
|
|
148
|
-
def user_settings
|
149
|
-
@user_settings ||= ['user.allow_password_reset?']
|
150
|
-
end
|
151
|
-
|
152
148
|
# A convenient drying method for specifying a prefix and options common to several settings.
|
153
149
|
#
|
154
150
|
# TrustyCms.config do |config|
|
data/app/models/user.rb
CHANGED
@@ -3,7 +3,7 @@ class User < ActiveRecord::Base
|
|
3
3
|
self.table_name = 'admins'
|
4
4
|
|
5
5
|
# :confirmable, :lockable, :timeoutable and :omniauthable
|
6
|
-
devise :
|
6
|
+
devise :two_factor_authenticatable, :registerable,
|
7
7
|
:recoverable, :rememberable, :trackable, :validatable
|
8
8
|
|
9
9
|
alias_attribute :created_by_id, :id
|
@@ -23,13 +23,6 @@
|
|
23
23
|
%p
|
24
24
|
= edit_config default_setting
|
25
25
|
|
26
|
-
- form.edit_users do
|
27
|
-
%fieldset
|
28
|
-
%h4 Passwords
|
29
|
-
- TrustyCms.config.user_settings.each do |user_setting|
|
30
|
-
%p
|
31
|
-
= edit_config user_setting
|
32
|
-
|
33
26
|
- render_region :form_bottom do |form_bottom|
|
34
27
|
- form_bottom.edit_buttons do
|
35
28
|
.buttons
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
%fieldset
|
2
2
|
- render_region :user do |user|
|
3
3
|
- user.preferences do
|
4
4
|
%h3
|
@@ -13,10 +13,6 @@
|
|
13
13
|
= t('email_address')
|
14
14
|
%span.uri
|
15
15
|
= current_user.email
|
16
|
-
%p.ruled
|
17
|
-
%label
|
18
|
-
= t('password')
|
19
|
-
%big •••••
|
20
16
|
%p.ruled
|
21
17
|
%label
|
22
18
|
= t('language')
|
@@ -25,7 +21,25 @@
|
|
25
21
|
.actions
|
26
22
|
= button_to t("edit_preferences"), edit_admin_user_path(current_user), :method => :get
|
27
23
|
|
28
|
-
|
24
|
+
%fieldset
|
25
|
+
- render_region :user do |user|
|
26
|
+
- user.preferences do
|
27
|
+
%h3
|
28
|
+
= t('security')
|
29
|
+
%p.ruled
|
30
|
+
%label
|
31
|
+
= t('password')
|
32
|
+
%span.value
|
33
|
+
••••••••••••••••••
|
34
|
+
%p.ruled
|
35
|
+
%label
|
36
|
+
= t('two_factor_authentication')
|
37
|
+
%span
|
38
|
+
= current_user.otp_required_for_login ? t('enabled') : t('disabled')
|
39
|
+
.actions
|
40
|
+
= button_to t('edit_security_settings'), admin_security_path, :method => :get
|
41
|
+
|
42
|
+
%fieldset
|
29
43
|
- render_region :trusty_config do |config|
|
30
44
|
- config.site do
|
31
45
|
%h3
|
@@ -40,11 +54,6 @@
|
|
40
54
|
%p.ruled
|
41
55
|
= show_config default_setting
|
42
56
|
|
43
|
-
- config.users do
|
44
|
-
%h4 Passwords
|
45
|
-
- TrustyCms.config.user_settings.each do |user_setting|
|
46
|
-
%p.ruled
|
47
|
-
= show_config user_setting
|
48
57
|
- if current_user.admin?
|
49
58
|
.actions
|
50
|
-
= button_to t("edit_configuration"), edit_admin_configuration_path, :method => :get
|
59
|
+
= button_to t("edit_configuration"), edit_admin_configuration_path, :method => :get
|
@@ -27,12 +27,9 @@
|
|
27
27
|
= f.label :email, t("email_address"), :class => 'optional'
|
28
28
|
= f.text_field 'email', :class => 'textbox', :maxlength => 255
|
29
29
|
|
30
|
-
- form.edit_password do
|
31
|
-
= render 'admin/users/password_fields', :f => f
|
32
|
-
|
33
30
|
- render_region :form_bottom, :locals => {:f => f} do |form_bottom|
|
34
31
|
- form_bottom.edit_buttons do
|
35
32
|
.buttons
|
36
33
|
= save_model_button @user
|
37
34
|
= t('or')
|
38
|
-
= link_to t('cancel'),
|
35
|
+
= link_to t('cancel'), admin_configuration_path, class: 'alt'
|
@@ -0,0 +1,57 @@
|
|
1
|
+
- @page_title = @user.name + ' - Security'
|
2
|
+
- body_classes << 'edit_security'
|
3
|
+
|
4
|
+
- render_region :main do |main|
|
5
|
+
- main.edit_header do
|
6
|
+
%h1
|
7
|
+
= t('security')
|
8
|
+
|
9
|
+
- main.edit_form do
|
10
|
+
%fieldset
|
11
|
+
%h3
|
12
|
+
= t('change_password')
|
13
|
+
= form_for @user, :url => admin_security_path, :html => { :method => :put, 'data-onsubmit_status' => "#{t('saving_changes')}…" } do |f|
|
14
|
+
- render_region :form, :locals => {:f => f} do |form|
|
15
|
+
- form.edit_password do
|
16
|
+
%fieldset#change-password
|
17
|
+
%p
|
18
|
+
= f.label :password, t('new_password')
|
19
|
+
= f.password_field 'password', :value => '', :maxlength => 40, :autocomplete => 'new-password'
|
20
|
+
%p
|
21
|
+
= f.label :password_confirmation, t('password_confirmation')
|
22
|
+
= f.password_field 'password_confirmation', :value => '', :maxlength => 40, :autocomplete => 'new-password'
|
23
|
+
|
24
|
+
- render_region :form_bottom, :locals => {:f => f} do |form_bottom|
|
25
|
+
- form_bottom.edit_buttons do
|
26
|
+
.buttons
|
27
|
+
= save_model_button @user
|
28
|
+
|
29
|
+
- main.two_factor do
|
30
|
+
%fieldset
|
31
|
+
%h3
|
32
|
+
= t('two_factor_authentication')
|
33
|
+
|
34
|
+
- if @two_factor_enabled
|
35
|
+
%fieldset
|
36
|
+
%p
|
37
|
+
= t('security_controller.two_factor_is_enabled')
|
38
|
+
= button_to t('disable'),
|
39
|
+
disable_two_factor_admin_security_path,
|
40
|
+
method: :post,
|
41
|
+
data: { confirm: t('security_controller.two_factor_disable_confirm') },
|
42
|
+
class: "button button-margin-top"
|
43
|
+
- else
|
44
|
+
%fieldset
|
45
|
+
%p
|
46
|
+
= t('security_controller.scan_qr_instructions')
|
47
|
+
= image_tag @qr_png_data, alt: t('security_controller.qr_alt')
|
48
|
+
%p
|
49
|
+
= t('security_controller.manual_key_instructions')
|
50
|
+
%strong= @user.otp_secret
|
51
|
+
|
52
|
+
.form-margin-top
|
53
|
+
= form_with url: verify_two_factor_admin_security_path, method: :post do |form|
|
54
|
+
%div
|
55
|
+
= form.label :otp_attempt, t('security_controller.enter_qr_code')
|
56
|
+
= form.text_field :otp_attempt, autofocus: true, size: 6, maxlength: 6
|
57
|
+
= form.submit t('security_controller.verify_and_enable')
|
@@ -1,10 +1,10 @@
|
|
1
1
|
- body_classes << 'login_form'
|
2
2
|
.login-form-content
|
3
3
|
.visual
|
4
|
-
= image_tag('/assets/admin/default_safe_login.svg', alt: '
|
4
|
+
= image_tag('/assets/admin/default_safe_login.svg', alt: 'Web browser with padlock on top')
|
5
5
|
.login
|
6
|
-
%h1 Log
|
7
|
-
= form_for(resource, as: resource_name, url:
|
6
|
+
%h1 Log In
|
7
|
+
= form_for(resource, as: resource_name, url: user_session_path) do |f|
|
8
8
|
.field
|
9
9
|
= f.label :email
|
10
10
|
= f.email_field :email, autofocus: true, autocomplete: 'email'
|
@@ -18,8 +18,8 @@
|
|
18
18
|
Remember Me
|
19
19
|
%br
|
20
20
|
.actions
|
21
|
-
= f.submit 'Log
|
21
|
+
= f.submit 'Log In'
|
22
22
|
- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations'
|
23
23
|
= link_to 'Forgot your password?', new_password_path(resource_name)
|
24
24
|
- if flash.alert
|
25
|
-
.error= flash.alert
|
25
|
+
.error= flash.alert
|
@@ -0,0 +1,14 @@
|
|
1
|
+
- body_classes << 'login_form'
|
2
|
+
.login-form-content
|
3
|
+
.visual
|
4
|
+
= image_tag('/assets/admin/default_safe_login.svg', alt: 'Web browser with padlock on top')
|
5
|
+
.login
|
6
|
+
%h1
|
7
|
+
= t('two_factor_authentication')
|
8
|
+
= form_with url: admin_two_factor_path, method: :post, local: true do |form|
|
9
|
+
.field
|
10
|
+
= form.label :otp_attempt, t('security_controller.enter_qr_code')
|
11
|
+
= form.text_field :otp_attempt, autofocus: true, maxlength: 6, size: 6
|
12
|
+
%br
|
13
|
+
.actions
|
14
|
+
= form.submit t('security_controller.verify_code')
|
@@ -15,9 +15,6 @@
|
|
15
15
|
= f.label :email, t('email_address') , :class => 'optional'
|
16
16
|
= f.text_field 'email', :class => 'textbox', :maxlength => 255
|
17
17
|
|
18
|
-
- form.edit_password do
|
19
|
-
= render 'password_fields', :f => f
|
20
|
-
|
21
18
|
- form.edit_roles do
|
22
19
|
- if current_user.admin?
|
23
20
|
%fieldset.multi_option
|
@@ -11,8 +11,14 @@
|
|
11
11
|
%th.user== #{t('name')} / #{t('username')}
|
12
12
|
- thead.roles_header do
|
13
13
|
%th.roles= t('roles')
|
14
|
+
- thead.two_factor_status_header do
|
15
|
+
%th.two_factor_status
|
16
|
+
= t('two_factor_authentication_status')
|
17
|
+
- thead.disable_two_factor_header do
|
18
|
+
%th.disable_two_factor
|
19
|
+
Disable 2FA
|
14
20
|
- thead.actions_header do
|
15
|
-
%th.actions
|
21
|
+
%th.actions= t('modify')
|
16
22
|
- thead.last_sign_in_at_header do
|
17
23
|
%th.last_sign_in_at= "Last Sign In"
|
18
24
|
%tbody
|
@@ -24,6 +30,21 @@
|
|
24
30
|
= link_to user.name, edit_admin_user_url(user)
|
25
31
|
- tbody.roles_cell do
|
26
32
|
%td.roles= roles(user)
|
33
|
+
- tbody.two_factor_status_cell do
|
34
|
+
%td.two_factor
|
35
|
+
- if user.otp_required_for_login
|
36
|
+
= t('enabled')
|
37
|
+
- else
|
38
|
+
= t('disabled')
|
39
|
+
- tbody.disable_two_factor_cell do
|
40
|
+
%td.actions
|
41
|
+
- if user.otp_required_for_login
|
42
|
+
- if !current_user.admin?
|
43
|
+
%span.action.disabled
|
44
|
+
%i.fas.fa-minus-circle
|
45
|
+
Disable
|
46
|
+
- else
|
47
|
+
= button_to 'Disable', disable_2fa_admin_user_path(user), method: :patch, data: { confirm: "Are you sure you want to disable 2FA for this user?" }
|
27
48
|
- tbody.actions_cell do
|
28
49
|
%td.actions
|
29
50
|
- if !current_user.admin?
|
@@ -8,16 +8,14 @@
|
|
8
8
|
= f.hidden_field :reset_password_token
|
9
9
|
.field
|
10
10
|
= f.label :password, 'New password'
|
11
|
-
%br/
|
12
11
|
- if @minimum_password_length
|
13
12
|
%em
|
14
13
|
(#{@minimum_password_length} characters minimum)
|
15
|
-
|
14
|
+
|
16
15
|
= f.password_field :password, autofocus: true, autocomplete: 'new-password'
|
16
|
+
%br/
|
17
17
|
.field
|
18
18
|
= f.label :password_confirmation, 'Confirm new password'
|
19
|
-
%br/
|
20
19
|
= f.password_field :password_confirmation, autocomplete: 'new-password'
|
21
20
|
.actions
|
22
21
|
= f.submit 'Change my password'
|
23
|
-
= render 'devise/shared/links'
|