lato 0.1.26 → 0.1.28
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/lato/authentication_controller.rb +63 -6
- data/app/helpers/lato/components_helper.rb +11 -1
- data/app/jobs/lato/application_job.rb +3 -1
- data/app/mailers/lato/invitation_mailer.rb +21 -0
- data/app/mailers/lato/user_mailer.rb +12 -0
- data/app/models/lato/invitation.rb +82 -0
- data/app/models/lato/log/user_signin.rb +8 -0
- data/app/models/lato/log.rb +14 -0
- data/app/models/lato/operation.rb +7 -1
- data/app/models/lato/user.rb +38 -9
- data/app/views/lato/authentication/_fields-registration.html.erb +37 -0
- data/app/views/lato/authentication/_form-accept-invitation.html.erb +18 -0
- data/app/views/lato/authentication/_form-signup.html.erb +1 -31
- data/app/views/lato/authentication/accept_invitation.html.erb +10 -0
- data/app/views/lato/components/_index.html.erb +28 -4
- data/app/views/lato/mailer/invitation/invite_mail.html.erb +17 -0
- data/app/views/lato/mailer/user/email_verification_mail.html.erb +1 -1
- data/app/views/lato/mailer/user/password_update_mail.html.erb +1 -1
- data/app/views/layouts/lato/_feedbacks.html.erb +15 -0
- data/app/views/layouts/lato/_mailer-head_content.html.erb +4 -4
- data/config/locales/en.yml +8 -0
- data/config/locales/it.yml +11 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20230109054412_create_lato_log_user_signins.rb +10 -0
- data/db/migrate/20230109061533_create_lato_invitations.rb +11 -0
- data/lib/lato/version.rb +1 -1
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bcb5a6f47f56626a7fd68c8ab3872971d88291b568c8ede302e2307648babd3
|
4
|
+
data.tar.gz: d250a7b34e0dcee6cadbd41a4f93b2fccaaa6f78dd0b56b4f96d2a5cd5b3c097
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61591a5033d2c16ca7bfbda32416d41060156298a4f2272daa210bf1203be2ccf4ec16e4f59034e05196a9f23dfc1621fa0b3e15db82421a930386c29b144d12
|
7
|
+
data.tar.gz: 73f3a4fdf44043aca72b8276c53a9d73d6285b59a49db1308d2c10e358f715d2c58b77f6c755763124b49072b5c11861f7d1b03f4dc0cbc1511fad4fd51a6d9a
|
@@ -1,12 +1,19 @@
|
|
1
1
|
module Lato
|
2
2
|
class AuthenticationController < ApplicationController
|
3
|
-
before_action :not_authenticate_session, only: %i[signin signin_action signup signup_action]
|
3
|
+
before_action :not_authenticate_session, only: %i[signin signin_action signup signup_action accept_invitation accept_invitation_action]
|
4
4
|
before_action :authenticate_session, only: %i[signout signout_action]
|
5
|
+
|
5
6
|
before_action :find_user, only: %i[verify_email verify_email_action update_password update_password_action]
|
6
|
-
before_action :
|
7
|
+
before_action :find_invitation, only: %i[accept_invitation accept_invitation_action]
|
8
|
+
|
7
9
|
before_action :lock_signup_if_disabled, only: %i[signup signup_action]
|
8
10
|
before_action :lock_recover_password_if_disabled, only: %i[recover_password recover_password_action update_password update_password_action]
|
9
11
|
|
12
|
+
before_action :hide_sidebar
|
13
|
+
|
14
|
+
# Signin
|
15
|
+
##
|
16
|
+
|
10
17
|
def signin
|
11
18
|
@user = Lato::User.new
|
12
19
|
end
|
@@ -15,7 +22,10 @@ module Lato
|
|
15
22
|
@user = Lato::User.new
|
16
23
|
|
17
24
|
respond_to do |format|
|
18
|
-
if @user.signin(params.require(:user).permit(:email, :password)
|
25
|
+
if @user.signin(params.require(:user).permit(:email, :password).merge(
|
26
|
+
ip_address: request.remote_ip,
|
27
|
+
user_agent: request.user_agent
|
28
|
+
))
|
19
29
|
session_create(@user.id)
|
20
30
|
|
21
31
|
format.html { redirect_to lato.root_path }
|
@@ -27,12 +37,15 @@ module Lato
|
|
27
37
|
end
|
28
38
|
end
|
29
39
|
|
40
|
+
# Signup
|
41
|
+
##
|
42
|
+
|
30
43
|
def signup
|
31
44
|
@user = Lato::User.new
|
32
45
|
end
|
33
46
|
|
34
47
|
def signup_action
|
35
|
-
@user = Lato::User.new(
|
48
|
+
@user = Lato::User.new(registration_params)
|
36
49
|
|
37
50
|
respond_to do |format|
|
38
51
|
if @user.save
|
@@ -47,6 +60,9 @@ module Lato
|
|
47
60
|
end
|
48
61
|
end
|
49
62
|
|
63
|
+
# Signout
|
64
|
+
##
|
65
|
+
|
50
66
|
def signout; end
|
51
67
|
|
52
68
|
def signout_action
|
@@ -58,6 +74,9 @@ module Lato
|
|
58
74
|
end
|
59
75
|
end
|
60
76
|
|
77
|
+
# Verify email
|
78
|
+
##
|
79
|
+
|
61
80
|
def verify_email
|
62
81
|
@code = params[:code]
|
63
82
|
end
|
@@ -74,6 +93,9 @@ module Lato
|
|
74
93
|
end
|
75
94
|
end
|
76
95
|
|
96
|
+
# Recover password
|
97
|
+
##
|
98
|
+
|
77
99
|
def recover_password
|
78
100
|
@user = Lato::User.new
|
79
101
|
end
|
@@ -92,6 +114,9 @@ module Lato
|
|
92
114
|
end
|
93
115
|
end
|
94
116
|
|
117
|
+
# Update password
|
118
|
+
##
|
119
|
+
|
95
120
|
def update_password; end
|
96
121
|
|
97
122
|
def update_password_action
|
@@ -106,23 +131,55 @@ module Lato
|
|
106
131
|
end
|
107
132
|
end
|
108
133
|
|
134
|
+
# Accept invitation
|
135
|
+
##
|
136
|
+
|
137
|
+
def accept_invitation
|
138
|
+
@user = Lato::User.new(email: @invitation.email)
|
139
|
+
end
|
140
|
+
|
141
|
+
def accept_invitation_action
|
142
|
+
@user = Lato::User.new(registration_params)
|
143
|
+
|
144
|
+
respond_to do |format|
|
145
|
+
if @user.accept_invitation(params.permit(:id, :accepted_code))
|
146
|
+
session_create(@user.id)
|
147
|
+
|
148
|
+
format.html { redirect_to lato.root_path }
|
149
|
+
format.json { render json: @user }
|
150
|
+
else
|
151
|
+
format.html { render :accept_invitation, status: :unprocessable_entity }
|
152
|
+
format.json { render json: @user.errors, status: :unprocessable_entity }
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
109
157
|
private
|
110
158
|
|
159
|
+
def registration_params
|
160
|
+
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :accepted_privacy_policy_version, :accepted_terms_and_conditions_version)
|
161
|
+
end
|
162
|
+
|
111
163
|
def find_user
|
112
164
|
@user = User.find_by(id: params[:id])
|
113
165
|
respond_to_with_not_found unless @user
|
114
166
|
end
|
115
167
|
|
168
|
+
def find_invitation
|
169
|
+
@invitation = Lato::Invitation.find_by(id: params[:id], accepted_code: params[:accepted_code])
|
170
|
+
respond_to_with_not_found unless @invitation
|
171
|
+
end
|
172
|
+
|
116
173
|
def lock_signup_if_disabled
|
117
174
|
return unless Lato.config.auth_disable_signup
|
118
175
|
|
119
|
-
respond_to_with_not_found
|
176
|
+
respond_to_with_not_found
|
120
177
|
end
|
121
178
|
|
122
179
|
def lock_recover_password_if_disabled
|
123
180
|
return unless Lato.config.auth_disable_recover_password
|
124
181
|
|
125
|
-
respond_to_with_not_found
|
182
|
+
respond_to_with_not_found
|
126
183
|
end
|
127
184
|
end
|
128
185
|
end
|
@@ -50,7 +50,8 @@ module Lato
|
|
50
50
|
columns = options[:columns] || @_lato_index[key][:columns] || collection.column_names || []
|
51
51
|
sortable_columns = @_lato_index[key][:sortable_columns] || []
|
52
52
|
searchable_columns = @_lato_index[key][:searchable_columns] || []
|
53
|
-
|
53
|
+
model_name = options[:model_name] || collection.model.name
|
54
|
+
model_name_underscore = options[:model_name] || model_name.underscore.gsub('/', '_')
|
54
55
|
|
55
56
|
render(
|
56
57
|
'lato/components/index',
|
@@ -59,11 +60,20 @@ module Lato
|
|
59
60
|
columns: columns,
|
60
61
|
sortable_columns: sortable_columns,
|
61
62
|
searchable_columns: searchable_columns,
|
63
|
+
model_name: model_name,
|
62
64
|
model_name_underscore: model_name_underscore,
|
63
65
|
custom_actions: options[:custom_actions] || {}
|
64
66
|
)
|
65
67
|
end
|
66
68
|
|
69
|
+
def lato_index_dynamic_label(params = {})
|
70
|
+
'Please override the method lato_index_dynamic_label in your application_helper.rb'
|
71
|
+
end
|
72
|
+
|
73
|
+
def lato_index_dynamic_value(params = {})
|
74
|
+
'Please override the method lato_index_dynamic_value in your application_helper.rb'
|
75
|
+
end
|
76
|
+
|
67
77
|
# Operation
|
68
78
|
##
|
69
79
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Lato
|
2
|
+
class InvitationMailer < ApplicationMailer
|
3
|
+
def invite_mail(invitation_id)
|
4
|
+
@invitation = Lato::Invitation.find(invitation_id)
|
5
|
+
|
6
|
+
set_invitation_locale
|
7
|
+
|
8
|
+
mail(
|
9
|
+
to: @invitation.email,
|
10
|
+
subject: 'Hai ricevuto un invito',
|
11
|
+
template_path: 'lato/mailer/invitation'
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def set_invitation_locale
|
18
|
+
I18n.locale = @invitation.lato_user&.locale || I18n.default_locale
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -3,6 +3,9 @@ module Lato
|
|
3
3
|
def email_verification_mail(user_id, code)
|
4
4
|
@user = Lato::User.find(user_id)
|
5
5
|
@code = code
|
6
|
+
|
7
|
+
set_user_locale
|
8
|
+
|
6
9
|
mail(
|
7
10
|
to: @user.email,
|
8
11
|
subject: 'Conferma il tuo indirizzo email',
|
@@ -13,11 +16,20 @@ module Lato
|
|
13
16
|
def password_update_mail(user_id, code)
|
14
17
|
@user = Lato::User.find(user_id)
|
15
18
|
@code = code
|
19
|
+
|
20
|
+
set_user_locale
|
21
|
+
|
16
22
|
mail(
|
17
23
|
to: @user.email,
|
18
24
|
subject: 'Imposta una nuova password',
|
19
25
|
template_path: 'lato/mailer/user'
|
20
26
|
)
|
21
27
|
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def set_user_locale
|
32
|
+
I18n.locale = @user.locale || I18n.default_locale
|
33
|
+
end
|
22
34
|
end
|
23
35
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Lato
|
2
|
+
class Invitation < ApplicationRecord
|
3
|
+
attr_accessor :actions
|
4
|
+
|
5
|
+
# Kredis
|
6
|
+
##
|
7
|
+
|
8
|
+
kredis_boolean :email_invite_semaphore, expires_in: 2.minutes
|
9
|
+
|
10
|
+
# Validations
|
11
|
+
##
|
12
|
+
|
13
|
+
validates :email, presence: true, uniqueness: true
|
14
|
+
|
15
|
+
# Relations
|
16
|
+
##
|
17
|
+
|
18
|
+
belongs_to :lato_user, class_name: 'Lato::User', foreign_key: :lato_user_id, optional: true
|
19
|
+
|
20
|
+
# Hooks
|
21
|
+
##
|
22
|
+
|
23
|
+
before_validation do
|
24
|
+
self.email = email&.downcase&.strip
|
25
|
+
end
|
26
|
+
|
27
|
+
# be sure that email is not already used by another user
|
28
|
+
before_create do
|
29
|
+
if Lato::User.find_by(email: email)
|
30
|
+
errors.add(:email, 'is already used by another user')
|
31
|
+
throw :abort
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# generate a random code for the invitation
|
36
|
+
before_create do
|
37
|
+
self.accepted_code = SecureRandom.hex(16)
|
38
|
+
end
|
39
|
+
|
40
|
+
# send an email to the invited user
|
41
|
+
after_create do
|
42
|
+
send_invite
|
43
|
+
end
|
44
|
+
|
45
|
+
# be sure accepted invitations can not be deleted
|
46
|
+
before_destroy do
|
47
|
+
throw :abort if accepted?
|
48
|
+
end
|
49
|
+
|
50
|
+
# Helpers
|
51
|
+
##
|
52
|
+
|
53
|
+
def accepted?
|
54
|
+
!!accepted_at
|
55
|
+
end
|
56
|
+
|
57
|
+
# Operations
|
58
|
+
##
|
59
|
+
|
60
|
+
def send_invite
|
61
|
+
if accepted?
|
62
|
+
errors.add(:base, :already_accepted)
|
63
|
+
return false
|
64
|
+
end
|
65
|
+
|
66
|
+
if email_invite_semaphore.value
|
67
|
+
errors.add(:base, :email_sending_limit)
|
68
|
+
return false
|
69
|
+
end
|
70
|
+
|
71
|
+
delivery = Lato::InvitationMailer.invite_mail(id).deliver_now
|
72
|
+
unless delivery
|
73
|
+
errors.add(:base, :email_sending_error)
|
74
|
+
return false
|
75
|
+
end
|
76
|
+
|
77
|
+
email_invite_semaphore.value = true
|
78
|
+
|
79
|
+
true
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Lato
|
2
|
+
module Log
|
3
|
+
# This module is used to add log to the application.
|
4
|
+
# Log are used to track user actions without sensitive data.
|
5
|
+
# Log should not be destroyed.
|
6
|
+
before_destroy do
|
7
|
+
throw :abort
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.table_name_prefix
|
11
|
+
'lato_log_'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -10,6 +10,11 @@ module Lato
|
|
10
10
|
has_one_attached :input_file
|
11
11
|
has_one_attached :output_file
|
12
12
|
|
13
|
+
# Relations
|
14
|
+
##
|
15
|
+
|
16
|
+
belongs_to :lato_user, class_name: 'Lato::User', foreign_key: :lato_user_id, optional: true
|
17
|
+
|
13
18
|
# Hooks
|
14
19
|
##
|
15
20
|
|
@@ -50,6 +55,7 @@ module Lato
|
|
50
55
|
end
|
51
56
|
|
52
57
|
# Operations
|
58
|
+
##
|
53
59
|
|
54
60
|
def start
|
55
61
|
begin
|
@@ -93,7 +99,7 @@ module Lato
|
|
93
99
|
}
|
94
100
|
operation_params[:input_file] = file unless file.nil?
|
95
101
|
|
96
|
-
Operation.create(operation_params)
|
102
|
+
Lato::Operation.create(operation_params)
|
97
103
|
end
|
98
104
|
end
|
99
105
|
end
|
data/app/models/lato/user.rb
CHANGED
@@ -24,6 +24,9 @@ module Lato
|
|
24
24
|
##
|
25
25
|
|
26
26
|
has_many :lato_operations, class_name: 'Lato::Operation', foreign_key: :lato_user_id, dependent: :nullify
|
27
|
+
has_many :lato_invitations, class_name: 'Lato::Invitation', foreign_key: :lato_user_id, dependent: :nullify
|
28
|
+
|
29
|
+
has_many :lato_log_user_signins, class_name: 'Lato::Log::UserSignin', foreign_key: :lato_user_id, dependent: :nullify
|
27
30
|
|
28
31
|
# Hooks
|
29
32
|
##
|
@@ -80,6 +83,15 @@ module Lato
|
|
80
83
|
self.id = user.id
|
81
84
|
reload
|
82
85
|
|
86
|
+
begin
|
87
|
+
lato_log_user_signins.create(
|
88
|
+
ip_address: params[:ip_address],
|
89
|
+
user_agent: params[:user_agent]
|
90
|
+
)
|
91
|
+
rescue StandardError => e
|
92
|
+
Rails.logger.error(e)
|
93
|
+
end
|
94
|
+
|
83
95
|
true
|
84
96
|
end
|
85
97
|
|
@@ -120,15 +132,6 @@ module Lato
|
|
120
132
|
true
|
121
133
|
end
|
122
134
|
|
123
|
-
def destroy_with_confirmation(params)
|
124
|
-
unless params[:email_confirmation] == email
|
125
|
-
errors.add(:email, :not_correct)
|
126
|
-
return
|
127
|
-
end
|
128
|
-
|
129
|
-
destroy
|
130
|
-
end
|
131
|
-
|
132
135
|
def request_recover_password(params)
|
133
136
|
user = Lato::User.find_by(email: params[:email])
|
134
137
|
unless user
|
@@ -184,5 +187,31 @@ module Lato
|
|
184
187
|
|
185
188
|
update(accepted_terms_and_conditions_version: Lato.config.legal_terms_and_conditions_version)
|
186
189
|
end
|
190
|
+
|
191
|
+
def destroy_with_confirmation(params)
|
192
|
+
unless params[:email_confirmation] == email
|
193
|
+
errors.add(:email, :not_correct)
|
194
|
+
return
|
195
|
+
end
|
196
|
+
|
197
|
+
destroy
|
198
|
+
end
|
199
|
+
|
200
|
+
def accept_invitation(params)
|
201
|
+
invitation = Lato::Invitation.find_by(id: params[:id], accepted_code: params[:accepted_code])
|
202
|
+
if !invitation || invitation.accepted? || invitation.email != email
|
203
|
+
errors.add(:base, :invitation_invalid)
|
204
|
+
return
|
205
|
+
end
|
206
|
+
|
207
|
+
ActiveRecord::Base.transaction do
|
208
|
+
raise ActiveRecord::Rollback unless save && invitation.update(
|
209
|
+
accepted_at: Time.now,
|
210
|
+
lato_user_id: id
|
211
|
+
)
|
212
|
+
|
213
|
+
true
|
214
|
+
end
|
215
|
+
end
|
187
216
|
end
|
188
217
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<%
|
2
|
+
|
3
|
+
email_readonly ||= false
|
4
|
+
|
5
|
+
%>
|
6
|
+
|
7
|
+
<div class="row">
|
8
|
+
<div class="col col-12 col-md-6 mb-3">
|
9
|
+
<%= lato_form_item_label form, :first_name %>
|
10
|
+
<%= lato_form_item_input_text form, :first_name, required: true %>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<div class="col col-12 col-md-6 mb-3">
|
14
|
+
<%= lato_form_item_label form, :last_name %>
|
15
|
+
<%= lato_form_item_input_text form, :last_name, required: true %>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
<div class="col col-12 mb-3">
|
19
|
+
<%= lato_form_item_label form, :email %>
|
20
|
+
<%= lato_form_item_input_email form, :email, required: true, readonly: email_readonly %>
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<div class="col col-12 col-md-6 mb-3">
|
24
|
+
<%= lato_form_item_label form, :password %>
|
25
|
+
<%= lato_form_item_input_password form, :password, required: true %>
|
26
|
+
</div>
|
27
|
+
|
28
|
+
<div class="col col-12 col-md-6 mb-3">
|
29
|
+
<%= lato_form_item_label form, :password_confirmation %>
|
30
|
+
<%= lato_form_item_input_password form, :password_confirmation, required: true %>
|
31
|
+
</div>
|
32
|
+
</div>
|
33
|
+
|
34
|
+
<div class="mb-3 text-muted" style="font-size: 14px;">
|
35
|
+
<%= lato_form_item_input_check form, :accepted_privacy_policy_version, I18n.t('lato.privacy_policy_checkbox', link: link_to(I18n.t('lato.privacy_policy'), Lato.config.legal_privacy_policy_url)), required: true %>
|
36
|
+
<%= lato_form_item_input_check form, :accepted_terms_and_conditions_version, I18n.t('lato.terms_and_conditions_checkbox', link: link_to(I18n.t('lato.terms_and_conditions'), Lato.config.legal_terms_and_conditions_url)), required: true %>
|
37
|
+
</div>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%
|
2
|
+
|
3
|
+
user ||= Lato::User.new
|
4
|
+
invitation ||= Lato::Invitation.new
|
5
|
+
|
6
|
+
%>
|
7
|
+
|
8
|
+
<%= turbo_frame_tag 'authentication_form-signup' do %>
|
9
|
+
<%= form_with model: user, url: lato.authentication_accept_invitation_action_path(id: invitation.id, accepted_code: invitation.accepted_code), data: { turbo_frame: '_self', controller: 'lato-form' } do |form| %>
|
10
|
+
<%= lato_form_errors user, class: %w[mb-3] %>
|
11
|
+
|
12
|
+
<%= render 'lato/authentication/fields-registration', form: form, email_readonly: true %>
|
13
|
+
|
14
|
+
<div class="d-flex justify-content-end">
|
15
|
+
<%= lato_form_submit form, I18n.t('lato.confirm') %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
<% end %>
|
@@ -8,37 +8,7 @@ user ||= Lato::User.new
|
|
8
8
|
<%= form_with model: user, url: lato.authentication_signup_action_path, data: { turbo_frame: '_self', controller: 'lato-form' } do |form| %>
|
9
9
|
<%= lato_form_errors user, class: %w[mb-3] %>
|
10
10
|
|
11
|
-
|
12
|
-
<div class="col col-12 col-md-6 mb-3">
|
13
|
-
<%= lato_form_item_label form, :first_name %>
|
14
|
-
<%= lato_form_item_input_text form, :first_name, required: true %>
|
15
|
-
</div>
|
16
|
-
|
17
|
-
<div class="col col-12 col-md-6 mb-3">
|
18
|
-
<%= lato_form_item_label form, :last_name %>
|
19
|
-
<%= lato_form_item_input_text form, :last_name, required: true %>
|
20
|
-
</div>
|
21
|
-
|
22
|
-
<div class="col col-12 mb-3">
|
23
|
-
<%= lato_form_item_label form, :email %>
|
24
|
-
<%= lato_form_item_input_email form, :email, required: true %>
|
25
|
-
</div>
|
26
|
-
|
27
|
-
<div class="col col-12 col-md-6 mb-3">
|
28
|
-
<%= lato_form_item_label form, :password %>
|
29
|
-
<%= lato_form_item_input_password form, :password, required: true %>
|
30
|
-
</div>
|
31
|
-
|
32
|
-
<div class="col col-12 col-md-6 mb-3">
|
33
|
-
<%= lato_form_item_label form, :password_confirmation %>
|
34
|
-
<%= lato_form_item_input_password form, :password_confirmation, required: true %>
|
35
|
-
</div>
|
36
|
-
</div>
|
37
|
-
|
38
|
-
<div class="mb-3 text-muted" style="font-size: 14px;">
|
39
|
-
<%= lato_form_item_input_check form, :accepted_privacy_policy_version, I18n.t('lato.privacy_policy_checkbox', link: link_to(I18n.t('lato.privacy_policy'), Lato.config.legal_privacy_policy_url)), required: true %>
|
40
|
-
<%= lato_form_item_input_check form, :accepted_terms_and_conditions_version, I18n.t('lato.terms_and_conditions_checkbox', link: link_to(I18n.t('lato.terms_and_conditions'), Lato.config.legal_terms_and_conditions_url)), required: true %>
|
41
|
-
</div>
|
11
|
+
<%= render 'lato/authentication/fields-registration', form: form %>
|
42
12
|
|
43
13
|
<div class="d-flex justify-content-end">
|
44
14
|
<%= lato_form_submit form, I18n.t('lato.signup') %>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<div class="w-100 h-100 d-flex justify-content-center align-items-center" style="min-height: calc(100vh - 54px - 2rem)">
|
2
|
+
<div class="card w-100" style="max-width: 550px">
|
3
|
+
<div class="card-header">
|
4
|
+
<h1 class="fs-3 mb-0 text-center"><%= I18n.t('lato.accept_invitation') %></h1>
|
5
|
+
</div>
|
6
|
+
<div class="card-body">
|
7
|
+
<%= render 'lato/authentication/form-accept-invitation', user: @user, invitation: @invitation %>
|
8
|
+
</div>
|
9
|
+
</div>
|
10
|
+
</div>
|
@@ -1,3 +1,9 @@
|
|
1
|
+
<%
|
2
|
+
|
3
|
+
collection_test_istance = collection.model.new
|
4
|
+
|
5
|
+
%>
|
6
|
+
|
1
7
|
<%= turbo_frame_tag "lato_index_#{key}_#{model_name_underscore}", class: 'lato-index' do %>
|
2
8
|
|
3
9
|
<%= form_tag request.path, method: :get, data: { turbo_frame: '_self' } do %>
|
@@ -38,10 +44,19 @@
|
|
38
44
|
<tbody>
|
39
45
|
<% columns.each do |column| %>
|
40
46
|
<tr>
|
41
|
-
<th><%= collection.model.human_attribute_name
|
47
|
+
<th><%= collection_test_istance.respond_to?(column) ? collection.model.human_attribute_name(column) : lato_index_dynamic_label({
|
48
|
+
key: key,
|
49
|
+
model_name: model_name,
|
50
|
+
column: column
|
51
|
+
}) %></th>
|
42
52
|
<td class="lato-index-col-<%= column %>">
|
43
53
|
<% viewer_function_name = "#{model_name_underscore}_#{column}" %>
|
44
|
-
<%= respond_to?(viewer_function_name) ? send(viewer_function_name, member) : member.send(column)
|
54
|
+
<%= respond_to?(viewer_function_name) ? send(viewer_function_name, member) : (collection_test_istance.respond_to?(column) ? member.send(column) : lato_index_dynamic_value({
|
55
|
+
key: key,
|
56
|
+
model_name: model_name,
|
57
|
+
column: column,
|
58
|
+
member: member
|
59
|
+
})) %>
|
45
60
|
</td>
|
46
61
|
</tr>
|
47
62
|
<% end %>
|
@@ -67,7 +82,11 @@
|
|
67
82
|
<% columns.each do |column| %>
|
68
83
|
<th scope="col" class="lato-index-col-<%= column %>">
|
69
84
|
<div class="d-flex align-items-center">
|
70
|
-
<span><%= collection.model.human_attribute_name
|
85
|
+
<span><%= collection_test_istance.respond_to?(column) ? collection.model.human_attribute_name(column) : lato_index_dynamic_label({
|
86
|
+
key: key,
|
87
|
+
model_name: model_name,
|
88
|
+
column: column
|
89
|
+
}) %></span>
|
71
90
|
<% if sortable_columns.include?(column) %>
|
72
91
|
<div class="btn-group ms-3">
|
73
92
|
<div class="position-relative btn btn-sm <%= params[:sort_by] == "#{column}|ASC" ? 'btn-primary' : 'btn-outline-primary' %>">
|
@@ -92,7 +111,12 @@
|
|
92
111
|
<% columns.each do |column| %>
|
93
112
|
<td class="lato-index-col-<%= column %>">
|
94
113
|
<% viewer_function_name = "#{model_name_underscore}_#{column}" %>
|
95
|
-
<%= respond_to?(viewer_function_name) ? send(viewer_function_name, member) : member.send(column)
|
114
|
+
<%= respond_to?(viewer_function_name) ? send(viewer_function_name, member) : (collection_test_istance.respond_to?(column) ? member.send(column) : lato_index_dynamic_value({
|
115
|
+
key: key,
|
116
|
+
model_name: model_name,
|
117
|
+
column: column,
|
118
|
+
member: member
|
119
|
+
})) %>
|
96
120
|
</td>
|
97
121
|
<% end %>
|
98
122
|
</tr>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<% if I18n.locale == 'en' %>
|
2
|
+
|
3
|
+
You have received an invitation to use <%= Lato.config.application_title %>.
|
4
|
+
<br><br>
|
5
|
+
Click the following link to accept the invitation and complete the registration:
|
6
|
+
<br><br>
|
7
|
+
<%= link_to lato.authentication_accept_invitation_url(id: @invitation.id, accepted_code: @invitation.accepted_code), lato.authentication_accept_invitation_url(id: @invitation.id, accepted_code: @invitation.accepted_code) %>
|
8
|
+
|
9
|
+
<% else %>
|
10
|
+
|
11
|
+
Hai ricevuto un invito per utilizzare <%= Lato.config.application_title %>.
|
12
|
+
<br><br>
|
13
|
+
Clicca il seguente link per accettare l'invito e completare la registrazione:
|
14
|
+
<br><br>
|
15
|
+
<%= link_to lato.authentication_accept_invitation_url(id: @invitation.id, accepted_code: @invitation.accepted_code), lato.authentication_accept_invitation_url(id: @invitation.id, accepted_code: @invitation.accepted_code) %>
|
16
|
+
|
17
|
+
<% end %>
|
@@ -13,4 +13,19 @@
|
|
13
13
|
</div>
|
14
14
|
</div>
|
15
15
|
<% end %>
|
16
|
+
|
17
|
+
<% if alert %>
|
18
|
+
<div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11">
|
19
|
+
<div data-controller="lato-feedback" id="feedbackAlert" class="toast hide" role="alert" aria-live="assertive" aria-atomic="true">
|
20
|
+
<div class="toast-header">
|
21
|
+
<i class="bi bi-check-circle-fill text-danger me-2"></i>
|
22
|
+
<strong class="me-auto"><%= I18n.t('lato.operation_failed') %></strong>
|
23
|
+
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
24
|
+
</div>
|
25
|
+
<div class="toast-body">
|
26
|
+
<%= alert %>
|
27
|
+
</div>
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
<% end %>
|
16
31
|
</div>
|
data/config/locales/en.yml
CHANGED
@@ -36,8 +36,10 @@ en:
|
|
36
36
|
signout_confirmation_request: "%{user}, Are you sure to leave?"
|
37
37
|
recover_password_code: Code received by email
|
38
38
|
operation_completed: Operation completed
|
39
|
+
operation_failed: Operation failed
|
39
40
|
privacy_policy_update_title: Privacy policy update
|
40
41
|
terms_and_conditions_update_title: Terms and conditions update
|
42
|
+
accept_invitation: Accept invitation
|
41
43
|
|
42
44
|
account_controller:
|
43
45
|
update_user_action_notice: Account information properly updated
|
@@ -79,3 +81,9 @@ en:
|
|
79
81
|
inclusion: not accepted
|
80
82
|
accepted_terms_and_conditions_version:
|
81
83
|
inclusion: not accepted
|
84
|
+
lato/invitation:
|
85
|
+
attributes:
|
86
|
+
base:
|
87
|
+
already_accepted: Invitation already accepted
|
88
|
+
email_sending_error: Unable to send mail
|
89
|
+
email_sending_limit: Wait at least 2 minutes to try a new invite attempt
|
data/config/locales/it.yml
CHANGED
@@ -38,8 +38,10 @@ it:
|
|
38
38
|
signout_confirmation_request: "%{user}, Sei sicuro di voler uscire dal tuo account?"
|
39
39
|
recover_password_code: Codice ricevuto via email
|
40
40
|
operation_completed: Operazione completata
|
41
|
+
operation_failed: Operazione fallita
|
41
42
|
privacy_policy_update_title: Aggiornamento privacy policy
|
42
43
|
terms_and_conditions_update_title: Aggiornamento termini e condizioni
|
44
|
+
accept_invitation: Accetta invito
|
43
45
|
|
44
46
|
account_controller:
|
45
47
|
update_user_action_notice: Informazioni account aggiornate correttamente
|
@@ -76,6 +78,7 @@ it:
|
|
76
78
|
password_update_code_invalid: Il codice di verifica non risulta valido
|
77
79
|
privacy_policy_invalid: Per accettare la privacy policy devi selezionare la checkbox di conferma
|
78
80
|
terms_and_conditions_invalid: Per accettare i termini e condizioni devi selezionare la checkbox di conferma
|
81
|
+
invitation_invalid: Invito non valido
|
79
82
|
password:
|
80
83
|
not_correct: non corretta
|
81
84
|
password_confirmation:
|
@@ -88,6 +91,14 @@ it:
|
|
88
91
|
inclusion: non accettata
|
89
92
|
accepted_terms_and_conditions_version:
|
90
93
|
inclusion: non accettati
|
94
|
+
lato/invitation:
|
95
|
+
attributes:
|
96
|
+
base:
|
97
|
+
already_accepted: Invito già accettato dall'utente
|
98
|
+
email_sending_error: Impossibile inviare mail
|
99
|
+
email_sending_limit: Attendi almeno 2 minuti per provare un nuovo tentativo di invito email
|
100
|
+
|
101
|
+
|
91
102
|
date:
|
92
103
|
abbr_day_names:
|
93
104
|
- dom
|
data/config/routes.rb
CHANGED
@@ -19,6 +19,8 @@ Lato::Engine.routes.draw do
|
|
19
19
|
post 'recover_password_action', to: 'authentication#recover_password_action', as: :authentication_recover_password_action
|
20
20
|
get 'update_password', to: 'authentication#update_password', as: :authentication_update_password
|
21
21
|
patch 'update_password_action', to: 'authentication#update_password_action', as: :authentication_update_password_action
|
22
|
+
get 'accept_invitation', to: 'authentication#accept_invitation', as: :authentication_accept_invitation
|
23
|
+
post 'accept_invitation_action', to: 'authentication#accept_invitation_action', as: :authentication_accept_invitation_action
|
22
24
|
end
|
23
25
|
|
24
26
|
scope :account do
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class CreateLatoInvitations < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
create_table :lato_invitations do |t|
|
4
|
+
t.string :email
|
5
|
+
t.datetime :accepted_at
|
6
|
+
t.string :accepted_code
|
7
|
+
t.references :lato_user, index: true, foreign_key: true
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/lato/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lato
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.28
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gregorio Galante
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-02-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -130,9 +130,13 @@ files:
|
|
130
130
|
- app/helpers/lato/components_helper.rb
|
131
131
|
- app/jobs/lato/application_job.rb
|
132
132
|
- app/mailers/lato/application_mailer.rb
|
133
|
+
- app/mailers/lato/invitation_mailer.rb
|
133
134
|
- app/mailers/lato/user_mailer.rb
|
134
135
|
- app/models/concerns/lato_user_application.rb
|
135
136
|
- app/models/lato/application_record.rb
|
137
|
+
- app/models/lato/invitation.rb
|
138
|
+
- app/models/lato/log.rb
|
139
|
+
- app/models/lato/log/user_signin.rb
|
136
140
|
- app/models/lato/operation.rb
|
137
141
|
- app/models/lato/session.rb
|
138
142
|
- app/models/lato/user.rb
|
@@ -142,11 +146,14 @@ files:
|
|
142
146
|
- app/views/lato/account/_form-password.html.erb
|
143
147
|
- app/views/lato/account/_form-user.html.erb
|
144
148
|
- app/views/lato/account/index.html.erb
|
149
|
+
- app/views/lato/authentication/_fields-registration.html.erb
|
150
|
+
- app/views/lato/authentication/_form-accept-invitation.html.erb
|
145
151
|
- app/views/lato/authentication/_form-recover-password.html.erb
|
146
152
|
- app/views/lato/authentication/_form-signin.html.erb
|
147
153
|
- app/views/lato/authentication/_form-signup.html.erb
|
148
154
|
- app/views/lato/authentication/_form-update-password.html.erb
|
149
155
|
- app/views/lato/authentication/_form-verify-email.html.erb
|
156
|
+
- app/views/lato/authentication/accept_invitation.html.erb
|
150
157
|
- app/views/lato/authentication/recover_password.html.erb
|
151
158
|
- app/views/lato/authentication/signin.html.erb
|
152
159
|
- app/views/lato/authentication/signout.html.erb
|
@@ -159,6 +166,7 @@ files:
|
|
159
166
|
- app/views/lato/components/_operation.html.erb
|
160
167
|
- app/views/lato/components/_page_head.html.erb
|
161
168
|
- app/views/lato/components/_sidebar_nav_item.html.erb
|
169
|
+
- app/views/lato/mailer/invitation/invite_mail.html.erb
|
162
170
|
- app/views/lato/mailer/user/email_verification_mail.html.erb
|
163
171
|
- app/views/lato/mailer/user/password_update_mail.html.erb
|
164
172
|
- app/views/lato/operations/show.html.erb
|
@@ -183,6 +191,8 @@ files:
|
|
183
191
|
- db/migrate/20221022205744_create_lato_users.rb
|
184
192
|
- db/migrate/20221118072130_create_lato_operations.rb
|
185
193
|
- db/migrate/20221229233844_add_locale_to_lato_user.rb
|
194
|
+
- db/migrate/20230109054412_create_lato_log_user_signins.rb
|
195
|
+
- db/migrate/20230109061533_create_lato_invitations.rb
|
186
196
|
- lib/lato.rb
|
187
197
|
- lib/lato/btstrap.rb
|
188
198
|
- lib/lato/config.rb
|