adminos 1.0.0.pre.rc.2 → 1.0.0.pre.rc.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -3
  3. data/README.md +26 -0
  4. data/adminos.gemspec +2 -2
  5. data/app/inputs/cropp_input.rb +13 -1
  6. data/app/inputs/filter_inputs/boolean_input.rb +18 -0
  7. data/app/inputs/filter_inputs/date_range_input.rb +36 -0
  8. data/app/inputs/filter_inputs/numeric_input.rb +40 -0
  9. data/app/inputs/filter_inputs/string_input.rb +40 -0
  10. data/lib/adminos.rb +23 -3
  11. data/lib/adminos/configuration.rb +9 -0
  12. data/lib/adminos/controllers/filters.rb +20 -0
  13. data/lib/adminos/controllers/resource.rb +18 -11
  14. data/lib/adminos/extensions/simple_form.rb +12 -0
  15. data/lib/adminos/features/search/elastic.rb +46 -0
  16. data/lib/adminos/features/search/pg_search.rb +49 -0
  17. data/lib/adminos/filters/forms.rb +55 -0
  18. data/lib/adminos/form_builder.rb +11 -0
  19. data/lib/adminos/helpers/models/searchable.rb +9 -0
  20. data/lib/adminos/helpers/view.rb +35 -0
  21. data/lib/generators/adminos/adminos_generator.rb +10 -7
  22. data/lib/generators/adminos/feedback_generator.rb +39 -0
  23. data/lib/generators/adminos/i18n_generator.rb +16 -4
  24. data/lib/generators/adminos/install_generator.rb +22 -0
  25. data/lib/generators/adminos/profile_generator.rb +34 -0
  26. data/lib/generators/adminos/search_generator.rb +38 -0
  27. data/lib/generators/adminos/two_factor_auth_generator.rb +81 -0
  28. data/lib/generators/templates/adminos/fields.slim +1 -1
  29. data/lib/generators/templates/adminos/locales/locale_fields.slim +7 -4
  30. data/lib/generators/templates/adminos/locales/model.rb.erb +2 -3
  31. data/lib/generators/templates/ci/.gitlab-ci.yml +1 -1
  32. data/lib/generators/templates/feedback/auto/app/controllers/admin/feedbacks_controller.rb +17 -0
  33. data/lib/generators/templates/feedback/auto/app/controllers/feedbacks_controller.rb +11 -0
  34. data/lib/generators/templates/feedback/auto/app/models/feedback.rb +6 -0
  35. data/lib/generators/templates/feedback/auto/app/views/admin/feedbacks/_fields.slim +5 -0
  36. data/lib/generators/templates/feedback/auto/app/views/admin/feedbacks/index.slim +28 -0
  37. data/lib/generators/templates/feedback/feedbacks_migration.rb +13 -0
  38. data/lib/generators/templates/field/locales/locale_fields.slim +1 -1
  39. data/lib/generators/templates/field/locales/model.rb.erb +2 -3
  40. data/lib/generators/templates/i18n/Gemfile +6 -1
  41. data/lib/generators/templates/i18n/auto/app/validators/locale_validator.rb +5 -1
  42. data/lib/generators/templates/i18n/auto/app/views/admin/base/_pills.slim +1 -5
  43. data/lib/generators/templates/i18n/auto/app/views/admin/pages/_locale_fields.slim +5 -5
  44. data/lib/generators/templates/i18n/auto/config/initializers/mobility.rb +92 -0
  45. data/lib/generators/templates/i18n/page.rb +2 -2
  46. data/lib/generators/templates/install/Gemfile +3 -5
  47. data/lib/generators/templates/install/README.md +22 -0
  48. data/lib/generators/templates/install/auto/Capfile +12 -2
  49. data/lib/generators/templates/install/auto/app/views/admin/base/_form.slim +1 -1
  50. data/lib/generators/templates/install/auto/app/views/shared/helpers/admin/_collection_header.slim +2 -0
  51. data/lib/generators/templates/install/auto/app/views/shared/helpers/admin/_object_link_new.slim +1 -1
  52. data/lib/generators/templates/install/auto/config/deploy/staging.rb +15 -10
  53. data/lib/generators/templates/install/auto/config/deploy/{shared → templates}/database.yml.erb +1 -1
  54. data/lib/generators/templates/install/auto/config/deploy/templates/nginx_conf.erb +96 -0
  55. data/lib/generators/templates/install/auto/config/deploy/templates/puma.rb.erb +52 -0
  56. data/lib/generators/templates/install/auto/config/environments/staging.rb +1 -1
  57. data/lib/generators/templates/install/auto/config/initializers/adminos.rb +3 -0
  58. data/lib/generators/templates/install/auto/config/locales/adminos.ru.yml +18 -0
  59. data/lib/generators/templates/install/auto/config/schedule.rb +0 -0
  60. data/lib/generators/templates/install/auto/config/systemd/puma.service.erb +19 -0
  61. data/lib/generators/templates/install/auto/config/systemd/sidekiq.service.erb +21 -0
  62. data/lib/generators/templates/install/auto/lib/capistrano/{template.rb → smart_templates.rb} +17 -3
  63. data/lib/generators/templates/install/auto/lib/capistrano/tasks/setup_config.cap +27 -20
  64. data/lib/generators/templates/install/deploy.rb.erb +13 -12
  65. data/lib/generators/templates/profile/auto/app/controllers/admin/profiles_controller.rb +26 -0
  66. data/lib/generators/templates/profile/auto/app/views/admin/profiles/edit.slim +17 -0
  67. data/lib/generators/templates/two_facto_auth/Gemfile +1 -0
  68. data/lib/generators/templates/two_facto_auth/auto/app/controllers/concerns/authenticates_with_two_factor.rb +36 -0
  69. data/lib/generators/templates/two_facto_auth/auto/app/controllers/users/sessions_controller.rb +5 -0
  70. data/lib/generators/templates/two_facto_auth/auto/app/views/admin/profiles/_2fa.slim +24 -0
  71. data/lib/generators/templates/two_facto_auth/auto/app/views/devise/sessions/two_factor.slim +15 -0
  72. data/spec/lib/generators/adminos/feedback_generator_rspec.rb +50 -0
  73. data/spec/lib/generators/adminos/install_generator_rspec.rb +6 -7
  74. data/spec/lib/generators/adminos/profile_generator_rspec.rb +33 -0
  75. data/spec/lib/generators/adminos/search_generator.rb +20 -0
  76. data/spec/lib/generators/adminos/two_factor_auth_generator_rspec.rb +61 -0
  77. data/spec/spec_helper.rb +4 -0
  78. data/spec/support/shared/generator.rb +1 -1
  79. metadata +55 -22
  80. data/bin/rspec +0 -29
  81. data/lib/adminos/extensions/globalize_actiontext.rb +0 -28
  82. data/lib/adminos/extensions/globalize_fields.rb +0 -19
  83. data/lib/generators/templates/adminos/locales/migration.rb.erb +0 -18
  84. data/lib/generators/templates/field/locales/migration.rb.erb +0 -13
  85. data/lib/generators/templates/i18n/add_translation_table_to_page.rb +0 -15
  86. data/lib/generators/templates/i18n/auto/config/initializers/globalize_fields.rb +0 -1
  87. data/lib/generators/templates/install/auto/config/deploy/shared/nginx.conf.erb +0 -28
  88. data/lib/generators/templates/install/auto/config/deploy/shared/unicorn.rb.erb +0 -35
  89. data/lib/generators/templates/install/auto/lib/capistrano/substitute_strings.rb +0 -12
  90. data/package-lock.json +0 -3
