lato 0.1.0
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +95 -0
- data/Rakefile +8 -0
- data/app/assets/config/lato_manifest.js +5 -0
- data/app/assets/images/lato/user-150x150.jpg +0 -0
- data/app/assets/images/lato/user-300x300.jpg +0 -0
- data/app/assets/images/lato/user-600x600.jpg +0 -0
- data/app/assets/images/lato/user-900x900.jpg +0 -0
- data/app/assets/javascripts/lato/application.js +6 -0
- data/app/assets/javascripts/lato/controllers/application.js +9 -0
- data/app/assets/javascripts/lato/controllers/index.js +11 -0
- data/app/assets/javascripts/lato/controllers/lato_action_controller.js +92 -0
- data/app/assets/javascripts/lato/controllers/lato_aside_opener_controller.js +21 -0
- data/app/assets/javascripts/lato/controllers/lato_feedback_controller.js +13 -0
- data/app/assets/javascripts/lato/controllers/lato_form_controller.js +60 -0
- data/app/assets/javascripts/lato/controllers/lato_hello_controller.js +12 -0
- data/app/assets/javascripts/lato/controllers/lato_operation_controller.js +24 -0
- data/app/assets/stylesheets/lato/application.scss +73 -0
- data/app/controllers/concerns/lato/componentable.rb +52 -0
- data/app/controllers/concerns/lato/layoutable.rb +27 -0
- data/app/controllers/concerns/lato/sessionable.rb +45 -0
- data/app/controllers/lato/account_controller.rb +82 -0
- data/app/controllers/lato/application_controller.rb +21 -0
- data/app/controllers/lato/authentication_controller.rb +121 -0
- data/app/controllers/lato/operations_controller.rb +23 -0
- data/app/helpers/lato/application_helper.rb +5 -0
- data/app/helpers/lato/components_helper.rb +183 -0
- data/app/jobs/lato/application_job.rb +59 -0
- data/app/mailers/lato/application_mailer.rb +6 -0
- data/app/mailers/lato/user_mailer.rb +23 -0
- data/app/models/lato/application_record.rb +5 -0
- data/app/models/lato/operation.rb +96 -0
- data/app/models/lato/session.rb +36 -0
- data/app/models/lato/user.rb +164 -0
- data/app/views/lato/account/_alert-accepted-privacy-policy-version.html.erb +20 -0
- data/app/views/lato/account/_alert-accepted-terms-and-conditions-version.html.erb +20 -0
- data/app/views/lato/account/_form-destroy.html.erb +21 -0
- data/app/views/lato/account/_form-password.html.erb +28 -0
- data/app/views/lato/account/_form-user.html.erb +40 -0
- data/app/views/lato/account/index.html.erb +65 -0
- data/app/views/lato/authentication/_form-recover-password.html.erb +20 -0
- data/app/views/lato/authentication/_form-signin.html.erb +31 -0
- data/app/views/lato/authentication/_form-signup.html.erb +47 -0
- data/app/views/lato/authentication/_form-update-password.html.erb +30 -0
- data/app/views/lato/authentication/_form-verify-email.html.erb +22 -0
- data/app/views/lato/authentication/recover_password.html.erb +13 -0
- data/app/views/lato/authentication/signin.html.erb +13 -0
- data/app/views/lato/authentication/signout.html.erb +11 -0
- data/app/views/lato/authentication/signup.html.erb +13 -0
- data/app/views/lato/authentication/update_password.html.erb +13 -0
- data/app/views/lato/authentication/verify_email.html.erb +7 -0
- data/app/views/lato/components/_index.html.erb +89 -0
- data/app/views/lato/components/_navbar_nav_item.html.erb +5 -0
- data/app/views/lato/components/_operation.html.erb +68 -0
- data/app/views/lato/components/_page_head.html.erb +15 -0
- data/app/views/lato/components/_sidebar_nav_item.html.erb +5 -0
- data/app/views/lato/mailer/user/email_verification_mail.html.erb +9 -0
- data/app/views/lato/mailer/user/password_update_mail.html.erb +9 -0
- data/app/views/lato/operations/show.html.erb +3 -0
- data/app/views/layouts/lato/_action.html.erb +17 -0
- data/app/views/layouts/lato/_aside-opener.html.erb +7 -0
- data/app/views/layouts/lato/_content.html.erb +5 -0
- data/app/views/layouts/lato/_feedbacks.html.erb +16 -0
- data/app/views/layouts/lato/_footer.html.erb +11 -0
- data/app/views/layouts/lato/_mailer-foot_content.html.erb +2 -0
- data/app/views/layouts/lato/_mailer-head_content.html.erb +2 -0
- data/app/views/layouts/lato/_navbar-brand_content.html.erb +1 -0
- data/app/views/layouts/lato/_navbar-nav_content.html.erb +15 -0
- data/app/views/layouts/lato/_navbar.html.erb +16 -0
- data/app/views/layouts/lato/_sidebar-nav_content.html.erb +3 -0
- data/app/views/layouts/lato/_sidebar.html.erb +5 -0
- data/app/views/layouts/lato/application.html.erb +44 -0
- data/app/views/layouts/lato/mailer.html.erb +3 -0
- data/config/importmap.rb +8 -0
- data/config/locales/it.yml +235 -0
- data/config/routes.rb +35 -0
- data/db/migrate/20221022205744_create_lato_users.rb +14 -0
- data/db/migrate/20221118072130_create_lato_operations.rb +14 -0
- data/lib/lato/btstrap.rb +36 -0
- data/lib/lato/config.rb +39 -0
- data/lib/lato/engine.rb +13 -0
- data/lib/lato/version.rb +3 -0
- data/lib/lato.rb +27 -0
- data/lib/tasks/lato_tasks.rake +28 -0
- metadata +199 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Lato
|
|
2
|
+
class ApplicationController < ActionController::Base
|
|
3
|
+
include Lato::Sessionable
|
|
4
|
+
include Lato::Layoutable
|
|
5
|
+
include Lato::Componentable
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
session_root_path = Lato.config.session_root_path ? main_app.send(Lato.config.session_root_path) : lato.account_path
|
|
9
|
+
redirect_to @session.valid? ? session_root_path : lato.authentication_signin_path
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
protected
|
|
13
|
+
|
|
14
|
+
def respond_to_with_404
|
|
15
|
+
respond_to do |format|
|
|
16
|
+
format.html { render plain: '', status: :not_found }
|
|
17
|
+
format.json { render json: {}, status: :not_found }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
module Lato
|
|
2
|
+
class AuthenticationController < ApplicationController
|
|
3
|
+
before_action :not_authenticate_session, only: %i[signin signin_action signup signup_action]
|
|
4
|
+
before_action :authenticate_session, only: %i[signout signout_action]
|
|
5
|
+
before_action :find_user, only: %i[verify_email verify_email_action update_password update_password_action]
|
|
6
|
+
before_action :hide_sidebar
|
|
7
|
+
before_action :lock_signup_if_disabled, only: %i[signup signup_action]
|
|
8
|
+
|
|
9
|
+
def signin
|
|
10
|
+
@user = Lato::User.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def signin_action
|
|
14
|
+
@user = Lato::User.new
|
|
15
|
+
|
|
16
|
+
respond_to do |format|
|
|
17
|
+
if @user.signin(params.require(:user).permit(:email, :password))
|
|
18
|
+
session_create(@user.id)
|
|
19
|
+
|
|
20
|
+
format.html { redirect_to lato.root_path }
|
|
21
|
+
format.json { render json: @user }
|
|
22
|
+
else
|
|
23
|
+
format.html { render :signin, status: :unprocessable_entity }
|
|
24
|
+
format.json { render json: @user.errors, status: :unprocessable_entity }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def signup
|
|
30
|
+
@user = Lato::User.new
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def signup_action
|
|
34
|
+
@user = Lato::User.new(params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :accepted_privacy_policy_version, :accepted_terms_and_conditions_version))
|
|
35
|
+
|
|
36
|
+
respond_to do |format|
|
|
37
|
+
if @user.save
|
|
38
|
+
session_create(@user.id)
|
|
39
|
+
|
|
40
|
+
format.html { redirect_to lato.root_path }
|
|
41
|
+
format.json { render json: @user }
|
|
42
|
+
else
|
|
43
|
+
format.html { render :signup, status: :unprocessable_entity }
|
|
44
|
+
format.json { render json: @user.errors, status: :unprocessable_entity }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def signout; end
|
|
50
|
+
|
|
51
|
+
def signout_action
|
|
52
|
+
session_destroy
|
|
53
|
+
|
|
54
|
+
respond_to do |format|
|
|
55
|
+
format.html { redirect_to lato.root_path }
|
|
56
|
+
format.json { render plain: '' }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def verify_email
|
|
61
|
+
@code = params[:code]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def verify_email_action
|
|
65
|
+
respond_to do |format|
|
|
66
|
+
if @user.verify_email(params.require(:user).permit(:code))
|
|
67
|
+
format.html { redirect_to lato.root_path, notice: 'Indirizzo email verificato correttamente' }
|
|
68
|
+
format.json { render json: @user }
|
|
69
|
+
else
|
|
70
|
+
format.html { render :verify_email, status: :unprocessable_entity }
|
|
71
|
+
format.json { render json: @user.errors, status: :unprocessable_entity }
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def recover_password
|
|
77
|
+
@user = Lato::User.new
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def recover_password_action
|
|
81
|
+
@user = Lato::User.new
|
|
82
|
+
|
|
83
|
+
respond_to do |format|
|
|
84
|
+
if @user.request_recover_password(params.require(:user).permit(:email))
|
|
85
|
+
format.html { redirect_to lato.authentication_update_password_path(id: @user.id) }
|
|
86
|
+
format.json { render json: @user }
|
|
87
|
+
else
|
|
88
|
+
format.html { render :recover_password, status: :unprocessable_entity }
|
|
89
|
+
format.json { render json: @user.errors, status: :unprocessable_entity }
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def update_password; end
|
|
95
|
+
|
|
96
|
+
def update_password_action
|
|
97
|
+
respond_to do |format|
|
|
98
|
+
if @user.update_password(params.require(:user).permit(:code, :password, :password_confirmation))
|
|
99
|
+
format.html { redirect_to lato.authentication_signin_path, notice: 'La tua password è stata aggiornata correttamente' }
|
|
100
|
+
format.json { render json: @user }
|
|
101
|
+
else
|
|
102
|
+
format.html { render :update_password, status: :unprocessable_entity }
|
|
103
|
+
format.json { render json: @user.errors, status: :unprocessable_entity }
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
|
|
110
|
+
def find_user
|
|
111
|
+
@user = User.find_by(id: params[:id])
|
|
112
|
+
respond_to_with_404 unless @user
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def lock_signup_if_disabled
|
|
116
|
+
return unless Lato.config.auth_disable_signup
|
|
117
|
+
|
|
118
|
+
respond_to_with_404
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Lato
|
|
2
|
+
class OperationsController < ApplicationController
|
|
3
|
+
before_action :authenticate_session
|
|
4
|
+
|
|
5
|
+
def show
|
|
6
|
+
@operation = Lato::Operation.find(params[:id])
|
|
7
|
+
return unless validate_user_access_to_operation
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def validate_user_access_to_operation
|
|
13
|
+
return true if @operation.lato_user_id == @session.user_id
|
|
14
|
+
|
|
15
|
+
respond_to do |format|
|
|
16
|
+
format.html { redirect_to lato.root_path }
|
|
17
|
+
format.json { render plain: '', status: :unauthorized }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
false
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
module Lato
|
|
2
|
+
module ComponentsHelper
|
|
3
|
+
# Navbar
|
|
4
|
+
##
|
|
5
|
+
|
|
6
|
+
def lato_navbar_nav_item(key, path, &block)
|
|
7
|
+
active = request.path == path
|
|
8
|
+
active = @navbar_key == key if @navbar_key
|
|
9
|
+
|
|
10
|
+
render 'lato/components/navbar_nav_item', active: active, path: path do
|
|
11
|
+
yield if block
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Sidebar
|
|
16
|
+
##
|
|
17
|
+
|
|
18
|
+
def lato_sidebar_nav_item(key, path, &block)
|
|
19
|
+
active = request.path == path
|
|
20
|
+
active = @sidebar_key == key if @sidebar_key
|
|
21
|
+
|
|
22
|
+
render 'lato/components/sidebar_nav_item', active: active, path: path do
|
|
23
|
+
yield if block
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Page head
|
|
28
|
+
##
|
|
29
|
+
|
|
30
|
+
def lato_page_head(title, breadcrumbs = [], &block)
|
|
31
|
+
render 'lato/components/page_head', title: title, breadcrumbs: breadcrumbs do
|
|
32
|
+
yield if block
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Index
|
|
37
|
+
##
|
|
38
|
+
|
|
39
|
+
def lato_index(collection, options = {})
|
|
40
|
+
key = options[:key] || 'default'
|
|
41
|
+
|
|
42
|
+
@_lato_index ||= {}
|
|
43
|
+
@_lato_index[key] ||= {}
|
|
44
|
+
columns = options[:columns] || @_lato_index[key][:columns] || collection.column_names || []
|
|
45
|
+
sortable_columns = @_lato_index[key][:sortable_columns] || []
|
|
46
|
+
searchable_columns = @_lato_index[key][:searchable_columns] || []
|
|
47
|
+
model_name_underscore = collection.model.name.underscore
|
|
48
|
+
|
|
49
|
+
render(
|
|
50
|
+
'lato/components/index',
|
|
51
|
+
key: key,
|
|
52
|
+
collection: collection,
|
|
53
|
+
columns: columns,
|
|
54
|
+
sortable_columns: sortable_columns,
|
|
55
|
+
searchable_columns: searchable_columns,
|
|
56
|
+
model_name_underscore: model_name_underscore,
|
|
57
|
+
custom_actions: options[:custom_actions] || {}
|
|
58
|
+
)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Operation
|
|
62
|
+
##
|
|
63
|
+
|
|
64
|
+
def lato_operation(operation)
|
|
65
|
+
render(
|
|
66
|
+
'lato/components/operation',
|
|
67
|
+
operation: operation
|
|
68
|
+
)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Forms
|
|
72
|
+
##
|
|
73
|
+
|
|
74
|
+
def _lato_form_input_options(form, key, options, action_change_event, classes = '')
|
|
75
|
+
# setup classes
|
|
76
|
+
options[:class] ||= []
|
|
77
|
+
options[:class].push(classes)
|
|
78
|
+
options[:class].push('is-invalid') unless form.object.errors[key].blank?
|
|
79
|
+
|
|
80
|
+
# setup stimulus
|
|
81
|
+
options[:data] ||= {}
|
|
82
|
+
options[:data][:action] ||= ''
|
|
83
|
+
options[:data][:action] += " #{action_change_event}->lato-form#onInputChange"
|
|
84
|
+
options[:data][:lato_form_target] = 'input'
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def lato_form_notices(options = {})
|
|
88
|
+
return unless notice
|
|
89
|
+
|
|
90
|
+
options[:class] ||= []
|
|
91
|
+
options[:class] += %w[alert alert-success]
|
|
92
|
+
options[:class] += %w[alert-dismissible fade show] unless options[:fixed]
|
|
93
|
+
|
|
94
|
+
content_tag :div, options do
|
|
95
|
+
concat notice
|
|
96
|
+
concat button_tag('', type: 'button', class: 'btn-close', data: { bs_dismiss: 'alert' }) unless options[:fixed]
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def lato_form_errors(instance, options = {})
|
|
101
|
+
return unless instance.errors.any?
|
|
102
|
+
|
|
103
|
+
options[:class] ||= []
|
|
104
|
+
options[:class] += %w[alert alert-danger]
|
|
105
|
+
options[:class] += %w[alert-dismissible fade show] unless options[:fixed]
|
|
106
|
+
|
|
107
|
+
errors_list = content_tag(:ul, class: %w[mb-0 ps-3]) do
|
|
108
|
+
instance.errors.collect do |error|
|
|
109
|
+
content_tag :li, error.full_message
|
|
110
|
+
end.join.html_safe
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
content_tag :div, options do
|
|
114
|
+
concat content_tag(:span, 'Si sono verificati i seguenti errori:')
|
|
115
|
+
concat errors_list
|
|
116
|
+
concat button_tag('', type: 'button', class: 'btn-close', data: { bs_dismiss: 'alert' }) unless options[:fixed]
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def lato_form_item_label(form, key, label = nil, options = {})
|
|
121
|
+
options[:class] ||= []
|
|
122
|
+
options[:class].push('form-label')
|
|
123
|
+
|
|
124
|
+
form.label key, label, options
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def lato_form_item_input_text(form, key, options = {})
|
|
128
|
+
_lato_form_input_options(form, key, options, :keyup, 'form-control')
|
|
129
|
+
|
|
130
|
+
form.text_field key, options
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def lato_form_item_input_email(form, key, options = {})
|
|
134
|
+
_lato_form_input_options(form, key, options, :keyup, 'form-control')
|
|
135
|
+
|
|
136
|
+
form.email_field key, options
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def lato_form_item_input_password(form, key, options = {})
|
|
140
|
+
_lato_form_input_options(form, key, options, :keyup, 'form-control')
|
|
141
|
+
|
|
142
|
+
form.password_field key, options
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def lato_form_item_input_check(form, key, label, options = {})
|
|
146
|
+
_lato_form_input_options(form, key, options, :change, 'form-check-input')
|
|
147
|
+
|
|
148
|
+
# TO-DO: Trovare il modo di calcolare l'id dato da rails a check_input_tag e metterlo nell'attributo :for di check_label_tag
|
|
149
|
+
|
|
150
|
+
content_tag :div, class: 'form-check' do
|
|
151
|
+
concat form.check_box(key, options)
|
|
152
|
+
concat label_tag(key, raw(label), class: 'form-check-label')
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def lato_form_submit(form, label, options = {})
|
|
157
|
+
options[:class] ||= []
|
|
158
|
+
options[:class].push('btn')
|
|
159
|
+
options[:class].push('btn-primary')
|
|
160
|
+
|
|
161
|
+
options[:data] ||= {}
|
|
162
|
+
options[:data][:lato_form_target] = 'submit'
|
|
163
|
+
|
|
164
|
+
form.submit label, options
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Data
|
|
168
|
+
##
|
|
169
|
+
|
|
170
|
+
def lato_data_badge(label, color = 'primary')
|
|
171
|
+
content_tag :span, label, class: "badge rounded-pill bg-#{color}"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def lato_data_user(label, image_url = nil)
|
|
175
|
+
image_url ||= image_path('lato/user-150x150')
|
|
176
|
+
|
|
177
|
+
content_tag :div, class: 'd-flex align-items-center' do
|
|
178
|
+
concat content_tag :div, '', class: 'border border-2 rounded-circle me-2', style: "background-position: center; background-size: cover; background-repeat: no-repeat; background-image: url(#{image_url}); width: 30px; height: 30px;"
|
|
179
|
+
concat content_tag :small, label, class: 'text-black'
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Lato
|
|
2
|
+
# ApplicationJob.
|
|
3
|
+
class ApplicationJob < ActiveJob::Base
|
|
4
|
+
around_perform :manage_operation
|
|
5
|
+
|
|
6
|
+
protected
|
|
7
|
+
|
|
8
|
+
def operation?
|
|
9
|
+
!!@operation
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def update_operation_percentage(percentage)
|
|
13
|
+
return false unless operation?
|
|
14
|
+
|
|
15
|
+
@operation.update(
|
|
16
|
+
percentage: percentage
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def save_operation_output_file(file_path)
|
|
23
|
+
return false unless operation?
|
|
24
|
+
|
|
25
|
+
file = File.open(file_path)
|
|
26
|
+
file_name = File.basename(file_path)
|
|
27
|
+
@operation.output_file.attach(
|
|
28
|
+
io: file,
|
|
29
|
+
filename: file_name
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def save_operation_output_message(message)
|
|
36
|
+
return false unless operation?
|
|
37
|
+
|
|
38
|
+
@operation.update(
|
|
39
|
+
active_job_output: @operation.active_job_output.merge(_message: message)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
true
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def manage_operation
|
|
48
|
+
@operation = Lato::Operation.find(arguments.first[:_operation_id]) if arguments.first && arguments.first.is_a?(Hash) && !arguments.first[:_operation_id].blank?
|
|
49
|
+
@operation&.running
|
|
50
|
+
|
|
51
|
+
begin
|
|
52
|
+
yield
|
|
53
|
+
@operation&.completed
|
|
54
|
+
rescue StandardError => e
|
|
55
|
+
@operation&.failed(e.message)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Lato
|
|
2
|
+
class UserMailer < ApplicationMailer
|
|
3
|
+
def email_verification_mail(user_id, code)
|
|
4
|
+
@user = Lato::User.find(user_id)
|
|
5
|
+
@code = code
|
|
6
|
+
mail(
|
|
7
|
+
to: @user.email,
|
|
8
|
+
subject: 'Conferma il tuo indirizzo email',
|
|
9
|
+
template_path: 'lato/mailer/user'
|
|
10
|
+
)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def password_update_mail(user_id, code)
|
|
14
|
+
@user = Lato::User.find(user_id)
|
|
15
|
+
@code = code
|
|
16
|
+
mail(
|
|
17
|
+
to: @user.email,
|
|
18
|
+
subject: 'Imposta una nuova password',
|
|
19
|
+
template_path: 'lato/mailer/user'
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module Lato
|
|
2
|
+
class Operation < ApplicationRecord
|
|
3
|
+
enum status: {
|
|
4
|
+
created: 0,
|
|
5
|
+
running: 1,
|
|
6
|
+
completed: 2,
|
|
7
|
+
failed: 3
|
|
8
|
+
}, _suffix: true
|
|
9
|
+
|
|
10
|
+
has_one_attached :input_file
|
|
11
|
+
has_one_attached :output_file
|
|
12
|
+
|
|
13
|
+
# Hooks
|
|
14
|
+
##
|
|
15
|
+
|
|
16
|
+
before_create do
|
|
17
|
+
self.status = :created
|
|
18
|
+
self.active_job_input ||= {}
|
|
19
|
+
self.active_job_output ||= {}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Questions
|
|
23
|
+
##
|
|
24
|
+
|
|
25
|
+
def finished?
|
|
26
|
+
completed_status? || failed_status?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def output_message?
|
|
30
|
+
active_job_output && !active_job_output['_message'].blank?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def output_error?
|
|
34
|
+
active_job_output && !active_job_output['_error'].blank?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def output_file?
|
|
38
|
+
output_file.attached?
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Helpers
|
|
42
|
+
##
|
|
43
|
+
|
|
44
|
+
def output_error
|
|
45
|
+
active_job_output['_error']
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def output_message
|
|
49
|
+
active_job_output['_message']
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Operations
|
|
53
|
+
|
|
54
|
+
def start
|
|
55
|
+
begin
|
|
56
|
+
active_job_name.constantize.perform_later(active_job_input.merge(_operation_id: id))
|
|
57
|
+
rescue StandardError
|
|
58
|
+
errors.add(:base, 'Impossibile eseguire il job')
|
|
59
|
+
return false
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
true
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def running
|
|
66
|
+
update(status: :running)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def failed(error = nil)
|
|
70
|
+
update(
|
|
71
|
+
status: :failed,
|
|
72
|
+
closed_at: Time.now,
|
|
73
|
+
active_job_output: error ? active_job_output.merge(_error: error) : active_job_output
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def completed(message = nil)
|
|
78
|
+
update(
|
|
79
|
+
status: :completed,
|
|
80
|
+
closed_at: Time.now,
|
|
81
|
+
active_job_output: message ? active_job_output.merge(_message: message) : active_job_output
|
|
82
|
+
)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Class
|
|
86
|
+
##
|
|
87
|
+
|
|
88
|
+
def self.generate(active_job_name, active_job_input = {}, user_id = nil)
|
|
89
|
+
Operation.create(
|
|
90
|
+
active_job_name: active_job_name,
|
|
91
|
+
active_job_input: active_job_input,
|
|
92
|
+
lato_user_id: user_id
|
|
93
|
+
)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Lato
|
|
2
|
+
class Session
|
|
3
|
+
def initialize(session)
|
|
4
|
+
@session = session
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# Questions
|
|
8
|
+
##
|
|
9
|
+
|
|
10
|
+
def valid?
|
|
11
|
+
!@session.blank?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def really_valid?
|
|
15
|
+
!!user
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Helpers
|
|
19
|
+
##
|
|
20
|
+
|
|
21
|
+
def user
|
|
22
|
+
@user ||= Lato::User.find_by(id: @session)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def user_id
|
|
26
|
+
@session
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Class
|
|
30
|
+
##
|
|
31
|
+
|
|
32
|
+
def self.generate_session_per_user(user_id)
|
|
33
|
+
user_id
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|