adminos 1.0.0.pre.rc.2 → 1.0.0.pre.rc.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -4
  3. data/README.md +26 -0
  4. data/adminos.gemspec +4 -4
  5. data/app/inputs/cropp_input.rb +15 -3
  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/configuration.rb +9 -0
  11. data/lib/adminos/controllers/filters.rb +20 -0
  12. data/lib/adminos/controllers/resource.rb +34 -14
  13. data/lib/adminos/extensions/simple_form.rb +12 -0
  14. data/lib/adminos/features/search/elastic.rb +46 -0
  15. data/lib/adminos/features/search/pg_search.rb +49 -0
  16. data/lib/adminos/filters/forms.rb +55 -0
  17. data/lib/adminos/form_builder.rb +11 -0
  18. data/lib/adminos/helpers/models/searchable.rb +9 -0
  19. data/lib/adminos/helpers/view.rb +35 -0
  20. data/lib/adminos.rb +23 -3
  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/devise/devise.ru.yml +15 -3
  46. data/lib/generators/templates/i18n/devise/views/mailer/confirmation_instructions.slim +3 -4
  47. data/lib/generators/templates/i18n/devise/views/mailer/reset_password_instructions.slim +5 -5
  48. data/lib/generators/templates/i18n/devise/views/mailer/unlock_instructions.slim +4 -4
  49. data/lib/generators/templates/i18n/page.rb +2 -2
  50. data/lib/generators/templates/install/Gemfile +4 -6
  51. data/lib/generators/templates/install/README.md +22 -0
  52. data/lib/generators/templates/install/admin_panel/versions/views/admin_versions/index.slim +1 -1
  53. data/lib/generators/templates/install/admin_panel/versions/views/admin_versions/show.slim +3 -3
  54. data/lib/generators/templates/install/auto/Capfile +12 -2
  55. data/lib/generators/templates/install/auto/app/controllers/admin/settings_controller.rb +1 -1
  56. data/lib/generators/templates/install/auto/app/helpers/versions_helper.rb +3 -3
  57. data/lib/generators/templates/install/auto/app/inputs/carrierwave_input.rb +2 -2
  58. data/lib/generators/templates/install/auto/app/inputs/checkbox_input.rb +1 -1
  59. data/lib/generators/templates/install/auto/app/services/export_xlsx.rb +6 -6
  60. data/lib/generators/templates/install/auto/app/views/admin/base/_form.slim +3 -3
  61. data/lib/generators/templates/install/auto/app/views/admin/helps/index.slim +9 -9
  62. data/lib/generators/templates/install/auto/app/views/admin/settings/edit.slim +2 -2
  63. data/lib/generators/templates/install/auto/app/views/shared/admin/_back_button.slim +1 -1
  64. data/lib/generators/templates/install/auto/app/views/shared/helpers/admin/_collection_header.slim +2 -0
  65. data/lib/generators/templates/install/auto/app/views/shared/helpers/admin/_object_link_new.slim +1 -1
  66. data/lib/generators/templates/install/auto/config/deploy/staging.rb +15 -10
  67. data/lib/generators/templates/install/auto/config/deploy/{shared → templates}/database.yml.erb +1 -1
  68. data/lib/generators/templates/install/auto/config/deploy/templates/nginx_conf.erb +96 -0
  69. data/lib/generators/templates/install/auto/config/deploy/templates/puma.rb.erb +52 -0
  70. data/lib/generators/templates/install/auto/config/environments/staging.rb +1 -1
  71. data/lib/generators/templates/install/auto/config/initializers/adminos.rb +3 -0
  72. data/lib/generators/templates/install/auto/config/locales/adminos.en.yml +30 -0
  73. data/lib/generators/templates/install/auto/config/locales/adminos.ru.yml +49 -2
  74. data/lib/generators/templates/install/auto/config/schedule.rb +0 -0
  75. data/lib/generators/templates/install/auto/config/systemd/puma.service.erb +19 -0
  76. data/lib/generators/templates/install/auto/config/systemd/sidekiq.service.erb +21 -0
  77. data/lib/generators/templates/install/auto/lib/capistrano/{template.rb → smart_templates.rb} +17 -3
  78. data/lib/generators/templates/install/auto/lib/capistrano/tasks/setup_config.cap +27 -20
  79. data/lib/generators/templates/install/deploy.rb.erb +13 -12
  80. data/lib/generators/templates/install/prepare_settings.rb +1 -1
  81. data/lib/generators/templates/profile/auto/app/controllers/admin/profiles_controller.rb +26 -0
  82. data/lib/generators/templates/profile/auto/app/views/admin/profiles/edit.slim +17 -0
  83. data/lib/generators/templates/two_facto_auth/Gemfile +1 -0
  84. data/lib/generators/templates/two_facto_auth/auto/app/controllers/concerns/authenticates_with_two_factor.rb +36 -0
  85. data/lib/generators/templates/two_facto_auth/auto/app/controllers/users/sessions_controller.rb +5 -0
  86. data/lib/generators/templates/two_facto_auth/auto/app/views/admin/profiles/_2fa.slim +24 -0
  87. data/lib/generators/templates/two_facto_auth/auto/app/views/devise/sessions/two_factor.slim +15 -0
  88. data/spec/lib/generators/adminos/feedback_generator_rspec.rb +50 -0
  89. data/spec/lib/generators/adminos/install_generator_rspec.rb +6 -7
  90. data/spec/lib/generators/adminos/profile_generator_rspec.rb +33 -0
  91. data/spec/lib/generators/adminos/search_generator.rb +20 -0
  92. data/spec/lib/generators/adminos/two_factor_auth_generator_rspec.rb +61 -0
  93. data/spec/spec_helper.rb +4 -0
  94. data/spec/support/shared/generator.rb +1 -1
  95. metadata +59 -26
  96. data/bin/rspec +0 -29
  97. data/lib/adminos/extensions/globalize_actiontext.rb +0 -28
  98. data/lib/adminos/extensions/globalize_fields.rb +0 -19
  99. data/lib/generators/templates/adminos/locales/migration.rb.erb +0 -18
  100. data/lib/generators/templates/field/locales/migration.rb.erb +0 -13
  101. data/lib/generators/templates/i18n/add_translation_table_to_page.rb +0 -15
  102. data/lib/generators/templates/i18n/auto/config/initializers/globalize_fields.rb +0 -1
  103. data/lib/generators/templates/install/auto/config/deploy/shared/nginx.conf.erb +0 -28
  104. data/lib/generators/templates/install/auto/config/deploy/shared/unicorn.rb.erb +0 -35
  105. data/lib/generators/templates/install/auto/lib/capistrano/substitute_strings.rb +0 -12
  106. data/package-lock.json +0 -3