@@ -0,0 +1,96 @@
1
+ upstream puma_<%= fetch(:nginx_upstream_name) %> { <%
2
+ @backends = [fetch(:puma_bind)].flatten.map do |m|
3
+ etype, address = /(tcp|unix|ssl):\/{1,2}(.+)/.match(m).captures
4
+ if etype == 'unix'
5
+ "server #{etype}:#{address} #{fetch(:nginx_socket_flags)};"
6
+ else
7
+ "server #{address.gsub(/0\.0\.0\.0(.+)/, "127.0.0.1\\1")} #{fetch(:nginx_http_flags)};"
8
+ end
9
+ end
10
+ %><% @backends.each do |server| %>
11
+ <%= server %><% end %>
12
+ }
13
+ <% if fetch(:nginx_use_ssl) -%>
14
+ server {
15
+ listen 80;
16
+ server_name <%= fetch(:nginx_server_name) %>;
17
+ return 301 https://$host$1$request_uri;
18
+ }
19
+ <% end -%>
20
+
21
+ server {
22
+ <% if fetch(:nginx_use_ssl) -%>
23
+ listen 443;
24
+ ssl on;
25
+ <% if fetch(:nginx_ssl_certificate) -%>
26
+ ssl_certificate <%= fetch(:nginx_ssl_certificate) %>;
27
+ <% else -%>
28
+ ssl_certificate /etc/letsencrypt/live/<%= fetch(:domain) %>/fullchain.pem;
29
+ <% end -%>
30
+ <% if fetch(:nginx_ssl_certificate_key) -%>
31
+ ssl_certificate_key <%= fetch(:nginx_ssl_certificate_key) %>;
32
+ <% else -%>
33
+ ssl_certificate_key /etc/letsencrypt/live/<%= fetch(:domain) %>/privkey.pem;
34
+ <% end -%>
35
+ include /etc/letsencrypt/options-ssl-nginx.conf;
36
+ ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
37
+ <% else -%>
38
+ listen 80;
39
+ <% end -%>
40
+ server_name <%= fetch(:nginx_server_name) %>;
41
+ root <%= current_path %>/public;
42
+ try_files $uri/index.html $uri @puma_<%= fetch(:nginx_upstream_name) %>;
43
+
44
+ client_max_body_size 4G;
45
+ keepalive_timeout 10;
46
+
47
+ error_page 500 502 504 /500.html;
48
+ error_page 503 @503;
49
+
50
+ location @puma_<%= fetch(:nginx_upstream_name) %> {
51
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
52
+ proxy_set_header Host $host;
53
+ proxy_redirect off;
54
+ proxy_set_header Upgrade $http_upgrade;
55
+ proxy_set_header Connection "Upgrade";
56
+ <% if fetch(:nginx_use_ssl) -%>
57
+ proxy_set_header X-Forwarded-Proto https;
58
+ <% else -%>
59
+ proxy_set_header X-Forwarded-Proto http;
60
+ <% end -%>
61
+ proxy_pass http://puma_<%= fetch(:nginx_upstream_name) %>;
62
+ # limit_req zone=one;
63
+ access_log <%= shared_path %>/log/nginx.access.log;
64
+ error_log <%= shared_path %>/log/nginx.error.log;
65
+ }
66
+
67
+ location ^~ /assets/ {
68
+ gzip_static on;
69
+ expires max;
70
+ add_header Cache-Control public;
71
+ }
72
+
73
+ location = /50x.html {
74
+ root html;
75
+ }
76
+
77
+ location = /404.html {
78
+ root html;
79
+ }
80
+
81
+ location @503 {
82
+ error_page 405 = /system/maintenance.html;
83
+ if (-f $document_root/system/maintenance.html) {
84
+ rewrite ^(.*)$ /system/maintenance.html break;
85
+ }
86
+ rewrite ^(.*)$ /503.html break;
87
+ }
88
+
89
+ if ($request_method !~ ^(GET|HEAD|PUT|PATCH|POST|DELETE|OPTIONS)$ ){
90
+ return 405;
91
+ }
92
+
93
+ if (-f $document_root/system/maintenance.html) {
94
+ return 503;
95
+ }
96
+ }
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env puma
2
+
3
+ directory '<%= current_path %>'
4
+ rackup "<%=fetch(:puma_rackup)%>"
5
+ environment '<%= fetch(:puma_env) %>'
6
+ <% if fetch(:puma_tag) %>
7
+ tag '<%= fetch(:puma_tag)%>'
8
+ <% end %>
9
+ pidfile "<%=fetch(:puma_pid)%>"
10
+ state_path "<%=fetch(:puma_state)%>"
11
+ stdout_redirect '<%=fetch(:puma_access_log)%>', '<%=fetch(:puma_error_log)%>', true
12
+
13
+
14
+ threads <%=fetch(:puma_threads).join(',')%>
15
+
16
+ <%= puma_plugins %>
17
+
18
+ <%= puma_bind %>
19
+ <% if fetch(:puma_control_app) %>
20
+ activate_control_app "<%= fetch(:puma_default_control_app) %>"
21
+ <% end %>
22
+ workers <%= puma_workers %>
23
+ <% if fetch(:puma_worker_timeout) %>
24
+ worker_timeout <%= fetch(:puma_worker_timeout).to_i %>
25
+ <% end %>
26
+
27
+ <% if puma_daemonize? %>
28
+ daemonize
29
+ <% end %>
30
+
31
+ <% if puma_preload_app? %>
32
+ preload_app!
33
+ <% else %>
34
+ prune_bundler
35
+ <% end %>
36
+
37
+ on_restart do
38
+ puts 'Refreshing Gemfile'
39
+ ENV["BUNDLE_GEMFILE"] = "<%= fetch(:bundle_gemfile, "#{current_path}/Gemfile") %>"
40
+ end
41
+
42
+ <% if puma_preload_app? and fetch(:puma_init_active_record) %>
43
+ before_fork do
44
+ ActiveRecord::Base.connection_pool.disconnect!
45
+ end
46
+
47
+ on_worker_boot do
48
+ ActiveSupport.on_load(:active_record) do
49
+ ActiveRecord::Base.establish_connection
50
+ end
51
+ end
52
+ <% end %>
@@ -25,7 +25,7 @@ Rails.application.configure do
25
25
  config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
