lesli_shield 1.1.5 → 1.1.7
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/Rakefile +3 -0
- data/app/assets/stylesheets/lesli_shield/application.css +140 -1
- data/app/assets/stylesheets/lesli_shield/confirmations.css +917 -18
- data/app/assets/stylesheets/lesli_shield/confirmations.tailwind.css +918 -0
- data/app/assets/stylesheets/lesli_shield/passwords.css +872 -18
- data/app/assets/stylesheets/lesli_shield/passwords.tailwind.css +873 -0
- data/app/assets/stylesheets/lesli_shield/registrations.css +904 -770
- data/app/assets/stylesheets/lesli_shield/registrations.tailwind.css +908 -0
- data/app/assets/stylesheets/lesli_shield/sessions.css +984 -32
- data/app/assets/stylesheets/lesli_shield/sessions.tailwind.css +983 -1
- data/app/controllers/lesli_shield/profile/passwords_controller.rb +119 -0
- data/app/controllers/lesli_shield/profiles_controller.rb +63 -0
- data/app/controllers/lesli_shield/sessions_controller.rb +1 -2
- data/app/controllers/lesli_shield/users_controller.rb +3 -7
- data/app/controllers/users/confirmations_controller.rb +162 -49
- data/app/controllers/users/passwords_controller.rb +211 -28
- data/app/controllers/users/registrations_controller.rb +108 -83
- data/app/controllers/users/sessions_controller.rb +122 -84
- data/app/interfaces/lesli_shield/authentication_interface.rb +3 -3
- data/app/interfaces/lesli_shield/authorization_interface.rb +2 -2
- data/app/mailers/lesli_shield/devise_mailer.rb +73 -17
- data/app/models/concerns/lesli_shield/user_authentication.rb +54 -0
- data/app/models/lesli_shield/account.rb +4 -1
- data/app/models/lesli_shield/invite.rb +1 -1
- data/app/models/lesli_shield/user/role.rb +1 -1
- data/app/models/lesli_shield/user.rb +5 -2
- data/app/services/lesli_shield/profile/password_service.rb +47 -0
- data/app/services/lesli_shield/profile_service.rb +24 -0
- data/app/services/lesli_shield/user_registration_service.rb +41 -74
- data/app/services/lesli_shield/user_session_service.rb +1 -1
- data/app/services/lesli_shield/user_validator_service.rb +35 -39
- data/app/views/devise/confirmations/new.html.erb +58 -12
- data/app/views/devise/confirmations/show.html.erb +27 -60
- data/app/views/devise/passwords/edit.html.erb +59 -25
- data/app/views/devise/passwords/new.html.erb +61 -26
- data/app/views/devise/registrations/new.html.erb +80 -53
- data/app/views/devise/sessions/new.html.erb +53 -36
- data/app/views/devise/shared/_application-devise-simple.erb +18 -19
- data/app/views/devise/shared/_demo.html.erb +8 -6
- data/app/views/devise/shared/_error_messages.html.erb +45 -10
- data/app/views/devise/shared/_links.html.erb +6 -13
- data/app/views/lesli_shield/invites/_form.html.erb +1 -1
- data/app/views/lesli_shield/invites/index.html.erb +3 -2
- data/app/views/lesli_shield/profiles/_password-form.html.erb +68 -0
- data/app/views/lesli_shield/profiles/show.html.erb +29 -0
- data/app/views/lesli_shield/users/_information-card.html.erb +35 -45
- data/app/views/lesli_shield/users/_information-form.html.erb +9 -1
- data/config/initializers/devise.rb +52 -328
- data/config/locales/translations.en.yml +65 -2
- data/config/locales/translations.es.yml +65 -2
- data/config/routes.rb +4 -0
- data/lib/lesli_shield/engine.rb +44 -4
- data/lib/lesli_shield/router.rb +52 -18
- data/lib/lesli_shield/version.rb +2 -2
- data/readme.md +6 -4
- metadata +30 -5
- data/app/assets/config/lesli_shield_manifest.js +0 -48
- data/app/assets/stylesheets/lesli_shield/application.tailwind.css +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<%#
|
|
2
|
+
|
|
2
3
|
Lesli
|
|
3
4
|
|
|
4
|
-
Copyright (c)
|
|
5
|
+
Copyright (c) 2026, Lesli Technologies, S. A.
|
|
5
6
|
|
|
6
7
|
This program is free software: you can redistribute it and/or modify
|
|
7
8
|
it under the terms of the GNU General Public License as published by
|
|
@@ -29,76 +30,102 @@ Building a better future, one line of code at a time.
|
|
|
29
30
|
// ·
|
|
30
31
|
%>
|
|
31
32
|
|
|
32
|
-
<%
|
|
33
|
-
|
|
34
|
-
# Check if demo mode is enable on initializer file
|
|
35
|
-
if Lesli.config.demo
|
|
36
|
-
resource.email = Lesli.config.company[:email]
|
|
37
|
-
resource.password = Lesli.config.security[:password]
|
|
38
|
-
end
|
|
39
|
-
%>
|
|
40
|
-
|
|
41
33
|
<%
|
|
42
34
|
title = I18n.t("overrides.lesli_shield.devise/registrations.view_title",
|
|
43
35
|
default: :"lesli_shield.devise/registrations.view_title")
|
|
44
36
|
%>
|
|
45
37
|
|
|
46
|
-
<%= render("devise/shared/application-devise", title:title) do %>
|
|
38
|
+
<%= render("devise/shared/application-devise", title: title) do %>
|
|
47
39
|
|
|
48
40
|
<%= form_for(
|
|
49
|
-
resource,
|
|
50
|
-
as: resource_name,
|
|
41
|
+
resource,
|
|
42
|
+
as: resource_name,
|
|
51
43
|
url: user_registration_path,
|
|
44
|
+
html: { class: "text-left" },
|
|
52
45
|
builder: LesliView::Forms::Builder
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
46
|
+
) do |form| %>
|
|
47
|
+
|
|
48
|
+
<p class="mb-6 text-center text-sm leading-6 text-slate-600">
|
|
49
|
+
<%= I18n.t("lesli_shield.devise/registrations.view_description") %>
|
|
50
|
+
</p>
|
|
51
|
+
|
|
52
|
+
<%= render "devise/shared/error_messages", resource: resource %>
|
|
53
|
+
|
|
54
|
+
<%= form.field_control_email(
|
|
55
|
+
:email,
|
|
56
|
+
label: I18n.t("lesli_shield.devise/registrations.label_email"),
|
|
57
|
+
message: resource.errors[:email].to_sentence.presence,
|
|
58
|
+
category: resource.errors[:email].any? ? :danger : nil,
|
|
59
|
+
icon: "person",
|
|
60
|
+
autofocus: true,
|
|
61
|
+
autocomplete: "email",
|
|
62
|
+
required: true,
|
|
63
|
+
autocapitalize: "none",
|
|
64
|
+
spellcheck: false
|
|
60
65
|
) %>
|
|
61
66
|
|
|
62
|
-
<%= form.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
<%= form.field_control_password(
|
|
68
|
+
:password,
|
|
69
|
+
label: I18n.t("lesli_shield.devise/registrations.label_password"),
|
|
70
|
+
message: resource.errors[:password].to_sentence.presence ||
|
|
71
|
+
I18n.t(
|
|
72
|
+
"lesli_shield.devise/registrations.view_password_length",
|
|
73
|
+
minimum: @minimum_password_length,
|
|
74
|
+
maximum: Devise.password_length.max
|
|
75
|
+
),
|
|
76
|
+
category: resource.errors[:password].any? ? :danger : nil,
|
|
77
|
+
icon: "key",
|
|
78
|
+
autocomplete: "new-password",
|
|
79
|
+
required: true,
|
|
80
|
+
minlength: @minimum_password_length,
|
|
81
|
+
maxlength: Devise.password_length.max,
|
|
82
|
+
value: ""
|
|
68
83
|
) %>
|
|
69
84
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
85
|
+
<%= form.field_control_password(
|
|
86
|
+
:password_confirmation,
|
|
87
|
+
label: I18n.t(
|
|
88
|
+
"lesli_shield.devise/registrations.label_password_confirmation"
|
|
89
|
+
),
|
|
90
|
+
message: resource.errors[:password_confirmation].to_sentence.presence,
|
|
91
|
+
category: resource.errors[:password_confirmation].any? ? :danger : nil,
|
|
92
|
+
icon: "key",
|
|
93
|
+
autocomplete: "new-password",
|
|
94
|
+
required: true,
|
|
95
|
+
minlength: @minimum_password_length,
|
|
96
|
+
maxlength: Devise.password_length.max,
|
|
97
|
+
value: ""
|
|
98
|
+
) %>
|
|
78
99
|
|
|
79
|
-
<div class="
|
|
80
|
-
<p class="
|
|
81
|
-
|
|
82
|
-
read and acknowledge the <a><u><b>Global Privacy Statement</b></u></a>
|
|
100
|
+
<div class="mb-4">
|
|
101
|
+
<p class="text-left text-xs leading-5 text-slate-500">
|
|
102
|
+
<%= I18n.t("lesli_shield.devise/registrations.view_legal_notice") %>
|
|
83
103
|
</p>
|
|
84
104
|
</div>
|
|
85
105
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
106
|
+
<%= form.field_control_button(
|
|
107
|
+
I18n.t(
|
|
108
|
+
"overrides.lesli_shield.devise/registrations.button_create_account",
|
|
109
|
+
default: :"lesli_shield.devise/registrations.button_create_account"
|
|
110
|
+
),
|
|
111
|
+
{
|
|
112
|
+
class: "w-full",
|
|
113
|
+
data: {
|
|
114
|
+
turbo_submits_with: I18n.t(
|
|
115
|
+
"lesli_shield.devise/registrations.button_creating_account"
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
icon: "person_add"
|
|
120
|
+
) %>
|
|
96
121
|
|
|
97
|
-
<p class="
|
|
122
|
+
<p class="mt-1 text-center text-sm text-slate-600">
|
|
98
123
|
<%= I18n.t("lesli_shield.devise/registrations.view_already_have_an_account") %>
|
|
99
|
-
<%= link_to(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
124
|
+
<%= link_to(
|
|
125
|
+
I18n.t("lesli_shield.devise/registrations.button_login"),
|
|
126
|
+
new_user_session_path,
|
|
127
|
+
class: "font-semibold text-[var(--lesli-color-primary)] underline underline-offset-2 hover:opacity-80 focus-visible:rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--lesli-color-primary)]"
|
|
128
|
+
) %>
|
|
129
|
+
</p>
|
|
103
130
|
<% end %>
|
|
104
131
|
<% end %>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Lesli
|
|
4
4
|
|
|
5
|
-
Copyright (c)
|
|
5
|
+
Copyright (c) 2026, Lesli Technologies, S. A.
|
|
6
6
|
|
|
7
7
|
This program is free software: you can redistribute it and/or modify
|
|
8
8
|
it under the terms of the GNU General Public License as published by
|
|
@@ -30,23 +30,48 @@ Building a better future, one line of code at a time.
|
|
|
30
30
|
// ·
|
|
31
31
|
%>
|
|
32
32
|
|
|
33
|
-
<%
|
|
34
|
-
|
|
35
|
-
# Check if demo mode is enable on initializer file
|
|
36
|
-
if Lesli.config.demo
|
|
37
|
-
resource.email = Lesli.config.company[:email]
|
|
38
|
-
resource.password = Lesli.config.security[:password]
|
|
39
|
-
end
|
|
40
|
-
%>
|
|
41
|
-
|
|
42
33
|
<%
|
|
43
34
|
title = I18n.t("overrides.lesli_shield.devise/sessions.view_title",
|
|
44
35
|
default: :"lesli_shield.devise/sessions.view_title")
|
|
36
|
+
|
|
37
|
+
demo_credentials = if Lesli.config.demo
|
|
38
|
+
{
|
|
39
|
+
email: Lesli.config.company[:email].to_s,
|
|
40
|
+
password: Lesli.config.security[:password].to_s
|
|
41
|
+
}
|
|
42
|
+
end
|
|
45
43
|
%>
|
|
46
44
|
|
|
47
45
|
<%= render("devise/shared/application-devise", title: title) do %>
|
|
48
46
|
|
|
49
|
-
<% authentication_error = flash[:alert].presence || flash[:error].presence %>
|
|
47
|
+
<% authentication_error = flash[:danger].presence || flash[:alert].presence || flash[:error].presence %>
|
|
48
|
+
|
|
49
|
+
<%
|
|
50
|
+
email_field_options = {
|
|
51
|
+
label: I18n.t("lesli_shield.devise/sessions.label_email", default: "Email address"),
|
|
52
|
+
category: authentication_error.present? ? :danger : nil,
|
|
53
|
+
icon: "person",
|
|
54
|
+
autofocus: true,
|
|
55
|
+
autocomplete: "email",
|
|
56
|
+
required: true,
|
|
57
|
+
placeholder: Lesli.config.company[:email]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
password_field_options = {
|
|
61
|
+
label: I18n.t("lesli_shield.devise/sessions.label_password", default: "Password"),
|
|
62
|
+
message: authentication_error,
|
|
63
|
+
category: authentication_error.present? ? :danger : nil,
|
|
64
|
+
icon: "key",
|
|
65
|
+
autocomplete: "current-password",
|
|
66
|
+
required: true,
|
|
67
|
+
placeholder: "••••••••"
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if demo_credentials
|
|
71
|
+
email_field_options[:value] = demo_credentials[:email]
|
|
72
|
+
password_field_options[:value] = demo_credentials[:password]
|
|
73
|
+
end
|
|
74
|
+
%>
|
|
50
75
|
|
|
51
76
|
<%= form_for(
|
|
52
77
|
resource,
|
|
@@ -57,34 +82,21 @@ title = I18n.t("overrides.lesli_shield.devise/sessions.view_title",
|
|
|
57
82
|
data: { turbo: false }
|
|
58
83
|
) do |form| %>
|
|
59
84
|
|
|
60
|
-
<% if
|
|
61
|
-
<%= render("devise/shared/demo") %>
|
|
85
|
+
<% if demo_credentials %>
|
|
86
|
+
<%= render("devise/shared/demo", credentials: demo_credentials) %>
|
|
62
87
|
<% end %>
|
|
63
88
|
|
|
64
|
-
<%= form.field_control_email(
|
|
65
|
-
:email,
|
|
66
|
-
label: I18n.t("lesli_shield.devise/sessions.label_email", default: "Email address"),
|
|
67
|
-
category: authentication_error.present? ? :danger : nil,
|
|
68
|
-
icon: "person",
|
|
69
|
-
autofocus: true,
|
|
70
|
-
autocomplete: "email",
|
|
71
|
-
required: true,
|
|
72
|
-
placeholder: Lesli.config.company[:email]
|
|
73
|
-
) %>
|
|
89
|
+
<%= form.field_control_email(:email, **email_field_options) %>
|
|
74
90
|
|
|
75
|
-
<%= form.field_control_password(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
autocomplete: "current-password",
|
|
82
|
-
required: true,
|
|
83
|
-
placeholder: "••••••••"
|
|
84
|
-
) %>
|
|
91
|
+
<%= form.field_control_password(:password, **password_field_options) %>
|
|
92
|
+
|
|
93
|
+
<%
|
|
94
|
+
redirect_after_login = params[:r].presence ||
|
|
95
|
+
params.dig(:user, :redirect).presence
|
|
96
|
+
%>
|
|
85
97
|
|
|
86
|
-
<% if
|
|
87
|
-
<%= hidden_field_tag "user[redirect]",
|
|
98
|
+
<% if redirect_after_login %>
|
|
99
|
+
<%= hidden_field_tag "user[redirect]", redirect_after_login %>
|
|
88
100
|
<% end %>
|
|
89
101
|
|
|
90
102
|
<%= form.field_control_button(
|
|
@@ -102,5 +114,10 @@ title = I18n.t("overrides.lesli_shield.devise/sessions.view_title",
|
|
|
102
114
|
<% end %>
|
|
103
115
|
<% end %>
|
|
104
116
|
|
|
105
|
-
<%= render("devise/shared/links",
|
|
117
|
+
<%= render("devise/shared/links",
|
|
118
|
+
password_reset:true,
|
|
119
|
+
#magic_link:true,
|
|
120
|
+
login:true,
|
|
121
|
+
#otp:true,
|
|
122
|
+
) %>
|
|
106
123
|
<% end %>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
=begin
|
|
1
|
+
<%#
|
|
3
2
|
|
|
4
3
|
Lesli
|
|
5
4
|
|
|
@@ -29,31 +28,31 @@ Building a better future, one line of code at a time.
|
|
|
29
28
|
|
|
30
29
|
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
31
30
|
// ·
|
|
32
|
-
=end
|
|
33
31
|
%>
|
|
34
32
|
|
|
35
|
-
<% title =
|
|
33
|
+
<% title = local_assigns.fetch(:title, "") %>
|
|
36
34
|
|
|
37
|
-
<main id="lesli-application">
|
|
38
|
-
<section class="
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
<div class="logo mb-4">
|
|
35
|
+
<main id="lesli-application" class="min-h-screen bg-white">
|
|
36
|
+
<section class="flex min-h-screen flex-col">
|
|
37
|
+
<header class="shrink-0 px-6 pb-10 pt-16 text-center sm:pb-12 sm:pt-24">
|
|
38
|
+
<div>
|
|
42
39
|
<%= image_tag(
|
|
43
40
|
"lesli_assets/brand/app-auth.svg",
|
|
44
|
-
:
|
|
45
|
-
:
|
|
41
|
+
class: "#{lesli_instance_code}-logo mx-auto mb-4 h-auto w-auto max-w-[130px]",
|
|
42
|
+
alt: I18n.t("lesli_shield.authentication.logo_alt", default: "Application logo")
|
|
43
|
+
)
|
|
46
44
|
%>
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
|
|
46
|
+
<% if title.present? %>
|
|
47
|
+
<h1 class="text-2xl font-semibold tracking-tight text-[var(--lesli-color-primary)]">
|
|
48
|
+
<%= title %>
|
|
49
|
+
</h1>
|
|
50
|
+
<% end %>
|
|
51
51
|
</div>
|
|
52
|
-
</
|
|
53
|
-
<div class="hero-body">
|
|
54
|
-
|
|
55
|
-
<%= yield %>
|
|
52
|
+
</header>
|
|
56
53
|
|
|
54
|
+
<div class="flex flex-1 flex-col items-center border-t border-slate-200 bg-slate-50 px-4 py-8 sm:px-6 [&>form]:my-6 [&>form]:w-full [&>form]:max-w-lg [&>form]:rounded-xl [&>form]:border [&>form]:border-slate-200 [&>form]:bg-white [&>form]:p-6 [&>form]:shadow-sm sm:[&>form]:my-8 sm:[&>form]:p-10">
|
|
55
|
+
<%= yield %>
|
|
57
56
|
</div>
|
|
58
57
|
</section>
|
|
59
58
|
</main>
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
|
|
2
|
-
<fieldset class="mb-8 rounded-xl border border-sky-200 bg-sky-50 px-4 pb-4 text-sm text-sky-950">
|
|
3
|
-
<legend class="px-2 font-semibold text-sky-800">
|
|
2
|
+
<fieldset data-demo-credentials class="mb-8 rounded-xl border border-sky-200 bg-sky-50 px-4 pb-4 text-sm text-sky-950">
|
|
3
|
+
<legend class="px-2 font-semibold text-sky-800">
|
|
4
|
+
<%= I18n.t("lesli_shield.devise/sessions.demo_title") %>
|
|
5
|
+
</legend>
|
|
4
6
|
<dl class="mt-1 grid grid-cols-[auto_1fr] gap-x-3 gap-y-1">
|
|
5
|
-
<dt class="font-medium"
|
|
6
|
-
<dd class="break-all"><%=
|
|
7
|
-
<dt class="font-medium"
|
|
8
|
-
<dd><%=
|
|
7
|
+
<dt class="font-medium"><%= I18n.t("lesli_shield.devise/sessions.demo_email") %>:</dt>
|
|
8
|
+
<dd class="break-all"><%= credentials.fetch(:email) %></dd>
|
|
9
|
+
<dt class="font-medium"><%= I18n.t("lesli_shield.devise/sessions.demo_password") %>:</dt>
|
|
10
|
+
<dd><%= credentials.fetch(:password) %></dd>
|
|
9
11
|
</dl>
|
|
10
12
|
</fieldset>
|
|
@@ -1,28 +1,63 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
<% if flash[:notice] %>
|
|
2
|
+
<div
|
|
3
|
+
class="mb-6 rounded-lg border border-emerald-200 bg-emerald-50 px-4 py-3 text-left text-sm text-emerald-900"
|
|
4
|
+
role="status"
|
|
5
|
+
aria-live="polite"
|
|
6
|
+
data-turbo-cache="false"
|
|
7
|
+
>
|
|
8
|
+
<%= flash[:notice] %>
|
|
5
9
|
</div>
|
|
6
10
|
<% end %>
|
|
7
11
|
|
|
8
12
|
<% if flash[:success] %>
|
|
9
|
-
<div
|
|
13
|
+
<div
|
|
14
|
+
class="mb-6 rounded-lg border border-emerald-200 bg-emerald-50 px-4 py-3 text-left text-sm text-emerald-900"
|
|
15
|
+
role="status"
|
|
16
|
+
aria-live="polite"
|
|
17
|
+
data-turbo-cache="false"
|
|
18
|
+
>
|
|
10
19
|
<%= flash[:success] %>
|
|
11
20
|
</div>
|
|
12
21
|
<% end %>
|
|
13
22
|
|
|
23
|
+
<% if flash[:alert] %>
|
|
24
|
+
<div
|
|
25
|
+
class="mb-6 rounded-lg border border-rose-200 bg-rose-50 px-4 py-3 text-left text-sm text-rose-900"
|
|
26
|
+
role="alert"
|
|
27
|
+
data-turbo-cache="false"
|
|
28
|
+
>
|
|
29
|
+
<%= flash[:alert] %>
|
|
30
|
+
</div>
|
|
31
|
+
<% end %>
|
|
32
|
+
|
|
33
|
+
<% if flash[:danger] %>
|
|
34
|
+
<div
|
|
35
|
+
class="mb-6 rounded-lg border border-rose-200 bg-rose-50 px-4 py-3 text-left text-sm text-rose-900"
|
|
36
|
+
role="alert"
|
|
37
|
+
data-turbo-cache="false"
|
|
38
|
+
>
|
|
39
|
+
<%= flash[:danger] %>
|
|
40
|
+
</div>
|
|
41
|
+
<% end %>
|
|
14
42
|
|
|
15
43
|
<% if resource.errors.any? %>
|
|
16
|
-
<div
|
|
17
|
-
|
|
44
|
+
<div
|
|
45
|
+
id="error_explanation"
|
|
46
|
+
class="mb-6 rounded-lg border border-rose-200 bg-rose-50 px-4 py-3 text-left text-rose-900"
|
|
47
|
+
role="alert"
|
|
48
|
+
tabindex="-1"
|
|
49
|
+
autofocus
|
|
50
|
+
data-turbo-cache="false"
|
|
51
|
+
>
|
|
52
|
+
<h2 class="text-sm font-semibold">
|
|
18
53
|
<%= I18n.t("errors.messages.not_saved",
|
|
19
54
|
count: resource.errors.count,
|
|
20
55
|
resource: resource.class.model_name.human.downcase)
|
|
21
56
|
%>
|
|
22
|
-
</
|
|
23
|
-
<ul>
|
|
57
|
+
</h2>
|
|
58
|
+
<ul class="mt-2 list-disc space-y-1 pl-5 text-sm">
|
|
24
59
|
<% resource.errors.full_messages.each do |message| %>
|
|
25
|
-
<li
|
|
60
|
+
<li><%= message %></li>
|
|
26
61
|
<% end %>
|
|
27
62
|
</ul>
|
|
28
63
|
</div>
|
|
@@ -42,25 +42,18 @@ Building a better future, one line of code at a time.
|
|
|
42
42
|
<% if login %>
|
|
43
43
|
<%= link_to(new_user_session_path) do %>
|
|
44
44
|
<span class="icon mr-1">
|
|
45
|
-
<
|
|
46
|
-
<path fill="#112a62" d="M6.253 2.41A6.253 6.253 0 0 0 .035 7.997a6.251 6.251 0 0 0 9.323 6.086 6.252 6.252 0 0 0 2.829-3.47h1.097v-.781h-.894a6.104 6.104 0 0 0 0-2.344h9.293l.879 1.172-.88 1.172h-.425l-1.055-1.059a.389.389 0 0 0-.554 0l-1.055 1.059h-.41l-.668-.997a.39.39 0 0 0-.649 0l-.668.997h-.57v.78h.781c.131 0 .252-.066.324-.175l.457-.684.457.684c.073.11.194.175.325.176h.78a.389.389 0 0 0 .278-.113l.895-.899.894.899a.388.388 0 0 0 .278.113h.78a.39.39 0 0 0 .313-.156l1.172-1.563a.39.39 0 0 0 0-.469L22.19 6.863a.39.39 0 0 0-.312-.156h-9.692A6.254 6.254 0 0 0 6.253 2.41Zm0 11.718c-.133 0-.261 0-.39-.02v-.76h.78v.76c-.128.02-.257.02-.39.02zM2.738 6.706h-.782v-.78h.782zm7.031-.78h.781v.78H9.77Zm-1.563 6.25h.782v.78h-.782zm-3.906.78H3.52v-.78H4.3zm6.25-1.562H9.77v-.781h.781ZM6.644 9.761v2.024h-.781V9.76a1.17 1.17 0 0 1-.711-.71H3.128v-.782h2.024a1.172 1.172 0 1 1 1.492 1.492zm-3.906 1.633h-.782v-.781h.782zm5.468-6.25v-.781h.782v.781zm-3.906 0H3.52v-.781H4.3zM1.566 8.269v.781H.804V8.27zm9.375.781V8.27h.781c0 .129.02.258.02.39 0 .133 0 .262-.02.391zM6.644 3.972h-.782v-.781h.781z"/>
|
|
47
|
-
<path fill="#112a62" d="m.134 2.09.492.61a8.595 8.595 0 0 1 10.973.125l.508-.594a9.372 9.372 0 0 0-11.973-.14ZM.69 14.774l-.492.609a9.38 9.38 0 0 0 11.973-.14l-.508-.594a8.596 8.596 0 0 1-10.972.125zM9.767 11.786v-.781h.782v.781z"/>
|
|
48
|
-
</svg>
|
|
45
|
+
<span class="material-symbols-outlined" aria-hidden="true">login</span>
|
|
49
46
|
</span>
|
|
50
|
-
<span
|
|
47
|
+
<span><%= I18n.t("lesli_shield.devise/shared.button_login") %></span>
|
|
51
48
|
<% end %>
|
|
52
49
|
<% end %>
|
|
53
50
|
|
|
54
51
|
<% if password_reset %>
|
|
55
52
|
<%= link_to(new_user_password_path) do %>
|
|
56
53
|
<span class="icon mr-2">
|
|
57
|
-
<
|
|
58
|
-
<path d="M10 4.75C8.55296 4.75 7.375 5.92796 7.375 7.375V8.25C6.89155 8.25 6.5 8.64155 6.5 9.125V13.5C6.5 13.9834 6.89155 14.375 7.375 14.375H12.625C13.1084 14.375 13.5 13.9834 13.5 13.5V9.125C13.5 8.64155 13.1084 8.25 12.625 8.25V7.375C12.625 5.92796 11.447 4.75 10 4.75ZM11.75 12.625H8.25V10H11.75V12.625ZM9.125 8.25V7.375C9.125 6.89264 9.51764 6.5 10 6.5C10.4824 6.5 10.875 6.89264 10.875 7.375V8.25H9.125Z" fill="#112A62"/>
|
|
59
|
-
<path d="M16.7549 3.14324C13.4431 -0.120437 8.34511 -0.489197 4.62839 2.0123L4.61745 0.577295C4.61526 0.336669 4.41839 0.141979 4.17667 0.143071L3.30167 0.149633C3.05996 0.151821 2.86527 0.348697 2.86745 0.590409L2.89151 3.86501C2.89479 4.21938 3.11026 4.53656 3.43729 4.67001C3.76542 4.80345 4.14056 4.72579 4.38993 4.47314C7.43941 1.3811 12.4343 1.34386 15.5264 4.39001C17.8867 6.71533 18.5308 10.2132 17.19 13.2111C17.0948 13.4244 17.1725 13.6738 17.3814 13.7799L18.1623 14.1791C18.3833 14.2917 18.6633 14.201 18.7661 13.9746C20.434 10.2996 19.6531 5.99904 16.7546 3.14304L16.7549 3.14324Z" fill="#112A62"/>
|
|
60
|
-
<path d="M16.5625 15.3296C16.2333 15.1962 15.8593 15.2739 15.6099 15.5265C12.5615 18.6197 7.56633 18.6569 4.47345 15.6096C2.11314 13.2843 1.46905 9.78647 2.80986 6.78851C2.90502 6.57523 2.82736 6.32587 2.61846 6.21978L1.83751 5.82055C1.61657 5.7079 1.33656 5.79868 1.23377 6.02509C-0.43528 9.70121 0.346732 14.0017 3.24518 16.8566C6.55702 20.1203 11.655 20.489 15.3717 17.9876L15.3826 19.4215C15.3848 19.6632 15.5817 19.8579 15.8234 19.8557L16.6984 19.8491C16.9401 19.8469 17.1348 19.6501 17.1326 19.4083L17.1086 16.1337C17.1053 15.7805 16.8898 15.4633 16.5628 15.3298L16.5625 15.3296Z" fill="#112A62"/>
|
|
61
|
-
</svg>
|
|
54
|
+
<span class="material-symbols-outlined" aria-hidden="true">lock_reset</span>
|
|
62
55
|
</span>
|
|
63
|
-
<span
|
|
56
|
+
<span><%= I18n.t("lesli_shield.devise/shared.button_reset_password") %></span>
|
|
64
57
|
<% end %>
|
|
65
58
|
<% end %>
|
|
66
59
|
|
|
@@ -75,7 +68,7 @@ Building a better future, one line of code at a time.
|
|
|
75
68
|
<path d="M9.9248 15.7502H7.5C5.7002 15.7502 4.25 14.3 4.25 12.5002C4.25 10.7004 5.7002 9.25024 7.5 9.25024H9.75C11.5498 9.25024 13 10.7004 13 12.5002C13 13.5002 13.6504 14.3498 14.5498 14.6252C14.8496 13.9748 15 13.2502 15 12.5002C15 9.59974 12.6504 7.25024 9.75 7.25024H7.5C4.5995 7.25024 2.25 9.59984 2.25 12.5002C2.25 15.4006 4.5996 17.7502 7.5 17.7502H9.75C10.3252 17.7502 10.9004 17.6506 11.4502 17.4504C10.8496 17.0002 10.3252 16.4006 9.9248 15.7502Z" fill="#112A62"/>
|
|
76
69
|
</svg>
|
|
77
70
|
</span>
|
|
78
|
-
<span
|
|
71
|
+
<span><%= I18n.t("lesli_shield.devise/shared.button_magic_link") %></span>
|
|
79
72
|
<% end %>
|
|
80
73
|
<% end %>
|
|
81
74
|
|
|
@@ -90,7 +83,7 @@ Building a better future, one line of code at a time.
|
|
|
90
83
|
<path fill="#112a62" d="m.134 2.09.492.61a8.595 8.595 0 0 1 10.973.125l.508-.594a9.372 9.372 0 0 0-11.973-.14ZM.69 14.774l-.492.609a9.38 9.38 0 0 0 11.973-.14l-.508-.594a8.596 8.596 0 0 1-10.972.125zM9.767 11.786v-.781h.782v.781z"/>
|
|
91
84
|
</svg>
|
|
92
85
|
</span>
|
|
93
|
-
<span
|
|
86
|
+
<span><%= I18n.t("lesli_shield.devise/shared.button_one_time_password") %></span>
|
|
94
87
|
<% end %>
|
|
95
88
|
<% end %>
|
|
96
89
|
</div>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<%= form.field_control_email(:email) %>
|
|
4
4
|
<%= form.field_control(:full_name) %>
|
|
5
5
|
<%= form.field_control(:telephone) %>
|
|
6
|
-
<%= form.
|
|
6
|
+
<%= form.field_control_textarea_rich(:notes) %>
|
|
7
7
|
<hr/>
|
|
8
8
|
<%= form.field_control_submit %>
|
|
9
9
|
<% end %>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Lesli
|
|
4
4
|
|
|
5
|
-
Copyright (c)
|
|
5
|
+
Copyright (c) 2026, Lesli Technologies, S. A.
|
|
6
6
|
|
|
7
7
|
This program is free software: you can redistribute it and/or modify
|
|
8
8
|
it under the terms of the GNU General Public License as published by
|
|
@@ -19,7 +19,7 @@ along with this program. If not, see http://www.gnu.org/licenses/.
|
|
|
19
19
|
|
|
20
20
|
Lesli · Ruby on Rails SaaS Development Framework.
|
|
21
21
|
|
|
22
|
-
Made with ♥ by
|
|
22
|
+
Made with ♥ by LesliTech
|
|
23
23
|
Building a better future, one line of code at a time.
|
|
24
24
|
|
|
25
25
|
@contact hello@lesli.tech
|
|
@@ -29,6 +29,7 @@ Building a better future, one line of code at a time.
|
|
|
29
29
|
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
30
|
// ·
|
|
31
31
|
%>
|
|
32
|
+
|
|
32
33
|
<%
|
|
33
34
|
columns = [{
|
|
34
35
|
field: "id",
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<div id="shield-profile-password-form" class="max-w-2xl">
|
|
2
|
+
<p class="mb-6 text-sm leading-6 text-slate-600">
|
|
3
|
+
<%= I18n.t("lesli_shield.profiles.password_description") %>
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
<%= form_with(
|
|
7
|
+
model: user,
|
|
8
|
+
url: profile_password_path,
|
|
9
|
+
method: :patch,
|
|
10
|
+
builder: LesliView::Forms::Builder
|
|
11
|
+
) do |form| %>
|
|
12
|
+
<%= form.fieldset do %>
|
|
13
|
+
<%= form.field_control_password(
|
|
14
|
+
:current_password,
|
|
15
|
+
label: I18n.t("lesli_shield.profiles.current_password"),
|
|
16
|
+
message: user.errors[:current_password].to_sentence.presence,
|
|
17
|
+
category: user.errors[:current_password].any? ? :danger : nil,
|
|
18
|
+
icon: "lock",
|
|
19
|
+
required: true,
|
|
20
|
+
autocomplete: "current-password",
|
|
21
|
+
value: ""
|
|
22
|
+
) %>
|
|
23
|
+
|
|
24
|
+
<%= form.field_control_password(
|
|
25
|
+
:password,
|
|
26
|
+
label: I18n.t("lesli_shield.profiles.new_password"),
|
|
27
|
+
message: user.errors[:password].to_sentence.presence ||
|
|
28
|
+
I18n.t(
|
|
29
|
+
"lesli_shield.profiles.password_hint",
|
|
30
|
+
minimum: Devise.password_length.min,
|
|
31
|
+
maximum: Devise.password_length.max
|
|
32
|
+
),
|
|
33
|
+
category: user.errors[:password].any? ? :danger : nil,
|
|
34
|
+
icon: "key",
|
|
35
|
+
required: true,
|
|
36
|
+
autocomplete: "new-password",
|
|
37
|
+
minlength: Devise.password_length.min,
|
|
38
|
+
maxlength: Devise.password_length.max,
|
|
39
|
+
value: ""
|
|
40
|
+
) %>
|
|
41
|
+
|
|
42
|
+
<%= form.field_control_password(
|
|
43
|
+
:password_confirmation,
|
|
44
|
+
label: I18n.t("lesli_shield.profiles.password_confirmation"),
|
|
45
|
+
message: user.errors[:password_confirmation].to_sentence.presence,
|
|
46
|
+
category: user.errors[:password_confirmation].any? ? :danger : nil,
|
|
47
|
+
icon: "key",
|
|
48
|
+
required: true,
|
|
49
|
+
autocomplete: "new-password",
|
|
50
|
+
minlength: Devise.password_length.min,
|
|
51
|
+
maxlength: Devise.password_length.max,
|
|
52
|
+
value: ""
|
|
53
|
+
) %>
|
|
54
|
+
|
|
55
|
+
<%= form.field_control_button(
|
|
56
|
+
I18n.t("lesli_shield.profiles.change_password"),
|
|
57
|
+
{
|
|
58
|
+
data: {
|
|
59
|
+
turbo_submits_with: I18n.t(
|
|
60
|
+
"lesli_shield.profiles.changing_password"
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
icon: "key"
|
|
65
|
+
) %>
|
|
66
|
+
<% end %>
|
|
67
|
+
<% end %>
|
|
68
|
+
</div>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<%= render LesliView::Layout::Container.new("shield-profile-show") do %>
|
|
2
|
+
<%= render "lesli_shield/users/information-card" %>
|
|
3
|
+
|
|
4
|
+
<%= render LesliView::Components::Tabs.new(
|
|
5
|
+
active_tab: @active_profile_tab.presence || params[:tab].presence_in(%w[information security]) || "information"
|
|
6
|
+
) do |tabs| %>
|
|
7
|
+
<% tabs.with_tab(
|
|
8
|
+
id: "information",
|
|
9
|
+
title: I18n.t("lesli_shield.profiles.information"),
|
|
10
|
+
icon: "info"
|
|
11
|
+
) do %>
|
|
12
|
+
<%= render(
|
|
13
|
+
"lesli_shield/users/information-form",
|
|
14
|
+
form_url: profile_path
|
|
15
|
+
) %>
|
|
16
|
+
<% end %>
|
|
17
|
+
|
|
18
|
+
<% tabs.with_tab(
|
|
19
|
+
id: "security",
|
|
20
|
+
title: I18n.t("lesli_shield.profiles.security"),
|
|
21
|
+
icon: "lock"
|
|
22
|
+
) do %>
|
|
23
|
+
<%= render(
|
|
24
|
+
"lesli_shield/profiles/password-form",
|
|
25
|
+
user: @user
|
|
26
|
+
) %>
|
|
27
|
+
<% end %>
|
|
28
|
+
<% end %>
|
|
29
|
+
<% end %>
|