plutonium 0.19.11 → 0.19.13

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.
@@ -1,30 +1,82 @@
1
- <h1 class="text-lg font-bold leading-tight tracking-tight text-gray-900 md:text-xl dark:text-white">
1
+ <h1
2
+ class="
3
+ text-lg font-bold leading-tight tracking-tight text-gray-900 md:text-xl
4
+ dark:text-white
5
+ "
6
+ >
2
7
  Sign in to your account
3
8
  </h1>
4
- <%= form_with url: rodauth.login_path, method: :post, data: { turbo: false }, class: "space-y-4" do |form| %>
9
+ <%= form_with url: rodauth.login_path, method: :post, data: { turbo: false, controller: "password-visibility" }, class: "space-y-4" do |form| %>
5
10
  <div>
6
- <%= form.label "login", rodauth.login_label, class: "block mb-2 text-sm font-semibold text-gray-900 dark:text-white" %>
7
- <%= form.email_field rodauth.login_param, value: params[rodauth.login_param],
8
- id: "login", autocomplete: rodauth.login_field_autocomplete_value,
9
- required: true,
10
- placeholder: "jane@acme.inc",
11
- class: "bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 #{rodauth.field_error(rodauth.login_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400" }", aria: ({ invalid: true, describedby: "login_error_message" } if rodauth.field_error(rodauth.login_param)) %>
11
+ <%= form.label "login",
12
+ rodauth.login_label,
13
+ class:
14
+ "block mb-2 text-sm font-semibold text-gray-900 dark:text-white" %>
15
+ <%= form.email_field rodauth.login_param,
16
+ value: params[rodauth.login_param],
17
+ id: "login",
18
+ autocomplete: rodauth.login_field_autocomplete_value,
19
+ required: true,
20
+ placeholder: "jane@acme.inc",
21
+ class:
22
+ "bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 #{rodauth.field_error(rodauth.login_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400"}",
23
+ aria:
24
+ (
25
+ if rodauth.field_error(rodauth.login_param)
26
+ { invalid: true, describedby: "login_error_message" }
27
+ end
28
+ ) %>
12
29
  <% unless rodauth.skip_login_field_on_login? %>
13
- <%= content_tag(:span, rodauth.field_error(rodauth.login_param), class: "block mt-1 text-red-600 text-sm dark:text-red-400", id: "login_error_message") if rodauth.field_error(rodauth.login_param) %>
30
+ <%= if rodauth.field_error(rodauth.login_param)
31
+ content_tag(
32
+ :span,
33
+ rodauth.field_error(rodauth.login_param),
34
+ class: "block mt-1 text-red-600 text-sm dark:text-red-400",
35
+ id: "login_error_message",
36
+ )
37
+ end %>
14
38
  <% end %>
15
39
  </div>
16
40
 
17
41
  <% unless rodauth.skip_password_field_on_login? %>
18
42
  <div>
19
- <%= form.label "password", rodauth.password_label, class: "block mb-2 text-sm font-semibold text-gray-900 dark:text-white" %>
20
- <%= form.password_field rodauth.password_param, value: "",
21
- id: "password",
22
- autocomplete: rodauth.password_field_autocomplete_value,
23
- required: true,
24
- class: "bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 #{rodauth.field_error(rodauth.password_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400" }", aria: ({ invalid: true, describedby: "password_error_message" } if rodauth.field_error(rodauth.password_param)) %>
25
- <%= content_tag(:span, rodauth.field_error(rodauth.password_param), class: "block mt-1 text-red-600 text-sm dark:text-red-400", id: "password_error_message") if rodauth.field_error(rodauth.password_param) %>
43
+ <%= form.label "password",
44
+ rodauth.password_label,
45
+ class:
46
+ "block mb-2 text-sm font-semibold text-gray-900 dark:text-white" %>
47
+ <%= form.password_field rodauth.password_param,
48
+ data: {
49
+ password_visibility_target: "password",
50
+ },
51
+ value: "",
52
+ id: "password",
53
+ autocomplete: rodauth.password_field_autocomplete_value,
54
+ required: true,
55
+ class:
56
+ "bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 #{rodauth.field_error(rodauth.password_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400"}",
57
+ aria:
58
+ (
59
+ if rodauth.field_error(rodauth.password_param)
60
+ {
61
+ invalid: true,
62
+ describedby: "password_error_message",
63
+ }
64
+ end
65
+ ) %>
66
+ <%= if rodauth.field_error(rodauth.password_param)
67
+ content_tag(
68
+ :span,
69
+ rodauth.field_error(rodauth.password_param),
70
+ class: "block mt-1 text-red-600 text-sm dark:text-red-400",
71
+ id: "password_error_message",
72
+ )
73
+ end %>
26
74
  </div>
