trek 0.1.23 → 0.1.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/AGENTS.md +55 -0
- data/CHANGELOG.md +20 -0
- data/CLAUDE.md +1 -0
- data/Gemfile.lock +6 -6
- data/Makefile +1 -0
- data/app/components/trek/form/actions_component/actions_component.css +2 -2
- data/app/controllers/concerns/trek/authentication.rb +1 -1
- data/app/controllers/concerns/trek/filters.rb +52 -0
- data/app/controllers/concerns/trek/localization.rb +1 -1
- data/app/controllers/concerns/trek/scopes.rb +24 -0
- data/app/helpers/trek/theme_helper.rb +2 -2
- data/app/models/concerns/trek/users/invitable.rb +4 -3
- data/config/locales/trek.en.yml +9 -6
- data/config/locales/trek.fr.yml +9 -6
- data/docs/.vitepress/config.mjs +5 -0
- data/docs/reference/controllers.md +72 -0
- data/lib/generators/trek/helpers.rb +15 -0
- data/lib/generators/trek/install/admin/user_password_resets_generator.rb +0 -4
- data/lib/generators/trek/install/admin/user_sessions_generator.rb +0 -7
- data/lib/generators/trek/install/admin/users_generator.rb +5 -1
- data/lib/generators/trek/install/agents_generator.rb +26 -0
- data/lib/generators/trek/install/attachments_generator.rb +3 -1
- data/lib/generators/trek/install/authentication_generator.rb +70 -1
- data/lib/generators/trek/install/authorization_generator.rb +4 -2
- data/lib/generators/trek/install/brakeman_generator.rb +4 -2
- data/lib/generators/trek/install/bundler_audit_generator.rb +4 -2
- data/lib/generators/trek/install/config_generator.rb +4 -0
- data/lib/generators/trek/install/healthcheck_generator.rb +4 -2
- data/lib/generators/trek/install/kaminari_generator.rb +4 -2
- data/lib/generators/trek/install/locales_generator.rb +10 -7
- data/lib/generators/trek/install/lookbook_generator.rb +3 -1
- data/lib/generators/trek/install/mailer_generator.rb +14 -9
- data/lib/generators/trek/install/page_generator.rb +4 -2
- data/lib/generators/trek/install/postmark_generator.rb +5 -3
- data/lib/generators/trek/install/rubocop_generator.rb +4 -2
- data/lib/generators/trek/install/scalingo_generator.rb +2 -1
- data/lib/generators/trek/install/slim_lint_generator.rb +4 -2
- data/lib/generators/trek/install/specs_generator.rb +3 -2
- data/lib/generators/trek/install/strip_attributes_generator.rb +4 -2
- data/lib/generators/trek/install/translations_generator.rb +3 -1
- data/lib/generators/trek/install/user_generator.rb +27 -1
- data/lib/generators/trek/install/yarn_generator.rb +8 -0
- data/lib/generators/trek/install_generator.rb +11 -4
- data/lib/generators/trek/templates/.gitlab-ci.yml +1 -1
- data/lib/generators/trek/templates/AGENTS.md +36 -0
- data/lib/generators/trek/templates/controllers/admin/base_controller.rb +1 -0
- data/lib/generators/trek/templates/controllers/admin/user_password_resets_controller.rb +26 -27
- data/lib/generators/trek/templates/controllers/admin/user_sessions_controller.rb +13 -20
- data/lib/generators/trek/templates/controllers/admin/users_controller.rb +13 -0
- data/lib/generators/trek/templates/controllers/concerns/trek/authentication.rb +62 -0
- data/lib/generators/trek/templates/layouts/admin.html.slim +1 -1
- data/lib/generators/trek/templates/mailers/admin/passwords_mailer.rb +13 -0
- data/lib/generators/trek/templates/mailers/admin_mailer.rb +13 -0
- data/lib/generators/trek/templates/migrations/create_users.rb.erb +11 -0
- data/lib/generators/trek/templates/migrations/user_sessions.rb.erb +11 -0
- data/lib/generators/trek/templates/migrations/users.rb.erb +2 -0
- data/lib/generators/trek/templates/models/current.rb +3 -0
- data/lib/generators/trek/templates/models/user.rb +2 -0
- data/lib/generators/trek/templates/models/user_session.rb +3 -0
- data/lib/generators/trek/templates/views/admin/dashboards/index.html.slim +2 -1
- data/lib/generators/trek/templates/views/admin/pages/_form.html.slim +0 -14
- data/lib/generators/trek/templates/views/admin/passwords_mailer/reset.en.html.slim +10 -0
- data/lib/generators/trek/templates/views/{user_mailer/reset_password_email.en.text.erb → admin/passwords_mailer/reset.en.text.erb} +3 -1
- data/lib/generators/trek/templates/views/admin/passwords_mailer/reset.fr.html.slim +10 -0
- data/lib/generators/trek/templates/views/admin/passwords_mailer/reset.fr.text.erb +11 -0
- data/lib/generators/trek/templates/views/admin/user_password_resets/edit.html.slim +7 -7
- data/lib/generators/trek/templates/views/admin/user_password_resets/new.html.slim +5 -2
- data/lib/generators/trek/templates/views/admin/user_sessions/new.html.slim +12 -3
- data/lib/generators/trek/templates/views/admin/users/show.html.slim +1 -1
- data/lib/generators/trek/templates/views/admin_mailer/invite.en.html.slim +9 -0
- data/lib/generators/trek/templates/views/{user_mailer/invite_email.en.text.erb → admin_mailer/invite.en.text.erb} +3 -1
- data/lib/generators/trek/templates/views/admin_mailer/invite.fr.html.slim +9 -0
- data/lib/generators/trek/templates/views/{user_mailer/reset_password_email.fr.text.erb → admin_mailer/invite.fr.text.erb} +3 -1
- data/lib/trek/version.rb +1 -1
- data/package.json +3 -2
- data/yarn.lock +1807 -2486
- metadata +22 -12
- data/app/models/trek/user_password_reset.rb +0 -12
- data/lib/generators/trek/templates/mailers/user_mailer.rb +0 -21
- data/lib/generators/trek/templates/views/user_mailer/invite_email.en.html.slim +0 -29
- data/lib/generators/trek/templates/views/user_mailer/invite_email.fr.html.slim +0 -29
- data/lib/generators/trek/templates/views/user_mailer/invite_email.fr.text.erb +0 -9
- data/lib/generators/trek/templates/views/user_mailer/reset_password_email.en.html.slim +0 -7
- data/lib/generators/trek/templates/views/user_mailer/reset_password_email.fr.html.slim +0 -7
|
@@ -6,13 +6,82 @@ module Trek
|
|
|
6
6
|
module Generators
|
|
7
7
|
module Install
|
|
8
8
|
class AuthenticationGenerator < Rails::Generators::Base
|
|
9
|
+
USER_MODEL_CLASS_NAME = "User".freeze
|
|
10
|
+
|
|
11
|
+
include Rails::Generators::Migration
|
|
9
12
|
include Trek::Generators::Helpers
|
|
10
13
|
|
|
11
14
|
desc "Setup authentication."
|
|
12
15
|
|
|
13
16
|
source_root File.expand_path("../templates", __dir__)
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
def add_bcrypt_gem
|
|
19
|
+
return if in_gemfile?("bcrypt")
|
|
20
|
+
|
|
21
|
+
gem "bcrypt", "~> 3.1.7"
|
|
22
|
+
bundle_install
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def copy_admin_authentication_concern
|
|
26
|
+
template "controllers/concerns/trek/authentication.rb",
|
|
27
|
+
"app/controllers/concerns/trek/authentication.rb"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def copy_user_session_model
|
|
31
|
+
template "models/user_session.rb",
|
|
32
|
+
"app/models/user_session.rb"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def copy_user_sessions_migration
|
|
36
|
+
return unless defined?(ActiveRecord)
|
|
37
|
+
|
|
38
|
+
migration_template("migrations/user_sessions.rb.erb",
|
|
39
|
+
"db/migrate/trek_user_sessions.rb",
|
|
40
|
+
migration_class_name:)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def inject_authentication_into_user_model
|
|
44
|
+
inject_into_class user_model_path,
|
|
45
|
+
USER_MODEL_CLASS_NAME,
|
|
46
|
+
user_model_injection
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def add_admin_auth_routes
|
|
50
|
+
route "resource :user_session, only: %i[new create destroy]", namespace: :admin
|
|
51
|
+
route "resources :user_password_resets, param: :token, only: %i[new create edit update]", namespace: :admin
|
|
52
|
+
route 'get :login, to: "user_sessions#new", as: :login', namespace: :admin
|
|
53
|
+
route 'delete :logout, to: "user_sessions#destroy", as: :logout', namespace: :admin
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def autocorrect_user_model
|
|
57
|
+
run "rubocop --autocorrect #{user_model_path}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def user_model_path
|
|
63
|
+
@user_model_path ||= File.join("app", "models", "#{USER_MODEL_CLASS_NAME.underscore}.rb")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def user_model_injection
|
|
67
|
+
<<-RUBY
|
|
68
|
+
has_secure_password
|
|
69
|
+
has_many :user_sessions, dependent: :destroy
|
|
70
|
+
|
|
71
|
+
# Both tokens invalidate once the password changes (password_salt). Invites
|
|
72
|
+
# get a longer window than a password reset, so they are a distinct purpose.
|
|
73
|
+
generates_token_for :password_reset, expires_in: 15.minutes do
|
|
74
|
+
password_salt&.last(10)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
generates_token_for :invite, expires_in: 1.week do
|
|
78
|
+
password_salt&.last(10)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
scope :privileged, -> { where(role: Trek::Users::Roles::PRIVILEGED_ROLES) }
|
|
82
|
+
|
|
83
|
+
RUBY
|
|
84
|
+
end
|
|
16
85
|
end
|
|
17
86
|
end
|
|
18
87
|
end
|
|
@@ -13,8 +13,10 @@ module Trek
|
|
|
13
13
|
source_root File.expand_path("../templates", __dir__)
|
|
14
14
|
|
|
15
15
|
def add_gem
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
return if in_gemfile?("action_policy")
|
|
17
|
+
|
|
18
|
+
gem "action_policy"
|
|
19
|
+
bundle_install
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
def run_install
|
|
@@ -12,8 +12,10 @@ module Trek
|
|
|
12
12
|
source_root File.expand_path("../../../../", __dir__)
|
|
13
13
|
|
|
14
14
|
def add_gem
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
return if in_gemfile?("brakeman")
|
|
16
|
+
|
|
17
|
+
gem "brakeman", group: [:development, :test]
|
|
18
|
+
bundle_install
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
end
|
|
@@ -12,8 +12,10 @@ module Trek
|
|
|
12
12
|
source_root File.expand_path("../../../../", __dir__)
|
|
13
13
|
|
|
14
14
|
def add_gem
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
return if in_gemfile?("bundler-audit")
|
|
16
|
+
|
|
17
|
+
gem "bundler-audit", group: [:development, :test]
|
|
18
|
+
bundle_install
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
end
|
|
@@ -22,6 +22,10 @@ module Trek
|
|
|
22
22
|
Rails.application.routes.default_url_options[:protocol] = Rails.application.config.force_ssl ? "https" : "http"
|
|
23
23
|
Rails.application.routes.default_url_options[:host] = ENV.fetch("DEFAULT_HOSTNAME", "localhost:3000")
|
|
24
24
|
Rails.application.config.canonical_url = "\#{Rails.application.routes.default_url_options[:protocol]}://\#{Rails.application.routes.default_url_options[:host]}"
|
|
25
|
+
|
|
26
|
+
# Mailers run outside a request, so in production they need the same host for
|
|
27
|
+
# link helpers. Development and test keep the host from their environment files.
|
|
28
|
+
ActionMailer::Base.default_url_options = Rails.application.routes.default_url_options if Rails.env.production?
|
|
25
29
|
RUBY
|
|
26
30
|
end
|
|
27
31
|
end
|
|
@@ -12,8 +12,10 @@ module Trek
|
|
|
12
12
|
source_root File.expand_path("../templates", __dir__)
|
|
13
13
|
|
|
14
14
|
def add_gem
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
return if in_gemfile?("rails-healthcheck")
|
|
16
|
+
|
|
17
|
+
gem "rails-healthcheck"
|
|
18
|
+
bundle_install
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def add_initializer
|
|
@@ -10,8 +10,10 @@ module Trek
|
|
|
10
10
|
desc "Install Kaminari."
|
|
11
11
|
|
|
12
12
|
def add_gem
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
return if in_gemfile?("kaminari")
|
|
14
|
+
|
|
15
|
+
gem "kaminari"
|
|
16
|
+
bundle_install
|
|
15
17
|
end
|
|
16
18
|
end
|
|
17
19
|
end
|
|
@@ -12,16 +12,19 @@ module Trek
|
|
|
12
12
|
|
|
13
13
|
source_root File.expand_path("../templates", __dir__)
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@locales = ENV["TREK_LOCALES"] || ask("What locales do you want to use? (e.g. en, fr)")
|
|
15
|
+
class_option :locales, type: :string,
|
|
16
|
+
desc: "Comma-separated locales to enable, e.g. en,fr (default: en)"
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
def set_locales
|
|
19
|
+
raw = options[:locales] || ENV["TREK_LOCALES"] || "en"
|
|
20
|
+
@locales = raw.split(",").map(&:strip)
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
invalid = @locales.reject { |locale| valid_locales?(locale) }
|
|
23
|
+
return if invalid.empty?
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
say "Ignoring unavailable locales: #{invalid.join(", ")}", :yellow
|
|
26
|
+
@locales -= invalid
|
|
27
|
+
@locales = ["en"] if @locales.empty?
|
|
25
28
|
end
|
|
26
29
|
|
|
27
30
|
def create_locales_initializer
|
|
@@ -13,11 +13,13 @@ module Trek
|
|
|
13
13
|
source_root File.expand_path("../../../../", __dir__)
|
|
14
14
|
|
|
15
15
|
def add_gem
|
|
16
|
+
install_needed = %w[lookbook listen actioncable].any? { |name| !in_gemfile?(name) }
|
|
17
|
+
|
|
16
18
|
gem "lookbook", ">= 2.3.13", group: :development unless in_gemfile?("lookbook")
|
|
17
19
|
gem "listen", group: :development unless in_gemfile?("listen")
|
|
18
20
|
gem "actioncable", group: :development unless in_gemfile?("actioncable")
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
bundle_install if install_needed
|
|
21
23
|
end
|
|
22
24
|
end
|
|
23
25
|
end
|
|
@@ -19,25 +19,30 @@ module Trek
|
|
|
19
19
|
"app/views/layouts/mailer.html.slim"
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
def
|
|
23
|
-
template "mailers/
|
|
24
|
-
"app/mailers/
|
|
22
|
+
def admin_mailer
|
|
23
|
+
template "mailers/admin_mailer.rb",
|
|
24
|
+
"app/mailers/admin_mailer.rb"
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
def
|
|
27
|
+
def passwords_mailer
|
|
28
|
+
template "mailers/admin/passwords_mailer.rb",
|
|
29
|
+
"app/mailers/admin/passwords_mailer.rb"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def copy_views_admin_mailer_invite
|
|
28
33
|
extensions.each do |extension|
|
|
29
34
|
locales.each do |lang|
|
|
30
|
-
template "views/
|
|
31
|
-
"app/views/
|
|
35
|
+
template "views/admin_mailer/invite.#{lang}#{extension}",
|
|
36
|
+
"app/views/admin_mailer/invite.#{lang}#{extension}"
|
|
32
37
|
end
|
|
33
38
|
end
|
|
34
39
|
end
|
|
35
40
|
|
|
36
|
-
def
|
|
41
|
+
def copy_views_passwords_mailer_reset
|
|
37
42
|
extensions.each do |extension|
|
|
38
43
|
locales.each do |lang|
|
|
39
|
-
template "views/
|
|
40
|
-
"app/views/
|
|
44
|
+
template "views/admin/passwords_mailer/reset.#{lang}#{extension}",
|
|
45
|
+
"app/views/admin/passwords_mailer/reset.#{lang}#{extension}"
|
|
41
46
|
end
|
|
42
47
|
end
|
|
43
48
|
end
|
|
@@ -55,8 +55,10 @@ module Trek
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def install_closure_tree
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
unless in_gemfile?("closure_tree")
|
|
59
|
+
gem "closure_tree", "~> 9.0"
|
|
60
|
+
bundle_install
|
|
61
|
+
end
|
|
60
62
|
rails_command "db:migrate" # `pages` table must exist
|
|
61
63
|
generate "closure_tree:migration Page"
|
|
62
64
|
end
|
|
@@ -13,8 +13,10 @@ module Trek
|
|
|
13
13
|
source_root File.expand_path("../templates", __dir__)
|
|
14
14
|
|
|
15
15
|
def add_gem
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
return if in_gemfile?("postmark-rails")
|
|
17
|
+
|
|
18
|
+
gem "postmark-rails"
|
|
19
|
+
bundle_install
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
def inject_postmark_to_application_mailer
|
|
@@ -28,7 +30,7 @@ module Trek
|
|
|
28
30
|
def inject_postmark_to_config
|
|
29
31
|
inject_into_file "config/environments/production.rb",
|
|
30
32
|
config_injection,
|
|
31
|
-
after:
|
|
33
|
+
after: %r{# Specify outgoing SMTP server\. Remember to add smtp/\* credentials via (?:bin/)?rails credentials:edit\.\n}
|
|
32
34
|
run "rubocop --autocorrect config/environments/production.rb", abort_on_failure: true
|
|
33
35
|
end
|
|
34
36
|
|
|
@@ -12,8 +12,10 @@ module Trek
|
|
|
12
12
|
source_root File.expand_path("../../../../", __dir__)
|
|
13
13
|
|
|
14
14
|
def add_gem
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
return if in_gemfile?("rubocop-rspec")
|
|
16
|
+
|
|
17
|
+
gem "rubocop-rspec", group: [:development, :test], require: false
|
|
18
|
+
bundle_install
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def copy_rubocop_config
|
|
@@ -12,8 +12,10 @@ module Trek
|
|
|
12
12
|
source_root File.expand_path("../../../../", __dir__)
|
|
13
13
|
|
|
14
14
|
def add_gem
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
return if in_gemfile?("slim_lint")
|
|
16
|
+
|
|
17
|
+
gem "slim_lint", group: [:development, :test]
|
|
18
|
+
bundle_install
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def copy_slim_lint_config
|
|
@@ -13,13 +13,14 @@ module Trek
|
|
|
13
13
|
source_root File.expand_path("../templates", __dir__)
|
|
14
14
|
|
|
15
15
|
def add_gems
|
|
16
|
+
install_needed = %w[rspec-rails capybara rspec_junit_formatter rspec-html-matchers simplecov].any? { |name| !in_gemfile?(name) }
|
|
17
|
+
|
|
16
18
|
gem "rspec-rails", "~> 8.0", group: [:development, :test] unless in_gemfile?("rspec-rails")
|
|
17
19
|
gem "capybara", "~> 3.38", group: [:test] unless in_gemfile?("capybara")
|
|
18
20
|
gem "rspec_junit_formatter", "~> 0.6.0", group: [:test] unless in_gemfile?("rspec_junit_formatter")
|
|
19
21
|
gem "rspec-html-matchers", "~> 0.10.0", group: [:test] unless in_gemfile?("rspec-html-matchers")
|
|
20
22
|
gem "simplecov", "~> 0.22.0", group: [:test] unless in_gemfile?("simplecov")
|
|
21
|
-
|
|
22
|
-
run "bundle install --quiet", abort_on_failure: true
|
|
23
|
+
bundle_install if install_needed
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
def run_install
|
|
@@ -12,8 +12,10 @@ module Trek
|
|
|
12
12
|
source_root File.expand_path("../templates", __dir__)
|
|
13
13
|
|
|
14
14
|
def add_gem
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
return if in_gemfile?("strip_attributes")
|
|
16
|
+
|
|
17
|
+
gem "strip_attributes"
|
|
18
|
+
bundle_install
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
end
|
|
@@ -13,11 +13,13 @@ module Trek
|
|
|
13
13
|
source_root File.expand_path("../templates", __dir__)
|
|
14
14
|
|
|
15
15
|
def add_gem
|
|
16
|
+
install_needed = %w[rails-i18n i18n-tasks deepl-rb mobility].any? { |name| !in_gemfile?(name) }
|
|
17
|
+
|
|
16
18
|
gem "rails-i18n", ">= 6.0.0" unless in_gemfile?("rails-i18n")
|
|
17
19
|
gem "i18n-tasks", "~> 1.0" unless in_gemfile?("i18n-tasks")
|
|
18
20
|
gem "deepl-rb", "~> 3.0" unless in_gemfile?("deepl-rb")
|
|
19
21
|
gem "mobility", "~> 1.3.2" unless in_gemfile?("mobility")
|
|
20
|
-
|
|
22
|
+
bundle_install if install_needed
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def run_install
|
|
@@ -15,11 +15,25 @@ module Trek
|
|
|
15
15
|
|
|
16
16
|
source_root File.expand_path("../templates", __dir__)
|
|
17
17
|
|
|
18
|
+
def create_user_model
|
|
19
|
+
return if user_model_existed?
|
|
20
|
+
|
|
21
|
+
template "models/user.rb", user_model_path
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def create_users_migration
|
|
25
|
+
return unless defined?(ActiveRecord)
|
|
26
|
+
return if user_model_existed?
|
|
27
|
+
|
|
28
|
+
migration_template("migrations/create_users.rb.erb",
|
|
29
|
+
"db/migrate/trek_create_users.rb",
|
|
30
|
+
migration_class_name:)
|
|
31
|
+
end
|
|
32
|
+
|
|
18
33
|
def inject_trek_to_user_model
|
|
19
34
|
inject_into_class user_model_path,
|
|
20
35
|
USER_MODEL_CLASS_NAME,
|
|
21
36
|
user_model_injection
|
|
22
|
-
run "rubocop --autocorrect #{user_model_path}", abort_on_failure: true
|
|
23
37
|
end
|
|
24
38
|
|
|
25
39
|
def copy_migration_files
|
|
@@ -30,12 +44,24 @@ module Trek
|
|
|
30
44
|
migration_class_name:)
|
|
31
45
|
end
|
|
32
46
|
|
|
47
|
+
def autocorrect_user_model
|
|
48
|
+
run "rubocop --autocorrect #{user_model_path}"
|
|
49
|
+
end
|
|
50
|
+
|
|
33
51
|
private
|
|
34
52
|
|
|
35
53
|
def tableized_model_class
|
|
36
54
|
USER_MODEL_CLASS_NAME.gsub("::", "").tableize
|
|
37
55
|
end
|
|
38
56
|
|
|
57
|
+
# Memoizes whether the User model existed *before* this generator ran, so the
|
|
58
|
+
# value stays stable after `create_user_model` writes the file.
|
|
59
|
+
def user_model_existed?
|
|
60
|
+
return @user_model_existed unless @user_model_existed.nil?
|
|
61
|
+
|
|
62
|
+
@user_model_existed = File.exist?(user_model_path)
|
|
63
|
+
end
|
|
64
|
+
|
|
39
65
|
def user_model_path
|
|
40
66
|
@user_model_path ||= File.join("app", "models", "#{user_file_path}.rb")
|
|
41
67
|
end
|
|
@@ -45,6 +45,14 @@ module Trek
|
|
|
45
45
|
run "yarn plugin import interactive-tools"
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
# The default bin/setup (generated by `rails new -j esbuild`) runs
|
|
49
|
+
# `yarn install --check-files`, but `--check-files` is not a valid flag
|
|
50
|
+
# under Yarn berry (the version we pin above), so it breaks `bin/setup`
|
|
51
|
+
# in CI. Drop the flag.
|
|
52
|
+
def fix_bin_setup
|
|
53
|
+
gsub_file "bin/setup", "yarn install --check-files", "yarn install"
|
|
54
|
+
end
|
|
55
|
+
|
|
48
56
|
private
|
|
49
57
|
|
|
50
58
|
def yarnrc_content
|
|
@@ -52,6 +52,9 @@ module Trek
|
|
|
52
52
|
<<~GITIGNORE
|
|
53
53
|
|
|
54
54
|
.DS_Store
|
|
55
|
+
|
|
56
|
+
# Keep the .env template tracked (Rails ignores all /.env* files).
|
|
57
|
+
!/.env.example
|
|
55
58
|
GITIGNORE
|
|
56
59
|
end
|
|
57
60
|
|
|
@@ -72,6 +75,10 @@ module Trek
|
|
|
72
75
|
generate "trek:install:mailer"
|
|
73
76
|
end
|
|
74
77
|
|
|
78
|
+
def install_user
|
|
79
|
+
generate "trek:install:user"
|
|
80
|
+
end
|
|
81
|
+
|
|
75
82
|
def install_authentication
|
|
76
83
|
generate "trek:install:authentication"
|
|
77
84
|
end
|
|
@@ -84,10 +91,6 @@ module Trek
|
|
|
84
91
|
generate "trek:install:healthcheck"
|
|
85
92
|
end
|
|
86
93
|
|
|
87
|
-
def install_user
|
|
88
|
-
generate "trek:install:user"
|
|
89
|
-
end
|
|
90
|
-
|
|
91
94
|
def install_translations
|
|
92
95
|
generate "trek:install:translations"
|
|
93
96
|
end
|
|
@@ -121,6 +124,10 @@ module Trek
|
|
|
121
124
|
generate "trek:install:readme"
|
|
122
125
|
end
|
|
123
126
|
|
|
127
|
+
def install_agents
|
|
128
|
+
generate "trek:install:agents"
|
|
129
|
+
end
|
|
130
|
+
|
|
124
131
|
def install_admin
|
|
125
132
|
generate "trek:install:admin"
|
|
126
133
|
generate "trek:install:admin:routes"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Guidance for AI coding agents working in this repository.
|
|
4
|
+
|
|
5
|
+
## About this project
|
|
6
|
+
|
|
7
|
+
This is a Ruby on Rails application whose back-office/admin is built with **Trek**, a Rails CMS engine. Trek was installed via `rails g trek:install` and provides the admin UI, authentication, authorization, attachments, and base content models. Project-specific work lives in `app/` — admin controllers under `app/controllers/admin/`, plus your own models, policies, and components. Prefer Trek's generators (`rails g trek:scaffold`, `rails g trek:admin:user`, …) over hand-writing admin plumbing.
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
make setup # install dependencies (yarn + bin/setup)
|
|
12
|
+
make dev # start the server (overmind)
|
|
13
|
+
make admin # create an admin user
|
|
14
|
+
make seed # seed the database
|
|
15
|
+
make test # run the RSpec suite (alias: make spec)
|
|
16
|
+
make lint # rubocop + slim-lint + eslint + stylelint + prettier
|
|
17
|
+
make fix # auto-correct lint/format issues
|
|
18
|
+
make scan # brakeman + bundle-audit
|
|
19
|
+
|
|
20
|
+
## Conventions
|
|
21
|
+
|
|
22
|
+
- **Ruby**: RuboCop with rubocop-rails-omakase — double-quoted strings, 120-col lines.
|
|
23
|
+
- **Views**: Slim templates + ViewComponents (linted with slim-lint).
|
|
24
|
+
- **Assets**: esbuild + PostCSS; Stimulus/Turbo (Hotwired).
|
|
25
|
+
- **i18n**: keep every locale file in `config/locales/` in sync across languages.
|
|
26
|
+
- **Git hooks**: lefthook auto-formats staged files on pre-commit — let it run.
|
|
27
|
+
|
|
28
|
+
## Upgrading Trek
|
|
29
|
+
|
|
30
|
+
**Whenever you bump the `trek` gem — and its companion `@etaminstudio/trek` npm package — always:**
|
|
31
|
+
|
|
32
|
+
1. **Read Trek's `CHANGELOG.md`** for every version between the installed and target version, not just the latest.
|
|
33
|
+
2. **Apply every "Upgrade note".** These are the manual steps host apps must perform (config tweaks, new initializers, regenerated files, data migrations). Do not skip them — the upgrade is not complete until each is applied.
|
|
34
|
+
3. **Remove now-redundant local code.** Where the changelog says a Trek change lets host apps drop or simplify a local patch, monkey-patch, or custom implementation, delete that code as part of the upgrade.
|
|
35
|
+
4. **Keep versions aligned**: the `trek` gem version and the `@etaminstudio/trek` npm version must match.
|
|
36
|
+
5. **Verify**: run `make lint` and `make test` before committing the upgrade.
|
|
@@ -2,9 +2,10 @@ module Admin
|
|
|
2
2
|
class UserPasswordResetsController < ApplicationController
|
|
3
3
|
include Trek::Authentication
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
before_action :
|
|
7
|
-
before_action :
|
|
5
|
+
allow_unauthenticated_access
|
|
6
|
+
before_action :set_token, only: %i[edit update]
|
|
7
|
+
before_action :set_user_by_token, only: %i[edit update]
|
|
8
|
+
rate_limit to: 5, within: 3.minutes, only: :create, with: -> { redirect_to new_admin_user_session_path, alert: t("notices.rate_limited") }
|
|
8
9
|
|
|
9
10
|
helper Trek::I18nHelper
|
|
10
11
|
helper Trek::ThemeHelper
|
|
@@ -14,44 +15,42 @@ module Admin
|
|
|
14
15
|
default_form_builder Trek::FormBuilder
|
|
15
16
|
|
|
16
17
|
def new
|
|
17
|
-
@user_password_reset = Trek::UserPasswordReset.new
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def edit
|
|
21
18
|
end
|
|
22
19
|
|
|
23
20
|
def create
|
|
24
|
-
|
|
21
|
+
if user = User.privileged.find_by(email: params[:email])
|
|
22
|
+
Admin::PasswordsMailer.reset(user).deliver_later
|
|
23
|
+
end
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
redirect_to new_admin_user_session_path, notice: t(".success")
|
|
26
|
+
end
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
def edit
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
def update
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
@user.update!(params.permit(:password))
|
|
33
|
+
@user.user_sessions.destroy_all
|
|
34
|
+
redirect_to new_admin_user_session_path, notice: t(".success")
|
|
35
|
+
rescue ActiveRecord::RecordInvalid
|
|
36
|
+
redirect_to edit_admin_user_password_reset_path(@token), alert: @user.errors.full_messages.join(", ")
|
|
38
37
|
end
|
|
39
38
|
|
|
40
39
|
private
|
|
41
40
|
|
|
42
|
-
def
|
|
43
|
-
@token = params[:
|
|
44
|
-
@user = User.load_from_reset_password_token(params[:id])
|
|
45
|
-
|
|
46
|
-
not_authenticated if @user.blank?
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def user_password_reset_params
|
|
50
|
-
params.require(:user_password_reset).permit(:email)
|
|
41
|
+
def set_token
|
|
42
|
+
@token = params[:token]
|
|
51
43
|
end
|
|
52
44
|
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
# The same edit/update flow is reached from a password-reset email and from
|
|
46
|
+
# an invitation email, which carry different token purposes (and expiries).
|
|
47
|
+
def set_user_by_token
|
|
48
|
+
@user = User.privileged.find_by_token_for(:invite, @token) ||
|
|
49
|
+
User.privileged.find_by_token_for!(:password_reset, @token)
|
|
50
|
+
rescue ActiveRecord::RecordNotFound
|
|
51
|
+
redirect_to new_admin_user_session_path, alert: t("admin.user_password_resets.not_found")
|
|
52
|
+
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
|
53
|
+
redirect_to new_admin_user_password_reset_path, alert: t("admin.user_password_resets.not_found")
|
|
55
54
|
end
|
|
56
55
|
end
|
|
57
56
|
end
|