lockify 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/users/confirmations_controller.rb +9 -6
- data/app/controllers/users/sessions_controller.rb +3 -7
- data/app/models/concerns/lockify_user.rb +2 -1
- data/app/views/user_mailer/confirmation_instructions.html.erb +36 -0
- data/app/views/user_mailer/reset_password_instructions.html.erb +37 -0
- data/app/views/users/confirmations/new.html.erb +142 -0
- data/app/views/users/passwords/edit.html.erb +191 -0
- data/app/views/users/passwords/new.html.erb +142 -0
- data/app/views/users/registrations/edit.html.erb +193 -0
- data/app/views/users/registrations/new.html.erb +187 -0
- data/app/views/users/sessions/new.html.erb +162 -0
- data/config/routes.rb +2 -28
- data/lib/generators/lockify/install/install_generator.rb +6 -4
- data/lib/generators/lockify/install/templates/migration.rb +1 -1
- data/lib/lockify/engine.rb +1 -0
- data/lib/lockify/version.rb +1 -1
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3774209347893e94e2c24afa116a1a68571a4b6b4d95cdc687fd5fae1fefcaf2
|
4
|
+
data.tar.gz: 6de1f0b5996ceff3e4d92208fb07c10701e7249e9f540eb6fada0716d2990c14
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ecb7a57ef9f67730ca3f773b40cd06720f1e507a6c88b3de9d5922f2e816db402be40044a3b8db84e505a094a858e3640050905e041e719d032250bb63279d7
|
7
|
+
data.tar.gz: 6159f071d115a51a99f999305747feb070bbcc7e45bfdb4c9b70ceb04e0b1575d4acfae46674ade259a9632d5c1a7b7e7275c32dfa91b6a5ee448e8765e266a4
|
@@ -23,17 +23,20 @@ class Users::ConfirmationsController < ApplicationController
|
|
23
23
|
def show
|
24
24
|
self.resource = User.find_by(confirmation_token: params[:confirmation_token])
|
25
25
|
|
26
|
-
if resource
|
26
|
+
if resource.nil?
|
27
|
+
set_flash_message!(:alert, :invalid_token)
|
28
|
+
redirect_to new_user_confirmation_path
|
29
|
+
elsif resource.confirmed?
|
30
|
+
set_flash_message!(:notice, :already_confirmed)
|
31
|
+
redirect_to new_user_session_path
|
32
|
+
elsif resource.confirmation_period_expired?
|
27
33
|
set_flash_message!(:alert, :expired)
|
28
34
|
redirect_to new_user_confirmation_path
|
29
|
-
|
35
|
+
else
|
30
36
|
resource.confirm!
|
31
37
|
sign_in(resource)
|
32
38
|
set_flash_message!(:notice, :confirmed)
|
33
|
-
redirect_to
|
34
|
-
else
|
35
|
-
set_flash_message!(:alert, :invalid_token)
|
36
|
-
redirect_to new_user_confirmation_path
|
39
|
+
redirect_to root_path
|
37
40
|
end
|
38
41
|
end
|
39
42
|
|
@@ -7,14 +7,14 @@ class Users::SessionsController < ApplicationController
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def create
|
10
|
-
self.resource = User.find_by(email:
|
10
|
+
self.resource = User.find_by(email: params[:email]&.downcase)
|
11
11
|
|
12
|
-
if resource&.authenticate(
|
12
|
+
if resource&.authenticate(params[:password])
|
13
13
|
if resource.valid_for_authentication?
|
14
14
|
resource.failed_attempts = 0 if resource.respond_to?(:failed_attempts=)
|
15
15
|
resource.save(validate: false) if resource.respond_to?(:failed_attempts)
|
16
16
|
|
17
|
-
sign_in(resource, remember_me:
|
17
|
+
sign_in(resource, remember_me: params[:remember_me] == '1')
|
18
18
|
respond_with resource, location: after_sign_in_path_for(resource)
|
19
19
|
else
|
20
20
|
set_flash_message!(:alert, :unconfirmed) unless resource.confirmed?
|
@@ -37,10 +37,6 @@ class Users::SessionsController < ApplicationController
|
|
37
37
|
|
38
38
|
protected
|
39
39
|
|
40
|
-
def sign_in_params
|
41
|
-
params.require(:user).permit(:email, :password, :remember_me)
|
42
|
-
end
|
43
|
-
|
44
40
|
def configure_sign_in_params
|
45
41
|
# Override in application if needed
|
46
42
|
end
|
@@ -22,7 +22,8 @@ module LockifyUser
|
|
22
22
|
def confirmation_period_expired?
|
23
23
|
return false unless respond_to?(:confirmation_sent_at)
|
24
24
|
return false unless Lockify.confirm_within
|
25
|
-
|
25
|
+
return false unless confirmation_sent_at
|
26
|
+
confirmation_sent_at.utc <= Lockify.confirm_within.ago
|
26
27
|
end
|
27
28
|
|
28
29
|
def confirm!
|
@@ -0,0 +1,36 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<style>
|
6
|
+
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
7
|
+
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
|
8
|
+
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; text-align: center; border-radius: 8px 8px 0 0; }
|
9
|
+
.content { background: #f8f9fa; padding: 30px; border-radius: 0 0 8px 8px; }
|
10
|
+
.btn { display: inline-block; background: #667eea; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; margin: 20px 0; }
|
11
|
+
</style>
|
12
|
+
</head>
|
13
|
+
<body>
|
14
|
+
<div class="container">
|
15
|
+
<div class="header">
|
16
|
+
<h1>¡Bienvenido!</h1>
|
17
|
+
</div>
|
18
|
+
<div class="content">
|
19
|
+
<h2>Confirma tu cuenta</h2>
|
20
|
+
<p>Hola <strong><%= @user.email %></strong>,</p>
|
21
|
+
<p>Gracias por registrarte. Para completar tu registro, confirma tu cuenta haciendo clic en el siguiente enlace:</p>
|
22
|
+
|
23
|
+
<p style="text-align: center;">
|
24
|
+
<%= link_to "Confirmar mi cuenta", @confirmation_url, class: "btn" %>
|
25
|
+
</p>
|
26
|
+
|
27
|
+
<p>Si no puedes hacer clic en el botón, copia y pega este enlace en tu navegador:</p>
|
28
|
+
<p style="word-break: break-all; background: #e9ecef; padding: 10px; border-radius: 4px;">
|
29
|
+
<%= @confirmation_url %>
|
30
|
+
</p>
|
31
|
+
|
32
|
+
<p>Si no te registraste en nuestro sitio, puedes ignorar este email.</p>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
</body>
|
36
|
+
</html>
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<style>
|
6
|
+
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
7
|
+
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
|
8
|
+
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; text-align: center; border-radius: 8px 8px 0 0; }
|
9
|
+
.content { background: #f8f9fa; padding: 30px; border-radius: 0 0 8px 8px; }
|
10
|
+
.btn { display: inline-block; background: #667eea; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; margin: 20px 0; }
|
11
|
+
</style>
|
12
|
+
</head>
|
13
|
+
<body>
|
14
|
+
<div class="container">
|
15
|
+
<div class="header">
|
16
|
+
<h1>Restablecer Contraseña</h1>
|
17
|
+
</div>
|
18
|
+
<div class="content">
|
19
|
+
<h2>Solicitud de cambio de contraseña</h2>
|
20
|
+
<p>Hola <strong><%= @user.email %></strong>,</p>
|
21
|
+
<p>Recibimos una solicitud para restablecer tu contraseña. Haz clic en el siguiente enlace para crear una nueva:</p>
|
22
|
+
|
23
|
+
<p style="text-align: center;">
|
24
|
+
<%= link_to "Cambiar mi contraseña", @reset_password_url, class: "btn" %>
|
25
|
+
</p>
|
26
|
+
|
27
|
+
<p>Si no puedes hacer clic en el botón, copia y pega este enlace en tu navegador:</p>
|
28
|
+
<p style="word-break: break-all; background: #e9ecef; padding: 10px; border-radius: 4px;">
|
29
|
+
<%= @reset_password_url %>
|
30
|
+
</p>
|
31
|
+
|
32
|
+
<p><strong>Importante:</strong> Este enlace expirará en 6 horas por seguridad.</p>
|
33
|
+
<p>Si no solicitaste este cambio, puedes ignorar este email. Tu contraseña no será modificada.</p>
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
</body>
|
37
|
+
</html>
|
@@ -0,0 +1,142 @@
|
|
1
|
+
<div class="auth-container">
|
2
|
+
<div class="auth-card">
|
3
|
+
<div class="auth-header">
|
4
|
+
<h2>Reenviar Confirmación</h2>
|
5
|
+
<p class="auth-subtitle">¿No recibiste el email de confirmación?</p>
|
6
|
+
</div>
|
7
|
+
|
8
|
+
<%= form_with(model: User.new, as: :user, url: user_confirmation_path, local: true, class: "auth-form") do |f| %>
|
9
|
+
<div class="form-group">
|
10
|
+
<%= f.label :email, "Email", class: "form-label" %>
|
11
|
+
<%= f.email_field :email, autofocus: true, autocomplete: "email", class: "form-input" %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class="form-actions">
|
15
|
+
<%= f.submit "Reenviar confirmación", class: "btn btn-primary" %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<div class="auth-links">
|
20
|
+
<%= link_to "← Volver al inicio de sesión", new_user_session_path, class: "auth-link" %>
|
21
|
+
<%= link_to "¿No tienes cuenta? Regístrate", new_user_registration_path, class: "auth-link" %>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
|
26
|
+
<style>
|
27
|
+
.auth-container {
|
28
|
+
min-height: 100vh;
|
29
|
+
display: flex;
|
30
|
+
align-items: center;
|
31
|
+
justify-content: center;
|
32
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
33
|
+
padding: 20px;
|
34
|
+
}
|
35
|
+
|
36
|
+
.auth-card {
|
37
|
+
background: white;
|
38
|
+
border-radius: 12px;
|
39
|
+
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
40
|
+
padding: 40px;
|
41
|
+
width: 100%;
|
42
|
+
max-width: 400px;
|
43
|
+
}
|
44
|
+
|
45
|
+
.auth-header {
|
46
|
+
text-align: center;
|
47
|
+
margin-bottom: 30px;
|
48
|
+
}
|
49
|
+
|
50
|
+
.auth-header h2 {
|
51
|
+
color: #2c3e50;
|
52
|
+
font-size: 28px;
|
53
|
+
font-weight: 600;
|
54
|
+
margin: 0 0 8px 0;
|
55
|
+
}
|
56
|
+
|
57
|
+
.auth-subtitle {
|
58
|
+
color: #64748b;
|
59
|
+
font-size: 14px;
|
60
|
+
margin: 0;
|
61
|
+
}
|
62
|
+
|
63
|
+
.auth-form {
|
64
|
+
width: 100%;
|
65
|
+
}
|
66
|
+
|
67
|
+
.form-group {
|
68
|
+
margin-bottom: 20px;
|
69
|
+
}
|
70
|
+
|
71
|
+
.form-label {
|
72
|
+
display: block;
|
73
|
+
color: #34495e;
|
74
|
+
font-weight: 500;
|
75
|
+
margin-bottom: 8px;
|
76
|
+
font-size: 14px;
|
77
|
+
}
|
78
|
+
|
79
|
+
.form-input {
|
80
|
+
width: 100%;
|
81
|
+
padding: 12px 16px;
|
82
|
+
border: 2px solid #e2e8f0;
|
83
|
+
border-radius: 8px;
|
84
|
+
font-size: 16px;
|
85
|
+
transition: border-color 0.3s ease;
|
86
|
+
box-sizing: border-box;
|
87
|
+
}
|
88
|
+
|
89
|
+
.form-input:focus {
|
90
|
+
outline: none;
|
91
|
+
border-color: #667eea;
|
92
|
+
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
93
|
+
}
|
94
|
+
|
95
|
+
.form-actions {
|
96
|
+
margin-top: 30px;
|
97
|
+
}
|
98
|
+
|
99
|
+
.btn {
|
100
|
+
display: inline-block;
|
101
|
+
padding: 12px 24px;
|
102
|
+
border: none;
|
103
|
+
border-radius: 8px;
|
104
|
+
font-size: 16px;
|
105
|
+
font-weight: 500;
|
106
|
+
text-decoration: none;
|
107
|
+
cursor: pointer;
|
108
|
+
transition: all 0.3s ease;
|
109
|
+
width: 100%;
|
110
|
+
text-align: center;
|
111
|
+
}
|
112
|
+
|
113
|
+
.btn-primary {
|
114
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
115
|
+
color: white;
|
116
|
+
}
|
117
|
+
|
118
|
+
.btn-primary:hover {
|
119
|
+
transform: translateY(-2px);
|
120
|
+
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
|
121
|
+
}
|
122
|
+
|
123
|
+
.auth-links {
|
124
|
+
text-align: center;
|
125
|
+
margin-top: 30px;
|
126
|
+
padding-top: 20px;
|
127
|
+
border-top: 1px solid #e2e8f0;
|
128
|
+
}
|
129
|
+
|
130
|
+
.auth-link {
|
131
|
+
display: block;
|
132
|
+
color: #667eea;
|
133
|
+
text-decoration: none;
|
134
|
+
font-size: 14px;
|
135
|
+
margin-bottom: 8px;
|
136
|
+
transition: color 0.3s ease;
|
137
|
+
}
|
138
|
+
|
139
|
+
.auth-link:hover {
|
140
|
+
color: #764ba2;
|
141
|
+
}
|
142
|
+
</style>
|
@@ -0,0 +1,191 @@
|
|
1
|
+
<div class="auth-container">
|
2
|
+
<div class="auth-card">
|
3
|
+
<div class="auth-header">
|
4
|
+
<h2>Cambiar Contraseña</h2>
|
5
|
+
<p class="auth-subtitle">Ingresa tu nueva contraseña</p>
|
6
|
+
</div>
|
7
|
+
|
8
|
+
<%= form_with(model: @user || User.new, as: :user, url: user_password_path, method: :patch, local: true, class: "auth-form") do |f| %>
|
9
|
+
<%= f.hidden_field :reset_password_token, value: params[:reset_password_token] %>
|
10
|
+
|
11
|
+
<% if @user&.errors&.any? %>
|
12
|
+
<div class="error-messages">
|
13
|
+
<h4><%= pluralize(@user.errors.count, "error") %> impidieron guardar:</h4>
|
14
|
+
<ul>
|
15
|
+
<% @user.errors.full_messages.each do |message| %>
|
16
|
+
<li><%= message %></li>
|
17
|
+
<% end %>
|
18
|
+
</ul>
|
19
|
+
</div>
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
<div class="form-group">
|
23
|
+
<%= f.label :password, "Nueva Contraseña", class: "form-label" %>
|
24
|
+
<small class="form-hint">(mínimo 6 caracteres)</small>
|
25
|
+
<%= f.password_field :password, autofocus: true, autocomplete: "new-password", class: "form-input" %>
|
26
|
+
</div>
|
27
|
+
|
28
|
+
<div class="form-group">
|
29
|
+
<%= f.label :password_confirmation, "Confirmar Nueva Contraseña", class: "form-label" %>
|
30
|
+
<%= f.password_field :password_confirmation, autocomplete: "new-password", class: "form-input" %>
|
31
|
+
</div>
|
32
|
+
|
33
|
+
<div class="form-actions">
|
34
|
+
<%= f.submit "Cambiar Contraseña", class: "btn btn-primary" %>
|
35
|
+
</div>
|
36
|
+
<% end %>
|
37
|
+
|
38
|
+
<div class="auth-links">
|
39
|
+
<%= link_to "← Volver al inicio de sesión", new_user_session_path, class: "auth-link" %>
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<style>
|
45
|
+
.auth-container {
|
46
|
+
min-height: 100vh;
|
47
|
+
display: flex;
|
48
|
+
align-items: center;
|
49
|
+
justify-content: center;
|
50
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
51
|
+
padding: 20px;
|
52
|
+
}
|
53
|
+
|
54
|
+
.auth-card {
|
55
|
+
background: white;
|
56
|
+
border-radius: 12px;
|
57
|
+
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
58
|
+
padding: 40px;
|
59
|
+
width: 100%;
|
60
|
+
max-width: 400px;
|
61
|
+
}
|
62
|
+
|
63
|
+
.auth-header {
|
64
|
+
text-align: center;
|
65
|
+
margin-bottom: 30px;
|
66
|
+
}
|
67
|
+
|
68
|
+
.auth-header h2 {
|
69
|
+
color: #2c3e50;
|
70
|
+
font-size: 28px;
|
71
|
+
font-weight: 600;
|
72
|
+
margin: 0 0 8px 0;
|
73
|
+
}
|
74
|
+
|
75
|
+
.auth-subtitle {
|
76
|
+
color: #64748b;
|
77
|
+
font-size: 14px;
|
78
|
+
margin: 0;
|
79
|
+
}
|
80
|
+
|
81
|
+
.auth-form {
|
82
|
+
width: 100%;
|
83
|
+
}
|
84
|
+
|
85
|
+
.form-group {
|
86
|
+
margin-bottom: 20px;
|
87
|
+
}
|
88
|
+
|
89
|
+
.form-label {
|
90
|
+
display: block;
|
91
|
+
color: #34495e;
|
92
|
+
font-weight: 500;
|
93
|
+
margin-bottom: 8px;
|
94
|
+
font-size: 14px;
|
95
|
+
}
|
96
|
+
|
97
|
+
.form-hint {
|
98
|
+
display: block;
|
99
|
+
color: #64748b;
|
100
|
+
font-size: 12px;
|
101
|
+
margin-bottom: 4px;
|
102
|
+
}
|
103
|
+
|
104
|
+
.form-input {
|
105
|
+
width: 100%;
|
106
|
+
padding: 12px 16px;
|
107
|
+
border: 2px solid #e2e8f0;
|
108
|
+
border-radius: 8px;
|
109
|
+
font-size: 16px;
|
110
|
+
transition: border-color 0.3s ease;
|
111
|
+
box-sizing: border-box;
|
112
|
+
}
|
113
|
+
|
114
|
+
.form-input:focus {
|
115
|
+
outline: none;
|
116
|
+
border-color: #667eea;
|
117
|
+
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
118
|
+
}
|
119
|
+
|
120
|
+
.form-actions {
|
121
|
+
margin-top: 30px;
|
122
|
+
}
|
123
|
+
|
124
|
+
.btn {
|
125
|
+
display: inline-block;
|
126
|
+
padding: 12px 24px;
|
127
|
+
border: none;
|
128
|
+
border-radius: 8px;
|
129
|
+
font-size: 16px;
|
130
|
+
font-weight: 500;
|
131
|
+
text-decoration: none;
|
132
|
+
cursor: pointer;
|
133
|
+
transition: all 0.3s ease;
|
134
|
+
width: 100%;
|
135
|
+
text-align: center;
|
136
|
+
}
|
137
|
+
|
138
|
+
.btn-primary {
|
139
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
140
|
+
color: white;
|
141
|
+
}
|
142
|
+
|
143
|
+
.btn-primary:hover {
|
144
|
+
transform: translateY(-2px);
|
145
|
+
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
|
146
|
+
}
|
147
|
+
|
148
|
+
.auth-links {
|
149
|
+
text-align: center;
|
150
|
+
margin-top: 30px;
|
151
|
+
padding-top: 20px;
|
152
|
+
border-top: 1px solid #e2e8f0;
|
153
|
+
}
|
154
|
+
|
155
|
+
.auth-link {
|
156
|
+
display: block;
|
157
|
+
color: #667eea;
|
158
|
+
text-decoration: none;
|
159
|
+
font-size: 14px;
|
160
|
+
margin-bottom: 8px;
|
161
|
+
transition: color 0.3s ease;
|
162
|
+
}
|
163
|
+
|
164
|
+
.auth-link:hover {
|
165
|
+
color: #764ba2;
|
166
|
+
}
|
167
|
+
|
168
|
+
.error-messages {
|
169
|
+
background: #fee2e2;
|
170
|
+
border: 1px solid #fecaca;
|
171
|
+
border-radius: 8px;
|
172
|
+
padding: 16px;
|
173
|
+
margin-bottom: 20px;
|
174
|
+
}
|
175
|
+
|
176
|
+
.error-messages h4 {
|
177
|
+
color: #dc2626;
|
178
|
+
margin: 0 0 8px 0;
|
179
|
+
font-size: 14px;
|
180
|
+
}
|
181
|
+
|
182
|
+
.error-messages ul {
|
183
|
+
margin: 0;
|
184
|
+
padding-left: 20px;
|
185
|
+
}
|
186
|
+
|
187
|
+
.error-messages li {
|
188
|
+
color: #dc2626;
|
189
|
+
font-size: 14px;
|
190
|
+
}
|
191
|
+
</style>
|
@@ -0,0 +1,142 @@
|
|
1
|
+
<div class="auth-container">
|
2
|
+
<div class="auth-card">
|
3
|
+
<div class="auth-header">
|
4
|
+
<h2>¿Olvidaste tu contraseña?</h2>
|
5
|
+
<p class="auth-subtitle">Te enviaremos instrucciones para restablecerla</p>
|
6
|
+
</div>
|
7
|
+
|
8
|
+
<%= form_with(model: User.new, as: :user, url: user_password_path, local: true, class: "auth-form") do |f| %>
|
9
|
+
<div class="form-group">
|
10
|
+
<%= f.label :email, "Email", class: "form-label" %>
|
11
|
+
<%= f.email_field :email, autofocus: true, autocomplete: "email", class: "form-input" %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class="form-actions">
|
15
|
+
<%= f.submit "Enviar instrucciones", class: "btn btn-primary" %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<div class="auth-links">
|
20
|
+
<%= link_to "← Volver al inicio de sesión", new_user_session_path, class: "auth-link" %>
|
21
|
+
<%= link_to "¿No tienes cuenta? Regístrate", new_user_registration_path, class: "auth-link" %>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
|
26
|
+
<style>
|
27
|
+
.auth-container {
|
28
|
+
min-height: 100vh;
|
29
|
+
display: flex;
|
30
|
+
align-items: center;
|
31
|
+
justify-content: center;
|
32
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
33
|
+
padding: 20px;
|
34
|
+
}
|
35
|
+
|
36
|
+
.auth-card {
|
37
|
+
background: white;
|
38
|
+
border-radius: 12px;
|
39
|
+
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
40
|
+
padding: 40px;
|
41
|
+
width: 100%;
|
42
|
+
max-width: 400px;
|
43
|
+
}
|
44
|
+
|
45
|
+
.auth-header {
|
46
|
+
text-align: center;
|
47
|
+
margin-bottom: 30px;
|
48
|
+
}
|
49
|
+
|
50
|
+
.auth-header h2 {
|
51
|
+
color: #2c3e50;
|
52
|
+
font-size: 28px;
|
53
|
+
font-weight: 600;
|
54
|
+
margin: 0 0 8px 0;
|
55
|
+
}
|
56
|
+
|
57
|
+
.auth-subtitle {
|
58
|
+
color: #64748b;
|
59
|
+
font-size: 14px;
|
60
|
+
margin: 0;
|
61
|
+
}
|
62
|
+
|
63
|
+
.auth-form {
|
64
|
+
width: 100%;
|
65
|
+
}
|
66
|
+
|
67
|
+
.form-group {
|
68
|
+
margin-bottom: 20px;
|
69
|
+
}
|
70
|
+
|
71
|
+
.form-label {
|
72
|
+
display: block;
|
73
|
+
color: #34495e;
|
74
|
+
font-weight: 500;
|
75
|
+
margin-bottom: 8px;
|
76
|
+
font-size: 14px;
|
77
|
+
}
|
78
|
+
|
79
|
+
.form-input {
|
80
|
+
width: 100%;
|
81
|
+
padding: 12px 16px;
|
82
|
+
border: 2px solid #e2e8f0;
|
83
|
+
border-radius: 8px;
|
84
|
+
font-size: 16px;
|
85
|
+
transition: border-color 0.3s ease;
|
86
|
+
box-sizing: border-box;
|
87
|
+
}
|
88
|
+
|
89
|
+
.form-input:focus {
|
90
|
+
outline: none;
|
91
|
+
border-color: #667eea;
|
92
|
+
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
93
|
+
}
|
94
|
+
|
95
|
+
.form-actions {
|
96
|
+
margin-top: 30px;
|
97
|
+
}
|
98
|
+
|
99
|
+
.btn {
|
100
|
+
display: inline-block;
|
101
|
+
padding: 12px 24px;
|
102
|
+
border: none;
|
103
|
+
border-radius: 8px;
|
104
|
+
font-size: 16px;
|
105
|
+
font-weight: 500;
|
106
|
+
text-decoration: none;
|
107
|
+
cursor: pointer;
|
108
|
+
transition: all 0.3s ease;
|
109
|
+
width: 100%;
|
110
|
+
text-align: center;
|
111
|
+
}
|
112
|
+
|
113
|
+
.btn-primary {
|
114
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
115
|
+
color: white;
|
116
|
+
}
|
117
|
+
|
118
|
+
.btn-primary:hover {
|
119
|
+
transform: translateY(-2px);
|
120
|
+
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
|
121
|
+
}
|
122
|
+
|
123
|
+
.auth-links {
|
124
|
+
text-align: center;
|
125
|
+
margin-top: 30px;
|
126
|
+
padding-top: 20px;
|
127
|
+
border-top: 1px solid #e2e8f0;
|
128
|
+
}
|
129
|
+
|
130
|
+
.auth-link {
|
131
|
+
display: block;
|
132
|
+
color: #667eea;
|
133
|
+
text-decoration: none;
|
134
|
+
font-size: 14px;
|
135
|
+
margin-bottom: 8px;
|
136
|
+
transition: color 0.3s ease;
|
137
|
+
}
|
138
|
+
|
139
|
+
.auth-link:hover {
|
140
|
+
color: #764ba2;
|
141
|
+
}
|
142
|
+
</style>
|
@@ -0,0 +1,193 @@
|
|
1
|
+
<div class="auth-container">
|
2
|
+
<div class="auth-card">
|
3
|
+
<div class="auth-header">
|
4
|
+
<h2>Editar Perfil</h2>
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<%= form_with(model: current_user, as: :user, url: user_registration_path, method: :patch, local: true, class: "auth-form") do |f| %>
|
8
|
+
<% if current_user.errors.any? %>
|
9
|
+
<div class="error-messages">
|
10
|
+
<h4><%= pluralize(current_user.errors.count, "error") %> impidieron guardar:</h4>
|
11
|
+
<ul>
|
12
|
+
<% current_user.errors.full_messages.each do |message| %>
|
13
|
+
<li><%= message %></li>
|
14
|
+
<% end %>
|
15
|
+
</ul>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<div class="form-group">
|
20
|
+
<%= f.label :email, "Email", class: "form-label" %>
|
21
|
+
<%= f.email_field :email, autofocus: true, autocomplete: "email", class: "form-input" %>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div class="form-group">
|
25
|
+
<%= f.label :password, "Nueva Contraseña", class: "form-label" %>
|
26
|
+
<small class="form-hint">(déjalo en blanco si no quieres cambiarlo)</small>
|
27
|
+
<%= f.password_field :password, autocomplete: "new-password", class: "form-input" %>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<div class="form-group">
|
31
|
+
<%= f.label :password_confirmation, "Confirmar Nueva Contraseña", class: "form-label" %>
|
32
|
+
<%= f.password_field :password_confirmation, autocomplete: "new-password", class: "form-input" %>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div class="form-group">
|
36
|
+
<%= f.label :current_password, "Contraseña Actual", class: "form-label" %>
|
37
|
+
<small class="form-hint">(necesaria para confirmar cambios)</small>
|
38
|
+
<%= f.password_field :current_password, autocomplete: "current-password", class: "form-input" %>
|
39
|
+
</div>
|
40
|
+
|
41
|
+
<div class="form-actions">
|
42
|
+
<%= f.submit "Actualizar", class: "btn btn-primary" %>
|
43
|
+
</div>
|
44
|
+
<% end %>
|
45
|
+
|
46
|
+
<div class="auth-links">
|
47
|
+
<%= link_to "← Volver", root_path, class: "auth-link" %>
|
48
|
+
</div>
|
49
|
+
</div>
|
50
|
+
</div>
|
51
|
+
|
52
|
+
<style>
|
53
|
+
.auth-container {
|
54
|
+
min-height: 100vh;
|
55
|
+
display: flex;
|
56
|
+
align-items: center;
|
57
|
+
justify-content: center;
|
58
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
59
|
+
padding: 20px;
|
60
|
+
}
|
61
|
+
|
62
|
+
.auth-card {
|
63
|
+
background: white;
|
64
|
+
border-radius: 12px;
|
65
|
+
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
66
|
+
padding: 40px;
|
67
|
+
width: 100%;
|
68
|
+
max-width: 400px;
|
69
|
+
}
|
70
|
+
|
71
|
+
.auth-header {
|
72
|
+
text-align: center;
|
73
|
+
margin-bottom: 30px;
|
74
|
+
}
|
75
|
+
|
76
|
+
.auth-header h2 {
|
77
|
+
color: #2c3e50;
|
78
|
+
font-size: 28px;
|
79
|
+
font-weight: 600;
|
80
|
+
margin: 0;
|
81
|
+
}
|
82
|
+
|
83
|
+
.auth-form {
|
84
|
+
width: 100%;
|
85
|
+
}
|
86
|
+
|
87
|
+
.form-group {
|
88
|
+
margin-bottom: 20px;
|
89
|
+
}
|
90
|
+
|
91
|
+
.form-label {
|
92
|
+
display: block;
|
93
|
+
color: #34495e;
|
94
|
+
font-weight: 500;
|
95
|
+
margin-bottom: 8px;
|
96
|
+
font-size: 14px;
|
97
|
+
}
|
98
|
+
|
99
|
+
.form-hint {
|
100
|
+
display: block;
|
101
|
+
color: #64748b;
|
102
|
+
font-size: 12px;
|
103
|
+
margin-bottom: 4px;
|
104
|
+
}
|
105
|
+
|
106
|
+
.form-input {
|
107
|
+
width: 100%;
|
108
|
+
padding: 12px 16px;
|
109
|
+
border: 2px solid #e2e8f0;
|
110
|
+
border-radius: 8px;
|
111
|
+
font-size: 16px;
|
112
|
+
transition: border-color 0.3s ease;
|
113
|
+
box-sizing: border-box;
|
114
|
+
}
|
115
|
+
|
116
|
+
.form-input:focus {
|
117
|
+
outline: none;
|
118
|
+
border-color: #667eea;
|
119
|
+
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
120
|
+
}
|
121
|
+
|
122
|
+
.form-actions {
|
123
|
+
margin-top: 30px;
|
124
|
+
}
|
125
|
+
|
126
|
+
.btn {
|
127
|
+
display: inline-block;
|
128
|
+
padding: 12px 24px;
|
129
|
+
border: none;
|
130
|
+
border-radius: 8px;
|
131
|
+
font-size: 16px;
|
132
|
+
font-weight: 500;
|
133
|
+
text-decoration: none;
|
134
|
+
cursor: pointer;
|
135
|
+
transition: all 0.3s ease;
|
136
|
+
width: 100%;
|
137
|
+
text-align: center;
|
138
|
+
}
|
139
|
+
|
140
|
+
.btn-primary {
|
141
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
142
|
+
color: white;
|
143
|
+
}
|
144
|
+
|
145
|
+
.btn-primary:hover {
|
146
|
+
transform: translateY(-2px);
|
147
|
+
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
|
148
|
+
}
|
149
|
+
|
150
|
+
.auth-links {
|
151
|
+
text-align: center;
|
152
|
+
margin-top: 30px;
|
153
|
+
padding-top: 20px;
|
154
|
+
border-top: 1px solid #e2e8f0;
|
155
|
+
}
|
156
|
+
|
157
|
+
.auth-link {
|
158
|
+
display: block;
|
159
|
+
color: #667eea;
|
160
|
+
text-decoration: none;
|
161
|
+
font-size: 14px;
|
162
|
+
margin-bottom: 8px;
|
163
|
+
transition: color 0.3s ease;
|
164
|
+
}
|
165
|
+
|
166
|
+
.auth-link:hover {
|
167
|
+
color: #764ba2;
|
168
|
+
}
|
169
|
+
|
170
|
+
.error-messages {
|
171
|
+
background: #fee2e2;
|
172
|
+
border: 1px solid #fecaca;
|
173
|
+
border-radius: 8px;
|
174
|
+
padding: 16px;
|
175
|
+
margin-bottom: 20px;
|
176
|
+
}
|
177
|
+
|
178
|
+
.error-messages h4 {
|
179
|
+
color: #dc2626;
|
180
|
+
margin: 0 0 8px 0;
|
181
|
+
font-size: 14px;
|
182
|
+
}
|
183
|
+
|
184
|
+
.error-messages ul {
|
185
|
+
margin: 0;
|
186
|
+
padding-left: 20px;
|
187
|
+
}
|
188
|
+
|
189
|
+
.error-messages li {
|
190
|
+
color: #dc2626;
|
191
|
+
font-size: 14px;
|
192
|
+
}
|
193
|
+
</style>
|
@@ -0,0 +1,187 @@
|
|
1
|
+
<div class="auth-container">
|
2
|
+
<div class="auth-card">
|
3
|
+
<div class="auth-header">
|
4
|
+
<h2>Crear Cuenta</h2>
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<%= form_with(model: User.new, as: :user, url: user_registration_path, local: true, class: "auth-form") do |f| %>
|
8
|
+
<% if @user&.errors&.any? %>
|
9
|
+
<div class="error-messages">
|
10
|
+
<h4><%= pluralize(@user.errors.count, "error") %> impidieron guardar:</h4>
|
11
|
+
<ul>
|
12
|
+
<% @user.errors.full_messages.each do |message| %>
|
13
|
+
<li><%= message %></li>
|
14
|
+
<% end %>
|
15
|
+
</ul>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<div class="form-group">
|
20
|
+
<%= f.label :email, "Email", class: "form-label" %>
|
21
|
+
<%= f.email_field :email, autofocus: true, autocomplete: "email", class: "form-input" %>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div class="form-group">
|
25
|
+
<%= f.label :password, "Contraseña", class: "form-label" %>
|
26
|
+
<small class="form-hint">(mínimo 6 caracteres)</small>
|
27
|
+
<%= f.password_field :password, autocomplete: "new-password", class: "form-input" %>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
<div class="form-group">
|
31
|
+
<%= f.label :password_confirmation, "Confirmar Contraseña", class: "form-label" %>
|
32
|
+
<%= f.password_field :password_confirmation, autocomplete: "new-password", class: "form-input" %>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div class="form-actions">
|
36
|
+
<%= f.submit "Crear Cuenta", class: "btn btn-primary" %>
|
37
|
+
</div>
|
38
|
+
<% end %>
|
39
|
+
|
40
|
+
<div class="auth-links">
|
41
|
+
<%= link_to "¿Ya tienes cuenta? Inicia sesión", new_user_session_path, class: "auth-link" %>
|
42
|
+
</div>
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
|
46
|
+
<style>
|
47
|
+
.auth-container {
|
48
|
+
min-height: 100vh;
|
49
|
+
display: flex;
|
50
|
+
align-items: center;
|
51
|
+
justify-content: center;
|
52
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
53
|
+
padding: 20px;
|
54
|
+
}
|
55
|
+
|
56
|
+
.auth-card {
|
57
|
+
background: white;
|
58
|
+
border-radius: 12px;
|
59
|
+
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
60
|
+
padding: 40px;
|
61
|
+
width: 100%;
|
62
|
+
max-width: 400px;
|
63
|
+
}
|
64
|
+
|
65
|
+
.auth-header {
|
66
|
+
text-align: center;
|
67
|
+
margin-bottom: 30px;
|
68
|
+
}
|
69
|
+
|
70
|
+
.auth-header h2 {
|
71
|
+
color: #2c3e50;
|
72
|
+
font-size: 28px;
|
73
|
+
font-weight: 600;
|
74
|
+
margin: 0;
|
75
|
+
}
|
76
|
+
|
77
|
+
.auth-form {
|
78
|
+
width: 100%;
|
79
|
+
}
|
80
|
+
|
81
|
+
.form-group {
|
82
|
+
margin-bottom: 20px;
|
83
|
+
}
|
84
|
+
|
85
|
+
.form-label {
|
86
|
+
display: block;
|
87
|
+
color: #34495e;
|
88
|
+
font-weight: 500;
|
89
|
+
margin-bottom: 8px;
|
90
|
+
font-size: 14px;
|
91
|
+
}
|
92
|
+
|
93
|
+
.form-hint {
|
94
|
+
display: block;
|
95
|
+
color: #64748b;
|
96
|
+
font-size: 12px;
|
97
|
+
margin-bottom: 4px;
|
98
|
+
}
|
99
|
+
|
100
|
+
.form-input {
|
101
|
+
width: 100%;
|
102
|
+
padding: 12px 16px;
|
103
|
+
border: 2px solid #e2e8f0;
|
104
|
+
border-radius: 8px;
|
105
|
+
font-size: 16px;
|
106
|
+
transition: border-color 0.3s ease;
|
107
|
+
box-sizing: border-box;
|
108
|
+
}
|
109
|
+
|
110
|
+
.form-input:focus {
|
111
|
+
outline: none;
|
112
|
+
border-color: #667eea;
|
113
|
+
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
114
|
+
}
|
115
|
+
|
116
|
+
.form-actions {
|
117
|
+
margin-top: 30px;
|
118
|
+
}
|
119
|
+
|
120
|
+
.btn {
|
121
|
+
display: inline-block;
|
122
|
+
padding: 12px 24px;
|
123
|
+
border: none;
|
124
|
+
border-radius: 8px;
|
125
|
+
font-size: 16px;
|
126
|
+
font-weight: 500;
|
127
|
+
text-decoration: none;
|
128
|
+
cursor: pointer;
|
129
|
+
transition: all 0.3s ease;
|
130
|
+
width: 100%;
|
131
|
+
text-align: center;
|
132
|
+
}
|
133
|
+
|
134
|
+
.btn-primary {
|
135
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
136
|
+
color: white;
|
137
|
+
}
|
138
|
+
|
139
|
+
.btn-primary:hover {
|
140
|
+
transform: translateY(-2px);
|
141
|
+
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
|
142
|
+
}
|
143
|
+
|
144
|
+
.auth-links {
|
145
|
+
text-align: center;
|
146
|
+
margin-top: 30px;
|
147
|
+
padding-top: 20px;
|
148
|
+
border-top: 1px solid #e2e8f0;
|
149
|
+
}
|
150
|
+
|
151
|
+
.auth-link {
|
152
|
+
display: block;
|
153
|
+
color: #667eea;
|
154
|
+
text-decoration: none;
|
155
|
+
font-size: 14px;
|
156
|
+
margin-bottom: 8px;
|
157
|
+
transition: color 0.3s ease;
|
158
|
+
}
|
159
|
+
|
160
|
+
.auth-link:hover {
|
161
|
+
color: #764ba2;
|
162
|
+
}
|
163
|
+
|
164
|
+
.error-messages {
|
165
|
+
background: #fee2e2;
|
166
|
+
border: 1px solid #fecaca;
|
167
|
+
border-radius: 8px;
|
168
|
+
padding: 16px;
|
169
|
+
margin-bottom: 20px;
|
170
|
+
}
|
171
|
+
|
172
|
+
.error-messages h4 {
|
173
|
+
color: #dc2626;
|
174
|
+
margin: 0 0 8px 0;
|
175
|
+
font-size: 14px;
|
176
|
+
}
|
177
|
+
|
178
|
+
.error-messages ul {
|
179
|
+
margin: 0;
|
180
|
+
padding-left: 20px;
|
181
|
+
}
|
182
|
+
|
183
|
+
.error-messages li {
|
184
|
+
color: #dc2626;
|
185
|
+
font-size: 14px;
|
186
|
+
}
|
187
|
+
</style>
|
@@ -0,0 +1,162 @@
|
|
1
|
+
<div class="auth-container">
|
2
|
+
<div class="auth-card">
|
3
|
+
<div class="auth-header">
|
4
|
+
<h2>Iniciar Sesión</h2>
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<%= form_with(url: user_session_path, local: true, class: "auth-form") do |f| %>
|
8
|
+
<div class="form-group">
|
9
|
+
<%= f.label :email, "Email", class: "form-label" %>
|
10
|
+
<%= f.email_field :email, autofocus: true, autocomplete: "email", class: "form-input" %>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<div class="form-group">
|
14
|
+
<%= f.label :password, "Contraseña", class: "form-label" %>
|
15
|
+
<%= f.password_field :password, autocomplete: "current-password", class: "form-input" %>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
<div class="form-group checkbox-group">
|
19
|
+
<%= f.check_box :remember_me, class: "form-checkbox" %>
|
20
|
+
<%= f.label :remember_me, "Recordarme", class: "checkbox-label" %>
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<div class="form-actions">
|
24
|
+
<%= f.submit "Iniciar Sesión", class: "btn btn-primary" %>
|
25
|
+
</div>
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
<div class="auth-links">
|
29
|
+
<%= link_to "¿No tienes cuenta? Regístrate", new_user_registration_path, class: "auth-link" %>
|
30
|
+
<%= link_to "¿Olvidaste tu contraseña?", new_user_password_path, class: "auth-link" %>
|
31
|
+
</div>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<style>
|
36
|
+
.auth-container {
|
37
|
+
min-height: 100vh;
|
38
|
+
display: flex;
|
39
|
+
align-items: center;
|
40
|
+
justify-content: center;
|
41
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
42
|
+
padding: 20px;
|
43
|
+
}
|
44
|
+
|
45
|
+
.auth-card {
|
46
|
+
background: white;
|
47
|
+
border-radius: 12px;
|
48
|
+
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
49
|
+
padding: 40px;
|
50
|
+
width: 100%;
|
51
|
+
max-width: 400px;
|
52
|
+
}
|
53
|
+
|
54
|
+
.auth-header {
|
55
|
+
text-align: center;
|
56
|
+
margin-bottom: 30px;
|
57
|
+
}
|
58
|
+
|
59
|
+
.auth-header h2 {
|
60
|
+
color: #2c3e50;
|
61
|
+
font-size: 28px;
|
62
|
+
font-weight: 600;
|
63
|
+
margin: 0;
|
64
|
+
}
|
65
|
+
|
66
|
+
.auth-form {
|
67
|
+
width: 100%;
|
68
|
+
}
|
69
|
+
|
70
|
+
.form-group {
|
71
|
+
margin-bottom: 20px;
|
72
|
+
}
|
73
|
+
|
74
|
+
.form-label {
|
75
|
+
display: block;
|
76
|
+
color: #34495e;
|
77
|
+
font-weight: 500;
|
78
|
+
margin-bottom: 8px;
|
79
|
+
font-size: 14px;
|
80
|
+
}
|
81
|
+
|
82
|
+
.form-input {
|
83
|
+
width: 100%;
|
84
|
+
padding: 12px 16px;
|
85
|
+
border: 2px solid #e2e8f0;
|
86
|
+
border-radius: 8px;
|
87
|
+
font-size: 16px;
|
88
|
+
transition: border-color 0.3s ease;
|
89
|
+
box-sizing: border-box;
|
90
|
+
}
|
91
|
+
|
92
|
+
.form-input:focus {
|
93
|
+
outline: none;
|
94
|
+
border-color: #667eea;
|
95
|
+
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
96
|
+
}
|
97
|
+
|
98
|
+
.checkbox-group {
|
99
|
+
display: flex;
|
100
|
+
align-items: center;
|
101
|
+
gap: 8px;
|
102
|
+
}
|
103
|
+
|
104
|
+
.form-checkbox {
|
105
|
+
width: auto;
|
106
|
+
margin: 0;
|
107
|
+
}
|
108
|
+
|
109
|
+
.checkbox-label {
|
110
|
+
margin: 0;
|
111
|
+
color: #64748b;
|
112
|
+
font-size: 14px;
|
113
|
+
}
|
114
|
+
|
115
|
+
.form-actions {
|
116
|
+
margin-top: 30px;
|
117
|
+
}
|
118
|
+
|
119
|
+
.btn {
|
120
|
+
display: inline-block;
|
121
|
+
padding: 12px 24px;
|
122
|
+
border: none;
|
123
|
+
border-radius: 8px;
|
124
|
+
font-size: 16px;
|
125
|
+
font-weight: 500;
|
126
|
+
text-decoration: none;
|
127
|
+
cursor: pointer;
|
128
|
+
transition: all 0.3s ease;
|
129
|
+
width: 100%;
|
130
|
+
text-align: center;
|
131
|
+
}
|
132
|
+
|
133
|
+
.btn-primary {
|
134
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
135
|
+
color: white;
|
136
|
+
}
|
137
|
+
|
138
|
+
.btn-primary:hover {
|
139
|
+
transform: translateY(-2px);
|
140
|
+
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
|
141
|
+
}
|
142
|
+
|
143
|
+
.auth-links {
|
144
|
+
text-align: center;
|
145
|
+
margin-top: 30px;
|
146
|
+
padding-top: 20px;
|
147
|
+
border-top: 1px solid #e2e8f0;
|
148
|
+
}
|
149
|
+
|
150
|
+
.auth-link {
|
151
|
+
display: block;
|
152
|
+
color: #667eea;
|
153
|
+
text-decoration: none;
|
154
|
+
font-size: 14px;
|
155
|
+
margin-bottom: 8px;
|
156
|
+
transition: color 0.3s ease;
|
157
|
+
}
|
158
|
+
|
159
|
+
.auth-link:hover {
|
160
|
+
color: #764ba2;
|
161
|
+
}
|
162
|
+
</style>
|
data/config/routes.rb
CHANGED
@@ -1,28 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# Sessions
|
4
|
-
get '/users/sign_in', to: 'users/sessions#new', as: :new_user_session
|
5
|
-
post '/users/sign_in', to: 'users/sessions#create', as: :user_session
|
6
|
-
delete '/users/sign_out', to: 'users/sessions#destroy', as: :destroy_user_session
|
7
|
-
|
8
|
-
# Registrations
|
9
|
-
get '/users/sign_up', to: 'users/registrations#new', as: :new_user_registration
|
10
|
-
post '/users', to: 'users/registrations#create', as: :user_registration
|
11
|
-
get '/users/edit', to: 'users/registrations#edit', as: :edit_user_registration
|
12
|
-
patch '/users', to: 'users/registrations#update'
|
13
|
-
put '/users', to: 'users/registrations#update'
|
14
|
-
delete '/users', to: 'users/registrations#destroy'
|
15
|
-
|
16
|
-
# Passwords
|
17
|
-
get '/users/password/new', to: 'users/passwords#new', as: :new_user_password
|
18
|
-
post '/users/password', to: 'users/passwords#create', as: :user_password
|
19
|
-
get '/users/password/edit', to: 'users/passwords#edit', as: :edit_user_password
|
20
|
-
patch '/users/password', to: 'users/passwords#update'
|
21
|
-
put '/users/password', to: 'users/passwords#update'
|
22
|
-
|
23
|
-
# Confirmations
|
24
|
-
get '/users/confirmation/new', to: 'users/confirmations#new', as: :new_user_confirmation
|
25
|
-
post '/users/confirmation', to: 'users/confirmations#create', as: :user_confirmation
|
26
|
-
get '/users/confirmation', to: 'users/confirmations#show'
|
27
|
-
end
|
28
|
-
end
|
1
|
+
# Rutas agregadas automáticamente por Lockify engine
|
2
|
+
# No necesitas agregar nada aquí
|
@@ -1,15 +1,13 @@
|
|
1
1
|
require 'rails/generators'
|
2
|
-
require 'rails/generators/active_record'
|
3
2
|
|
4
3
|
module Lockify
|
5
4
|
module Generators
|
6
5
|
class InstallGenerator < Rails::Generators::Base
|
7
|
-
include ActiveRecord::Generators::Migration
|
8
|
-
|
9
6
|
source_root File.expand_path('templates', __dir__)
|
10
7
|
|
11
8
|
def create_migration
|
12
|
-
|
9
|
+
timestamp = Time.current.strftime("%Y%m%d%H%M%S")
|
10
|
+
create_file "db/migrate/#{timestamp}_add_lockify_to_users.rb", migration_content
|
13
11
|
end
|
14
12
|
|
15
13
|
def add_lockify_to_user_model
|
@@ -90,6 +88,10 @@ module Lockify
|
|
90
88
|
def readme(path)
|
91
89
|
say File.read(File.join(File.dirname(__FILE__), "templates", path))
|
92
90
|
end
|
91
|
+
|
92
|
+
def migration_content
|
93
|
+
File.read(File.join(File.dirname(__FILE__), "templates", "migration.rb"))
|
94
|
+
end
|
93
95
|
end
|
94
96
|
end
|
95
97
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class AddLockifyToUsers < ActiveRecord::Migration[
|
1
|
+
class AddLockifyToUsers < ActiveRecord::Migration[8.0]
|
2
2
|
def change
|
3
3
|
# Rename encrypted_password to password_digest if it exists
|
4
4
|
if column_exists?(:users, :encrypted_password)
|
data/lib/lockify/engine.rb
CHANGED
@@ -23,6 +23,7 @@ module Lockify
|
|
23
23
|
get '/users/sign_up', to: 'users/registrations#new', as: :new_user_registration
|
24
24
|
post '/users', to: 'users/registrations#create', as: :user_registration
|
25
25
|
get '/users/edit', to: 'users/registrations#edit', as: :edit_user_registration
|
26
|
+
get '/users', to: 'users/registrations#show'
|
26
27
|
patch '/users', to: 'users/registrations#update'
|
27
28
|
put '/users', to: 'users/registrations#update'
|
28
29
|
delete '/users', to: 'users/registrations#destroy'
|
data/lib/lockify/version.rb
CHANGED
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lockify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Govani G. Sanchez Orduña
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
@@ -74,6 +74,14 @@ files:
|
|
74
74
|
- app/views/lockify/sessions/new.html.erb
|
75
75
|
- app/views/lockify/shared/_error_messages.html.erb
|
76
76
|
- app/views/lockify/shared/_links.html.erb
|
77
|
+
- app/views/user_mailer/confirmation_instructions.html.erb
|
78
|
+
- app/views/user_mailer/reset_password_instructions.html.erb
|
79
|
+
- app/views/users/confirmations/new.html.erb
|
80
|
+
- app/views/users/passwords/edit.html.erb
|
81
|
+
- app/views/users/passwords/new.html.erb
|
82
|
+
- app/views/users/registrations/edit.html.erb
|
83
|
+
- app/views/users/registrations/new.html.erb
|
84
|
+
- app/views/users/sessions/new.html.erb
|
77
85
|
- config/locales/en.yml
|
78
86
|
- config/locales/es.yml
|
79
87
|
- config/routes.rb
|