27
75
  <% end %>
28
76
 
29
- <%= form.submit rodauth.login_button, class: "w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-semibold rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800" %>
77
+ <%= render "password_visibility" %>
78
+
79
+ <%= form.submit rodauth.login_button,
80
+ class:
81
+ "w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-semibold rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800" %>
30
82
  <% end %>
@@ -0,0 +1,19 @@
1
+ <div class="flex space-x-2 items-center">
2
+ <input
3
+ type="checkbox"
4
+ name="reveal-password"
5
+ id="reveal-password"
6
+ class="
7
+ text-primary-500 rounded transition-colors duration-200 checked:bg-primary-500
8
+ hover:bg-primary-200 focus:ring-primary-500
9
+ "
10
+ data-password-visibility-target="checkbox"
11
+ data-action="password-visibility#toggle"
12
+ >
13
+ <label
14
+ for="reveal-password"
15
+ class="block text-sm font-semibold text-gray-900 dark:text-white"
16
+ >
17
+ Show Password
18
+ </label>
19
+ </div>
@@ -1,59 +1,158 @@
1
- <h1 class="text-lg font-bold leading-tight tracking-tight text-gray-900 md:text-xl dark:text-white">
1
+ <h1
2
+ class="
3
+ text-lg font-bold leading-tight tracking-tight text-gray-900 md:text-xl
4
+ dark:text-white
5
+ "
6
+ >
2
7
  Create an account
3
8
  </h1>
4
- <%= form_with url: rodauth.create_account_path, method: :post, data: { turbo: false }, class: "space-y-4" do |form| %>
9
+ <%= form_with url: rodauth.create_account_path, method: :post, data: { turbo: false, controller: "password-visibility" }, class: "space-y-4" do |form| %>
5
10
  <div>
6
- <%= form.label "login", rodauth.login_label, class: "block mb-2 text-sm font-semibold text-gray-900 dark:text-white" %>
7
- <%= form.email_field rodauth.login_param, value: params[rodauth.login_param],
8
- id: "login",
9
- autocomplete: "email",
10
- required: true,
11
- placeholder: "jane@acme.inc",
12
- class: "bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 #{rodauth.field_error(rodauth.login_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400" }", aria: ({ invalid: true, describedby: "login_error_message" } if rodauth.field_error(rodauth.login_param)) %>
13
- <%= content_tag(:span, rodauth.field_error(rodauth.login_param), class: "block mt-1 text-red-600 text-sm dark:text-red-400", id: "login_error_message") if rodauth.field_error(rodauth.login_param) %>
11
+ <%= form.label "login",
12
+ rodauth.login_label,
13
+ class:
14
+ "block mb-2 text-sm font-semibold text-gray-900 dark:text-white" %>
15
+ <%= form.email_field rodauth.login_param,
16
+ value: params[rodauth.login_param],
17
+ id: "login",
18
+ autocomplete: "email",
19
+ required: true,
20
+ placeholder: "jane@acme.inc",
21
+ class:
22
+ "bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 #{rodauth.field_error(rodauth.login_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400"}",
23
+ aria:
24
+ (
25
+ if rodauth.field_error(rodauth.login_param)
26
+ { invalid: true, describedby: "login_error_message" }
27
+ end
28
+ ) %>
29
+ <%= if rodauth.field_error(rodauth.login_param)
30
+ content_tag(
31
+ :span,
32
+ rodauth.field_error(rodauth.login_param),
33
+ class: "block mt-1 text-red-600 text-sm dark:text-red-400",
34
+ id: "login_error_message",
35
+ )
36
+ end %>
14
37
  </div>
15
38
 
16
39
  <% if rodauth.require_login_confirmation? %>
17
40
  <div>
