alchemy-devise 8.0.0.b → 8.0.0

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 (30) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/README.md +4 -3
  4. data/app/assets/builds/alchemy-devise.css +1 -1
  5. data/app/assets/stylesheets/alchemy-devise/login.scss +45 -22
  6. data/app/controllers/alchemy/admin/passwords_controller.rb +1 -1
  7. data/app/controllers/alchemy/admin/user_sessions_controller.rb +2 -2
  8. data/app/controllers/alchemy/admin/users_controller.rb +1 -1
  9. data/app/models/alchemy/user.rb +10 -2
  10. data/app/views/alchemy/admin/passwords/edit.html.erb +16 -9
  11. data/app/views/alchemy/admin/passwords/new.html.erb +17 -8
  12. data/app/views/alchemy/admin/user_sessions/_logo.html.erb +35 -0
  13. data/app/views/alchemy/admin/user_sessions/new.html.erb +22 -9
  14. data/app/views/alchemy/admin/users/_fields.html.erb +17 -11
  15. data/app/views/alchemy/admin/users/_resource_table.html.erb +2 -2
  16. data/app/views/alchemy/admin/users/index.html.erb +2 -7
  17. data/app/views/alchemy/admin/users/signup.html.erb +4 -2
  18. data/config/initializers/alchemy.rb +0 -2
  19. data/config/locales/de.yml +5 -0
  20. data/config/locales/en.yml +5 -0
  21. data/db/migrate/20251127170649_add_rememberable_column.rb +5 -0
  22. data/lib/alchemy/devise/configuration.rb +46 -0
  23. data/lib/alchemy/devise/version.rb +1 -1
  24. data/lib/alchemy/devise.rb +24 -39
  25. data/lib/generators/alchemy/devise/install/templates/devise.rb.tt +1 -1
  26. metadata +7 -5
  27. data/app/assets/builds/alchemy-devise.css.map +0 -1
  28. data/app/views/alchemy/admin/users/_table.html.erb +0 -28
  29. data/app/views/alchemy/admin/users/_user.html.erb +0 -41
  30. /data/{lib → app/models}/alchemy/devise/ability.rb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c1338a60cd662f003273c43a2389f1138c7c889909fc0aaf8ddb7ee6ab59812
4
- data.tar.gz: a86d926627ab17965deb01378a3d67e872a3b042fee0e1340290702bb0b19229
3
+ metadata.gz: aa739c92a801c881866bb6892e6173fdd1fd71cee618ec1f71e14fb8fb97308e
4
+ data.tar.gz: 7ab851553d4284cb21cfe6fe9042925008ad01209412c3587fd48b3adc267769
5
5
  SHA512:
6
- metadata.gz: 184e26ecc9d543c34db5aaa90aa83ab7d37b21113bd33af9878cc6e5bf5bf1e441914029198a4233f6b68d6eb5bc0c9bb6b6ab26e9cf2aaa9cf5f736590944be
7
- data.tar.gz: 6e49acd84dc13aa600b75b3eaaacfc71498375f4fb7363c37bba61bfc8f4267efd02f87f750f2abbf109c5dfd5eed29abd7a648beb0d22017c352e678c8e08c3
6
+ metadata.gz: 338681631406095227adee11ed992a8c6b9a32027cfa332792f4207e735df90f0dc289268c5b9c78382910f8615fcc070b9426f823886e8336fdadc37330ddea
7
+ data.tar.gz: b01851129e4b08a1535895d7aad2ea50038514a72ff988f82ae92d8a679e3b42b3168d801ae3b10356e3b4b9ec332578307754a2209637a8b9d9b038b33b3731
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 8.0.0 (2025-11-28)
4
+
5
+ - Enable rememberable module [#237](https://github.com/AlchemyCMS/alchemy-devise/pull/237) ([tvdeyen](https://github.com/tvdeyen))
6
+ - Use Alchemy::Configuration for config [#236](https://github.com/AlchemyCMS/alchemy-devise/pull/236) ([tvdeyen](https://github.com/tvdeyen))
7
+ - CI: Test Alchemy 8.0-stable branch [#234](https://github.com/AlchemyCMS/alchemy-devise/pull/234) ([tvdeyen](https://github.com/tvdeyen))
8
+ - Make `Alchemy::Devise::Ability` auto-loadable [#233](https://github.com/AlchemyCMS/alchemy-devise/pull/233) ([mamhoff](https://github.com/mamhoff))
9
+ - Login, Signup and Password reset forms improvements [#231](https://github.com/AlchemyCMS/alchemy-devise/pull/231) ([tvdeyen](https://github.com/tvdeyen))
10
+ - Test with Rails 8.0 [#230](https://github.com/AlchemyCMS/alchemy-devise/pull/230) ([tvdeyen](https://github.com/tvdeyen))
11
+ - New login screen with dark mode support [#229](https://github.com/AlchemyCMS/alchemy-devise/pull/229) ([tvdeyen](https://github.com/tvdeyen))
12
+ - Updates for Alchemy 8.0 [#228](https://github.com/AlchemyCMS/alchemy-devise/pull/228) ([mamhoff](https://github.com/mamhoff))
13
+ - Update puma requirement from ~> 6.0 to ~> 7.0 [#227](https://github.com/AlchemyCMS/alchemy-devise/pull/227) ([dependabot](https://github.com/apps/dependabot))
14
+ - Update rspec-rails requirement from ~> 7.1 to ~> 8.0 [#226](https://github.com/AlchemyCMS/alchemy-devise/pull/226) ([dependabot](https://github.com/apps/dependabot))
15
+ - Add support for Alchemy 8.0 [#225](https://github.com/AlchemyCMS/alchemy-devise/pull/225) ([tvdeyen](https://github.com/tvdeyen))
16
+ - Load Base Controller Extension when autoloading [#216](https://github.com/AlchemyCMS/alchemy-devise/pull/216) ([mamhoff](https://github.com/mamhoff))
17
+
3
18
  ## 7.4.1 (2025-02-12)
4
19
 
5
20
  - Fix module icon for Alchemy 7.4 [#224](https://github.com/AlchemyCMS/alchemy-devise/pull/224) ([tvdeyen](https://github.com/tvdeyen))
data/README.md CHANGED
@@ -42,14 +42,15 @@ Default Devise modules included in `Alchemy::User` model
42
42
  - `:validatable`
43
43
  - `:timeoutable`
44
44
  - `:recoverable`
45
+ - `:rememberable`
45
46
 
46
- If you want to add additional modules into the Alchemy user class append them to `Alchemy.devise_modules` in an initializer in your app.
47
+ If you want to add additional modules into the Alchemy user class append them to `Alchemy::Devise.config.devise_modules` in an initializer in your app.
47
48
 
48
49
  ### Register additional modules example
49
50
 
50
51
  ```ruby
51
52
  # config/initializers/alchemy.rb
52
- Alchemy.devise_modules << :registerable
53
+ Alchemy::Devise.config.devise_modules << :registerable
53
54
  ```
54
55
 
55
56
  ### Using old encryption
@@ -58,7 +59,7 @@ If your app uses an old encryption that needs the +devise-encryptable+ gem you a
58
59
 
59
60
  ```ruby
60
61
  # config/initializers/alchemy.rb
61
- Alchemy.devise_modules << :encryptable
62
+ Alchemy::Devise.config.devise_modules << :encryptable
62
63
  ```
63
64
 
64
65
  ## Testing
@@ -1 +1 @@
1
- body.user_sessions,body.passwords{background-color:var(--color-blue_dark);color:var(--color-white)}body.user_sessions a,body.passwords a{color:var(--color-white)}body.user_sessions #errors,body.user_sessions .message.info,body.passwords #errors,body.passwords .message.info{border-color:rgba(0,0,0,0)}body.user_sessions #errors,body.passwords #errors{margin-left:157px}#logo{width:275px;height:auto;margin:0 0 1em 164px}.login_signup_box{position:absolute;width:450px;top:50%;left:50%;transform:translate(-60%, -50%);--form-field-label-color: var(--color-white);--button-secondary-bg-color: var(--color-blue_dark);--button-secondary-hover-bg-color: var(--color-blue_medium)}.no-js .login_signup_box{display:none}.login_signup_box .message{margin-left:157px}.login_signup_box .link{text-align:right}.login_signup_box button.secondary{color:var(--color-white);border-color:var(--color-white)}/*# sourceMappingURL=alchemy-devise.css.map */
1
+ body.user_sessions #errors,body.user_sessions .message.info,body.passwords #errors,body.passwords .message.info{border-color:rgba(0,0,0,0)}body.user_sessions #errors,body.passwords #errors{margin-left:157px}.logo-box{width:250px;margin:0 10px 1.5em 200px}.logo-box svg{width:200px;height:auto}.login_signup_box{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%)}.login_signup_box alchemy-message{width:300px;margin-left:var(--form-left-column-width)}.no-js .login_signup_box{display:none}.login_signup_box .message{margin-left:157px}.login_signup_box .submit{display:flex;align-items:center;justify-content:space-between;gap:var(--spacing-4);margin-left:var(--form-left-column-width);padding-left:var(--spacing-0)}.login_signup_box .submit.align-right{justify-content:end}.login_signup_box .submit>label{text-align:start}.login_signup_box .submit>label input[type=checkbox]{margin:0 var(--spacing-0) 0 0}.login_signup_box .submit>a{display:inline-flex;align-items:center;gap:var(--spacing-0)}.login_signup_box .submit>a:hover alchemy-icon{transform:translateX(-2px);transition:transform var(--transition-duration)}
@@ -1,12 +1,5 @@
1
1
  body.user_sessions,
2
2
  body.passwords {
3
- background-color: var(--color-blue_dark);
4
- color: var(--color-white);
5
-
6
- a {
7
- color: var(--color-white);
8
- }
9
-
10
3
  #errors,
11
4
  .message.info {
12
5
  border-color: transparent;
@@ -17,21 +10,26 @@ body.passwords {
17
10
  }
18
11
  }
19
12
 
20
- #logo {
21
- width: 275px;
22
- height: auto;
23
- margin: 0 0 1em 164px;
13
+ .logo-box {
14
+ width: 250px;
15
+ margin: 0 10px 1.5em 200px;
16
+
17
+ svg {
18
+ width: 200px;
19
+ height: auto;
20
+ }
24
21
  }
25
22
 
26
23
  .login_signup_box {
27
24
  position: absolute;
28
- width: 450px;
29
25
  top: 50%;
30
26
  left: 50%;
31
- transform: translate(-60%, -50%);
32
- --form-field-label-color: var(--color-white);
33
- --button-secondary-bg-color: var(--color-blue_dark);
34
- --button-secondary-hover-bg-color: var(--color-blue_medium);
27
+ transform: translate(-50%, -50%);
28
+
29
+ alchemy-message {
30
+ width: 300px;
31
+ margin-left: var(--form-left-column-width);
32
+ }
35
33
 
36
34
  .no-js & {
37
35
  display: none;
@@ -41,12 +39,37 @@ body.passwords {
41
39
  margin-left: 157px;
42
40
  }
43
41
 
44
- .link {
45
- text-align: right;
46
- }
42
+ .submit {
43
+ display: flex;
44
+ align-items: center;
45
+ justify-content: space-between;
46
+ gap: var(--spacing-4);
47
+ margin-left: var(--form-left-column-width);
48
+ padding-left: var(--spacing-0);
49
+
50
+ &.align-right {
51
+ justify-content: end;
52
+ }
53
+
54
+ > label {
55
+ text-align: start;
56
+
57
+ input[type="checkbox"] {
58
+ margin: 0 var(--spacing-0) 0 0;
59
+ }
60
+ }
61
+
62
+ > a {
63
+ display: inline-flex;
64
+ align-items: center;
65
+ gap: var(--spacing-0);
47
66
 
48
- button.secondary {
49
- color: var(--color-white);
50
- border-color: var(--color-white);
67
+ &:hover {
68
+ alchemy-icon {
69
+ transform: translateX(-2px);
70
+ transition: transform var(--transition-duration);
71
+ }
72
+ }
73
+ }
51
74
  }
52
75
  }
@@ -9,7 +9,7 @@ module Alchemy
9
9
 
10
10
  helper "Alchemy::Admin::Base"
11
11
 
12
- layout Alchemy::Devise.layout
12
+ layout Alchemy::Devise.config.layout
13
13
 
14
14
  private
15
15
 
@@ -13,7 +13,7 @@ module Alchemy
13
13
 
14
14
  helper "Alchemy::Admin::Base"
15
15
 
16
- layout Alchemy::Devise.layout
16
+ layout Alchemy::Devise.config.layout
17
17
 
18
18
  def create
19
19
  authenticate_user!
@@ -49,7 +49,7 @@ module Alchemy
49
49
 
50
50
  # Overwriting the default of Devise
51
51
  def after_sign_out_path_for(resource_or_scope)
52
- if request.referer.blank? || request.referer.to_s =~ /admin/
52
+ if request.referer.blank? || request.referer.to_s.include?("admin")
53
53
  root_path
54
54
  else
55
55
  request.referer
@@ -98,7 +98,7 @@ module Alchemy
98
98
  deliver_welcome_mail
99
99
  redirect_to admin_pages_path
100
100
  else
101
- render :signup
101
+ render :signup, status: :unprocessable_content
102
102
  end
103
103
  end
104
104
 
@@ -17,7 +17,7 @@ module Alchemy
17
17
  :tag_list
18
18
  ]
19
19
 
20
- devise(*Alchemy.devise_modules)
20
+ devise(*Alchemy::Devise.config.devise_modules)
21
21
 
22
22
  include Alchemy::Taggable
23
23
 
@@ -25,7 +25,7 @@ module Alchemy
25
25
 
26
26
  has_many :folded_pages
27
27
 
28
- validates_uniqueness_of :login
28
+ validates :login, uniqueness: {case_sensitive: false}, presence: :login_required?
29
29
  validates_presence_of :alchemy_roles
30
30
 
31
31
  # Unlock all locked pages before destroy.
@@ -140,6 +140,14 @@ module Alchemy
140
140
  alias_method :name, :fullname
141
141
  alias_method :alchemy_display_name, :fullname
142
142
 
143
+ def email_required?
144
+ ::Devise.authentication_keys.include?(:email)
145
+ end
146
+
147
+ def login_required?
148
+ ::Devise.authentication_keys.include?(:login)
149
+ end
150
+
143
151
  # Returns true if the last request not longer ago then the logged_in_time_out
144
152
  def logged_in?
145
153
  raise "Can not determine the records login state because there is no last_request_at column" if !respond_to?(:last_request_at)
@@ -3,10 +3,12 @@
3
3
  <% end %>
4
4
 
5
5
  <div class="login_signup_box">
6
- <%= image_tag 'alchemy/alchemy-logo.svg', id: 'logo' %>
6
+ <%= render "alchemy/admin/user_sessions/logo" %>
7
7
  <% if @user.errors.blank? %>
8
8
  <%= render_message do %>
9
- <h1><%= Alchemy.t('Password reset') %></h1>
9
+ <p>
10
+ <strong><%= Alchemy.t('Password reset') %></strong>
11
+ </p>
10
12
  <p><%= Alchemy.t('Please enter a new password') %></p>
11
13
  <% end %>
12
14
  <% else %>
@@ -16,13 +18,18 @@
16
18
  <% end %>
17
19
  <%= alchemy_form_for resource, as: resource_name, url: admin_update_password_path, method: 'patch' do |f| %>
18
20
  <%= f.hidden_field :reset_password_token %>
19
- <%= f.input :password, autofocus: true, label: Alchemy.t("New password") %>
20
- <%= f.input :password_confirmation, label: Alchemy.t("Confirm new password") %>
21
- <div class="input link">
22
- <small>
23
- <%= link_to Alchemy.t(:back), alchemy.admin_login_path %>
24
- </small>
21
+ <%= f.input :password, autofocus: true, label: Alchemy.t("New password"),
22
+ required: true, input_html: {autocomplete: "new-password"} %>
23
+ <%= f.input :password_confirmation, label: Alchemy.t("Confirm new password"),
24
+ required: true, input_html: {autocomplete: "new-password"} %>
25
+ <div class="submit">
26
+ <%= link_to alchemy.admin_login_path do %>
27
+ <%= render_icon("arrow-left-s", size: "1x") %>
28
+ <%= Alchemy.t(:login) %>
29
+ <% end %>
30
+ <button type="submit">
31
+ <%= Alchemy.t("Change password") %>
32
+ </button>
25
33
  </div>
26
- <%= f.submit Alchemy.t("Change password") %>
27
34
  <% end %>
28
35
  </div>
@@ -3,10 +3,12 @@
3
3
  <% end %>
4
4
 
5
5
  <div class="login_signup_box">
6
- <%= image_tag 'alchemy/alchemy-logo.svg', id: 'logo' %>
6
+ <%= render "alchemy/admin/user_sessions/logo" %>
7
7
  <% if @user.errors.blank? %>
8
8
  <%= render_message do %>
9
- <h1><%= Alchemy.t('Password reset') %></h1>
9
+ <p>
10
+ <strong><%= Alchemy.t('Password reset') %></strong>
11
+ </p>
10
12
  <p><%= Alchemy.t('Please enter your email address') %></p>
11
13
  <% end %>
12
14
  <% else %>
@@ -17,12 +19,19 @@
17
19
  <%= alchemy_form_for :user, url: admin_reset_password_path, html: {method: 'post'} do |f| %>
18
20
  <%= f.input :email,
19
21
  autofocus: true,
20
- input_html: {value: params[:email]} %>
21
- <div class="input link">
22
- <small>
23
- <%= link_to Alchemy.t(:back), alchemy.admin_login_path %>
24
- </small>
22
+ required: true,
23
+ input_html: {
24
+ autocomplete: "email",
25
+ value: params[:email]
26
+ } %>
27
+ <div class="submit">
28
+ <%= link_to alchemy.admin_login_path do %>
29
+ <%= render_icon("arrow-left-s", size: "1x") %>
30
+ <%= Alchemy.t(:login) %>
31
+ <% end %>
32
+ <button type="submit">
33
+ <%= Alchemy.t("Send reset instructions") %>
34
+ </button>
25
35
  </div>
26
- <%= f.submit Alchemy.t("Send reset instructions"), input_html: {class: 'secondary'} %>
27
36
  <% end %>
28
37
  </div>
@@ -0,0 +1,35 @@
1
+ <div class="logo-box">
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ width="267"
5
+ height="91"
6
+ viewBox="0 0 267 91"
7
+ >
8
+ <path
9
+ d="M261.749 29.77h-9.812l-.72 2.738a193.53 193.53 0 0 0-.802 3.217c-.334-1.384-.604-2.5-.767-3.162l-.685-2.792H234.075c-1.102-.371-2.338-.564-3.705-.564-2.537 0-4.557.864-6.104 1.934-1.406-1.15-3.402-1.934-6.221-1.934-1.341 0-2.524.242-3.564.625l-.006-.061H201.334v4.17c-2.345-3.051-5.884-4.735-10.401-4.735-4.196 0-8.831 1.936-11.655 6.784-1.194-3.746-3.896-6.784-9.557-6.784-1.385 0-2.626.24-3.727.617v-12.19l-4.204.623-6.934 1.027-3.132.464v10.324a22.109 22.109 0 0 0-6.086-.864c-5.96 0-9.341 2.652-11.128 4.876-.108.133-.2.284-.303.422V17.633l-4.207.623-6.933 1.027-3.131.464v24.04l-5.118-18.709-.739-2.701H99.863l-.745 2.686L95.854 36.8 80.915 21.597a2.922 2.922 0 0 0-2.823-.776l-18.554 4.875a2.918 2.918 0 0 0-.634-.981L39.437 4.906a2.927 2.927 0 0 0-2.826-.777L9.797 11.173a2.92 2.92 0 0 0-2.073 2.054L.372 40.078a2.922 2.922 0 0 0 .735 2.818L20.6 62.705a2.921 2.921 0 0 0 2.822.774l9.259-2.43-3.051 11.1a2.921 2.921 0 0 0 .735 2.821l10.94 11.122a2.92 2.92 0 0 0 2.822.778l15.08-3.953a2.919 2.919 0 0 0 2.077-2.055l3.536-12.978.316.324a2.928 2.928 0 0 0 2.064.872c.254.001.508-.031.761-.098l20.839-5.48H103.275l.72-2.733.82-3.121h3.794l.822 3.122.718 2.732h24.059v-4.307c.07.092.133.194.207.282 1.729 2.119 5.001 4.643 10.76 4.643 2.735 0 4.945-.705 6.55-1.415v.797H180.119v-4.383c2.392 3.007 5.737 4.495 9.134 4.885-1.602 1.106-3.095 2.759-4.467 4.952-2.161 3.454-3.211 6.441-3.211 9.137 0 2.014.524 3.774 1.562 5.236 1.388 1.967 3.57 3.053 6.143 3.053.226 0 .384-.016.896-.073.142-.014.243-.025.312-.03 1.014-.043 2.078-.446 4.047-1.521.468-.248.973-.622 2.077-1.656.966 3.029 2.97 3.501 4.119 3.501 2.479 0 4.354-1.665 4.575-4.057.007-.045.041-.233.189-.649.774 1.335 2.059 2.415 4.188 2.415 2.658 0 4.791-2.088 6.555-4.378.065.155.132.312.203.47 1.794 4.082 4.646 4.694 6.185 4.694.76 0 1.52-.168 2.307-.503.228.213.463.419.726.605a6.818 6.818 0 0 0 3.993 1.302c2.273 0 4.515-.764 6.661-2.274 3.357-2.369 4.061-5.111 4.061-6.996 0-2.266-1.092-4.215-3.014-5.406a4.177 4.177 0 0 0 2.142-1.312c.918 1.27 1.794 2.475 2.303 3.129l1.917 2.468 2.74-1.503.268-.144c2.382-1.291 7.335-3.979 9.847-12.048l8.677-27.888 1.479-4.759h-4.984z"
10
+ fill="transparent"
11
+ />
12
+ <path
13
+ fill="currentColor"
14
+ d="M102.705 26.102h8.626l9.245 33.793h-7.549l-1.541-5.856h-9.448l-1.541 5.856h-7.189l9.397-33.793zm.411 23.008h7.291c-1.282-5.857-2.925-12.841-3.594-16.487-.719 3.647-2.362 10.63-3.697 16.487zm27.472 10.786h-6.931V22.969l6.931-1.026v37.953zm22.187-1.748c-.977.409-3.545 2.364-7.549 2.364-6.883 0-10.682-4.314-10.682-13.405 0-9.554 3.953-14.176 11.143-14.176 2.878 0 5.239.719 6.163 1.079l-.822 5.083c-.666-.256-2.517-.822-4.365-.822-3.388 0-4.981 2.62-4.981 8.579 0 6.061 1.747 8.267 4.775 8.267 2.108 0 4.008-1.128 4.726-1.386l1.592 4.417zm2.671-35.179l6.931-1.026v14.943h.105c.717-.667 3.079-3.954 7.291-3.954 4.826 0 6.728 2.979 6.728 9.193v17.771h-6.934V43.819c0-3.801-.616-4.879-2.721-4.879-2.107 0-3.853 2.157-4.47 2.876v18.079h-6.931V22.969zm44.73 35.026c-.771.514-3.956 2.518-9.038 2.518-5.957 0-10.785-3.852-10.785-13.097 0-9.811 4.775-14.484 10.63-14.484 5.854 0 9.963 3.646 9.963 12.273 0 1.851-.257 3.339-.309 3.597h-13.401c.05 4.571 2.311 6.469 5.235 6.469 2.773 0 5.086-1.231 6.319-1.795l1.386 4.519zm-12.941-13.509h7.034c0-5.237-1.437-6.624-3.338-6.624-1.798 0-3.646 1.643-3.696 6.624zm17.82-10.989h6.107l.31 3.543c.772-.925 2.722-4.109 6.624-4.109 2.98 0 4.828 1.027 5.598 4.057.874-1.181 3.03-4.057 6.728-4.057 4.468 0 6.37 2.517 6.37 9.141v17.823h-6.883V42.637c0-2.311-.358-3.697-2.158-3.697-1.797 0-3.183 2.054-3.543 2.876v18.079h-6.625V42.637c0-2.311-.358-3.697-2.157-3.697-1.796 0-3.131 2.003-3.542 2.876v18.079h-6.828V33.497zm56.744 0l-8.679 27.887c-2.156 6.934-6.213 8.886-8.37 10.067-.718-.926-2.414-3.287-3.081-4.213.771-.668 4.467-2.566 5.546-6.778l-8.318-26.963h7.239c.771 3.132 3.545 14.688 4.314 19.002.821-4.417 3.545-15.87 4.367-19.002h6.982z"
15
+ />
16
+ <g>
17
+ <path
18
+ fill="currentColor"
19
+ d="M193.986 68.011c.319 0 .667.193 1.031.578.897.95 1.506 1.125 2.353.546.367-.254.548-.633.508-1.05-.054-.799-.66-1.456-1.799-1.957-.818-.364-1.438-.541-1.896-.541-2.436.013-4.74 1.736-6.854 5.116-1.807 2.889-2.722 5.389-2.722 7.435 0 1.336.326 2.474.969 3.379.796 1.128 1.983 1.701 3.526 1.701.029 0 .213-.016.555-.054.268-.028.427-.045.47-.046.306 0 .867-.139 2.703-1.14.226-.117.704-.468 2.439-2.166 1.932-1.896 2.285-2.549 2.366-2.884.084-.275.01-.583-.22-.921-.238-.344-.523-.518-.838-.518a.786.786 0 0 0-.708.429c-.872 1.35-1.932 2.444-3.146 3.266-1.295.868-2.615 1.308-3.923 1.308-.778 0-1.671-.234-1.671-2.074 0-1.427.742-3.47 2.211-6.08 1.621-2.872 3.183-4.327 4.646-4.327zm30.25 10.553c-.354 0-.695.247-1.103.798-.301.408-.535.409-.654.408-.259-.01-1.135-.388-1.441-4.977l-.305-4.414c-.25-1.795-.915-2.704-1.979-2.704-.68 0-1.78.545-4.245 4.804a46.07 46.07 0 0 1-2.457 3.695c-.936 1.256-1.511 1.87-1.856 2.171-.082-.436-.124-.979-.124-1.635 0-.533.027-1.253.081-2.143.055-.995.089-1.633.101-1.925.039-2.004-.251-3.293-.885-3.941a1.569 1.569 0 0 0-1.157-.483c-1.114 0-2.453 1.26-4.214 3.968-.44.683-1.144 1.88-2.093 3.565.149-2.311.529-4.59 1.141-6.795.071-.267.054-.669-.433-1.089-.33-.287-.703-.436-1.107-.436-.863 0-1.277 1.173-1.539 2.19-.313 1.16-.526 2.592-.635 4.245-.119 1.754-.181 3.891-.181 6.36 0 .357.075.868.233 1.577.203.807.5 1.631 1.17 1.631.813 0 1.32-.423 1.381-1.157.113-1.165 1.095-3.422 2.918-6.71 1.54-2.804 2.334-3.953 2.701-4.42 0 .089 0 .194-.005.32-.15 3.265-.211 5.245-.182 5.886.105 2.516.823 3.792 2.139 3.792 1.21 0 2.685-1.261 4.636-3.968.255-.355 2.324-3.588 3.537-5.488.234-.37.414-.648.545-.854.012.086.021.184.031.293.052.55.064 1.329.038 2.328v2.002c.01 1.115.313 2.354.903 3.685.812 1.851 1.907 2.786 3.252 2.786.459 0 .972-.164 1.575-.502.819-.475 1.234-1.083 1.234-1.804.001-.652-.392-1.059-1.021-1.059zm6.628-4.902c-2.19 0-2.468-.365-2.475-.365 0-.874.821-2.04 2.372-3.37 1.809-1.556 2.828-1.882 3.366-1.882.036 0 .073.003.123.006.072.004.298.046.826.328.721.386.872.415 1.009.415.727 0 1.163-.494 1.163-1.324 0-.631-.425-1.187-1.268-1.647-.651-.35-1.201-.517-1.684-.517-1.572 0-3.401 1.039-5.592 3.175-2.195 2.138-3.262 3.892-3.262 5.361 0 .738.509 1.313 1.518 1.711.65.258 1.33.402 2.023.432l3.86.141c.473.023.891.157 1.28.407.556.367.619.737.619.983 0 .86-1.161 1.629-2.133 2.122-1.358.688-2.57 1.035-3.598 1.035-.625 0-.625-.247-.625-.444 0-.104.017-.197.054-.283.126-.3.213-.694.266-1.218l.035-.339-.312-.132c-.656-.279-1.311.032-1.813.841-.316.495-.47.93-.47 1.33 0 .904.4 1.646 1.192 2.199a3.557 3.557 0 0 0 2.134.712c1.598 0 3.218-.569 4.811-1.693 1.794-1.263 2.701-2.733 2.701-4.371.002-2.398-2.057-3.613-6.12-3.613z"
20
+ />
21
+ </g>
22
+ <g fill-rule="evenodd" clip-rule="evenodd" fill="currentColor">
23
+ <path
24
+ d="M47.632 51.588L23.382 57.956 5.754 40.043 12.401 15.762 36.65 9.393 54.254 27.305z"
25
+ />
26
+ <path
27
+ d="M57.42 79.029L43.781 82.603 33.888 72.543 37.632 58.91 51.244 55.334 61.138 65.395z"
28
+ />
29
+ <path
30
+ d="M86.963 59.079L67.775 64.128 53.829 49.94 59.066 30.726 78.277 25.679 92.223 39.865z"
31
+ />
32
+ </g>
33
+ </svg>
34
+ <small><%= Alchemy.version %></small>
35
+ </div>
@@ -3,17 +3,30 @@
3
3
  <% end %>
4
4
 
5
5
  <div class="login_signup_box">
6
- <%= image_tag 'alchemy/alchemy-logo.svg', id: 'logo' %>
6
+ <%= render "alchemy/admin/user_sessions/logo" %>
7
+ <%= render_message do %>
8
+ <p>
9
+ <strong><%= Alchemy.t('modules.user_sessions') %></strong>
10
+ </p>
11
+ <p><%= Alchemy.t('welcome_please_identify_notice') %></p>
12
+ <% end %>
7
13
  <%= alchemy_form_for :user, url: {action: 'create'}, id: 'login', data: { turbo: false } do |f| %>
8
- <%= f.input Devise.authentication_keys.first, autofocus: true %>
9
- <%= f.input :password %>
10
- <div class="input link">
11
- <small>
12
- <%= link_to Alchemy.t('Forgot your password?'), admin_new_password_path %>
13
- </small>
14
- </div>
14
+ <%= f.input Devise.authentication_keys.first, autofocus: true, required: true,
15
+ input_html: {autocomplete: Devise.authentication_keys.first == :email ? "email" : "username"} %>
16
+ <%= f.input :password, required: true, input_html: {autocomplete: "current-password"} %>
17
+ <% if devise_mapping.rememberable? %>
18
+ <div class="input">
19
+ <span class="control-label">&nbsp;</span>
20
+
21
+ <%= f.label :remember_me, class: "checkbox" do %>
22
+ <%= f.check_box :remember_me, checked: true %>
23
+ <%= Alchemy.t(:remember_me, scope: 'admin.login', days: Devise.remember_for.in_days.to_i) %>
24
+ <% end %>
25
+ </div>
26
+ <% end %>
15
27
  <div class="submit">
16
- <button class="secondary"><%= Alchemy.t(:login) %></button>
28
+ <%= link_to Alchemy.t('Forgot your password?'), admin_new_password_path %>
29
+ <button type="submit"><%= Alchemy.t(:login) %></button>
17
30
  </div>
18
31
  <% end %>
19
32
  </div>
@@ -1,13 +1,15 @@
1
- <%= f.input :firstname %>
2
- <%= f.input :lastname %>
3
- <%= f.input :login, autofocus: true %>
4
- <%= f.input :email %>
5
- <%= f.input :language,
6
- collection: translations_for_select,
7
- include_blank: false,
8
- input_html: {class: 'alchemy_selectbox'} %>
9
- <%= f.input :password %>
10
- <%= f.input :password_confirmation %>
1
+ <%= f.input :firstname, input_html: {autocomplete: "given-name"} %>
2
+ <%= f.input :lastname, input_html: {autocomplete: "family-name"} %>
3
+ <%= f.input :login, autofocus: true, required: @user.login_required?, input_html: {autocomplete: "username"} %>
4
+ <%= f.input :email, required: @user.email_required?, input_html: {autocomplete: "email"} %>
5
+ <% if Alchemy::I18n.available_locales.many? %>
6
+ <div class="input select">
7
+ <%= f.label(:language) %>
8
+ <%= render Alchemy::Admin::LocaleSelect.new(f.field_name(:language)) %>
9
+ </div>
10
+ <% end %>
11
+ <%= f.input :password, required: while_signup?, input_html: {autocomplete: "new-password"} %>
12
+ <%= f.input :password_confirmation, required: while_signup?, input_html: {autocomplete: "new-password"} %>
11
13
  <% if can_update_role? %>
12
14
  <%= f.input :alchemy_roles,
13
15
  collection: @user_roles,
@@ -27,4 +29,8 @@
27
29
  </div>
28
30
  <% end %>
29
31
  <%= f.input :send_credentials, as: 'boolean' %>
30
- <%= f.submit Alchemy.t(:save) %>
32
+ <div class="submit align-right">
33
+ <button type="submit">
34
+ <%= Alchemy.t(:save) %>
35
+ </button>
36
+ </div>
@@ -8,7 +8,7 @@
8
8
  alchemy.edit_admin_user_path(user), {
9
9
  title: Alchemy.t(:edit_user),
10
10
  overflow: true,
11
- size: "430x560"
11
+ size: "430x500"
12
12
  },
13
13
  title: Alchemy.t(:edit_user) %>
14
14
  <% else %>
@@ -28,7 +28,7 @@
28
28
  <%= user.human_roles_string %>
29
29
  <% end %>
30
30
  <% table.delete_button tooltip: Alchemy.t(:delete_user), confirm_message: Alchemy.t(:confirm_to_delete_user) %>
31
- <% table.edit_button tooltip: Alchemy.t(:edit_user), dialog_size: "430x560" %>
31
+ <% table.edit_button tooltip: Alchemy.t(:edit_user), dialog_size: "430x500" %>
32
32
  <% end %>
33
33
 
34
34
  <%= paginate @users, theme: "alchemy" %>
@@ -12,7 +12,7 @@
12
12
  tooltip_placement: "top-start",
13
13
  dialog_options: {
14
14
  title: Alchemy.t(:create_user),
15
- size: "430x560"
15
+ size: "430x500"
16
16
  },
17
17
  if_permitted_to: [:create, Alchemy::User]
18
18
  ) %>
@@ -22,12 +22,7 @@
22
22
  <div id="archive_all" class="resources-table-wrapper">
23
23
  <% if @users.any? %>
24
24
  <%= render "alchemy/admin/resources/table_header" %>
25
-
26
- <% if Alchemy::Admin.const_defined?(:Resource) %>
27
- <%= render "resource_table" %>
28
- <% else %>
29
- <%= render "table" %>
30
- <% end %>
25
+ <%= render "resource_table" %>
31
26
 
32
27
  <%= paginate @users, theme: 'alchemy' %>
33
28
 
@@ -3,9 +3,11 @@
3
3
  <% end %>
4
4
 
5
5
  <div class="login_signup_box">
6
- <%= image_tag 'alchemy/alchemy-logo.svg', id: 'logo' %>
6
+ <%= render "alchemy/admin/user_sessions/logo" %>
7
7
  <%= render_message do %>
8
- <h1><%= Alchemy.t('Welcome to Alchemy') %></h1>
8
+ <p>
9
+ <strong><%= Alchemy.t('Welcome to Alchemy') %></strong>
10
+ </p>
9
11
  <p><%= Alchemy.t("Please Signup") %></p>
10
12
  <% end %>
11
13
  <%= alchemy_form_for [:admin, @user] do |f| %>
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Rails.application.config.to_prepare do
4
- require "alchemy/devise/ability"
5
-
6
4
  Alchemy.register_ability(Alchemy::Devise::Ability)
7
5
 
8
6
  Alchemy::Modules.register_module({
@@ -0,0 +1,5 @@
1
+ de:
2
+ alchemy:
3
+ admin:
4
+ login:
5
+ remember_me: "Für %{days} Tage angemeldet bleiben"
@@ -0,0 +1,5 @@
1
+ en:
2
+ alchemy:
3
+ admin:
4
+ login:
5
+ remember_me: "Remember me for %{days} days"
@@ -0,0 +1,5 @@
1
+ class AddRememberableColumn < ActiveRecord::Migration[7.1]
2
+ def change
3
+ add_column :alchemy_users, :remember_created_at, :datetime, if_not_exists: true
4
+ end
5
+ end
@@ -0,0 +1,46 @@
1
+ require "alchemy/configuration"
2
+
3
+ module Alchemy
4
+ module Devise
5
+ class Configuration < Alchemy::Configuration
6
+ # Layout for Alchemy Devise controllers
7
+ # Default is +alchemy/admin+
8
+ option :layout, :string, default: "alchemy/admin"
9
+
10
+ # Devise modules included in +Alchemy::User+ model
11
+ #
12
+ # === Default modules
13
+ #
14
+ # [
15
+ # :database_authenticatable,
16
+ # :trackable,
17
+ # :validatable,
18
+ # :timeoutable,
19
+ # :recoverable,
20
+ # :rememberable
21
+ # ]
22
+ #
23
+ # If you want to add additional modules into the Alchemy user class append
24
+ # them to this collection in an initializer in your app.
25
+ #
26
+ # === Example
27
+ #
28
+ # # config/initializers/alchemy.rb
29
+ # Alchemy::Devise.config.devise_modules << :registerable
30
+ #
31
+ # If your app uses an old encryption that needs the +devise-encryptable+ gem
32
+ # you also need to load the devise module.
33
+ #
34
+ # Alchemy::Devise.config.devise_modules << :encryptable
35
+ #
36
+ option :devise_modules, :collection, collection_class: Set, item_type: :symbol, default: [
37
+ :database_authenticatable,
38
+ :trackable,
39
+ :validatable,
40
+ :timeoutable,
41
+ :recoverable,
42
+ :rememberable
43
+ ]
44
+ end
45
+ end
46
+ end
@@ -1,5 +1,5 @@
1
1
  module Alchemy
2
2
  module Devise
3
- VERSION = "8.0.0.b"
3
+ VERSION = "8.0.0"
4
4
  end
5
5
  end
@@ -1,48 +1,33 @@
1
+ require "alchemy/devise/configuration"
1
2
  require "alchemy/devise/engine"
2
3
 
3
4
  module Alchemy
4
- # Devise modules included in +Alchemy::User+ model
5
- #
6
- # === Default modules
7
- #
8
- # [
9
- # . :database_authenticatable,
10
- # :trackable,
11
- # :validatable,
12
- # :timeoutable,
13
- # :recoverable
14
- # . ]
15
- #
16
- # If you want to add additional modules into the Alchemy user class append
17
- # them to this collection in an initializer in your app.
18
- #
19
- # === Example
20
- #
21
- # # config/initializers/alchemy.rb
22
- # Alchemy.devise_modules << :registerable
23
- #
24
- # If your app uses an old encryption that needs the +devise-encryptable+ gem
25
- # you also need to load the devise module.
26
- #
27
- # Alchemy.devise_modules << :encryptable
28
- #
29
- def self.devise_modules
30
- @devise_modules ||= [
31
- :database_authenticatable,
32
- :trackable,
33
- :validatable,
34
- :timeoutable,
35
- :recoverable
36
- ]
37
- end
38
-
39
5
  module Devise
40
- def self.layout=(value)
41
- @layout = value
6
+ extend self
7
+
8
+ def deprecator
9
+ ActiveSupport::Deprecation.new("9.0", "Alchemy::Devise")
42
10
  end
43
11
 
44
- def self.layout
45
- @layout || "alchemy/admin"
12
+ delegate :layout=, to: :config
13
+ deprecate "layout=": "Use `Alchemy::Devise.config.layout=` instead.",
14
+ deprecator: Alchemy::Devise.deprecator
15
+
16
+ delegate :layout, to: :config
17
+ deprecate layout: "Use `Alchemy::Devise.config.layout` instead.",
18
+ deprecator: Alchemy::Devise.deprecator
19
+
20
+ def config
21
+ @config ||= Alchemy::Devise::Configuration.new
22
+ end
23
+
24
+ def configure(&blk)
25
+ yield config
46
26
  end
47
27
  end
28
+
29
+ extend self
30
+
31
+ deprecate devise_modules: "Alchemy::Devise.config.devise_modules", deprecator: Alchemy::Devise.deprecator
32
+ delegate :devise_modules, to: "Alchemy::Devise.config"
48
33
  end
@@ -302,7 +302,7 @@ Devise.setup do |config|
302
302
  # apps is `200 OK` and `302 Found` respectively, but new apps are generated with
303
303
  # these new defaults that match Hotwire/Turbo behavior.
304
304
  # Note: These might become the new default in future versions of Devise.
305
- config.responder.error_status = :unprocessable_entity
305
+ config.responder.error_status = :unprocessable_content
306
306
  config.responder.redirect_status = :see_other
307
307
 
308
308
  # ==> Configuration for :registerable
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alchemy-devise
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.0.0.b
4
+ version: 8.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas von Deyen
@@ -152,22 +152,21 @@ files:
152
152
  - LICENSE
153
153
  - README.md
154
154
  - app/assets/builds/alchemy-devise.css
155
- - app/assets/builds/alchemy-devise.css.map
156
155
  - app/assets/stylesheets/alchemy-devise.scss
157
156
  - app/assets/stylesheets/alchemy-devise/login.scss
158
157
  - app/controllers/alchemy/admin/passwords_controller.rb
159
158
  - app/controllers/alchemy/admin/user_sessions_controller.rb
160
159
  - app/controllers/alchemy/admin/users_controller.rb
161
160
  - app/mailers/alchemy/notifications.rb
161
+ - app/models/alchemy/devise/ability.rb
162
162
  - app/models/alchemy/user.rb
163
163
  - app/patches/controllers/alchemy/devise/base_controller_patch.rb
164
164
  - app/views/alchemy/admin/passwords/edit.html.erb
165
165
  - app/views/alchemy/admin/passwords/new.html.erb
166
+ - app/views/alchemy/admin/user_sessions/_logo.html.erb
166
167
  - app/views/alchemy/admin/user_sessions/new.html.erb
167
168
  - app/views/alchemy/admin/users/_fields.html.erb
168
169
  - app/views/alchemy/admin/users/_resource_table.html.erb
169
- - app/views/alchemy/admin/users/_table.html.erb
170
- - app/views/alchemy/admin/users/_user.html.erb
171
170
  - app/views/alchemy/admin/users/edit.html.erb
172
171
  - app/views/alchemy/admin/users/index.html.erb
173
172
  - app/views/alchemy/admin/users/new.html.erb
@@ -185,13 +184,16 @@ files:
185
184
  - app/views/alchemy/notifications/reset_password_instructions.es.text.erb
186
185
  - app/views/alchemy/notifications/reset_password_instructions.ru.text.erb
187
186
  - config/initializers/alchemy.rb
187
+ - config/locales/de.yml
188
+ - config/locales/en.yml
188
189
  - config/routes.rb
189
190
  - config/spring.rb
190
191
  - db/migrate/20131015124700_create_alchemy_users.rb
191
192
  - db/migrate/20131225232042_add_alchemy_roles_to_alchemy_users.rb
192
193
  - db/migrate/20141209144532_add_indexes_to_alchemy_users.rb
194
+ - db/migrate/20251127170649_add_rememberable_column.rb
193
195
  - lib/alchemy/devise.rb
194
- - lib/alchemy/devise/ability.rb
196
+ - lib/alchemy/devise/configuration.rb
195
197
  - lib/alchemy/devise/engine.rb
196
198
  - lib/alchemy/devise/test_support/factories.rb
197
199
  - lib/alchemy/devise/version.rb
@@ -1 +0,0 @@
1
- {"version":3,"sourceRoot":"","sources":["../stylesheets/alchemy-devise/login.scss"],"names":[],"mappings":"AAAA,kCAEE,wCACA,yBAEA,sCACE,yBAGF,gHAEE,2BAGF,kDACE,kBAIJ,MACE,YACA,YACA,qBAGF,kBACE,kBACA,YACA,QACA,SACA,gCACA,6CACA,oDACA,4DAEA,yBACE,aAGF,2BACE,kBAGF,wBACE,iBAGF,mCACE,yBACA","file":"alchemy-devise.css"}
@@ -1,28 +0,0 @@
1
- <table class="list" id="user_list">
2
- <thead>
3
- <tr>
4
- <th class="icon"></th>
5
- <th class="login">
6
- <%= sort_link @query, :login, hide_indicator: true %>
7
- </th>
8
- <th class="name">
9
- <%= sort_link @query, :firstname, hide_indicator: true %>
10
- </th>
11
- <th>
12
- <%= sort_link @query, :lastname, hide_indicator: true %>
13
- </th>
14
- <th class="email">
15
- <%= sort_link @query, :email, hide_indicator: true %>
16
- </th>
17
- <th><%= Alchemy::User.human_attribute_name('language') %></th>
18
- <th>
19
- <%= sort_link @query, :last_sign_in_at, hide_indicator: true %>
20
- </th>
21
- <th class="role"><%= Alchemy::User.human_attribute_name('roles') %></th>
22
- <th class="tools"></th>
23
- </tr>
24
- </thead>
25
- <tbody>
26
- <%= render partial: "user", collection: @users %>
27
- </tbody>
28
- </table>
@@ -1,41 +0,0 @@
1
- <tr class="<%= cycle('even', 'odd') %>">
2
- <td class="icon">
3
- <%= render_icon(:user, style: user.logged_in? ? 'solid' : 'regular') %>
4
- </td>
5
- <td class="login">
6
- <% if can?(:edit, user) %>
7
- <%= link_to_dialog user.login,
8
- alchemy.edit_admin_user_path(user), {
9
- title: Alchemy.t(:edit_user),
10
- overflow: true,
11
- size: '430x560'
12
- },
13
- title: Alchemy.t(:edit_user) %>
14
- <% end %>
15
- </td>
16
- <td class="name"><%= user.firstname %></td>
17
- <td><%= user.lastname %></td>
18
- <td class="email"><%= user.email %></td>
19
- <td><%= Alchemy.t(user.language, scope: 'translations', default: Alchemy.t(:unknown)) %></td>
20
- <td><%= user.last_sign_in_at.present? ? l(user.last_sign_in_at, format: 'alchemy.default'.to_sym) : Alchemy.t(:unknown) %></td>
21
- <td class="role"><%= user.human_roles_string %></td>
22
- <td class="tools">
23
- <% if can?(:destroy, user) %>
24
- <%= delete_button alchemy.admin_user_path(user), {
25
- message: Alchemy.t(:confirm_to_delete_user),
26
- title: Alchemy.t(:delete_user),
27
- icon: :minus
28
- },
29
- title: Alchemy.t(:delete_user) %>
30
- <% end %>
31
- <% if can?(:edit, user) %>
32
- <%= link_to_dialog render_icon(:edit),
33
- alchemy.edit_admin_user_path(user), {
34
- title: Alchemy.t(:edit_user),
35
- overflow: true,
36
- size: '430x560'
37
- },
38
- title: Alchemy.t(:edit_user) %>
39
- <% end %>
40
- </td>
41
- </tr>
File without changes