@@ -51,6 +51,17 @@ en:
51
51
  file: Photo
52
52
 
53
53
  admin:
54
+ welcome: Entrance to admin dashboard
55
+ helps:
56
+ title_html: General notes on adding and editing information
57
+ hint1_html: "Everywhere, where it is possible to add this or that entity (for example, a page), <b>in the right upper part of the page there is a 'Add' button</b>."
58
+ hint2_html: "Some types of records can be <b>published</b> (and will be displayed on the site) and <b>archived</b> (saved in the database, they can be edited, but they will not be published on the site). <b>The status of a published entry is indicated by <i class="icon-eye-open"></i> icon on the right side of the list</b> (the absence of an icon indicates that the entry has been archived)."
59
+ hint3_html: "Some lists have the ability to <b>manually sort the records</b> (the order of display on the site and in the lists). Sometimes you want to bring some record before the previous one. This is true, for example, for a list of pages. <b>To move a record up or down, simply drag it to the desired place with the mouse pointer</b> (by pressing the left mouse button first, when the pointer is above <i class="icon-move"></i> icon)."
60
+ hint4_html: "Some lists include <b>group operations</b> — publish, archive, and delete. To perform a group operation, you need to select the records with which the operation will be carried out - this can be done with checkboxes, and then selecting an operation from the list at the bottom of the page (click on the appropriate button). These operations can also be performed with individual objects in order not to enter the record editing page."
61
+ hint5_html: "If <b>editing records</b> is available, <i class="icon-edit"></i> icon appears in the list. Clicking this icon opens the edit page for the corresponding entry."
62
+ hint6_html: "All <b>specific page settings</b> are in '#{link_to I18n.t('admin.settings.actions.index.header'), edit_admin_settings_path}' section."
63
+ hint7_html: "In cases where this is provided for page layout, the text fields are equipped with a <b>WYSIWYG editor</b>. The editor has the ability to post images and insert video code (embedded video) from the YouTube service."
64
+ icons_meaning: Icons meaning
54
65
  actions:
55
66
  create: Create
56
67
  update: Update
@@ -100,6 +111,11 @@ en:
100
111
  labels:
101
112
  actions:
102
113
  show: Show modifications
114
+ save_table: Save table
115
+ changes: Changes
116
+ field: Field
117
+ old_value: Old value
118
+ new_value: New value
103
119
  settings:
104
120
  actions:
105
121
  index:
@@ -136,6 +152,11 @@ en:
136
152
  cancel: Cancel
137
153
  destroy: Delete
138
154
  edit: Edit
155
+ apply: Apply
156
+ save: Save
157
+ choose: Choose
158
+ login: Login
159
+ sign_up: Sign up
139
160
  show: Show modifications
140
161
  go_to_root: Home
141
162
  info: Information
@@ -155,6 +176,10 @@ en:
155
176
  set_nav_published_on: Add to navigation
156
177
  set_published_off: Remove from publication
157
178
  set_published_on: Publish
179
+ image:
180
+ width: Width
181
+ height: Height
182
+ cropped: Кадрированное изображение
158
183
 
159
184
  sites:
160
185
  holding: Holding
@@ -162,3 +187,8 @@ en:
162
187
 
163
188
  unauthorized:
164
189
  default: You must login or register.
190
+ authentication:
191
+ two_factor: Two-factor authentication
192
+ key: Key
193
+ switch_on_2fa: Switch on 2FA
194
+ switch_off_2fa: Switch off 2FA
@@ -159,10 +159,16 @@ ru:
159
159
  admin:
160
160
  add: Добавить
161
161
  add_child: Добавить подраздел
162
+ duplication: Дублировать
162
163
  back: Назад
163
164
  cancel: Отменить
164
165
  destroy: Удалить
165
166
  edit: Редактировать
167
+ apply: Применить
168
+ save: Сохранить
169
+ choose: Выбрать
170
+ login: Логин
171
+ sign_up: Регистрация
166
172
  show: Просмотр изменений
167
173
  go_to_root: Перейти на сайт
168
174
  info: Справка
@@ -173,16 +179,20 @@ ru:
173
179
  seo: SEO
174
180
  logout: Выйти
175
181
  nav_published: В навигации
176
- published: Опубликована
182
+ published: Опубликовано
177
183
  locked: Закреплена
178
184
  server_restart: Перезагрузить сервер
179
- unpublished: Не опубликована
185
+ unpublished: Не опубликовано
180
186
  batch_actions:
181
187
  destroy: Удалить
182
188
  set_nav_published_off: Убрать из навигации
183
189
  set_nav_published_on: Опубликовать в навигации
184
190
  set_published_off: Снять с публикации
185
191
  set_published_on: Опубликовать
192
+ image:
193
+ width: Ширина
194
+ height: Высота
195
+ cropped: Кадрированное изображение
186
196
 
187
197
  confirmations:
188
198
  destroy:
@@ -198,11 +208,21 @@ ru:
198
208
  title: &layouts_admin_title Панель управления
199
209
 
200
210
  admin:
211
+ welcome: Вход в систему администрирования
201
212
  actions:
202
213
  create: Создание
203
214
  update: Обновление
204
215
  destroy: Удаление
205
216
  helps:
217
+ title_html: "Общие замечания по&nbsp;добавлению и&nbsp;редактированию информации:"
218
+ hint1_html: "Везде, где можно добавить ту&nbsp;или иную сущность (например, страницу), <b>в правой верхней части страницы есть кнопка «добавить»</b>."
219
+ hint2_html: "Некоторые типы записей могут быть <b>опубликованы</b> (и&nbsp;будут отображаться на&nbsp;сайте) и&nbsp;<b>заархивированы</b> (сохранятся в&nbsp;базе, их&nbsp;можно редактировать, но&nbsp;они не&nbsp;будут опубликованы на&nbsp;сайте). <b>Состояние опубликованной записи обозначается пиктограммой <i class="icon-eye-open"></i> в&nbsp;правой части списка</b> (отсутствие пиктограммы обозначает&nbsp;то, что запись заархивирована)."
220
+ hint3_html: "В&nbsp; некоторых списках есть возможность <b>ручной сортировки записей</b> (порядок отображения на&nbsp;сайте и&nbsp;в&nbsp;списках). Иногда требуется вывести какую-то запись раньше предыдущей. Это справедливо, например, для списка страниц. <b>Чтобы переместить запись выше или ниже, достаточно просто перетащить её&nbsp;в&nbsp;нужное место указателем мыши</b> (предварительно нажав левую кнопку мыши, когда указатель находится над пиктограммой <i class="icon-move"></i>)."
221
+ hint4_html: "В&nbsp; некоторых списках предусмотрены <b>групповые операции</b>&nbsp;— публикация, архивирование и&nbsp;удаление. Чтобы выполнить групповую операцию, необходимо выбрать записи, с&nbsp;которыми будет осуществляться операция&nbsp;— это можно сделать, отметив эти записи галочками в&nbsp;чекбоксах,&nbsp;— а&nbsp;затем выбрать операцию из&nbsp;списка внизу страницы (нажать на&nbsp;соответствующую кнопку). Эти операции можно выполнять также и&nbsp;с&nbsp;отдельными объектами (то&nbsp;есть по&nbsp;одному), чтобы не&nbsp;заходить на&nbsp;страницу редактирования записи."
222
+ hint5_html: "Если <b>редактирование записей</b> доступно, то&nbsp;в&nbsp;списке присутствует пиктограмма <i class="icon-edit"></i>. Щелчок по&nbsp;этой пиктограмме открывает страницу редактирования соответствующей записи."
223
+ hint6_html: "Все <b>специфичные настройки страниц</b> вынесены в раздел «#{link_to I18n.t('admin.settings.actions.index.header'), edit_admin_settings_path}»."
224
+ hint7_html: "В&nbsp;случаях, где это предусмотрено оформлением страниц, текстовые поля оснащены <b>WYSIWYG-редактором</b>. Редактор имеет возможность размещения изображений и&nbsp;вставки кода для видео (встроенное видео) с&nbsp;сервиса YouTube."
225
+ icons_meaning: Значение пиктограмм
206
226
  actions:
207
227
  index:
208
228
  header: Панель управления
@@ -247,6 +267,28 @@ ru:
247
267
  labels:
248
268
  actions:
249
269
  show: Просмотр изменений
270
+ save_table: Сохранить таблицу
271
+ changes: Изменения
272
+ field: Поле
273
+ old_value: Старое значение
274
+ new_value: Новое значение
275
+ feedbacks:
276
+ actions:
277
+ index:
278
+ header: Обратная связь
279
+ title: Обратная связь
280
+ labels:
281
+ actions:
282
+ create: Добавить feedback
283
+ edit: Сохранить feedback
284
+ edit_stay_in_place: Сохранить feedback и редактировать
285
+ new: Добавить feedback
286
+ new_stay_in_place: Добавить feedback и редактировать
287
+ update: Сохранить feedback
288
+ profile:
289
+ actions:
290
+ index:
291
+ header: Мой профиль
250
292
  settings:
251
293
  actions:
252
294
  index:
@@ -290,3 +332,8 @@ ru:
290
332
 
291
333
  unauthorized:
292
334
  default: Необходимо войти или зарегистрироваться.
335
+ authentication:
336
+ two_factor: Двухфакторная аутентификация
337
+ key: Ключ
338
+ switch_on_2fa: Включить 2FA
339
+ switch_off_2fa: Выключить 2FA
@@ -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', 'storage'
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
@@ -1,3 +1,3 @@
1
1
 
2
2
 