18
- <%= form.label "login-confirm", rodauth.login_confirm_label, class: "block mb-2 text-sm font-semibold text-gray-900 dark:text-white" %>
19
- <%= form.email_field rodauth.login_confirm_param, value: params[rodauth.login_confirm_param],
20
- id: "login-confirm",
21
- autocomplete: "email",
22
- required: true,
23
- placeholder: "jane@acme.inc",
24
- class: "bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 #{rodauth.field_error(rodauth.login_confirm_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400" }", aria: ({ invalid: true, describedby: "login-confirm_error_message" } if rodauth.field_error(rodauth.login_confirm_param)) %>
25
- <%= content_tag(:span, rodauth.field_error(rodauth.login_confirm_param), class: "block mt-1 text-red-600 text-sm dark:text-red-400", id: "login-confirm_error_message") if rodauth.field_error(rodauth.login_confirm_param) %>
41
+ <%= form.label "login-confirm",
42
+ rodauth.login_confirm_label,
43
+ class:
44
+ "block mb-2 text-sm font-semibold text-gray-900 dark:text-white" %>
45
+ <%= form.email_field rodauth.login_confirm_param,
46
+ value: params[rodauth.login_confirm_param],
47
+ id: "login-confirm",
48
+ autocomplete: "email",
49
+ required: true,
50
+ placeholder: "jane@acme.inc",
51
+ class:
52
+ "bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 #{rodauth.field_error(rodauth.login_confirm_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400"}",
53
+ aria:
54
+ (
55
+ if rodauth.field_error(rodauth.login_confirm_param)
56
+ {
57
+ invalid: true,
58
+ describedby: "login-confirm_error_message",
59
+ }
60
+ end
61
+ ) %>
62
+ <%= if rodauth.field_error(rodauth.login_confirm_param)
63
+ content_tag(
64
+ :span,
65
+ rodauth.field_error(rodauth.login_confirm_param),
66
+ class: "block mt-1 text-red-600 text-sm dark:text-red-400",
67
+ id: "login-confirm_error_message",
68
+ )
69
+ end %>
26
70
  </div>
27
71
  <% end %>
28
72
 
29
73
  <% if rodauth.create_account_set_password? %>
30
74
  <div>
31
- <%= form.label "password", rodauth.password_label, class: "block mb-2 text-sm font-semibold text-gray-900 dark:text-white" %>
32
- <%= form.password_field rodauth.password_param, value: "",
33
- id: "password",
34
- autocomplete: rodauth.password_field_autocomplete_value,
35
- required: true,
36
- class: "bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 #{rodauth.field_error(rodauth.password_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400" }", aria: ({ invalid: true, describedby: "password_error_message" } if rodauth.field_error(rodauth.password_param)) %>
37
- <%= content_tag(:span, rodauth.field_error(rodauth.password_param), class: "block mt-1 text-red-600 text-sm dark:text-red-400", id: "password_error_message") if rodauth.field_error(rodauth.password_param) %>
75
+ <%= form.label "password",
76
+ rodauth.password_label,
77
+ class:
78
+ "block mb-2 text-sm font-semibold text-gray-900 dark:text-white" %>
79
+ <%= form.password_field rodauth.password_param,
80
+ data: {
81
+ password_visibility_target: "password",
82
+ },
83
+ value: "",
84
+ id: "password",
85
+ autocomplete: rodauth.password_field_autocomplete_value,
86
+ required: true,
87
+ class:
88
+ "bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 #{rodauth.field_error(rodauth.password_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400"}",
89
+ aria:
90
+ (
91
+ if rodauth.field_error(rodauth.password_param)
92
+ {
93
+ invalid: true,
94
+ describedby: "password_error_message",
95
+ }
96
+ end
97
+ ) %>
98
+ <%= if rodauth.field_error(rodauth.password_param)
99
+ content_tag(
100
+ :span,
101
+ rodauth.field_error(rodauth.password_param),
102
+ class: "block mt-1 text-red-600 text-sm dark:text-red-400",
103
+ id: "password_error_message",
104
+ )
105
+ end %>
38
106
  </div>
39
107
 
40
108
  <% if rodauth.require_password_confirmation? %>
41
109
  <div>
