kowl 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +7 -0
  3. data/README.md +383 -0
  4. data/bin/console +14 -0
  5. data/bin/kowl +106 -0
  6. data/bin/setup +13 -0
  7. data/lib/kowl/actions.rb +240 -0
  8. data/lib/kowl/docker.rb +447 -0
  9. data/lib/kowl/generators/README.md +5 -0
  10. data/lib/kowl/generators/action_generator.rb +113 -0
  11. data/lib/kowl/generators/admin_generator.rb +114 -0
  12. data/lib/kowl/generators/assets_generator.rb +188 -0
  13. data/lib/kowl/generators/base.rb +40 -0
  14. data/lib/kowl/generators/circleci_generator.rb +11 -0
  15. data/lib/kowl/generators/config_generator.rb +180 -0
  16. data/lib/kowl/generators/controller_generator.rb +64 -0
  17. data/lib/kowl/generators/database_generator.rb +42 -0
  18. data/lib/kowl/generators/decorators_generator.rb +16 -0
  19. data/lib/kowl/generators/docker_generator.rb +40 -0
  20. data/lib/kowl/generators/dotfiles_generator.rb +73 -0
  21. data/lib/kowl/generators/libs_generator.rb +19 -0
  22. data/lib/kowl/generators/mailer_generator.rb +58 -0
  23. data/lib/kowl/generators/misc_generator.rb +20 -0
  24. data/lib/kowl/generators/overrides/app_base.rb +15 -0
  25. data/lib/kowl/generators/overrides/app_builder.rb +58 -0
  26. data/lib/kowl/generators/overrides/app_generator.rb +249 -0
  27. data/lib/kowl/generators/pages_generator.rb +46 -0
  28. data/lib/kowl/generators/routes_generator.rb +20 -0
  29. data/lib/kowl/generators/sidekiq_generator.rb +31 -0
  30. data/lib/kowl/generators/staging_generator.rb +14 -0
  31. data/lib/kowl/generators/test_generator.rb +42 -0
  32. data/lib/kowl/generators/text_files_generator.rb +41 -0
  33. data/lib/kowl/generators/users_and_auth_generator.rb +143 -0
  34. data/lib/kowl/generators/uuid_generator.rb +39 -0
  35. data/lib/kowl/generators/views_and_helpers_generator.rb +104 -0
  36. data/lib/kowl/geodb.rb +96 -0
  37. data/lib/kowl/helpers.rb +139 -0
  38. data/lib/kowl/templates/Gemfile.erb.tt +253 -0
  39. data/lib/kowl/templates/README.md.erb +33 -0
  40. data/lib/kowl/templates/app/assets/javascripts/semantic.js.tt +26 -0
  41. data/lib/kowl/templates/app/assets/stylesheets/administrate/application.scss +44 -0
  42. data/lib/kowl/templates/app/assets/stylesheets/bootstrap/_custom_styling.scss +38 -0
  43. data/lib/kowl/templates/app/assets/stylesheets/bootstrap/application-mailer.scss +1 -0
  44. data/lib/kowl/templates/app/assets/stylesheets/bootstrap/application.scss +14 -0
  45. data/lib/kowl/templates/app/assets/stylesheets/bootstrap/components/_alerts.scss +7 -0
  46. data/lib/kowl/templates/app/assets/stylesheets/bootstrap/components/_errors.scss +28 -0
  47. data/lib/kowl/templates/app/assets/stylesheets/bootstrap/components/_navbar.scss +17 -0
  48. data/lib/kowl/templates/app/assets/stylesheets/bootstrap/variables.scss +6 -0
  49. data/lib/kowl/templates/app/assets/stylesheets/semantic/_custom_styling.scss +20 -0
  50. data/lib/kowl/templates/app/assets/stylesheets/semantic/application.scss +24 -0
  51. data/lib/kowl/templates/app/controllers/admin/application_controller.rb +29 -0
  52. data/lib/kowl/templates/app/controllers/admin/login_activities_controller.rb +29 -0
  53. data/lib/kowl/templates/app/controllers/admin/users_controller.rb +37 -0
  54. data/lib/kowl/templates/app/controllers/concerns/auth/authentication.rb +18 -0
  55. data/lib/kowl/templates/app/controllers/concerns/auth/authorization.rb +20 -0
  56. data/lib/kowl/templates/app/controllers/concerns/auth/error_handlers.rb +27 -0
  57. data/lib/kowl/templates/app/controllers/concerns/noauth/error_handlers.rb +25 -0
  58. data/lib/kowl/templates/app/controllers/users_controller.rb +17 -0
  59. data/lib/kowl/templates/app/dashboards/login_activity_dashboard.rb.tt +59 -0
  60. data/lib/kowl/templates/app/dashboards/rich_text_body_dashboard.rb.tt +17 -0
  61. data/lib/kowl/templates/app/dashboards/user_dashboard.rb.tt +60 -0
  62. data/lib/kowl/templates/app/fields/gravatar_field.rb +10 -0
  63. data/lib/kowl/templates/app/fields/rich_text_area_field.rb +8 -0
  64. data/lib/kowl/templates/app/inputs/rich_text_area_input.rb +11 -0
  65. data/lib/kowl/templates/app/javascript/administrate/components/date_time_picker.js.tt +32 -0
  66. data/lib/kowl/templates/app/javascript/administrate/components/table.js.tt +49 -0
  67. data/lib/kowl/templates/app/javascript/administrate/index.js +3 -0
  68. data/lib/kowl/templates/app/javascript/packs/administrate.js.tt +21 -0
  69. data/lib/kowl/templates/app/javascript/packs/semantic.js +11 -0
  70. data/lib/kowl/templates/app/mailers/application_mailer.rb +7 -0
  71. data/lib/kowl/templates/app/mailers/devise_mailer.rb +5 -0
  72. data/lib/kowl/templates/app/models/login_activity.rb.tt +29 -0
  73. data/lib/kowl/templates/app/models/user.rb.tt +72 -0
  74. data/lib/kowl/templates/app/policies/application_policy.rb +38 -0
  75. data/lib/kowl/templates/app/policies/login_activity_policy.rb +35 -0
  76. data/lib/kowl/templates/app/policies/user_policy.rb +43 -0
  77. data/lib/kowl/templates/app/views/admin/templates/navigation.erb.tt +23 -0
  78. data/lib/kowl/templates/app/views/admin/views/application/_javascript.html.erb +21 -0
  79. data/lib/kowl/templates/app/views/admin/views/users/_collection.html.erb +102 -0
  80. data/lib/kowl/templates/app/views/admin/views/users/_form.html.erb +46 -0
  81. data/lib/kowl/templates/app/views/admin/views/users/edit.html.erb +36 -0
  82. data/lib/kowl/templates/app/views/admin/views/users/index.html.erb +66 -0
  83. data/lib/kowl/templates/app/views/fields/gravatar_field/_form.html.erb +6 -0
  84. data/lib/kowl/templates/app/views/fields/gravatar_field/_index.html.erb +1 -0
  85. data/lib/kowl/templates/app/views/fields/gravatar_field/_show.html.erb +1 -0
  86. data/lib/kowl/templates/app/views/fields/rich_text_area_field/_form.html.erb +6 -0
  87. data/lib/kowl/templates/app/views/fields/rich_text_area_field/_index.html.erb +1 -0
  88. data/lib/kowl/templates/app/views/fields/rich_text_area_field/_show.html.erb +1 -0
  89. data/lib/kowl/templates/app/views/layouts/admin.html.erb.tt +47 -0
  90. data/lib/kowl/templates/app/views/layouts/devise_mailer.html.erb +14 -0
  91. data/lib/kowl/templates/app/views/pages/welcome/bootstrap.html.erb +18 -0
  92. data/lib/kowl/templates/app/views/pages/welcome/bootstrap.html.haml +17 -0
  93. data/lib/kowl/templates/app/views/pages/welcome/bootstrap.html.slim +17 -0
  94. data/lib/kowl/templates/app/views/pages/welcome/default.html.erb +0 -0
  95. data/lib/kowl/templates/app/views/pages/welcome/default.html.haml +0 -0
  96. data/lib/kowl/templates/app/views/pages/welcome/default.html.slim +0 -0
  97. data/lib/kowl/templates/app/views/pages/welcome/semantic.html.erb +20 -0
  98. data/lib/kowl/templates/app/views/pages/welcome/semantic.html.haml +17 -0
  99. data/lib/kowl/templates/app/views/pages/welcome/semantic.html.slim +17 -0
  100. data/lib/kowl/templates/app/views/shared/footer/bootstrap.html.erb.tt +5 -0
  101. data/lib/kowl/templates/app/views/shared/footer/bootstrap.html.haml.tt +3 -0
  102. data/lib/kowl/templates/app/views/shared/footer/bootstrap.html.slim.tt +3 -0
  103. data/lib/kowl/templates/app/views/shared/footer/semantic.html.erb.tt +7 -0
  104. data/lib/kowl/templates/app/views/shared/footer/semantic.html.haml.tt +5 -0
  105. data/lib/kowl/templates/app/views/shared/footer/semantic.html.slim.tt +5 -0
  106. data/lib/kowl/templates/app/views/shared/navigation/bootstrap.html.erb.tt +51 -0
  107. data/lib/kowl/templates/app/views/shared/navigation/bootstrap.html.haml.tt +36 -0
  108. data/lib/kowl/templates/app/views/shared/navigation/bootstrap.html.slim.tt +36 -0
  109. data/lib/kowl/templates/app/views/shared/navigation/semantic.html.erb.tt +48 -0
  110. data/lib/kowl/templates/app/views/shared/navigation/semantic.html.haml.tt +36 -0
  111. data/lib/kowl/templates/app/views/shared/navigation/semantic.html.slim.tt +36 -0
  112. data/lib/kowl/templates/app/workers/scheduler/pghero_scheduler.rb +11 -0
  113. data/lib/kowl/templates/config/autoprefixer.yml +4 -0
  114. data/lib/kowl/templates/config/db/mysql.yml.tt +43 -0
  115. data/lib/kowl/templates/config/db/oracle.yml.tt +29 -0
  116. data/lib/kowl/templates/config/db/postgresql.yml.tt +37 -0
  117. data/lib/kowl/templates/config/db/sqlite3.yml.tt +20 -0
  118. data/lib/kowl/templates/config/db/sqlserver.yml.tt +28 -0
  119. data/lib/kowl/templates/config/initializers/administrate.rb.tt +9 -0
  120. data/lib/kowl/templates/config/initializers/bullet.rb +21 -0
  121. data/lib/kowl/templates/config/initializers/devise-security.rb +44 -0
  122. data/lib/kowl/templates/config/initializers/devise_argon2.rb +29 -0
  123. data/lib/kowl/templates/config/initializers/faker.rb +6 -0
  124. data/lib/kowl/templates/config/initializers/generators.rb.tt +31 -0
  125. data/lib/kowl/templates/config/initializers/geocoder.rb +10 -0
  126. data/lib/kowl/templates/config/initializers/letter_opener.rb +13 -0
  127. data/lib/kowl/templates/config/initializers/lockbox.rb +11 -0
  128. data/lib/kowl/templates/config/initializers/logging.rb +6 -0
  129. data/lib/kowl/templates/config/initializers/lograge.rb +7 -0
  130. data/lib/kowl/templates/config/initializers/logstop.rb +4 -0
  131. data/lib/kowl/templates/config/initializers/middleware.rb +9 -0
  132. data/lib/kowl/templates/config/initializers/oj.rb +7 -0
  133. data/lib/kowl/templates/config/initializers/pagy.rb.tt +16 -0
  134. data/lib/kowl/templates/config/initializers/postmark.rb +8 -0
  135. data/lib/kowl/templates/config/initializers/rack_attack.rb.tt +71 -0
  136. data/lib/kowl/templates/config/initializers/sass.rb +5 -0
  137. data/lib/kowl/templates/config/initializers/sidekiq.rb +11 -0
  138. data/lib/kowl/templates/config/initializers/simpleform/semantic.rb +225 -0
  139. data/lib/kowl/templates/config/initializers/slim.rb +6 -0
  140. data/lib/kowl/templates/config/initializers/sparkpost.rb +13 -0
  141. data/lib/kowl/templates/config/routes.rb.tt +28 -0
  142. data/lib/kowl/templates/config/sidekiq.yml.tt +17 -0
  143. data/lib/kowl/templates/db/migrations/create_action_text_tables.action_text.rb.tt +16 -0
  144. data/lib/kowl/templates/db/migrations/create_active_storage_tables.active_storage.rb.tt +29 -0
  145. data/lib/kowl/templates/db/migrations/devise.rb.tt +59 -0
  146. data/lib/kowl/templates/db/migrations/login_activities.rb.tt +41 -0
  147. data/lib/kowl/templates/db/seeds.rb.tt +14 -0
  148. data/lib/kowl/templates/docker/Dockerfile.alpine.tt +92 -0
  149. data/lib/kowl/templates/docker/Dockerfile.debian.tt +133 -0
  150. data/lib/kowl/templates/docker/docker-compose.yml.tt +55 -0
  151. data/lib/kowl/templates/docker/mysql/Dockerfile.tt +15 -0
  152. data/lib/kowl/templates/dotfiles/Aptfile.tt +34 -0
  153. data/lib/kowl/templates/dotfiles/Brewfile.tt +49 -0
  154. data/lib/kowl/templates/dotfiles/Procfile.tt +12 -0
  155. data/lib/kowl/templates/dotfiles/codeclimate.yml +76 -0
  156. data/lib/kowl/templates/dotfiles/coffeelint.json +10 -0
  157. data/lib/kowl/templates/dotfiles/coffeelintignore +15 -0
  158. data/lib/kowl/templates/dotfiles/dockerignore +23 -0
  159. data/lib/kowl/templates/dotfiles/editorconfig +13 -0
  160. data/lib/kowl/templates/dotfiles/env.tt +58 -0
  161. data/lib/kowl/templates/dotfiles/erb-lint.yml +10 -0
  162. data/lib/kowl/templates/dotfiles/erdconfig.tt +24 -0
  163. data/lib/kowl/templates/dotfiles/eslintignore +20 -0
  164. data/lib/kowl/templates/dotfiles/eslintrc.js +31 -0
  165. data/lib/kowl/templates/dotfiles/fasterer.yml +14 -0
  166. data/lib/kowl/templates/dotfiles/foreman +1 -0
  167. data/lib/kowl/templates/dotfiles/gitattributes +15 -0
  168. data/lib/kowl/templates/dotfiles/gitignore +69 -0
  169. data/lib/kowl/templates/dotfiles/haml-lint.yml +23 -0
  170. data/lib/kowl/templates/dotfiles/jsbeautifyrc +15 -0
  171. data/lib/kowl/templates/dotfiles/jshintrc +3 -0
  172. data/lib/kowl/templates/dotfiles/mailmap +3 -0
  173. data/lib/kowl/templates/dotfiles/nvmrc +1 -0
  174. data/lib/kowl/templates/dotfiles/prettierignore +21 -0
  175. data/lib/kowl/templates/dotfiles/prettierrc.js +62 -0
  176. data/lib/kowl/templates/dotfiles/pryrc +7 -0
  177. data/lib/kowl/templates/dotfiles/rspec +3 -0
  178. data/lib/kowl/templates/dotfiles/rubocop.yml.tt +78 -0
  179. data/lib/kowl/templates/dotfiles/scss-lint.yml +132 -0
  180. data/lib/kowl/templates/dotfiles/simplecov +19 -0
  181. data/lib/kowl/templates/dotfiles/slim-lint.yml +23 -0
  182. data/lib/kowl/templates/dotfiles/slugignore +10 -0
  183. data/lib/kowl/templates/dotfiles/yamllint +7 -0
  184. data/lib/kowl/templates/dotfiles/yarnclean +46 -0
  185. data/lib/kowl/templates/lib/tasks/stats.rake +42 -0
  186. data/lib/kowl/templates/tests/factories/README.md +0 -0
  187. data/lib/kowl/templates/tests/factories/login_activity.rb +11 -0
  188. data/lib/kowl/templates/tests/factories/user.rb +11 -0
  189. data/lib/kowl/templates/tests/minitest/README.md +3 -0
  190. data/lib/kowl/templates/tests/minitest/application_system_test_case.rb +7 -0
  191. data/lib/kowl/templates/tests/minitest/controllers/pages_controller_test.rb +10 -0
  192. data/lib/kowl/templates/tests/minitest/models/login_activity_test.rb +8 -0
  193. data/lib/kowl/templates/tests/minitest/models/user_test.rb +15 -0
  194. data/lib/kowl/templates/tests/minitest/policies/login_activity_policy_test.rb +7 -0
  195. data/lib/kowl/templates/tests/minitest/policies/user_policy_test.rb +7 -0
  196. data/lib/kowl/templates/tests/minitest/support/capybara.rb +38 -0
  197. data/lib/kowl/templates/tests/minitest/support/database_cleaner.rb +20 -0
  198. data/lib/kowl/templates/tests/minitest/support/database_cleaner_support.rb +15 -0
  199. data/lib/kowl/templates/tests/minitest/support/deferred_garbage_collection.rb +21 -0
  200. data/lib/kowl/templates/tests/minitest/support/devise.rb +16 -0
  201. data/lib/kowl/templates/tests/minitest/support/factories.rb +6 -0
  202. data/lib/kowl/templates/tests/minitest/support/formulaic.rb +8 -0
  203. data/lib/kowl/templates/tests/minitest/support/helpers/devise_helper.rb +57 -0
  204. data/lib/kowl/templates/tests/minitest/support/papertrail.rb +17 -0
  205. data/lib/kowl/templates/tests/minitest/support/pundit.rb +0 -0
  206. data/lib/kowl/templates/tests/minitest/support/shoulda.rb +11 -0
  207. data/lib/kowl/templates/tests/minitest/support/simplecov.rb +8 -0
  208. data/lib/kowl/templates/tests/minitest/test_helper.rb +17 -0
  209. data/lib/kowl/templates/tests/rspec/README.md +9 -0
  210. data/lib/kowl/templates/tests/rspec/controllers/admin/application_controller_spec.rb +12 -0
  211. data/lib/kowl/templates/tests/rspec/controllers/admin/users_controller_spec.rb +14 -0
  212. data/lib/kowl/templates/tests/rspec/controllers/pages_controller_spec.rb +10 -0
  213. data/lib/kowl/templates/tests/rspec/features/README.md +15 -0
  214. data/lib/kowl/templates/tests/rspec/features/visitor_sign_up_spec.rb +25 -0
  215. data/lib/kowl/templates/tests/rspec/helpers/application_helper_spec.rb +7 -0
  216. data/lib/kowl/templates/tests/rspec/helpers/pages_helper_spec.rb +15 -0
  217. data/lib/kowl/templates/tests/rspec/models/login_activity_spec.rb +11 -0
  218. data/lib/kowl/templates/tests/rspec/models/user_spec.rb +21 -0
  219. data/lib/kowl/templates/tests/rspec/policies/login_activity_policy_spec.rb +59 -0
  220. data/lib/kowl/templates/tests/rspec/policies/user_policy_spec.rb +56 -0
  221. data/lib/kowl/templates/tests/rspec/rails_helper.rb +72 -0
  222. data/lib/kowl/templates/tests/rspec/requests/pages_spec.rb +11 -0
  223. data/lib/kowl/templates/tests/rspec/spec_helper.rb +96 -0
  224. data/lib/kowl/templates/tests/rspec/support/bullet.rb +17 -0
  225. data/lib/kowl/templates/tests/rspec/support/capybara.rb +37 -0
  226. data/lib/kowl/templates/tests/rspec/support/controller_testing.rb +10 -0
  227. data/lib/kowl/templates/tests/rspec/support/database_cleaner.rb +55 -0
  228. data/lib/kowl/templates/tests/rspec/support/deferred_garbage_collection.rb +32 -0
  229. data/lib/kowl/templates/tests/rspec/support/devise.rb +21 -0
  230. data/lib/kowl/templates/tests/rspec/support/factories.rb +5 -0
  231. data/lib/kowl/templates/tests/rspec/support/formulaic.rb +8 -0
  232. data/lib/kowl/templates/tests/rspec/support/helpers/devise_helpers.rb +56 -0
  233. data/lib/kowl/templates/tests/rspec/support/papertrail.rb +5 -0
  234. data/lib/kowl/templates/tests/rspec/support/pi_ci.rb +6 -0
  235. data/lib/kowl/templates/tests/rspec/support/pundit.rb +6 -0
  236. data/lib/kowl/templates/tests/rspec/support/shoulda.rb +10 -0
  237. data/lib/kowl/templates/tests/rspec/support/sidekiq.rb +10 -0
  238. data/lib/kowl/templates/tests/rspec/support/simplecov.rb +7 -0
  239. data/lib/kowl/templates/tests/rspec/support/warden.rb +8 -0
  240. data/lib/kowl/templates/text_files/AUTHORS.md +4 -0
  241. data/lib/kowl/templates/text_files/CHANGELOG.md.tt +12 -0
  242. data/lib/kowl/templates/text_files/CODE_OF_CONDUCT.md +76 -0
  243. data/lib/kowl/templates/text_files/TODO.md +7 -0
  244. data/lib/kowl/templates/text_files/VERSION +1 -0
  245. data/lib/kowl/templates/text_files/humans.txt.tt +15 -0
  246. data/lib/kowl/templates/text_files/robots.txt.tt +6 -0
  247. data/lib/kowl/templates/text_files/security.txt +6 -0
  248. data/lib/kowl/version.rb +9 -0
  249. data/lib/kowl.rb +18 -0
  250. metadata +404 -0
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationMailer < ActionMailer::Base
4
+ # The DEFAULT_EMAIL should be set in your .env file
5
+ default from: ENV.fetch('DEFAULT_EMAIL'){ 'noreply@example.com' }
6
+ layout 'mailer'
7
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DeviseMailer < Devise::Mailer
4
+ layout 'devise_mailer'
5
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LoginActivity < ApplicationRecord
4
+ # == Attributes =====================================
5
+ <%- if options[:encrypt] -%>
6
+ encrypts :identity, :ip
7
+ blind_index :identity, :ip
8
+ <%- end -%>
9
+
10
+ # == Constants ======================================
11
+
12
+ # == Extensions =====================================
13
+
14
+ # == Relationships ==================================
15
+ belongs_to :user, polymorphic: true, optional: true
16
+
17
+ # == Validations ====================================
18
+
19
+ # == Scopes =========================================
20
+ # This is used, by default to only show successful logins
21
+ # => This will remove users that are seeded, creates, and/or failed attempts
22
+ default_scope -> { where(user_type: 'User') }
23
+
24
+ # == Callbacks ======================================
25
+
26
+ # == ClassMethods ===================================
27
+
28
+ # == InstanceMethods ================================
29
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ class User < ApplicationRecord
4
+ # == Attributes =====================================
5
+ alias_attribute :avatar, :email
6
+ <%- unless options[:skip_mailer] -%>
7
+ def devise_mailer
8
+ DeviseMailer
9
+ end
10
+ <%- end -%>
11
+ <%- if options[:encrypt] -%>
12
+ # Encrypted user attributes
13
+ encrypts :email
14
+ blind_index :email
15
+ <%- end -%>
16
+
17
+ def self.policy_class
18
+ UserPolicy
19
+ end
20
+
21
+ # == Constants =====================================
22
+ enum role: { superuser: 0, staff: 1, user: 2, visitor: 3 }
23
+ # enum role: { superuser: 'superuser', staff: 'staff', user: 'user', visitor: 'visitor' }
24
+
25
+ # == Extensions ====================================
26
+ # Include default devise modules. Others available are:
27
+ # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
28
+ devise :database_authenticatable, :registerable,
29
+ :recoverable, :rememberable, :secure_validatable,
30
+ :lockable, :timeoutable, :trackable,
31
+ email_validation: false # Since we are using valid_email validator for a stricter email validator
32
+ # https://github.com/micke/valid_email2/issues/121
33
+
34
+ # == Relationships =================================
35
+ <%- if options[:database] == 'sqlserver' -%>
36
+ has_many :login_activities, as: :user, dependent: :delete_all, inverse_of: :user # devise audit log
37
+ <%- else -%>
38
+ has_many :login_activities, -> { order(created_at: :desc) }, as: :user, dependent: :delete_all, inverse_of: :user # devise audit log
39
+ <%- end -%>
40
+
41
+ # == Validations ===================================
42
+ # minimum length of 5 to match: a@a.a
43
+ validates :email, presence: true, 'valid_email_2/email': { disposable: false }, length: { minimum: 5, maximum: 255 }, uniqueness: { case_sensitive: false }, allow_nil: false
44
+ validates :role, presence: true, inclusion: { in: roles.keys }, allow_nil: false
45
+
46
+ # == Scopes ========================================
47
+
48
+ # == Callbacks =====================================
49
+ # Before any validations ensure a default role is set
50
+ before_validation do
51
+ self.role ||= :user
52
+ end
53
+
54
+ # == Class Methods =================================
55
+ def admin?
56
+ role?(:superuser)
57
+ end
58
+
59
+ def staff?
60
+ role?(:staff)
61
+ end
62
+
63
+ def staff_member?
64
+ role?(:superuser) || role?(:staff)
65
+ end
66
+
67
+ def role?(role)
68
+ self.role == role.to_s
69
+ end
70
+
71
+ # == Instance Methods ==============================
72
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationPolicy
4
+ attr_reader :current_user, :record
5
+
6
+ def initialize(current_user, record)
7
+ raise Pundit::NotAuthorizedError, 'must be logged in' unless current_user
8
+
9
+ @current_user = current_user
10
+ @record = record
11
+ end
12
+
13
+ def admin?
14
+ current_user.admin? if current_user.present?
15
+ end
16
+
17
+ def staff?
18
+ current_user.staff? if current_user.present?
19
+ end
20
+
21
+ # Used to verify if the persons role is set to either superuser or staff
22
+ def staff_member?
23
+ admin? || staff?
24
+ end
25
+
26
+ class Scope
27
+ attr_reader :user, :scope
28
+
29
+ def initialize(user, scope)
30
+ @user = user
31
+ @scope = scope
32
+ end
33
+
34
+ def resolve
35
+ scope.all
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ class LoginActivityPolicy < ApplicationPolicy
4
+ def show?
5
+ # Only display all login activity if the current user is an admin
6
+ # => Otherwise if the user is a staff member, only display login activity for everyone who isn't an admin
7
+ # => If somehow a user hits this page, only allow them to see login activity for themselves
8
+ admin? || (staff? && record.user.role != 'superuser') || (staff_member? && current_user.id == record.user_id)
9
+ end
10
+
11
+ def index?
12
+ admin? || current_user.id == record.user_id
13
+ end
14
+
15
+ # All audit logs should not be modifiable, by any means
16
+ def edit?
17
+ false
18
+ end
19
+
20
+ def new?
21
+ edit?
22
+ end
23
+
24
+ def create?
25
+ edit?
26
+ end
27
+
28
+ def update?
29
+ edit?
30
+ end
31
+
32
+ def destroy?
33
+ edit?
34
+ end
35
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ class UserPolicy < ApplicationPolicy
4
+ def index?
5
+ admin?
6
+ end
7
+
8
+ # Account should not be create-able, unless someone is explicitly signing up to create an account
9
+ def new?
10
+ false
11
+ end
12
+
13
+ def create?
14
+ false
15
+ end
16
+
17
+ def show?
18
+ # Admins should be able to see all users
19
+ # Staff members should only be able to see people who aren't superusers
20
+ # And everyone should see records for themselves
21
+ admin? || (staff? && record.role != 'superuser') || (staff_member? && current_user.id == record.id)
22
+ end
23
+
24
+ def update?
25
+ # Ensure only superusers can edit other superusers.
26
+ # => This is because we don't want a staff member editing a superuser/manager's account
27
+ # => If the current_user only has the staff as role they can only edit someone who isn't a superuser
28
+ admin? || (staff? && record.role != 'superuser') || (staff_member? && current_user.id == record.id)
29
+ end
30
+
31
+ def edit?
32
+ update?
33
+ end
34
+
35
+ def destroy?
36
+ # This was added because a user shouldn't be able to delete themselves from the admin dashboard
37
+ admin? && current_user.id != record.id
38
+ end
39
+
40
+ def impersonate?
41
+ admin? && current_user.id != record.id
42
+ end
43
+ end
@@ -0,0 +1,23 @@
1
+ <%%#
2
+ # Navigation
3
+
4
+ This partial is used to display the navigation in Administrate.
5
+ By default, the navigation contains navigation links
6
+ for all resources in the admin dashboard,
7
+ as defined by the routes in the `admin/` namespace
8
+ %>
9
+
10
+ <nav class="navigation" role="navigation">
11
+ <%%= link_to "#{icon('fas', 'home')} Homepage".html_safe, root_path, class: 'navigation__link navigation__link--inactive', title: 'Return to homepage' %>
12
+ <%% Administrate::Namespace.new(namespace).resources_with_index_route.each do |resource| %>
13
+ <%%= link_to(
14
+ display_resource_name(resource),
15
+ resource_index_route(resource),
16
+ class: "navigation__link navigation__link--#{nav_link_state(resource)}"
17
+ ) if valid_action? :index, resource %>
18
+ <%% end %>
19
+ <%- unless options[:skip_sidekiq] -%>
20
+ <%%= link_to('Sidekiq', '/sidekiq', class: 'navigation__link navigation__link--inactive') if current_user.admin? %>
21
+ <%- end -%>
22
+ <%%= link_to('LetterOpener'.html_safe, '/letter_opener', class: 'navigation__link navigation__link--inactive') if Rails.env.development? && current_user.admin? %>
23
+ </nav>
@@ -0,0 +1,21 @@
1
+ <%#
2
+ # Javascript Partial
3
+ https://github.com/thoughtbot/administrate/wiki/Rails-6-&-Webpacker
4
+
5
+ This partial imports the necessary javascript on each page.
6
+ By default, it includes the application JS,
7
+ but each page can define additional JS sources
8
+ by providing a `content_for(:javascript)` block.
9
+
10
+ Administrate::Engine.javascripts.each do |js_path|
11
+ <= echo javascript_include_tag js_path
12
+ <% end
13
+ %>
14
+
15
+ <%= yield :javascript %>
16
+ <% if Rails.env.test? %>
17
+ <%= javascript_tag do %>
18
+ $.fx.off = true;
19
+ $.ajaxSetup({ async: false });
20
+ <% end %>
21
+ <% end %>
@@ -0,0 +1,102 @@
1
+ <%#
2
+ # Collection
3
+
4
+ This partial is used on the `index` and `show` pages
5
+ to display a collection of resources in an HTML table.
6
+
7
+ ## Local variables:
8
+
9
+ - `collection_presenter`:
10
+ An instance of [Administrate::Page::Collection][1].
11
+ The table presenter uses `ResourceDashboard::COLLECTION_ATTRIBUTES` to determine
12
+ the columns displayed in the table
13
+ - `resources`:
14
+ An ActiveModel::Relation collection of resources to be displayed in the table.
15
+ By default, the number of resources is limited by pagination
16
+ or by a hard limit to prevent excessive page load times
17
+
18
+ [1]: http://www.rubydoc.info/gems/administrate/Administrate/Page/Collection
19
+ %>
20
+ <table aria-labelledby="<%= table_title %>">
21
+ <thead>
22
+ <tr>
23
+ <td>&nbsp;</td>
24
+ <% collection_presenter.attribute_types.each do |attr_name, attr_type| %>
25
+ <th class="cell-label
26
+ cell-label--<%= attr_type.html_class %>
27
+ cell-label--<%= collection_presenter.ordered_html_class(attr_name) %>"
28
+ scope="col"
29
+ role="columnheader"
30
+ aria-sort="<%= sort_order(collection_presenter.ordered_html_class(attr_name)) %>">
31
+ <%= link_to(sanitized_order_params(page, collection_field_name).merge(
32
+ collection_presenter.order_params_for(attr_name, key: collection_field_name)
33
+ )) do %>
34
+ <%= t(
35
+ "helpers.label.#{collection_presenter.resource_name}.#{attr_name}",
36
+ default: attr_name.to_s,
37
+ ).titleize %>
38
+ <% if collection_presenter.ordered_by?(attr_name) %>
39
+ <span class="cell-label__sort-indicator cell-label__sort-indicator--<%= collection_presenter.ordered_html_class(attr_name) %>">
40
+ <svg aria-hidden="true">
41
+ <use xlink:href="#icon-up-caret" />
42
+ </svg>
43
+ </span>
44
+ <% end %>
45
+ <% end %>
46
+ </th>
47
+ <% end %>
48
+ <% [valid_action?(:edit, collection_presenter.resource_name),
49
+ valid_action?(:destroy, collection_presenter.resource_name)].count(true).times do %>
50
+ <th scope="col"></th>
51
+ <% end %>
52
+ </tr>
53
+ </thead>
54
+
55
+ <tbody>
56
+ <% resources.each do |resource| %>
57
+ <%- if show_action? :show, resource %>
58
+ <tr class="js-table-row"
59
+ tabindex="0"
60
+ <% if valid_action? :show, collection_presenter.resource_name %>
61
+ <%= %(role=link data-url=#{polymorphic_path([namespace, resource])}) %>
62
+ <% end %>
63
+ >
64
+ <td>
65
+ <%- if resource.class.to_s == "User" && policy(resource).impersonate? %>
66
+ <%= link_to (raw icon('fas','theater-masks')), impersonate_user_path(resource.id) %>
67
+ <% end %>
68
+ </td>
69
+ <% collection_presenter.attributes_for(resource).each do |attribute| %>
70
+ <td class="cell-data cell-data--<%= attribute.html_class %>">
71
+ <% if show_action? :show, resource -%>
72
+ <a href="<%= polymorphic_path([namespace, resource]) -%>"
73
+ class="action-show"
74
+ >
75
+ <%= render_field attribute %>
76
+ </a>
77
+ <% end -%>
78
+ </td>
79
+ <% end %>
80
+
81
+ <% if valid_action? :edit, collection_presenter.resource_name %>
82
+ <td><%= link_to(
83
+ t("administrate.actions.edit"),
84
+ [:edit, namespace, resource],
85
+ class: "action-edit",
86
+ ) if show_action? :edit, resource%></td>
87
+ <% end %>
88
+
89
+ <% if valid_action? :destroy, collection_presenter.resource_name %>
90
+ <td><%= link_to(
91
+ t("administrate.actions.destroy"),
92
+ [namespace, resource],
93
+ class: "text-color-red",
94
+ method: :delete,
95
+ data: { confirm: t("administrate.actions.confirm") }
96
+ ) if show_action? :destroy, resource %></td>
97
+ <% end %>
98
+ </tr>
99
+ <% end %>
100
+ <% end %>
101
+ </tbody>
102
+ </table>
@@ -0,0 +1,46 @@
1
+ <%#
2
+ # Form Partial
3
+
4
+ This partial is rendered on a resource's `new` and `edit` pages,
5
+ and renders all form fields for a resource's editable attributes.
6
+
7
+ ## Local variables:
8
+
9
+ - `page`:
10
+ An instance of [Administrate::Page::Form][1].
11
+ Contains helper methods to display a form,
12
+ and knows which attributes should be displayed in the resource's form.
13
+
14
+ [1]: http://www.rubydoc.info/gems/administrate/Administrate/Page/Form
15
+ %>
16
+
17
+ <%= form_for([namespace, page.resource], html: { class: "form" }) do |f| %>
18
+ <% if page.resource.errors.any? %>
19
+ <div id="error_explanation">
20
+ <h2>
21
+ <%= t(
22
+ "administrate.form.errors",
23
+ pluralized_errors: pluralize(page.resource.errors.count, t("administrate.form.error")),
24
+ resource_name: display_resource_name(page.resource_name)
25
+ ) %>
26
+ </h2>
27
+
28
+ <ul>
29
+ <% page.resource.errors.full_messages.each do |message| %>
30
+ <li class="flash-error"><%= message %></li>
31
+ <% end %>
32
+ </ul>
33
+ </div>
34
+ <% end %>
35
+
36
+ <% page.attributes.each do |attribute| -%>
37
+ <% next if attribute.attribute == :role && !current_user.admin? %>
38
+ <div class="field-unit field-unit--<%= attribute.html_class %>">
39
+ <%= render_field attribute, f: f %>
40
+ </div>
41
+ <% end -%>
42
+
43
+ <div class="form-actions">
44
+ <%= f.submit %>
45
+ </div>
46
+ <% end %>
@@ -0,0 +1,36 @@
1
+ <%#
2
+ # Edit
3
+
4
+ This view is the template for the edit page.
5
+
6
+ It displays a header, and renders the `_form` partial to do the heavy lifting.
7
+
8
+ ## Local variables:
9
+
10
+ - `page`:
11
+ An instance of [Administrate::Page::Form][1].
12
+ Contains helper methods to help display a form,
13
+ and knows which attributes should be displayed in the resource's form.
14
+
15
+ [1]: http://www.rubydoc.info/gems/administrate/Administrate/Page/Form
16
+ %>
17
+
18
+ <% content_for(:title) { t("administrate.actions.edit_resource", name: page.page_title) } %>
19
+
20
+ <header class="main-content__header" role="banner">
21
+ <h1 class="main-content__page-title">
22
+ <%= content_for(:title) %>
23
+ </h1>
24
+
25
+ <div>
26
+ <%= link_to(
27
+ t("administrate.actions.show_resource", name: page.page_title),
28
+ [namespace, page.resource],
29
+ class: "button",
30
+ ) if valid_action?(:show) && show_action?(:show, page.resource) %>
31
+ </div>
32
+ </header>
33
+
34
+ <section class="main-content__body">
35
+ <%= render "form", page: page %>
36
+ </section>
@@ -0,0 +1,66 @@
1
+ <%#
2
+ # Index
3
+
4
+ This view is the template for the index page.
5
+ It is responsible for rendering the search bar, header and pagination.
6
+ It renders the `_table` partial to display details about the resources.
7
+
8
+ ## Local variables:
9
+
10
+ - `page`:
11
+ An instance of [Administrate::Page::Collection][1].
12
+ Contains helper methods to help display a table,
13
+ and knows which attributes should be displayed in the resource's table.
14
+ - `resources`:
15
+ An instance of `ActiveRecord::Relation` containing the resources
16
+ that match the user's search criteria.
17
+ By default, these resources are passed to the table partial to be displayed.
18
+ - `search_term`:
19
+ A string containing the term the user has searched for, if any.
20
+ - `show_search_bar`:
21
+ A boolean that determines if the search bar should be shown.
22
+
23
+ [1]: http://www.rubydoc.info/gems/administrate/Administrate/Page/Collection
24
+ %>
25
+
26
+ <% content_for(:title) do %>
27
+ <%= display_resource_name(page.resource_name) %>
28
+ <% end %>
29
+
30
+ <header class="main-content__header" role="banner">
31
+ <h1 class="main-content__page-title" id="page-title">
32
+ <%= content_for(:title) %>
33
+ </h1>
34
+
35
+ <% if show_search_bar %>
36
+ <%= render(
37
+ "search",
38
+ search_term: search_term,
39
+ resource_name: display_resource_name(page.resource_name)
40
+ ) %>
41
+ <% end %>
42
+
43
+ <div>
44
+ <%= link_to(
45
+ t(
46
+ "administrate.actions.new_resource",
47
+ name: page.resource_name.titleize.downcase
48
+ ),
49
+ [:new, namespace, page.resource_path],
50
+ class: "button",
51
+ ) if valid_action?(:new) && show_action?(:new, new_resource) %>
52
+ </div>
53
+ </header>
54
+
55
+ <section class="main-content__body main-content__body--flush">
56
+ <%= render(
57
+ "collection",
58
+ collection_presenter: page,
59
+ collection_field_name: resource_name,
60
+ page: page,
61
+ resources: resources,
62
+ table_title: "page-title"
63
+ ) %>
64
+
65
+ <%= paginate resources %>
66
+ </section>
@@ -0,0 +1,6 @@
1
+ <div class="field-unit__label">
2
+ <%= f.label field.attribute %>
3
+ </div>
4
+ <div class="field-unit__field">
5
+ <%= f.text_field field.attribute %>
6
+ </div>
@@ -0,0 +1 @@
1
+ <%= image_tag field.gravatar_url %>
@@ -0,0 +1 @@
1
+ <%= image_tag field.gravatar_url %>
@@ -0,0 +1,6 @@
1
+ <div class="field-unit__label">
2
+ <%= f.label field.attribute %>
3
+ </div>
4
+ <div class="field-unit__field">
5
+ <%= f.rich_text_area(field.attribute) %>
6
+ </div>
@@ -0,0 +1,47 @@
1
+ <%#
2
+ # Application Layout
3
+
4
+ This view template is used as the layout
5
+ for every page that Administrate generates.
6
+
7
+ By default, it renders:
8
+ - Navigation
9
+ - Content for a search bar
10
+ (if provided by a `content_for` block in a nested page)
11
+ - Flashes
12
+ - Links to stylesheets and JavaScripts
13
+ %>
14
+
15
+ <!DOCTYPE html>
16
+ <html lang="<%%= I18n.locale %>">
17
+ <head>
18
+ <meta charset="utf-8">
19
+ <meta name="robots" content="noodp, noydir, index, follow">
20
+ <meta name="viewport" content="initial-scale=1">
21
+ <%%- set_meta_tags title: (content_for(:title) || 'Dashboard') %>
22
+ <%%= display_meta_tags site: '<%= app_name.titleize %>' %>
23
+ <%- unless options[:skip_javascript] -%>
24
+ <%%= javascript_pack_tag 'administrate'<%= options[:skip_turbolinks] ? '' : ", 'data-turbolinks-track': 'reload'" -%> %>
25
+ <%- end -%>
26
+ <%%= render "stylesheet" %>
27
+ <%%= csrf_meta_tags %>
28
+ <%- unless options[:skip_turbolinks] || options[:skip_javascript] -%>
29
+ <meta name="turbolinks-root" content="/admin">
30
+ <%- end -%>
31
+ </head>
32
+ <body>
33
+ <div class="app-container">
34
+ <%%= render "navigation" -%>
35
+ <main class="main-content" role="main">
36
+ <%%= render "flashes" -%>
37
+ <%%= yield %>
38
+ </main>
39
+ </div>
40
+ <div style="display: none; width: 0; height: 0; overflow: hidden; position: absolute">
41
+ <%%= render "icons" %>
42
+ </div>
43
+ <%- unless options[:skip_javascript] -%>
44
+ <%%= render "javascript" %>
45
+ <%- end -%>
46
+ </body>
47
+ </html>
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5
+ <%= stylesheet_link_tag "application-mailer", media: "all" %>
6
+ </head>
7
+ <body class="bg-light">
8
+ <div class="container-fluid">
9
+ <div class="card card-body my-3">
10
+ <%= yield %>
11
+ </div>
12
+ </div>
13
+ </body>
14
+ </html>
@@ -0,0 +1,18 @@
1
+ <h2><%= title('Welcome') %></h2>
2
+ <p class="lead">
3
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
4
+ Mauris maximus vulputate gravida.
5
+ Integer eget mauris at orci molestie porta.
6
+ </p>
7
+ <p>
8
+ In scelerisque leo vitae lacus commodo, eu tincidunt nisi suscipit.
9
+ Pellentesque at sapien duiDuis sit amet arcu non ante sodales varius.
10
+ Fusce nibh nulla, mollis a dolor eu, iaculis pharetra lectus.
11
+ Sed turpis quam, imperdiet ut faucibus sit amet, efficitur ut nulla.
12
+ Duis non accumsan lacus.
13
+ Vestibulum nec diam quis dui convallis rhoncus quis sit amet massa.
14
+ Maecenas ac est purus. Aliquam erat volutpat.
15
+ Vestibulum tempus pharetra viverra.
16
+ Etiam vestibulum et elit in vulputate.
17
+ Quisque eget elementum purus, id volutpat augue.
18
+ </p>
@@ -0,0 +1,17 @@
1
+ %h2 = title('Welcome')
2
+ %p.lead
3
+ | Lorem ipsum dolor sit amet, consectetur adipiscing elit.
4
+ | Mauris maximus vulputate gravida.
5
+ | Integer eget mauris at orci molestie porta.
6
+
7
+ %p
8
+ | In scelerisque leo vitae lacus commodo, eu tincidunt nisi suscipit.
9
+ | Pellentesque at sapien duiDuis sit amet arcu non ante sodales varius.
10
+ | Fusce nibh nulla, mollis a dolor eu, iaculis pharetra lectus.
11
+ | Sed turpis quam, imperdiet ut faucibus sit amet, efficitur ut nulla.
12
+ | Duis non accumsan lacus.
13
+ | Vestibulum nec diam quis dui convallis rhoncus quis sit amet massa.
14
+ | Maecenas ac est purus. Aliquam erat volutpat.
15
+ | Vestibulum tempus pharetra viverra.
16
+ | Etiam vestibulum et elit in vulputate.
17
+ | Quisque eget elementum purus, id volutpat augue.