26
26
 
27
27
  # Compress JavaScripts and CSS.
28
- config.assets.js_compressor = :uglifier
28
+ config.assets.js_compressor = config.assets.js_compressor = Uglifier.new(harmony: true)
29
29
  # config.assets.css_compressor = :sass
30
30
 
31
31
  # Do not fallback to assets pipeline if a precompiled asset is missed.
@@ -0,0 +1,3 @@
1
+ Adminos.configure do |config|
2
+ config.search_engine = Adminos::Search::PgSearch
3
+ end
@@ -159,6 +159,7 @@ ru:
159
159
  admin:
160
160
  add: Добавить
161
161
  add_child: Добавить подраздел
162
+ duplication: Дублировать
162
163
  back: Назад
163
164
  cancel: Отменить
164
165
  destroy: Удалить
@@ -247,6 +248,23 @@ ru:
247
248
  labels:
248
249
  actions:
249
250
  show: Просмотр изменений
251
+ feedbacks:
252
+ actions:
253
+ index:
254
+ header: Обратная связь
255
+ title: Обратная связь
256
+ labels:
257
+ actions:
258
+ create: Добавить feedback
259
+ edit: Сохранить feedback
260
+ edit_stay_in_place: Сохранить feedback и редактировать
261
+ new: Добавить feedback
262
+ new_stay_in_place: Добавить feedback и редактировать
263
+ update: Сохранить feedback
264
+ profile:
265
+ actions:
266
+ index:
267
+ header: Мой профиль
250
268
  settings:
251
269
  actions:
252
270
  index:
@@ -0,0 +1,19 @@
1
+ [Unit]
2
+ Description = <%= fetch(:application) %> Puma Web Server
3
+ After = network.target
4
+
5
+ [Service]
6
+ Type = simple
7
+ Environment = RAILS_ENV=<%= fetch(:rails_env) %>
8
+ Environment = PWD=<%= current_path %>
9
+ WorkingDirectory = <%= current_path %>
10
+ ExecStart = /home/<%= fetch(:user) %>/.rvm/bin/rvm <%= fetch(:rvm_ruby_version) %> do <%= current_path %>/bin/puma -S <%= shared_path %>/tmp/pids/puma.state -C <%= shared_path %>/puma.rb
11
+ ExecStop = /home/<%= fetch(:user) %>/.rvm/bin/rvm <%= fetch(:rvm_ruby_version) %> do <%= current_path %>/bin/pumactl -S <%= shared_path %>/tmp/pids/puma.state -F <%= shared_path %>/puma.rb stop
12
+ ExecReload = /home/<%= fetch(:user) %>/.rvm/bin/rvm <%= fetch(:rvm_ruby_version) %> do <%= current_path %>/bin/pumactl -S <%= shared_path %>/tmp/pids/puma.state -F <%= shared_path %>/puma.rb phased-restart
13
+ User = <%= fetch(:user) %>
14
+ Group = <%= fetch(:group) || fetch(:user) %>
15
+ Restart = always
16
+ KillMode = process
17
+
18
+ [Install]
19
+ WantedBy = multi-user.target
@@ -0,0 +1,21 @@
1
+ [Unit]
2
+ Description = <%= fetch(:application) %> Sidekiq Background Worker
3
+ After = multi-user.target
4
+
5
+ [Service]
6
+ Type = simple
7
+ Environment = RAILS_ENV=<%= fetch(:rails_env) %>
8
+ Environment = PWD=<%= current_path %>
9
+ EnvironmentFile=/etc/environment
10
+ WorkingDirectory = <%= current_path %>
11
+ ExecStart = /home/<%= fetch(:user) %>/.rvm/bin/rvm <%= fetch(:rvm_ruby_version) %> do <%= current_path %>/bin/sidekiq -e <%= fetch(:rails_env) %> -L <%= shared_path %>/log/sidekiq.log -P <%= shared_path %>/tmp/pids/sidekiq.pid
12
+ ExecStop = /home/<%= fetch(:user) %>/.rvm/bin/rvm <%= fetch(:rvm_ruby_version) %> do <%= current_path %>/bin/sidekiqctl stop <%= shared_path %>/tmp/pids/sidekiq.pid
13
+ User = <%= fetch(:user) %>
14
+ Group = <%= fetch(:group) || fetch(:user) %>
15
+ KillMode = process
16
+ UMask = 0002
17
+ RestartSec = 1
18
+ Restart = always
19
+
20
+ [Install]
21
+ WantedBy = multi-user.target
@@ -1,10 +1,10 @@
1
1
  # will first try and copy the file:
2
2
  # config/deploy/#{full_app_name}/#{from}.erb
3
3
  # to:
4
- # shared/config/to
4
+ # templates/config/to
5
5
  # if the original source path doesn exist then it will
6
6
  # search in:
7
- # config/deploy/shared/#{from}.erb
7
+ # config/deploy/templates/#{from}.erb
8
8
  # this allows files which are common to all enviros to
9
9
  # come from a single source while allowing specific
10
10
  # ones to be over-ridden
@@ -26,8 +26,22 @@ end
26
26
  def template_file(name)
27
27
  if File.exist?((file = "config/deploy/#{fetch(:full_app_name)}/#{name}.erb"))
28
28
  return file
29
- elsif File.exist?((file = "config/deploy/shared/#{name}.erb"))
29
+ elsif File.exist?((file = "config/deploy/templates/#{name}.erb"))
30
+ return file
31
+ elsif File.exist?((file = "config/deploy/templates/#{name}"))
30
32
  return file
31
33
  end
32
34
  return nil
33
35
  end
36
+
37
+ # we often want to refer to variables which
38
+ # are defined in subsequent stage files. This
39
+ # let's us use the {{var}} to represent fetch(:var)
40
+ # in strings which are only evaluated at runtime.
41
+ def sub_strings(input_string)
42
+ output_string = input_string
43
+ input_string.scan(/{{(\w*)}}/).each do |var|
44
+ output_string.gsub!("{{#{var[0]}}}", fetch(var[0].to_sym))
45
+ end
46
+ output_string
47
+ end
@@ -1,9 +1,11 @@
1
+ require "capistrano/smart_templates"
2
+
1
3
  namespace :deploy do