3
- Settings.first_or_initialize.update_attributes email: 'studio@molinos.ru', email_header_from: 'studio@molinos.ru', company_name: 'Molinos'
3
+ Settings.first_or_initialize.update email: 'studio@molinos.ru', email_header_from: 'studio@molinos.ru', company_name: 'Molinos'
@@ -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
@@ -0,0 +1,5 @@
1
+ class Users::SessionsController < Devise::SessionsController
2
+ include AuthenticatesWithTwoFactor
3
+
4
+ prepend_before_action :authenticate_with_two_factor, only: [:create]
5
+ end
@@ -0,0 +1,24 @@
1
+ .f__fieldset
2
+ .f__legend=t('authentication.two_factor')
3
+ - if resource.otp_required_for_login
4
+ .f
5
+ .f__wrapper
6
+ .f-field
7
+ .f-field__label
8
+ label.f-label=t('authentication.key')
9
+ .f-field__container
10
+ .f-field__text =resource.otp.secret
11
+ .f-field
12
+ .f-field__label
13
+ label.f-label Google Authenticator QR
14
+ .f-field__container
15
+ = google_authenticator_qrcode(resource)
16
+ .f-field
17
+ .f-field__container
18
+ = link_to t('authentication.switch_off_2fa'), toggle_two_factor_admin_profile_path, method: :post, class: 'btn btn btn-primary'
19
+ - else
20
+ .f
21
+ .f__wrapper
22
+ .f-field
23
+ .f-field__container
24
+ = link_to t('authentication.switch_on_2fa'), toggle_two_factor_admin_profile_path, method: :post, class: 'btn btn btn-primary'
@@ -0,0 +1,15 @@
1
+ - @body_class = "page--auth ready"
2
+
3
+ .auth
4
+ .auth__title Adminos
5
+ .auth__welcome= t('admin.welcome')
6
+
7
+ = simple_form_for resource, as: resource_name, url: session_path(resource_name), wrapper: :auth, html: { class: 'form auth__form' } do |f|
8
+ = f.input :otp_attempt, placeholder: '2FA'
9
+
10
+ .form__submit.centered
11
+ = f.submit t('admin.users.labels.form.login'), class: 'button button--rounded'
12
+
13
+ - if flash.present?
14
+ .auth__message
15
+ = show_flash_alert
@@ -0,0 +1,50 @@
1
+ require 'support/generators'
2
+
3
+ RSpec.describe Adminos::Generators::FeedbackGenerator, type: :generator do
4
+
5
+ prepare_app(folder_name: 'dummy')
6
+ generate('adminos:feedback')
7
+
8
+ context 'controllers' do
9
+ describe 'app/controllers/feedbacks_controller.rb' do
10
+ subject { file('app/controllers/feedbacks_controller.rb') }
11
+ it { is_expected.to exist }
12
+ end
13
+
14
+ describe 'app/controllers/admin/feedbacks_controller.rb' do
15
+ subject { file('app/controllers/admin/feedbacks_controller.rb') }
16
+ it { is_expected.to exist }
17
+ end
18
+ end
19
+
20
+ context 'models' do
21
+ describe 'app/models/feedback.rb' do
22
+ subject { file('app/models/feedback.rb') }
23
+ it { is_expected.to exist }
24
+ end
25
+ end
26
+
27
+ context 'views' do
28
+ describe 'app/views/admin/feedbacks/_fields.slim' do
29
+ subject { file('app/views/admin/feedbacks/_fields.slim') }
30
+ it { is_expected.to exist }
31
+ end
32
+
33
+ describe 'app/views/admin/feedbacks/index.slim' do
34
+ subject { file('app/views/admin/feedbacks/index.slim') }
35
+ it { is_expected.to exist }
36
+ end
37
+
38
+ describe 'app/views/shared/admin/_sidebar.slim' do
39
+ subject { file('app/views/shared/admin/_sidebar.slim') }
40
+ it { is_expected.to contain /admin_feedbacks_path/ }
41
+ end
42
+ end
43
+
44
+ context 'config' do
45
+ describe 'config/routes.rb' do
46
+ subject { file('config/routes.rb') }
47
+ it { is_expected.to contain /resources :feedbacks, except: :show do/ }
48
+ end
49
+ end
50
+ end
@@ -168,6 +168,11 @@ RSpec.describe Adminos::Generators::InstallGenerator, type: :generator do
168
168
  it { is_expected.to exist }