42
- <%= form.label "password-confirm", rodauth.password_confirm_label, class: "block mb-2 text-sm font-semibold text-gray-900 dark:text-white" %>
43
- <%= form.password_field rodauth.password_confirm_param, value: "",
44
- id: "password-confirm",
45
- autocomplete: "new-password",
46
- required: true,
47
- class: "bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 #{rodauth.field_error(rodauth.password_confirm_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400" }", aria: ({ invalid: true, describedby: "password-confirm_error_message" } if rodauth.field_error(rodauth.password_confirm_param)) %>
48
- <%= content_tag(:span, rodauth.field_error(rodauth.password_confirm_param), class: "block mt-1 text-red-600 text-sm dark:text-red-400", id: "password-confirm_error_message") if rodauth.field_error(rodauth.password_confirm_param) %>
110
+ <%= form.label "password-confirm",
111
+ rodauth.password_confirm_label,
112
+ class:
113
+ "block mb-2 text-sm font-semibold text-gray-900 dark:text-white" %>
114
+ <%= form.password_field rodauth.password_confirm_param,
115
+ data: {
116
+ password_visibility_target: "password",
117
+ },
118
+ value: "",
119
+ id: "password-confirm",
120
+ autocomplete: "new-password",
121
+ required: true,
122
+ class:
123
+ "bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 #{rodauth.field_error(rodauth.password_confirm_param) ? "border-red-600 focus:ring-red-600 focus:border-red-600 dark:border-red-400 dark:focus:ring-red-400" : "border-gray-300 dark:border-gray-700 dark:focus:border-emerald-400 dark:focus:ring-emerald-400"}",
124
+ aria:
125
+ (
126
+ if rodauth.field_error(rodauth.password_confirm_param)
127
+ {
128
+ invalid: true,
129
+ describedby: "password-confirm_error_message",
130
+ }
131
+ end
132
+ ) %>
133
+ <%= if rodauth.field_error(rodauth.password_confirm_param)
134
+ content_tag(
135
+ :span,
136
+ rodauth.field_error(rodauth.password_confirm_param),
137
+ class: "block mt-1 text-red-600 text-sm dark:text-red-400",
138
+ id: "password-confirm_error_message",
139
+ )
140
+ end %>
49
141
  </div>
50
142
  <% end %>
51
143
  <% end %>
52
144
 
53
- <%= form.submit rodauth.create_account_button, class: "w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800" %>
145
+ <%= render "password_visibility" %>
146
+
147
+ <%= form.submit rodauth.create_account_button,
148
+ class:
149
+ "w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800" %>
54
150
  <% end %>
55
151
 
56
152
  <p class="text-sm font-medium text-gray-500 dark:text-gray-400">
57
153
  Already have an account?
58
- <%= link_to "Login", rodauth.login_path, class: "text-primary-600 rounded-sm text-sm hover:underline hover:text-primary-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-600 dark:text-primary-300 dark:hover:text-primary-400 dark:focus-visible:ring-2 dark:focus-visible:ring-primary-300" %>
154
+ <%= link_to "Login",
155
+ rodauth.login_path,
156
+ class:
157
+ "text-primary-600 rounded-sm text-sm hover:underline hover:text-primary-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-600 dark:text-primary-300 dark:hover:text-primary-400 dark:focus-visible:ring-2 dark:focus-visible:ring-primary-300" %>
59
158
  </p>
@@ -0,0 +1,88 @@
1
+ return unless defined?(Rodauth::Rails)
2
+
3
+ require "rails/generators/base"
4
+
5
+ require_relative "../lib/plutonium_generators"
6
+
7
+ module Pu
8
+ module Rodauth
9
+ class AdminGenerator < ::Rails::Generators::Base
10
+ include PlutoniumGenerators::Concerns::Logger
11
+
12
+ source_root "#{__dir__}/templates"
13
+
14
+ desc "Generate a rodauth-rails account optimized for performing admin tasks"
15
+
16
+ argument :name
17
+
18
+ def start
19
+ generate_admin_account
20
+ configure_admin_account
21
+ rescue => e
22
+ exception "#{self.class} failed:", e
23
+ end
24
+
25
+ private
26
+
27
+ def generate_admin_account
28
+ invoke "pu:rodauth:account", [name],
29
+ defaults: false,
30
+ **admin_features,
31
+ force: options[:force],
32
+ skip: options[:skip]
33
+ end
34
+
35
+ def configure_admin_account
36
+ # Prevent account creation from web
37
+ insert_into_file "app/rodauth/#{normalized_name}_rodauth_plugin.rb", indent(<<~EOT, 4), after: /# ==> Hooks\n/
38
+
39
+ # Prevent using the web to sign up.
40
+ before_create_account_route do
41
+ request.halt unless internal_request?
42
+ end
43
+
44
+ EOT
45
+
46
+ # Customize login flow
47
+ insert_into_file "app/rodauth/#{normalized_name}_rodauth_plugin.rb", indent(<<~EOT, 4), before: /\n.*# ==> Emails/
48
+
49
+ # Only ask for password after asking for the login
50
+ use_multi_phase_login? true
51
+ EOT
52
+
53
+ # Configure MFA return
54
+ gsub_file(
55
+ "app/rodauth/#{normalized_name}_rodauth_plugin.rb",
56
+ /.*two_factor_auth_return_to_requested_location?.*/,
57
+ indent("two_factor_auth_return_to_requested_location? true", 4),
58
+ verbose: false
59
+ )
60
+
61
+ # Configure MFA flash message
62
+ insert_into_file "app/rodauth/#{normalized_name}_rodauth_plugin.rb", indent(<<~EOT, 4), after: /# Override default flash messages.*\n/
63
+ two_factor_not_setup_error_flash "You need to setup two factor authentication"
64
+ EOT
65
+
66
+ template "app/views/_login_form_footer.html.erb.tt", "app/views/rodauth/#{normalized_name}/_login_form_footer.html.erb"
67
+
68
+ template "lib/tasks/rodauth_admin.rake", "lib/tasks/rodauth_#{normalized_name}.rake"
69
+ end
70
+
71
+ def admin_features
72
+ [
73
+ :login, :remember, :logout,
74
+ :create_account, :verify_account, :close_account,
75
+ :reset_password, :reset_password_notify, :change_password,
76
+ :otp, :recovery_codes,
77
+ :lockout, :active_sessions, :audit_logging,
78
+ :password_grace_period,
79
+ :internal_request
80
+ ].map { |feature| [feature, true] }.to_h
81
+ end
82
+
83
+ def display_name = name.humanize.downcase
84
+
85
+ def normalized_name = name.underscore
86
+ end
87
+ end
88
+ end
@@ -71,6 +71,7 @@ module Pu
71
71
  }