4
+ desc "Set up config files"
2
5
  task :setup_config do
3
6
  on roles(:app) do
4
7
  # make the config dir
5
8
  execute :mkdir, "-p #{shared_path}/config"
6
- full_app_name = fetch(:full_app_name)
7
9
 
8
10
  # config files to be uploaded to shared/config, see the
9
11
  # definition of smart_template for details of operation.
@@ -12,28 +14,33 @@ namespace :deploy do
12
14
  # everything should be in deploy/shared with params which differ
13
15
  # set in the stage files
14
16
 
15
- begin
16
- config_files = fetch(:config_files)
17
- config_files.each do |file|
18
- smart_template file
19
- end
20
-
21
- # which of the above files should be marked as executable
22
- executable_files = fetch(:executable_config_files)
23
-
24
- #executable_files.each do |file|
25
- # execute :chmod, "+x #{shared_path}/config/#{file}"
26
- #end
17
+ config_files = fetch(:config_files, [])
18
+ config_files.each do |file|
19
+ smart_template file
20
+ end
27
21
 
28
- # symlink stuff which should be... symlinked
29
- symlinks = fetch(:symlinks)
22
+ # which of the above files should be marked as executable
23
+ executable_config_files = fetch(:executable_config_files, [])
24
+ executable_config_files.each do |file|
25
+ execute :chmod, "+x #{shared_path}/config/#{file}"
26
+ end
30
27
 
31
- symlinks.each do |symlink|
32
- sudo "ln -nfs #{shared_path}/config/#{symlink[:source]} #{sub_strings(symlink[:link])}"
33
- end
34
- rescue Exception => e
35
- log "ERROR: #{e.to_s}"
28
+ # symlink stuff which should be... symlinked
29
+ symlinks = fetch(:symlinks, [])
30
+ symlinks.each do |symlink|
31
+ sudo "ln -nfs #{shared_path}/config/#{symlink[:source]} #{sub_strings(symlink[:link])}"
36
32
  end
37
33
  end
38
34
  end
35
+
36
+ desc "Set up new deployment"
37
+ task setup: %i[setup_config puma:nginx_config]
38
+
39
+ desc "Set up Systemd services"
40
+ task setup_systemd: %i[systemd:puma:setup]
41
+ # task setup_systemd: %i[systemd:puma:setup systemd:sidekiq:setup]
42
+
43
+ desc "Enable Systemd services"
44
+ task enable_systemd: %i[systemd:puma:enable]
45
+ # task enable_systemd: %i[systemd:puma:enable systemd:sidekiq:enable]
39
46
  end
@@ -1,21 +1,22 @@
1
- set :application, :<%= application_name %>
2
- set :repo_url, "git@gitlab.molinos.ru:studio/#{application}.git"
1
+ set :application, '<%= application_name %>'
2
+ set :repo_url, "git@gitlab.molinos.ru:studio/#{fetch(:application)}.git"
3
3
 
4
- # Default value for :linked_files is []
5
- set :linked_files, fetch(:linked_files, []).push('config/database.yml', '.env', 'config/master.key')
6
- # Default value for linked_dirs is []
7
- set :linked_dirs, fetch(:linked_dirs, []).push(
8
- 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'storage'
9
- )
4
+ set :config_files, %w[config/database.yml .env]
5
+ append :linked_files, 'config/database.yml', '.env', 'config/master.key'
6
+ append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets',
7
+ 'vendor/bundle', 'public/system', 'public/uploads'
10
8
 