169
169
  end
170
170
 
171
+ describe 'config/initializers/adminos.rb' do
172
+ subject { file( 'config/initializers/adminos.rb') }
173
+ it { is_expected.to exist }
174
+ end
175
+
171
176
  describe 'config/locales/devise.ru.yml' do
172
177
  subject { file( 'config/locales/devise.ru.yml') }
173
178
  it { is_expected.to exist }
@@ -250,7 +255,6 @@ RSpec.describe Adminos::Generators::InstallGenerator, type: :generator do
250
255
  describe 'app/models/page.rb' do
251
256
  subject { file('app/models/page.rb') }
252
257
  it { is_expected.to contain /translates :name, .*/ }
253
- it { is_expected.to contain /accepts_nested_attributes_for :translations/ }
254
258
  end
255
259
  end
256
260
 
@@ -295,11 +299,6 @@ RSpec.describe Adminos::Generators::InstallGenerator, type: :generator do
295
299
  end
296
300
 
297
301
  context 'config' do
298
- describe 'config/initializers/globalize_fields.rb' do
299
- subject { file('config/initializers/globalize_fields.rb') }
300
- it { is_expected.to exist }
301
- end
302
-
303
302
  describe 'config/routes.rb' do
304
303
  subject { file('config/routes.rb') }
305
304
  it { is_expected.to contain /scope '\(:locale\)'/ }
@@ -314,7 +313,7 @@ RSpec.describe Adminos::Generators::InstallGenerator, type: :generator do
314
313
  context 'Gemfile' do
315
314
  describe 'Gemfile' do
316
315
  subject { file('Gemfile') }
317
- it { is_expected.to contain /gem 'globalize'/ }
316
+ it { is_expected.to contain /gem 'mobility'/ }
318
317
  end
319
318
  end
320
319
  end
@@ -0,0 +1,33 @@
1
+ require 'support/generators'
2
+
3
+ RSpec.describe Adminos::Generators::ProfileGenerator, type: :generator do
4
+
5
+ prepare_app(folder_name: 'dummy')
6
+ generate('adminos:profile')
7
+
8
+ context 'controllers' do
9
+ describe 'app/controllers/admin/profiles_controller.rb' do
10
+ subject { file('app/controllers/admin/profiles_controller.rb') }
11
+ it { is_expected.to exist }
12
+ end
13
+ end
14
+
15
+ context 'views' do
16
+ describe 'app/views/admin/profiles/edit.slim' do
17
+ subject { file('app/views/admin/profiles/edit.slim') }
18
+ it { is_expected.to exist }
19
+ end
20
+
21
+ describe 'app/views/shared/admin/_sidebar.slim' do
22
+ subject { file('app/views/shared/admin/_sidebar.slim') }
23
+ it { is_expected.to contain /link_to edit_admin_profile_path/ }
24
+ end
25
+ end
26
+
27
+ context 'config' do
28
+ describe 'config/routes.rb' do
29
+ subject { file('config/routes.rb') }
30
+ it { is_expected.to contain /resource :profile, only: \[:edit, :update\]/ }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ require 'support/generators'
2
+
3
+ RSpec.describe Adminos::Generators::SearchGenerator, type: :generator do
4
+ prepare_app(folder_name: 'dummy')
5
+ generate('adminos article')
6
+ generate('adminos:search Article')
7
+
8
+ describe "app/models/article.rb" do
9
+ subject { file("app/models/article.rb") }
10
+
11
+ it { is_expected.to contain /include Adminos::Searchable/ }
12
+ it { is_expected.to contain /searchable/ }
13
+ end
14
+
15
+ describe "app/views/admin/articles/index.slim" do
16
+ subject { file("app/views/admin/articles/index.slim") }
17
+
18
+ it { is_expected.to contain "= render 'shared/admin/search_form'" }
19
+ end
20
+ end