72
72
  },
73
73
  reset_password_notify: {default: true},
74
+ password_grace_period: {},
74
75
  change_login: {
75
76
  default: true,
76
77
  views: %w[change_login]
@@ -41,6 +41,8 @@ module Pu
41
41
  end
42
42
 
43
43
  def add_dev_config
44
+ return if Rails.version.to_f >= 8.0
45
+
44
46
  insert_into_file "config/environments/development.rb",
45
47
  "\n config.action_mailer.default_url_options = { host: '127.0.0.1', port: ENV.fetch('PORT', 3000) }\n",
46
48
  before: /^end/
@@ -0,0 +1,8 @@
1
+ <%% unless rodauth(:<%= normalized_name %>).login_form_footer_links.empty? %>
2
+ <ul>
3
+ <%% rodauth(:<%= normalized_name %>).login_form_footer_links.sort.each do |_, link, text| %>
4
+ <%% next if rodauth(:<%= normalized_name %>).try(:create_account_path) == link %>
5
+ <li><%%= link_to text, link, class: "text-primary-600 rounded-sm text-sm hover:underline hover:text-primary-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-600 dark:text-primary-300 dark:hover:text-primary-400 dark:focus-visible:ring-2 dark:focus-visible:ring-primary-300" %></li>
6
+ <%% end %>
7
+ </ul>
8
+ <%% end %>
@@ -0,0 +1,11 @@
1
+ namespace :rodauth do
2
+ desc "Create a <%= display_name %> account"
3
+ task <%= normalized_name %>: :environment do
4
+ require "tty-prompt"
5
+
6
+ prompt = TTY::Prompt.new
7
+ email = ENV["EMAIL"] || prompt.ask("Email:", required: true)
8
+
9
+ RodauthApp.rodauth(:<%= normalized_name %>).create_account(login: email)
10
+ end
11
+ end
@@ -47,9 +47,9 @@ module Plutonium
47
47
  setup_phlexi_themes
48
48
  end
49
49
 
50
- rake_tasks do
51
- load "tasks/create_rodauth_admin.rake"
52
- end
50
+ # rake_tasks do
51
+ # load "tasks/create_rodauth_admin.rake"
52
+ # end
53
53
 
54
54
  config.after_initialize do
55
55
  Plutonium::Reloader.start! if Plutonium.configuration.enable_hotreload
@@ -44,7 +44,7 @@ module Plutonium
44
44
  class: "bg-white border-b border-gray-200 px-4 py-2.5 dark:bg-gray-800 dark:border-gray-700 fixed left-0 right-0 top-0 z-50",
45
45
  data: {
46
46
  controller: "resource-header",
47
- header_sidebar_outlet: "#sidebar-navigation"
47
+ resource_header_sidebar_outlet: "#sidebar-navigation"
48
48
  }
49
49
  ) do
50
50
  div(class: "flex flex-wrap justify-between items-center") do
@@ -70,7 +70,7 @@ module Plutonium
70
70
  # @private
71
71
  def render_sidebar_toggle