11
9
  set :rvm_ruby_version, Pathname(__dir__).join('../.ruby-version').read.chomp
12
10
 
13
11
  set :db_local_clean, true
14
12
  set :assets_dir, %w[public/system]
15
13
 
16
- after 'deploy:publishing', 'deploy:restart'
14
+ set :nginx_server_name, -> { "#{fetch(:domain)} localhost #{fetch(:application)}.local" }
15
+ set :nginx_upstream_name, -> { "#{fetch(:application)}_#{fetch(:stage)}" }
16
+ set :nginx_config_name, -> { "#{fetch(:domain)}.conf" }
17
+ set :nginx_use_ssl, true
18
+
17
19
  namespace :deploy do
18
- task :restart do
19
- invoke 'unicorn:restart'
20
- end
20
+ # after :restart, 'systemd:sidekiq:reload-or-restart'
21
+ after :publishing, :restart
21
22
  end
@@ -0,0 +1,26 @@
1
+ class Admin::ProfilesController < Admin::BaseController
2
+ load_and_authorize_resource param_method: :strong_params, class: User
3
+
4
+ def update
5
+ if resource.update_with_password(strong_params)
6
+ flash[:notice] = t 'flash.actions.update.notice'
7
+ redirect_to action: :edit
8
+ else
9
+ flash[:error] = t 'flash.actions.update.alert'
10
+ render action: :edit
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def resource
17
+ @resource ||= current_user
18
+ end
19
+
20
+ helper_method :resource
21
+
22
+ def strong_params
23
+ params.require(:user).permit :email, :password, :password_confirmation,
24
+ :current_password
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ - title 'Профиль'
2
+ = resource_header 'Профиль'
3
+
4
+ = simple_form_for [:admin, resource], url: admin_profile_path, wrapper: :admin, html: { method: :put } do |f|
5
+ .f
6
+ .f__wrapper
7
+ .f__fieldset
8
+ = f.input :email
9
+ = f.input :password, hint: 'Оставьте пустым если не хотите изменить'
10
+ = f.input :password_confirmation, hint: 'Повторите пароль'
11
+ = f.input :current_password, hint: 'Введите текущий пароль'
12
+
13
+ .f
14
+ .f__wrapper
15
+ .f-submit.f-submit--fixed
16
+ .wrapper
17
+ = f.button :submit, resource_button_value_main, class: 'btn btn-primary btn--done'
@@ -0,0 +1 @@
1
+ gem 'devise-two-factor'
@@ -0,0 +1,36 @@
1
+ module AuthenticatesWithTwoFactor
2
+ extend ActiveSupport::Concern
3
+ def authenticate_with_two_factor
4
+ devise_parameter_sanitizer.permit(:sign_in, keys: [:otp_attempt])
5
+
6
+ # remove otp_user_id if new login
7
+ cookies.delete :otp_user_id if sign_in_params[:email]
8
+
9
+ try_set_otp_user_id
10
+ try_sign_in_user
11
+ end
12
+
13
+ private
14
+
15
+ def try_set_otp_user_id
16
+ user = User.find_by_email(sign_in_params[:email])
17
+
18
+ return unless user&.otp_required_for_login
19
+ return unless user.valid_password?(sign_in_params[:password])
20
+
21
+ cookies.signed[:otp_user_id] = { value: user.id, expires: 5.minutes.from_now }
22
+ end
23
+
24
+ def try_sign_in_user
25
+ user = User.find_by(id: cookies.signed[:otp_user_id])
26
+
27
+ return unless user
28
+
29
+ if user.current_otp == sign_in_params[:otp_attempt]
30
+ sign_in(user)
31
+ else
32
+ self.resource = User.new
33
+ render 'devise/sessions/two_factor'
34
+ end
35
+ end
36
+ end