lato 3.5.8 → 3.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +0 -1
- data/app/controllers/concerns/lato/componentable.rb +1 -1
- data/app/controllers/lato/account_controller.rb +14 -0
- data/app/controllers/lato/authentication_controller.rb +56 -8
- data/app/models/lato/user.rb +33 -1
- data/app/views/lato/account/_form-authenticator.html.erb +41 -0
- data/app/views/lato/account/index.html.erb +11 -0
- data/app/views/lato/authentication/_form-authenticator.html.erb +28 -0
- data/app/views/lato/authentication/authenticator.html.erb +10 -0
- data/config/locales/en.yml +10 -0
- data/config/locales/it.yml +10 -0
- data/config/routes.rb +3 -0
- data/db/migrate/20240318074025_add_authenticator_secret_to_user.rb +5 -0
- data/lib/lato/config.rb +7 -1
- data/lib/lato/dependency_helper.rb +44 -0
- data/lib/lato/version.rb +1 -1
- data/lib/lato.rb +3 -1
- metadata +36 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 124f38d5389e35689d3829980d788e5531af092d45fd378b5fbaabdc039ebe51
|
4
|
+
data.tar.gz: e6a938bc4549803deb41efd7df596e85148d84488d442f75ac46b9bb8c0191bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fed883559fd4d1859aacc7ca6ca2dc2d65935c1d91d769c23ba71b940d2067cc8d320b84512a9adbd6b0a1540f7e3b33098664c89298a18277fda7fa548a7dc9
|
7
|
+
data.tar.gz: 9b87edd528d4c10bb7c82f4b8fa7769d6625560668657dea98b085661d22696c215d138fc3a5af0947d22cfb20c63b014503f472d99516bf6b0594398809e0ca
|
data/README.md
CHANGED
@@ -37,7 +37,7 @@ module Lato
|
|
37
37
|
if collection.respond_to?(:lato_index_search)
|
38
38
|
collection = collection.lato_index_search(search)
|
39
39
|
else
|
40
|
-
query = @_lato_index[key][:searchable_columns].map { |k| "lower(#{k}) LIKE :search" }
|
40
|
+
query = @_lato_index[key][:searchable_columns].map { |k| "#{k.to_s == 'id' ? k : "lower(#{k})"} LIKE :search" }
|
41
41
|
collection = collection.where(query.join(' OR '), search: "%#{search.downcase.strip}%")
|
42
42
|
end
|
43
43
|
end
|
@@ -55,6 +55,20 @@ module Lato
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
+
def update_authenticator_action
|
59
|
+
return respond_to_with_not_found unless Lato.config.authenticator_connection
|
60
|
+
|
61
|
+
respond_to do |format|
|
62
|
+
if @session.user.generate_authenticator_secret
|
63
|
+
format.html { redirect_to lato.account_path }
|
64
|
+
format.json { render json: @session.user }
|
65
|
+
else
|
66
|
+
format.html { render :index, status: :unprocessable_entity }
|
67
|
+
format.json { render json: @session.user.errors, status: :unprocessable_entity }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
58
72
|
def request_verify_email_action
|
59
73
|
respond_to do |format|
|
60
74
|
if @session.user.request_verify_email
|
@@ -10,6 +10,7 @@ module Lato
|
|
10
10
|
before_action :lock_signup_if_disabled, only: %i[signup signup_action]
|
11
11
|
before_action :lock_recover_password_if_disabled, only: %i[recover_password recover_password_action update_password update_password_action]
|
12
12
|
before_action :lock_web3_if_disabled, only: %i[web3_signin web3_signin_action]
|
13
|
+
before_action :lock_authenticator_if_disabled, only: %i[authenticator authenticator_action]
|
13
14
|
|
14
15
|
before_action :hide_sidebar
|
15
16
|
|
@@ -28,10 +29,13 @@ module Lato
|
|
28
29
|
ip_address: request.remote_ip,
|
29
30
|
user_agent: request.user_agent
|
30
31
|
))
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
if create_session_or_start_authenticator(@user)
|
33
|
+
format.html { redirect_to lato.root_path }
|
34
|
+
format.json { render json: @user }
|
35
|
+
else
|
36
|
+
format.html { redirect_to lato.authentication_authenticator_path }
|
37
|
+
format.json { render json: @user }
|
38
|
+
end
|
35
39
|
else
|
36
40
|
format.html { render :signin, status: :unprocessable_entity }
|
37
41
|
format.json { render json: @user.errors, status: :unprocessable_entity }
|
@@ -54,10 +58,13 @@ module Lato
|
|
54
58
|
web3_nonce: session[:web3_nonce]
|
55
59
|
))
|
56
60
|
session[:web3_nonce] = nil
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
+
if create_session_or_start_authenticator(@user)
|
62
|
+
format.html { redirect_to lato.root_path }
|
63
|
+
format.json { render json: @user }
|
64
|
+
else
|
65
|
+
format.html { redirect_to lato.authentication_authenticator_path }
|
66
|
+
format.json { render json: @user }
|
67
|
+
end
|
61
68
|
else
|
62
69
|
session[:web3_nonce] = nil
|
63
70
|
format.html { render :web3_signin, status: :unprocessable_entity }
|
@@ -183,6 +190,31 @@ module Lato
|
|
183
190
|
end
|
184
191
|
end
|
185
192
|
|
193
|
+
# Authenticator
|
194
|
+
##
|
195
|
+
|
196
|
+
def authenticator
|
197
|
+
@user = Lato::User.find_by_id(session[:authenticator_user_id])
|
198
|
+
return respond_to_with_not_found unless @user
|
199
|
+
end
|
200
|
+
|
201
|
+
def authenticator_action
|
202
|
+
@user = Lato::User.find_by_id(session[:authenticator_user_id])
|
203
|
+
|
204
|
+
respond_to do |format|
|
205
|
+
if @user.authenticator(params.require(:user).permit(:authenticator_code))
|
206
|
+
session[:authenticator_user_id] = nil
|
207
|
+
session_create(@user.id)
|
208
|
+
|
209
|
+
format.html { redirect_to lato.root_path }
|
210
|
+
format.json { render json: @user }
|
211
|
+
else
|
212
|
+
format.html { render :authenticator, status: :unprocessable_entity }
|
213
|
+
format.json { render json: @user.errors, status: :unprocessable_entity }
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
186
218
|
private
|
187
219
|
|
188
220
|
def registration_params
|
@@ -199,6 +231,16 @@ module Lato
|
|
199
231
|
respond_to_with_not_found unless @invitation
|
200
232
|
end
|
201
233
|
|
234
|
+
def create_session_or_start_authenticator(user)
|
235
|
+
if !Lato.config.authenticator_connection || Lato.config.auth_disable_authenticator || !user.authenticator_enabled?
|
236
|
+
session_create(user.id)
|
237
|
+
return true
|
238
|
+
end
|
239
|
+
|
240
|
+
session[:authenticator_user_id] = user.id
|
241
|
+
false
|
242
|
+
end
|
243
|
+
|
202
244
|
def lock_signup_if_disabled
|
203
245
|
return unless Lato.config.auth_disable_signup
|
204
246
|
|
@@ -215,6 +257,12 @@ module Lato
|
|
215
257
|
return if Lato.config.web3_connection && !Lato.config.auth_disable_web3
|
216
258
|
|
217
259
|
|
260
|
+
respond_to_with_not_found
|
261
|
+
end
|
262
|
+
|
263
|
+
def lock_authenticator_if_disabled
|
264
|
+
return if Lato.config.authenticator_connection && !Lato.config.auth_disable_authenticator
|
265
|
+
|
218
266
|
respond_to_with_not_found
|
219
267
|
end
|
220
268
|
end
|
data/app/models/lato/user.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Lato
|
2
2
|
class User < ApplicationRecord
|
3
|
+
include Lato::DependencyHelper
|
3
4
|
include LatoUserApplication
|
4
5
|
|
5
6
|
has_secure_password
|
@@ -53,6 +54,10 @@ module Lato
|
|
53
54
|
@valid_accepted_terms_and_conditions_version ||= accepted_terms_and_conditions_version >= Lato.config.legal_terms_and_conditions_version
|
54
55
|
end
|
55
56
|
|
57
|
+
def authenticator_enabled?
|
58
|
+
!authenticator_secret.blank?
|
59
|
+
end
|
60
|
+
|
56
61
|
# Helpers
|
57
62
|
##
|
58
63
|
|
@@ -64,6 +69,10 @@ module Lato
|
|
64
69
|
@gravatar_image_url ||= "https://www.gravatar.com/avatar/#{Digest::MD5.hexdigest(email)}?s=#{size}"
|
65
70
|
end
|
66
71
|
|
72
|
+
def authenticator_qr_code_base64(size = 200)
|
73
|
+
"data:image/png;base64,#{Base64.strict_encode64(RQRCode::QRCode.new(ROTP::TOTP.new(authenticator_secret, :issuer => Lato.config.application_title).provisioning_uri(email).to_s).as_png(size: size, border_modules: 0).to_s)}"
|
74
|
+
end
|
75
|
+
|
67
76
|
# Operations
|
68
77
|
##
|
69
78
|
|
@@ -112,6 +121,8 @@ module Lato
|
|
112
121
|
end
|
113
122
|
|
114
123
|
def web3_signin(params)
|
124
|
+
depends_on('eth')
|
125
|
+
|
115
126
|
self.web3_address = params[:web3_address]
|
116
127
|
|
117
128
|
user = Lato::User.find_by(web3_address: params[:web3_address].downcase)
|
@@ -221,7 +232,9 @@ module Lato
|
|
221
232
|
|
222
233
|
c_password_update_code('')
|
223
234
|
|
224
|
-
update(params.permit(:password, :password_confirmation)
|
235
|
+
update(params.permit(:password, :password_confirmation).merge(
|
236
|
+
authenticator_secret: nil # Reset authenticator secret when password is updated
|
237
|
+
))
|
225
238
|
end
|
226
239
|
|
227
240
|
def update_accepted_privacy_policy_version(params)
|
@@ -269,6 +282,8 @@ module Lato
|
|
269
282
|
end
|
270
283
|
|
271
284
|
def add_web3_connection(params)
|
285
|
+
depends_on('eth')
|
286
|
+
|
272
287
|
signature_pubkey = Eth::Signature.personal_recover(params[:web3_nonce], params[:web3_signed_nonce])
|
273
288
|
signature_address = Eth::Util.public_key_to_address signature_pubkey
|
274
289
|
unless signature_address.to_s.downcase == params[:web3_address].downcase
|
@@ -287,6 +302,23 @@ module Lato
|
|
287
302
|
true
|
288
303
|
end
|
289
304
|
|
305
|
+
def generate_authenticator_secret
|
306
|
+
update(authenticator_secret: ROTP::Base32.random)
|
307
|
+
end
|
308
|
+
|
309
|
+
def authenticator(params)
|
310
|
+
return false unless authenticator_enabled?
|
311
|
+
|
312
|
+
totp = ROTP::TOTP.new(authenticator_secret)
|
313
|
+
result = totp.verify(params[:authenticator_code])
|
314
|
+
unless result
|
315
|
+
errors.add(:base, :authenticator_code_invalid)
|
316
|
+
return
|
317
|
+
end
|
318
|
+
|
319
|
+
true
|
320
|
+
end
|
321
|
+
|
290
322
|
# Cache
|
291
323
|
##
|
292
324
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<%
|
2
|
+
|
3
|
+
user ||= Lato::User.new
|
4
|
+
|
5
|
+
%>
|
6
|
+
|
7
|
+
<%= turbo_frame_tag 'account_form-authenticator' do %>
|
8
|
+
<%= form_with model: user, url: lato.account_update_authenticator_action_path, data: { turbo_frame: '_self', controller: 'lato-form' } do |form| %>
|
9
|
+
<%= lato_form_notices class: %w[mb-3] %>
|
10
|
+
<%= lato_form_errors user, class: %w[mb-3] %>
|
11
|
+
|
12
|
+
<% if user.authenticator_secret %>
|
13
|
+
<div class="d-block d-md-flex align-items-stretch">
|
14
|
+
<div class="text-center mb-3 mb-md-0 me-md-3">
|
15
|
+
<img src="<%= user.authenticator_qr_code_base64 %>" />
|
16
|
+
</div>
|
17
|
+
<div class="d-flex flex-column justify-content-between">
|
18
|
+
<div class="alert alert-light">
|
19
|
+
<p>
|
20
|
+
<%= raw I18n.t('lato.account_authenticator_ready_qr') %>
|
21
|
+
</p>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div class="d-flex justify-content-end">
|
25
|
+
<%= lato_form_submit form, I18n.t('lato.reset_qr_code'), class: %w[btn-danger] %>
|
26
|
+
</div>
|
27
|
+
</div>
|
28
|
+
</div>
|
29
|
+
<% else %>
|
30
|
+
<div class="alert alert-light mb-0">
|
31
|
+
<h4 class="alert-heading"><%= I18n.t('lato.account_authenticator_start_title') %></h4>
|
32
|
+
<p>
|
33
|
+
<%= raw I18n.t('lato.account_authenticator_start_description') %>
|
34
|
+
</p>
|
35
|
+
<p class="mb-0">
|
36
|
+
<%= lato_form_submit form, I18n.t('lato.generate_qr_code'), class: %w[btn-primary] %>
|
37
|
+
</p>
|
38
|
+
</div>
|
39
|
+
<% end %>
|
40
|
+
<% end %>
|
41
|
+
<% end %>
|
@@ -32,6 +32,17 @@
|
|
32
32
|
</div>
|
33
33
|
<% end %>
|
34
34
|
|
35
|
+
<% if Lato.config.authenticator_connection %>
|
36
|
+
<div class="card mb-4">
|
37
|
+
<div class="card-header">
|
38
|
+
<h2 class="fs-4 mb-0"><%= I18n.t('lato.account_authenticator') %></h2>
|
39
|
+
</div>
|
40
|
+
<div class="card-body">
|
41
|
+
<%= render 'lato/account/form-authenticator', user: @session.user %>
|
42
|
+
</div>
|
43
|
+
</div>
|
44
|
+
<% end %>
|
45
|
+
|
35
46
|
<div class="card mb-4">
|
36
47
|
<div class="card-header">
|
37
48
|
<h2 class="fs-4 mb-0"><%= I18n.t('lato.account_delete') %></h2>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<%
|
2
|
+
|
3
|
+
user ||= Lato::User.new
|
4
|
+
|
5
|
+
%>
|
6
|
+
|
7
|
+
<%= turbo_frame_tag 'authentication_form-authenticator' do %>
|
8
|
+
<%= form_with model: user, url: lato.authentication_authenticator_action_path, method: :post, data: { turbo_frame: '_self', controller: 'lato-form' } do |form| %>
|
9
|
+
<%= lato_form_notices class: %w[mb-3] %>
|
10
|
+
<%= lato_form_errors user, class: %w[mb-3] %>
|
11
|
+
|
12
|
+
<div class="mb-3 text-center">
|
13
|
+
<p><%= raw I18n.t('lato.authenticator_code_help', email: user.email) %></p>
|
14
|
+
</div>
|
15
|
+
|
16
|
+
<div class="mb-3">
|
17
|
+
<%= lato_form_item_input_text form, :authenticator_code, required: true %>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<div>
|
21
|
+
<%= lato_form_submit form, I18n.t('lato.confirm'), class: %w[d-block w-100] %>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div class="text-center mt-3 mb-3">
|
25
|
+
<%= I18n.t('lato.or').downcase %> <%= link_to I18n.t('lato.reset_password').downcase, lato.authentication_recover_password_path %>
|
26
|
+
</div>
|
27
|
+
<% end %>
|
28
|
+
<% end %>
|
@@ -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: 400px">
|
3
|
+
<div class="card-header">
|
4
|
+
<h1 class="fs-3 mb-0 text-center"><%= I18n.t('lato.authenticator') %></h1>
|
5
|
+
</div>
|
6
|
+
<div class="card-body">
|
7
|
+
<%= render 'lato/authentication/form-authenticator', user: @user %>
|
8
|
+
</div>
|
9
|
+
</div>
|
10
|
+
</div>
|
data/config/locales/en.yml
CHANGED
@@ -49,6 +49,15 @@ en:
|
|
49
49
|
web3_signin: Web3 Login
|
50
50
|
retry: Retry
|
51
51
|
back: Go back
|
52
|
+
account_authenticator: Google Authenticator
|
53
|
+
account_authenticator_start_title: Enable Google Authenticator
|
54
|
+
account_authenticator_start_description: Generate a QR code by clicking the button below and scan it with the Google Authenticator app on your phone.<br>This will allow you to use the protect your account with a second factor authentication.
|
55
|
+
account_authenticator_ready_qr: Scan the QR code with the Google Authenticator app to use the account protection with a second factor authentication.
|
56
|
+
generate_qr_code: Generate QR code
|
57
|
+
reset_qr_code: Reset QR code
|
58
|
+
authenticator: Two-factor authentication
|
59
|
+
authenticator_code_help: Insert the code generated by the Google Authenticator app for the account <b>%{email}</b>
|
60
|
+
reset_password: Reset your password
|
52
61
|
|
53
62
|
account_controller:
|
54
63
|
update_user_action_notice: Account information properly updated
|
@@ -82,6 +91,7 @@ en:
|
|
82
91
|
terms_and_conditions_invalid: To accept the terms and conditions you must select the confirmation checkbox
|
83
92
|
web3_address_invalid: The address you send is not corretly signed
|
84
93
|
web3_connection_error: Impossible to connect the wallet
|
94
|
+
authenticator_code_invalid: The code you inserted is not correct
|
85
95
|
password:
|
86
96
|
not_correct: not correct
|
87
97
|
email:
|
data/config/locales/it.yml
CHANGED
@@ -51,6 +51,15 @@ it:
|
|
51
51
|
web3_signin: Accedi con Web3
|
52
52
|
retry: Riprova
|
53
53
|
back: Torna indietro
|
54
|
+
account_authenticator: Google Authenticator
|
55
|
+
account_authenticator_start_title: Abilita Google Authenticator
|
56
|
+
account_authenticator_start_description: Genera un codice QR cliccando il pulsante sottostante e scansionalo con l'app Google Authenticator sul tuo telefono.<br>Questo ti permetterà di proteggere il tuo account con un'autenticazione a due fattori.
|
57
|
+
account_authenticator_ready_qr: Scansiona il codice QR con l'app Google Authenticator per utilizzare la protezione dell'account con un'autenticazione a due fattori.
|
58
|
+
generate_qr_code: Genera codice QR
|
59
|
+
reset_qr_code: Resetta codice QR
|
60
|
+
authenticator: Autenticazione a due fattori
|
61
|
+
authenticator_code_help: Inserisci il codice generato dall'app Google Authenticator per l'account <b>%{email}</b>
|
62
|
+
reset_password: Reimposta la tua password
|
54
63
|
|
55
64
|
account_controller:
|
56
65
|
update_user_action_notice: Informazioni account aggiornate correttamente
|
@@ -90,6 +99,7 @@ it:
|
|
90
99
|
invitation_invalid: Invito non valido
|
91
100
|
web3_address_invalid: L'inidirizzo inviato non è correttamente firmato
|
92
101
|
web3_connection_error: Impossibile connettere il wallet
|
102
|
+
authenticator_code_invalid: Il codice inserito non è corretto
|
93
103
|
password:
|
94
104
|
not_correct: non corretta
|
95
105
|
password_confirmation:
|
data/config/routes.rb
CHANGED
@@ -26,6 +26,8 @@ Lato::Engine.routes.draw do
|
|
26
26
|
patch 'update_password_action', to: 'authentication#update_password_action', as: :authentication_update_password_action
|
27
27
|
get 'accept_invitation', to: 'authentication#accept_invitation', as: :authentication_accept_invitation
|
28
28
|
post 'accept_invitation_action', to: 'authentication#accept_invitation_action', as: :authentication_accept_invitation_action
|
29
|
+
get 'authenticator', to: 'authentication#authenticator', as: :authentication_authenticator
|
30
|
+
post 'authenticator_action', to: 'authentication#authenticator_action', as: :authentication_authenticator_action
|
29
31
|
end
|
30
32
|
|
31
33
|
# Account
|
@@ -35,6 +37,7 @@ Lato::Engine.routes.draw do
|
|
35
37
|
get '', to: 'account#index', as: :account
|
36
38
|
patch 'update_user_action', to: 'account#update_user_action', as: :account_update_user_action
|
37
39
|
patch 'update_web3_action', to: 'account#update_web3_action', as: :account_update_web3_action
|
40
|
+
patch 'update_authenticator_action', to: 'account#update_authenticator_action', as: :account_update_authenticator_action
|
38
41
|
patch 'request_verify_email_action', to: 'account#request_verify_email_action', as: :account_request_verify_email_action
|
39
42
|
patch 'update_password_action', to: 'account#update_password_action', as: :account_update_password_action
|
40
43
|
delete 'destroy_action', to: 'account#destroy_action', as: :account_destroy_action
|
data/lib/lato/config.rb
CHANGED
@@ -10,7 +10,7 @@ module Lato
|
|
10
10
|
attr_accessor :session_lifetime, :session_root_path
|
11
11
|
|
12
12
|
# Authentication configs
|
13
|
-
attr_accessor :auth_disable_signup, :auth_disable_recover_password, :auth_disable_web3
|
13
|
+
attr_accessor :auth_disable_signup, :auth_disable_recover_password, :auth_disable_web3, :auth_disable_authenticator
|
14
14
|
|
15
15
|
# Assets configs
|
16
16
|
attr_accessor :assets_stylesheet_entry
|
@@ -22,8 +22,12 @@ module Lato
|
|
22
22
|
attr_accessor :legal_privacy_policy_url, :legal_privacy_policy_version, :legal_terms_and_conditions_url, :legal_terms_and_conditions_version
|
23
23
|
|
24
24
|
# Web3 connection
|
25
|
+
# NOTE: It requires the gem 'eth' to be installed in the application Gemfile
|
25
26
|
attr_accessor :web3_connection
|
26
27
|
|
28
|
+
# Authenticator connection
|
29
|
+
attr_accessor :authenticator_connection
|
30
|
+
|
27
31
|
def initialize
|
28
32
|
@application_title = 'Lato'
|
29
33
|
@application_version = '1.0.0'
|
@@ -34,6 +38,7 @@ module Lato
|
|
34
38
|
@auth_disable_signup = false
|
35
39
|
@auth_disable_recover_password = false
|
36
40
|
@auth_disable_web3 = false
|
41
|
+
@auth_disable_authenticator = false
|
37
42
|
|
38
43
|
@assets_stylesheet_entry = 'application'
|
39
44
|
|
@@ -48,6 +53,7 @@ module Lato
|
|
48
53
|
@legal_terms_and_conditions_version = 1
|
49
54
|
|
50
55
|
@web3_connection = false
|
56
|
+
@authenticator_connection = false
|
51
57
|
end
|
52
58
|
end
|
53
59
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# NOTE: Taken from https://github.com/andreibondarev/langchainrb/blob/main/lib/langchain/dependency_helper.rb
|
4
|
+
# Thanks to Andrei Bondarev for the inspiration!!
|
5
|
+
|
6
|
+
module Lato
|
7
|
+
module DependencyHelper
|
8
|
+
class LoadError < ::LoadError; end
|
9
|
+
|
10
|
+
class VersionError < ScriptError; end
|
11
|
+
|
12
|
+
# This method requires and loads the given gem, and then checks to see if the version of the gem meets the requirements listed in `lato.gemspec`
|
13
|
+
# This solution was built to avoid auto-loading every single gem in the Gemfile when the developer will mostly likely be only using a few of them.
|
14
|
+
#
|
15
|
+
# @param gem_name [String] The name of the gem to load
|
16
|
+
# @return [Boolean] Whether or not the gem was loaded successfully
|
17
|
+
# @raise [LoadError] If the gem is not installed
|
18
|
+
# @raise [VersionError] If the gem is installed, but the version does not meet the requirements
|
19
|
+
#
|
20
|
+
def depends_on(gem_name, req: true)
|
21
|
+
gem(gem_name) # require the gem
|
22
|
+
|
23
|
+
return(true) unless defined?(Bundler) # If we're in a non-bundler environment, we're no longer able to determine if we'll meet requirements
|
24
|
+
|
25
|
+
gem_version = Gem.loaded_specs[gem_name].version
|
26
|
+
gem_requirement = Bundler.load.dependencies.find { |g| g.name == gem_name }&.requirement
|
27
|
+
|
28
|
+
raise LoadError unless gem_requirement
|
29
|
+
|
30
|
+
unless gem_requirement.satisfied_by?(gem_version)
|
31
|
+
raise VersionError, "The #{gem_name} gem is installed, but version #{gem_requirement} is required. You have #{gem_version}."
|
32
|
+
end
|
33
|
+
|
34
|
+
lib_name = gem_name if req == true
|
35
|
+
lib_name = req if req.is_a?(String)
|
36
|
+
|
37
|
+
require(lib_name) if lib_name
|
38
|
+
|
39
|
+
true
|
40
|
+
rescue ::LoadError
|
41
|
+
raise LoadError, "Could not load #{gem_name}. Please ensure that the #{gem_name} gem is installed."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/lato/version.rb
CHANGED
data/lib/lato.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
require "kaminari"
|
2
2
|
require "bootstrap"
|
3
3
|
require "browser"
|
4
|
-
require "
|
4
|
+
require "rotp"
|
5
|
+
require "rqrcode"
|
5
6
|
|
6
7
|
require "lato/version"
|
7
8
|
require "lato/engine"
|
8
9
|
require "lato/config"
|
9
10
|
require "lato/btstrap"
|
11
|
+
require "lato/dependency_helper"
|
10
12
|
|
11
13
|
module Lato
|
12
14
|
class << self
|
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: 3.
|
4
|
+
version: 3.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gregorio Galante
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-03-
|
11
|
+
date: 2024-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -95,7 +95,21 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: rqrcode
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rotp
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
115
|
- - ">="
|
@@ -108,6 +122,20 @@ dependencies:
|
|
108
122
|
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: eth
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
111
139
|
description: A Rails engine that includes what you need to build a new project!
|
112
140
|
email:
|
113
141
|
- me@gregoriogalante.com
|
@@ -162,6 +190,7 @@ files:
|
|
162
190
|
- app/models/lato/user.rb
|
163
191
|
- app/views/lato/account/_alert-accepted-privacy-policy-version.html.erb
|
164
192
|
- app/views/lato/account/_alert-accepted-terms-and-conditions-version.html.erb
|
193
|
+
- app/views/lato/account/_form-authenticator.html.erb
|
165
194
|
- app/views/lato/account/_form-destroy.html.erb
|
166
195
|
- app/views/lato/account/_form-password.html.erb
|
167
196
|
- app/views/lato/account/_form-user.html.erb
|
@@ -169,6 +198,7 @@ files:
|
|
169
198
|
- app/views/lato/account/index.html.erb
|
170
199
|
- app/views/lato/authentication/_fields-registration.html.erb
|
171
200
|
- app/views/lato/authentication/_form-accept-invitation.html.erb
|
201
|
+
- app/views/lato/authentication/_form-authenticator.html.erb
|
172
202
|
- app/views/lato/authentication/_form-recover-password.html.erb
|
173
203
|
- app/views/lato/authentication/_form-signin.html.erb
|
174
204
|
- app/views/lato/authentication/_form-signup.html.erb
|
@@ -176,6 +206,7 @@ files:
|
|
176
206
|
- app/views/lato/authentication/_form-verify-email.html.erb
|
177
207
|
- app/views/lato/authentication/_form-web3-signin.html.erb
|
178
208
|
- app/views/lato/authentication/accept_invitation.html.erb
|
209
|
+
- app/views/lato/authentication/authenticator.html.erb
|
179
210
|
- app/views/lato/authentication/recover_password.html.erb
|
180
211
|
- app/views/lato/authentication/signin.html.erb
|
181
212
|
- app/views/lato/authentication/signout.html.erb
|
@@ -226,9 +257,11 @@ files:
|
|
226
257
|
- db/migrate/20230823165716_create_lato_log_user_signups.rb
|
227
258
|
- db/migrate/20240222125124_add_web3_to_lato_users.rb
|
228
259
|
- db/migrate/20240222171418_add_indexes_on_lato_users_email.rb
|
260
|
+
- db/migrate/20240318074025_add_authenticator_secret_to_user.rb
|
229
261
|
- lib/lato.rb
|
230
262
|
- lib/lato/btstrap.rb
|
231
263
|
- lib/lato/config.rb
|
264
|
+
- lib/lato/dependency_helper.rb
|
232
265
|
- lib/lato/engine.rb
|
233
266
|
- lib/lato/version.rb
|
234
267
|
- lib/tasks/lato_tasks.rake
|