72
72
  button(
73
- data_action: "header#toggleDrawer",
73
+ data_action: "resource-header#toggleDrawer",
74
74
  aria_controls: "#sidebar-navigation",
75
75
  class: %(p-2 mr-2 text-gray-600 rounded-lg cursor-pointer lg:hidden hover:text-gray-900
76
76
  hover:bg-gray-100 focus:bg-gray-100 dark:focus:bg-gray-700 focus:ring-2
@@ -97,11 +97,11 @@ module Plutonium
97
97
  # Renders the toggle icons for the sidebar button
98
98
  # @private
99
99
  def render_toggle_icons
100
- span(data_header_target: "openIcon") do
100
+ span(data_resource_header_target: "openIcon") do
101
101
  render Phlex::TablerIcons::Menu.new(class: "w-6 h-6")
102
102
  end
103
103
 
104
- span(data_header_target: "closeIcon", class: "hidden", aria_hidden: "true") do
104
+ span(data_resource_header_target: "closeIcon", class: "hidden", aria_hidden: "true") do
105
105
  render Phlex::TablerIcons::X.new(class: "w-6 h-6")
106
106
  end
107
107
 
@@ -24,6 +24,7 @@ module Plutonium
24
24
  # @private
25
25
  def render_sidebar_container(&)
26
26
  aside(
27
+ data: {controller: "sidebar"},
27
28
  id: "sidebar-navigation",
28
29
  aria: {label: "Sidebar Navigation"},
29
30
  class: "fixed top-0 left-0 z-40 w-64 h-screen pt-14 transition-transform -translate-x-full lg:translate-x-0",
@@ -43,7 +44,7 @@ module Plutonium
43
44
 
44
45
  # @private
45
46
  def render_color_mode_controls
46
- div(class: "hidden absolute bottom-0 left-0 justify-center p-4 space-x-4 w-full lg:flex bg-white dark:bg-gray-800 z-20 border-r border-gray-200 dark:border-gray-700") do
47
+ div(class: "absolute bottom-0 left-0 justify-center p-4 space-x-4 w-full flex bg-white dark:bg-gray-800 z-20 border-r border-gray-200 dark:border-gray-700") do
47
48
  render ColorModeSelector.new
48
49
  end
49
50
  end
@@ -1,5 +1,5 @@
1
1
  module Plutonium
2
- VERSION = "0.19.11"
2
+ VERSION = "0.19.13"
3
3
  NEXT_MAJOR_VERSION = VERSION.split(".").tap { |v|
4
4
  v[1] = v[1].to_i + 1
5
5
  v[2] = 0
data/lib/tasks/.keep ADDED
File without changes
data/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@radioactive-labs/plutonium",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@radioactive-labs/plutonium",
9
- "version": "0.3.2",
9
+ "version": "0.3.4",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@hotwired/stimulus": "^3.2.2",
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radioactive-labs/plutonium",
3
- "version": "0.3.3",
3
+ "version": "0.3.6",
4
4
  "description": "Core assets for the Plutonium gem",
5
5
  "type": "module",
6
6
  "main": "src/js/core.js",
@@ -0,0 +1,17 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ export default class extends Controller {
4
+ static targets = ["password", "checkbox"];
5
+
6
+ connect() {
7
+ this.checkboxTarget.checked = false // ensure password is hidden by default
8
+ }
9
+
10
+ toggle() {
11
+ if (this.passwordTarget.type == "password") {
12
+ this.passwordTargets.forEach((passwordTarget) => passwordTarget.type = "text")
13
+ } else {
14
+ this.passwordTargets.forEach((passwordTarget) => passwordTarget.type = "password")
15
+ }
16
+ }
17
+ }
@@ -16,9 +16,13 @@ import ResourceTabListController from "./resource_tab_list_controller.js"
16
16
  import AttachmentInputController from "./attachment_input_controller.js"
17
17
  import AttachmentPreviewController from "./attachment_preview_controller.js"
18
18
  import AttachmentPreviewContainerController from "./attachment_preview_container_controller.js"
19
+ import SidebarController from "./sidebar_controller.js"
20
+ import PasswordVisibilityController from "./password_visibility_controller.js"
19
21
 
20
22
  export default function (application) {
21
23
  // Register controllers here
24
+ application.register("password-visibility", PasswordVisibilityController)
25
+ application.register("sidebar", SidebarController)
22
26
  application.register("resource-header", ResourceHeaderController)
23
27
  application.register("nested-resource-form-fields", NestedResourceFormFieldsController)
24
28
  application.register("form", FormController)
@@ -0,0 +1,3 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ export default class extends Controller {}