lesli 5.0.3 → 5.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/lesli_manifest.js +2 -1
  3. data/app/assets/images/lesli/brand/app-logo2.svg +52 -0
  4. data/app/assets/javascripts/lesli/users/confirmations.js +32 -0
  5. data/app/assets/javascripts/lesli/users/passwords.js +3 -3
  6. data/app/assets/javascripts/lesli/users/registrations.js +3 -3
  7. data/app/assets/javascripts/lesli/users/sessions.js +3 -3
  8. data/app/assets/stylesheets/lesli/users/confirmations.scss +28 -6
  9. data/app/controllers/lesli/application_controller.rb +3 -3
  10. data/app/controllers/lesli/application_lesli_controller.rb +2 -2
  11. data/app/controllers/lesli/interfaces/application/authorization.rb +2 -2
  12. data/app/controllers/lesli/interfaces/application/logger.rb +14 -38
  13. data/app/controllers/lesli/interfaces/application/requester.rb +1 -1
  14. data/app/controllers/lesli/roles_controller.rb +3 -1
  15. data/app/controllers/lesli/shared/dashboards_controller.rb +308 -0
  16. data/app/controllers/users/confirmations_controller.rb +63 -27
  17. data/app/controllers/users/passwords_controller.rb +67 -30
  18. data/app/controllers/users/sessions_controller.rb +2 -4
  19. data/app/helpers/lesli/general_helper.rb +1 -1
  20. data/app/helpers/lesli/navigation_helper.rb +17 -16
  21. data/app/lib/lesli/system.rb +14 -5
  22. data/app/mailers/lesli/application_lesli_mailer.rb +8 -19
  23. data/app/mailers/lesli/devise_mailer.rb +29 -3
  24. data/app/models/concerns/account_initializer.rb +100 -0
  25. data/app/models/concerns/{user_guard.rb → user_security.rb} +7 -8
  26. data/app/models/lesli/account.rb +9 -26
  27. data/app/models/lesli/application_lesli_record.rb +2 -1
  28. data/app/models/lesli/descriptor/privilege.rb +38 -0
  29. data/app/models/lesli/descriptor.rb +18 -1
  30. data/app/models/lesli/role/power.rb +70 -0
  31. data/app/models/lesli/role/privilege.rb +38 -0
  32. data/app/models/lesli/role.rb +20 -15
  33. data/app/models/lesli/shared/dashboard.rb +162 -0
  34. data/app/models/lesli/system_controller.rb +1 -0
  35. data/app/models/lesli/user/{role.rb → power.rb} +1 -1
  36. data/app/{services/lesli/role_service.rb → models/lesli/user/setting.rb} +10 -9
  37. data/app/models/lesli/user.rb +11 -20
  38. data/app/operators/lesli/controller_operator.rb +148 -0
  39. data/app/operators/lesli/descriptor_privilege_operator.rb +75 -0
  40. data/app/operators/lesli/role_power_operator.rb +108 -0
  41. data/app/operators/lesli/user_registration_operator.rb +121 -0
  42. data/app/services/lesli/user_service.rb +2 -4
  43. data/app/services/lesli/{user/session_service.rb → user_session_service.rb} +11 -4
  44. data/app/views/devise/confirmations/new.html.erb +0 -14
  45. data/app/views/devise/confirmations/show.html.erb +63 -0
  46. data/app/views/devise/passwords/edit.html.erb +78 -24
  47. data/app/views/devise/passwords/new.html.erb +2 -3
  48. data/app/views/lesli/emails/devise_mailer/confirmation_instructions.html.erb +1 -1
  49. data/app/views/lesli/emails/devise_mailer/reset_password_instructions.html.erb +23 -0
  50. data/app/views/lesli/partials/_application-lesli-engines.html.erb +1 -1
  51. data/app/views/lesli/partials/_application-lesli-header.html.erb +3 -1
  52. data/app/views/lesli/partials/_application-lesli-icons.html.erb +1 -1
  53. data/config/initializers/devise.rb +2 -0
  54. data/config/locales/translations.en.yml +13 -3
  55. data/config/locales/translations.es.yml +13 -3
  56. data/config/routes.rb +4 -2
  57. data/db/migrate/v1.0/0010000110_create_lesli_accounts.rb +2 -0
  58. data/db/{tables/0010001010_create_account_settings.rb → migrate/v1.0/0010001010_create_lesli_account_settings.rb} +5 -5
  59. data/db/{tables/0010003110_create_user_settings.rb → migrate/v1.0/0010003110_create_lesli_user_settings.rb} +4 -4
  60. data/db/migrate/v1.0/0010003210_create_lesli_user_sessions.rb +6 -2
  61. data/db/migrate/v1.0/{0010003410_create_lesli_user_roles.rb → 0010003410_create_lesli_user_powers.rb} +4 -4
  62. data/db/migrate/v1.0/0010005010_create_lesli_descriptors.rb +1 -1
  63. data/db/migrate/v1.0/{0010003910_create_lesli_user_agents.rb → 0010005510_create_lesli_role_powers.rb} +7 -9
  64. data/db/{tables/0010005710_create_role_privileges.rb → migrate/v1.0/0010005710_create_lesli_role_privileges.rb} +6 -6
  65. data/db/seed/development/users.rb +3 -4
  66. data/db/seed/tools.rb +4 -4
  67. data/db/seeds.rb +16 -29
  68. data/lib/lesli/engine.rb +33 -10
  69. data/lib/lesli/version.rb +1 -1
  70. data/lib/mailer_previews/devise_mailer_preview.rb +7 -0
  71. data/lib/sass/lesli/bulma/loader.scss +3 -0
  72. data/lib/sass/lesli/layouts/application-navbar.scss +1 -1
  73. data/lib/sass/lesli/pages/devise-simple.scss +2 -1
  74. data/lib/tasks/lesli/controllers.rake +1 -94
  75. data/lib/tasks/lesli/db.rake +43 -3
  76. data/lib/tasks/lesli/dev.rake +66 -0
  77. data/lib/tasks/lesli/engine.rake +59 -0
  78. data/lib/tasks/lesli/privileges.rake +54 -0
  79. data/lib/tasks/lesli_tasks.rake +5 -0
  80. data/lib/vue/application.js +11 -3
  81. data/lib/vue/devise/passwords.js +7 -7
  82. data/lib/vue/devise/registrations.js +2 -2
  83. data/lib/vue/devise/sessions.js +11 -6
  84. data/lib/vue/layouts/application-header.vue +15 -3
  85. data/lib/vue/shared/dashboards/apps/edit.vue +215 -0
  86. data/lib/vue/{apps → shared}/dashboards/apps/index.vue +3 -5
  87. data/lib/vue/{apps → shared}/dashboards/apps/show.vue +26 -16
  88. data/lib/vue/{apps → shared}/dashboards/components/form.vue +31 -43
  89. data/lib/vue/shared/stores/dashboard.js +251 -0
  90. data/lib/vue/stores/translations.json +24 -72
  91. data/lib/vue/stores/{user.js → users.js} +1 -1
  92. data/lib/webpack/base.js +3 -2
  93. data/lib/webpack/core.js +2 -1
  94. data/readme.md +23 -7
  95. metadata +63 -65
  96. data/app/models/concerns/account_engines.rb +0 -249
  97. data/app/models/concerns/user_polyfill.rb +0 -134
  98. data/db/migrate/v1.0/0010001510_create_lesli_account_requests.rb +0 -45
  99. data/db/migrate/v1.0/0010003810_create_lesli_user_requests.rb +0 -44
  100. data/db/tables/0010005510_create_role_descriptors.rb +0 -44
  101. data/lib/vue/apps/dashboards/apps/edit.vue +0 -105
  102. data/lib/vue/apps/dashboards/components/preview.vue +0 -172
  103. /data/app/assets/icons/lesli/{cloud-vault.svg → cloud-guard.svg} +0 -0
  104. /data/lib/vue/{apps → shared}/cloudobjects/action.vue +0 -0
  105. /data/lib/vue/{apps → shared}/cloudobjects/discussion/content.vue +0 -0
  106. /data/lib/vue/{apps → shared}/cloudobjects/discussion/element.vue +0 -0
  107. /data/lib/vue/{apps → shared}/cloudobjects/discussion/filters.vue +0 -0
  108. /data/lib/vue/{apps → shared}/cloudobjects/discussion/new.vue +0 -0
  109. /data/lib/vue/{apps → shared}/cloudobjects/discussion.vue +0 -0
  110. /data/lib/vue/{apps → shared}/cloudobjects/file/grid.vue +0 -0
  111. /data/lib/vue/{apps → shared}/cloudobjects/file/list.vue +0 -0
  112. /data/lib/vue/{apps → shared}/cloudobjects/file.vue +0 -0
  113. /data/lib/vue/{apps → shared}/dashboards/apps/new.vue +0 -0
  114. /data/lib/vue/{apps → shared}/workflows2/apps/actions/form.vue +0 -0
  115. /data/lib/vue/{apps → shared}/workflows2/apps/actions/forms/chatroom-form.vue +0 -0
  116. /data/lib/vue/{apps → shared}/workflows2/apps/actions/forms/cloud-object-clone-form.vue +0 -0
  117. /data/lib/vue/{apps → shared}/workflows2/apps/actions/forms/cloud-object-file-form.vue +0 -0
  118. /data/lib/vue/{apps → shared}/workflows2/apps/actions/forms/email-form.vue +0 -0
  119. /data/lib/vue/{apps → shared}/workflows2/apps/actions/forms/notification-form.vue +0 -0
  120. /data/lib/vue/{apps → shared}/workflows2/apps/actions/forms/send-cloud-object-file.vue +0 -0
  121. /data/lib/vue/{apps → shared}/workflows2/apps/actions/forms/task-form.vue +0 -0
  122. /data/lib/vue/{apps → shared}/workflows2/apps/actions/index.vue +0 -0
  123. /data/lib/vue/{apps → shared}/workflows2/apps/checks/form.vue +0 -0
  124. /data/lib/vue/{apps → shared}/workflows2/apps/checks/index.vue +0 -0
  125. /data/lib/vue/{apps → shared}/workflows2/apps/index.vue +0 -0
  126. /data/lib/vue/{apps → shared}/workflows2/apps/new.vue +0 -0
  127. /data/lib/vue/{apps → shared}/workflows2/apps/show.vue +0 -0
  128. /data/lib/vue/{apps → shared}/workflows2/components/associations.vue +0 -0
  129. /data/lib/vue/{apps → shared}/workflows2/components/chart.vue +0 -0
  130. /data/lib/vue/{apps → shared}/workflows2/components/workflow-form.vue +0 -0
  131. /data/lib/vue/{apps → shared}/workflows2/components/workflow-status-dropdown.vue +0 -0
@@ -17,7 +17,7 @@ GNU General Public License for more details.
17
17
  You should have received a copy of the GNU General Public License
18
18
  along with this program. If not, see http://www.gnu.org/licenses/.
19
19
 
20
- Lesli · Ruby on Rails SaaS development platform.
20
+ Lesli · Ruby on Rails SaaS Development Framework.
21
21
 
22
22
  Made with ♥ by https://www.lesli.tech
23
23
  Building a better future, one line of code at a time.
@@ -27,7 +27,7 @@ Building a better future, one line of code at a time.
27
27
  @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
28
28
 
29
29
  // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
- // ·
30
+ // ·
31
31
  =end
32
32
 
33
33
  module Lesli
@@ -69,10 +69,10 @@ module Lesli
69
69
  # allowed core methods:
70
70
  # [:index, :create, :update, :destroy, :new, :show, :edit, :options, :search, :resources]
71
71
  def authorize_privileges
72
- return true
72
+
73
73
  # check if user has access to the requested controller
74
74
  # this search is over all the privileges for all the roles of the user
75
- granted = current_user.has_privileges?(params[:controller], params[:action])
75
+ granted = current_user.has_privileges_for?(params[:controller], params[:action])
76
76
 
77
77
  # get the path to which the user is limited to
78
78
  limited_path = current_user.has_role_limited_to_path?
@@ -64,15 +64,14 @@ module Lesli
64
64
 
65
65
  def log_account_requests
66
66
  return unless Lesli.config.security.dig(:enable_analytics)
67
+ return unless defined?(LesliAudit)
67
68
  return unless current_user
68
- return unless session[:user_session_id]
69
69
 
70
70
  # Try to save a unique record for this request configuration
71
- current_user.account.requests.upsert(
71
+ current_user.account.audit.account_requests.upsert(
72
72
  {
73
73
  request_controller: controller_path,
74
74
  request_action: action_name,
75
- request_method: request.method,
76
75
  request_count: 1
77
76
  },
78
77
 
@@ -80,7 +79,7 @@ module Lesli
80
79
  unique_by: %i[request_controller request_action created_at account_id],
81
80
 
82
81
  # if request id is not unique, increase the counter for this configuration
83
- on_duplicate: Arel.sql("request_count = lesli_account_requests.request_count + 1")
82
+ on_duplicate: Arel.sql("request_count = lesli_audit_account_requests.request_count + 1")
84
83
  )
85
84
  end
86
85
 
@@ -88,55 +87,32 @@ module Lesli
88
87
  # this is disabled by default in the settings file
89
88
  def log_user_requests
90
89
  return unless Lesli.config.security.dig(:enable_analytics)
90
+ return unless defined?(LesliAudit)
91
91
  return unless current_user
92
92
  return unless session[:user_session_id]
93
-
93
+
94
94
  # Try to save a unique record for this request configuration
95
- current_user.requests.upsert(
95
+ current_user.account.audit.user_requests.upsert(
96
96
  {
97
- request_count: 1,
98
- session_id: session[:user_session_id]
97
+ request_controller: controller_path,
98
+ request_action: action_name,
99
+ session_id: session[:user_session_id],
100
+ user_id: current_user.id,
101
+ request_count: 1
99
102
  },
100
-
103
+
101
104
  # group of columns to consider a request as unique
102
- unique_by: %i[created_at user_id session_id],
105
+ unique_by: %i[request_controller request_action created_at user_id session_id],
103
106
 
104
107
  # if request id is not unique
105
108
  # - increase the counter for this configuration
106
109
  # - update the datetime of the last request
107
110
  on_duplicate: Arel.sql(
108
- 'request_count = lesli_user_requests.request_count + 1,'\
109
- 'updated_at = current_timestamp'
111
+ 'request_count = lesli_audit_user_requests.request_count + 1'
110
112
  )
111
113
  )
112
114
  end
113
115
 
114
- # Track user agents
115
- # this is disabled by default in the settings file
116
- def log_user_agent
117
- return unless Lesli.config.security.dig(:enable_analytics)
118
- return unless current_user
119
- return unless session[:user_session_id]
120
-
121
- user_agent = get_user_agent(false)
122
-
123
- # Try to save a unique record for this agent configuration
124
- current_user.agents.upsert(
125
- {
126
- os: user_agent[:os] || "unknown",
127
- platform: user_agent[:platform] || "unknown",
128
- browser: user_agent[:browser] || "unknown",
129
- version: user_agent[:version] || "unknown",
130
- count: 1
131
- },
132
- # group of columns to consider a agent as unique
133
- unique_by: %i[platform os browser version user_id],
134
-
135
- # if request id is not unique, increase the counter for this configuration
136
- on_duplicate: Arel.sql("count = lesli_user_agents.count + 1")
137
- )
138
- end
139
-
140
116
  # Track specific account activity
141
117
  # this is disabled by default in the settings file
142
118
  def log_account_activity(system_module, system_process, title = nil, payload = nil, description = nil)
@@ -69,7 +69,7 @@ module Lesli
69
69
  @query = {
70
70
  search: params[:search] || nil,
71
71
  pagination: {
72
- perPage: (params[:perPage] ? params[:perPage].to_i : 15),
72
+ perPage: (params[:perPage] ? params[:perPage].to_i : 10),
73
73
  page: (params[:page] ? params[:page].to_i : 1)
74
74
  },
75
75
  order: {
@@ -36,7 +36,9 @@ module Lesli
36
36
 
37
37
  def list
38
38
  respond_to do |format|
39
- format.json { respond_with_successful(RoleService.new(current_user, query).list(params)) }
39
+ format.json {
40
+ respond_with_successful(Role.list(current_user, query, params))
41
+ }
40
42
  end
41
43
  end
42
44
  end
@@ -0,0 +1,308 @@
1
+ =begin
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2023, Lesli Technologies, S. A.
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see http://www.gnu.org/licenses/.
19
+
20
+ Lesli · Ruby on Rails SaaS Development Framework.
21
+
22
+ Made with ♥ by https://www.lesli.tech
23
+ Building a better future, one line of code at a time.
24
+
25
+ @contact hello@lesli.tech
26
+ @website https://www.lesli.tech
27
+ @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
28
+
29
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
+ // ·
31
+ =end
32
+ module Lesli
33
+ module Shared
34
+ class DashboardsController < ApplicationLesliController
35
+ before_action :set_dashboard, only: [:show, :update, :destroy, :options]
36
+
37
+ def index
38
+ respond_to do |format|
39
+ format.html {}
40
+ format.json do
41
+ dynamic_info = self.class.dynamic_info
42
+ model = dynamic_info[:model]
43
+
44
+ dashboards = model.list(current_user, @query)
45
+ respond_with_successful(dashboards)
46
+ end
47
+ end
48
+ end
49
+
50
+ def show
51
+ respond_to do |format|
52
+ format.html {}
53
+ format.json do
54
+ return respond_with_not_found unless @dashboard
55
+ respond_with_successful(@dashboard.show)
56
+ end
57
+ end
58
+ end
59
+
60
+ def new
61
+ end
62
+
63
+ def edit
64
+ end
65
+
66
+ # @controller_action_param :name [String] The name of the new dashboard
67
+ # @controller_action_param :default [Boolean] A flag that marks this dashboard as default or not. The default dashboard is the dashboard all users will have access to on the root page
68
+ # @controller_action_param :main [Boolean] A flag that marks this dashboard as main. Since a user can have multiple dashboards, this is the one they will see on the root page when loging in
69
+ # @controller_action_param :roles_id [Integer] The id of the role that will have access to this dashboard
70
+ # @controller_action_param :user_main_id [Integer] The id of the user
71
+ # @controller_action_param :component_attributes [Array] Array of hashes that represent the attributes of the dashboard components
72
+ # @controller_action_param :component_attributes.name [String] The name of this component given to the user
73
+ # @controller_action_param :component_attributes.component_id [String] An enum value, that indicates which component is being loaded
74
+ # @controller_action_param :component_attributes.layout [Integer] Number from 1 to 12, bigger numbers default to 12, smallest numbers default to 1. The column size that the UI component will use
75
+ # @controller_action_param :component_attributes.index [Integer] The position of the component in the layout
76
+ # @controller_action_param :component_attributes.configuration [Hash] Specific filtering and configuration of the components
77
+ # @return [Json] Json that contains wheter the creation of the dashboard was successful or not.
78
+ # If it is not successful, it returns an error message
79
+ # @description Creates a new dashboard associated to the *current_user*'s *account*
80
+ # @example
81
+ # # Executing this controller's action from javascript's frontend
82
+ # let data = {
83
+ # dashboard: {
84
+ # name: "Sales Dashboard",
85
+ # default: false,
86
+ # roles_id: 3,
87
+ # components_attributes: [
88
+ # {
89
+ # name: 'Projects Count',
90
+ # component_id: projects_component,
91
+ # layout: 4,
92
+ # index: 3,
93
+ # configuration: {}
94
+ # }, {
95
+ # name: 'New Customers Count',
96
+ # component_id: new_customers_component,
97
+ # layout: 4,
98
+ # index: 3,
99
+ # configuration: {}
100
+ # }
101
+ # ]
102
+ # }
103
+ # };
104
+ # this.http.post('127.0.0.1/help/dashboards', data);
105
+ def create
106
+ dynamic_info = self.class.dynamic_info
107
+ module_name = dynamic_info[:module_name]
108
+ model = dynamic_info[:model]
109
+ full_module_name = dynamic_info[:full_module_name].underscore
110
+
111
+ dashboard = model.new(dashboard_params)
112
+ dashboard["#{full_module_name}_account_id".to_sym] = current_user.account.id
113
+ dashboard.user_creator = current_user
114
+
115
+ if dashboard.save
116
+ respond_with_successful(dashboard)
117
+ else
118
+ respond_with_error(dashboard.errors.full_messages.to_sentence)
119
+ end
120
+ end
121
+
122
+ # @controller_action_param :name [String] The name of the new dashboard
123
+ # @controller_action_param :default [Boolean] A flag that marks this dashboard as default or not. The default dashboard is the dashboard all users will have access to on the root page
124
+ # @controller_action_param :main [Boolean] A flag that marks this dashboard as main. Since a user can have multiple dashboards, this is the one they will see on the root page when loging in
125
+ # @controller_action_param :roles_id [Integer] The id of the role that will have access to this dashboard
126
+ # @controller_action_param :user_main_id [Integer] The id of the user
127
+ # @controller_action_param :component_attributes [Array] Array of hashes that represent the attributes of the dashboard components
128
+ # @controller_action_param :component_attributes.name [String] The name of this component given to the user
129
+ # @controller_action_param :component_attributes.component_id [String] An enum value, that indicates which component is being loaded
130
+ # @controller_action_param :component_attributes.layout [Integer] Number from 1 to 12, bigger numbers default to 12, smallest numbers default to 1. The column size that the UI component will use
131
+ # @controller_action_param :component_attributes.index [Integer] The position of the component in the layout
132
+ # @controller_action_param :component_attributes.configuration [Hash] Specific filtering and configuration of the components
133
+ # @return [Json] Json that contains wheter the dashboard was successfully updated or not.
134
+ # If it it not successful, it returns an error message
135
+ # @description Updates an existing dashboard associated to the *current_user*'s *account*.
136
+ # @example
137
+ # # Executing this controller's action from javascript's frontend
138
+ # let dashboard_id = 4;
139
+ # let data = {
140
+ # dashboard: {
141
+ # name: "Sales Dashboard",
142
+ # default: false,
143
+ # roles_id: 3,
144
+ # components_attributes: [
145
+ # {
146
+ # name: 'Projects Count',
147
+ # component_id: projects_component,
148
+ # layout: 4,
149
+ # index: 3,
150
+ # configuration: {}
151
+ # }, {
152
+ # name: 'New Customers Count',
153
+ # component_id: new_customers_component,
154
+ # layout: 4,
155
+ # index: 3,
156
+ # configuration: {}
157
+ # }
158
+ # ]
159
+ # }
160
+ # };
161
+ # this.http.put(`127.0.0.1/help/dashboards/${dashboard_id}`, data);
162
+ def update
163
+ return respond_with_not_found unless @dashboard
164
+
165
+ if @dashboard.update(dashboard_params)
166
+ respond_with_successful(@dashboard.show)
167
+ else
168
+ respond_with_error(@dashboard.errors.full_messages.to_sentence)
169
+ end
170
+ end
171
+
172
+ # @return [Json] Json that contains wheter the dashboard was successfully deleted or not.
173
+ # If it it not successful, it returns an error message
174
+ # @description Deletes an existing *dashboard* associated to the *current_user*'s *account*.
175
+ # Since the dashboard has details, these are also deleted. However, if there
176
+ # is an existing *cloud_object* associated to the *dashboard*, it cannot be deleted
177
+ # @example
178
+ # # Executing this controller's action from javascript's frontend
179
+ # let dashboard_id = 4;
180
+ # this.http.delete(`127.0.0.1/help/dashboards/${dashboard_id}`);
181
+ def destroy
182
+ return respond_with_not_found unless @dashboard
183
+
184
+ if @dashboard.destroy
185
+ respond_with_successful
186
+ else
187
+ respond_with_error(@dashboard.errors.full_messages.to_sentence)
188
+ end
189
+ end
190
+
191
+ def options
192
+ dynamic_info = self.class.dynamic_info
193
+ model = dynamic_info[:module_model]
194
+
195
+ respond_with_successful(model.options(current_user, @query))
196
+ end
197
+
198
+ def resource_component
199
+ dynamic_info = self.class.dynamic_info
200
+ component_model = dynamic_info[:component_model]
201
+
202
+ component_id = sanitize(params[:component_id].to_sym)
203
+
204
+ # We verify if the method exists, and if it is in the available component list
205
+ if component_model.respond_to?(component_id) && component_model.component_ids[component_id]
206
+ respond_with_successful(component_model.public_send(component_id, current_user, @query))
207
+ else
208
+ respond_with_not_found()
209
+ end
210
+ end
211
+
212
+ private
213
+
214
+ # @return [void]
215
+ # @description Sets the variable @dashboard. The variable contains the *cloud_object* *dashboard*
216
+ # to be handled by the controller action that called this method
217
+ # @example
218
+ # #suppose params[:id] = 1
219
+ # puts @dashboard # will display nil
220
+ # set_dashboard
221
+ # puts @dashboard # will display an instance of CloudHelp:TicketDashboard
222
+ def set_dashboard
223
+ dynamic_info = self.class.dynamic_info
224
+
225
+ model = dynamic_info[:module_model]
226
+ module_name = dynamic_info[:module_name]
227
+ module_name_full = dynamic_info[:module_name_full].underscore
228
+
229
+ # When params[:id] is 'default' order of priority is:
230
+ # Main dashboard for user goes first
231
+ # Main dashboard for role goes second
232
+ # Default dashboard goes third
233
+ if params[:id] == "default"
234
+ # Main dashboard for user
235
+ @dashboard = model.find_by(
236
+ #"#{full_module_name}_account_id".to_sym => current_user.account.id,
237
+ account_id: current_user.account.id,
238
+ main: true,
239
+ #user_main_id: current_user.id
240
+ )
241
+
242
+ return if @dashboard
243
+
244
+ # Main dashboard for role
245
+ # @dashboard = model.find_by(
246
+ # :account_id => current_user.account.id,
247
+ # role_id: current_user.roles.first.id
248
+ # )
249
+ # return if @dashboard
250
+
251
+ # Default dashboard
252
+ @dashboard = model.find_by(
253
+ account_id: current_user.account.id,
254
+ default: true
255
+ )
256
+ else
257
+ @dashboard = model.find_by(
258
+ id: params[:id],
259
+ :account_id => current_user.account.id,
260
+ )
261
+ end
262
+ end
263
+
264
+ def dashboard_params
265
+ params.require(:dashboard).permit(
266
+ :name,
267
+ :default,
268
+ :roles_id,
269
+ components_attributes: [
270
+ :id,
271
+ :name,
272
+ :component_id,
273
+ :layout,
274
+ :index,
275
+ {query_configuration: {}},
276
+ {custom_configuration: {}},
277
+ :_destroy
278
+ ]
279
+ )
280
+ end
281
+
282
+ private
283
+
284
+ # Build the Rails models and engine information for
285
+ # the current engine implementing the shared dashboards
286
+ # Example: For the LesliAudit engine
287
+ # {
288
+ # :module_name => "audit",
289
+ # :module_name_full => "LesliAudit",
290
+ # :module_model => "LesliAudit::Dashboard",
291
+ # :module_model_component => "LesliAudit::Dashboard::Component"
292
+ # }
293
+ def self.dynamic_info
294
+
295
+ module_info = self.name.split("::")
296
+
297
+ module_name = module_info[0].sub("Lesli", "").downcase
298
+
299
+ {
300
+ module_name: module_name,
301
+ module_name_full: module_info[0],
302
+ module_model: "#{ module_info[0] }::Dashboard".constantize,
303
+ module_model_component: "#{ module_info[0] }::Dashboard::Component".constantize
304
+ }
305
+ end
306
+ end
307
+ end
308
+ end
@@ -1,30 +1,66 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  class Users::ConfirmationsController < Devise::ConfirmationsController
4
- # GET /resource/confirmation/new
5
- # def new
6
- # super
7
- # end
8
-
9
- # POST /resource/confirmation
10
- # def create
11
- # super
12
- # end
13
-
14
- # GET /resource/confirmation?confirmation_token=abcdef
15
- # def show
16
- # super
17
- # end
18
-
19
- # protected
20
-
21
- # The path used after resending confirmation instructions.
22
- # def after_resending_confirmation_instructions_path_for(resource_name)
23
- # super(resource_name)
24
- # end
25
-
26
- # The path used after confirmation.
27
- # def after_confirmation_path_for(resource_name, resource)
28
- # super(resource_name, resource)
29
- # end
3
+
4
+ def show
5
+
6
+ # delete all previus messages
7
+ flash.clear
8
+
9
+ # get the confirmation token sent through get params
10
+ token = params[:confirmation_token]
11
+
12
+ # validate that token were sent
13
+ if token.blank?
14
+ return flash[:danger] = I18n.t("core.users/confirmations.messages_warning_invalid_token")
15
+ end
16
+
17
+ # check if token belongs to a unconfirmed user
18
+ user = Lesli::User.find_by(:confirmation_token => token, :confirmed_at => nil)
19
+
20
+ # validate that user were found
21
+ if user.blank?
22
+ return flash[:danger] = I18n.t("core.users/confirmations.messages_warning_invalid_token")
23
+ end
24
+
25
+ # register a log with a validation atempt for the user
26
+ log = user.logs.create({ description: "confirmation_atempt_successful" })
27
+
28
+ registration_operator = Lesli::UserRegistrationOperator.new(user)
29
+
30
+ # confirm the user
31
+ registration_operator.confirm
32
+
33
+ # let the user knows that the confirmation is done
34
+ flash[:success] = I18n.t("core.users/confirmations.messages_success_email_updated")
35
+
36
+ # if new account, launch account onboarding in another thread,
37
+ # so the user can continue with the registration process
38
+ registration_operator.create_account if user.account.blank?
39
+ #Thread.new { registration_operator.create_account } if user.account.blank?
40
+
41
+ end
42
+
43
+
44
+ # @controller_action_param :email [String] The registered user email
45
+ # @return [Json] Json that contains wheter the email confirmation was sent or not.
46
+ # If it is not successful, it returs an error message
47
+ # @description Resends a email confirmation an already registered user
48
+ # @example
49
+ # # Executing this controller's action from javascript's frontend
50
+ # let email = 'john.doe@email.com';
51
+ # let data = {
52
+ # user: {
53
+ # email: email
54
+ # }
55
+ # };
56
+ # this.http.post('127.0.0.1/conformation', data);
57
+ def create
58
+ super do |resource|
59
+ if successfully_sent?(resource)
60
+ return respond_with_successful
61
+ else
62
+ return respond_with_error(resource.errors.full_messages.to_sentence)
63
+ end
64
+ end
65
+ end
30
66
  end
@@ -1,34 +1,71 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Users::PasswordsController < Devise::PasswordsController
4
- # GET /resource/password/new
5
- # def new
6
- # super
7
- # end
8
-
9
- # POST /resource/password
10
- # def create
11
- # super
12
- # end
13
-
14
- # GET /resource/password/edit?reset_password_token=abcdef
15
- # def edit
16
- # super
17
- # end
18
-
19
- # PUT /resource/password
20
- # def update
21
- # super
22
- # end
23
-
24
- # protected
25
-
26
- # def after_resetting_password_path_for(resource)
27
- # super(resource)
28
- # end
29
-
30
- # The path used after sending reset password instructions
31
- # def after_sending_reset_password_instructions_path_for(resource_name)
32
- # super(resource_name)
33
- # end
4
+
5
+ # Sends an email with a token, so the user can reset their password
6
+ def create
7
+
8
+ if params[:user].blank?
9
+ #Account::Activity.log("core", "/password/create", "password_creation_failed", "no_valid_email")
10
+ return respond_with_error(I18n.t("core.shared.messages_warning_user_not_found"))
11
+ end
12
+
13
+ if params[:user][:email].blank?
14
+ #Account::Activity.log("core", "/password/create", "password_creation_failed", "no_valid_email")
15
+ return respond_with_error(I18n.t("core.shared.messages_warning_user_not_found"))
16
+ end
17
+
18
+ user = Lesli::User.find_by(:email => params[:user][:email])
19
+
20
+ if user.blank?
21
+ # Account::Activity.log("core", "/password/create", "password_creation_failed", "no_valid_email", {
22
+ # email: (params[:user][:email] || "")
23
+ # })
24
+ return respond_with_error(I18n.t("core.shared.messages_warning_user_not_found"))
25
+ end
26
+
27
+ unless user.active
28
+ # user.logs.create({title: "password_creation_failed", description: "user_not_active"})
29
+ # Account::Activity.log("core", "/password/create", "password_creation_failed", "user_not_active")
30
+ return respond_with_error(I18n.t("core.users/passwords.messages_danger_inactive_user"))
31
+ end
32
+
33
+ token = user.generate_password_reset_token
34
+
35
+ #user.logs.create({ title: "password_creation_successful" })
36
+
37
+ begin
38
+ Lesli::DeviseMailer.reset_password_instructions(user, token).deliver_now
39
+ respond_with_successful
40
+ rescue => exception
41
+ #Honeybadger.notify(exception)
42
+ respond_with_error(exception.message)
43
+ end
44
+ end
45
+
46
+ def update
47
+ super do |resource|
48
+
49
+ # check if password update was ok
50
+ if resource.errors.empty?
51
+
52
+ # reset password expiration due the user just updated his password
53
+ if resource.has_expired_password?
54
+ resource.update(password_expiration_at: nil)
55
+ end
56
+
57
+ resource.logs.create(title: "password_reset_successful")
58
+
59
+ return respond_with_successful
60
+
61
+ else
62
+
63
+ resource.logs.create(title: "password_reset_error") if resource.id
64
+
65
+ return respond_with_error(resource.errors.full_messages.to_sentence)
66
+
67
+ end
68
+
69
+ end
70
+ end
34
71
  end
@@ -89,7 +89,8 @@ class Users::SessionsController < Devise::SessionsController
89
89
 
90
90
 
91
91
  # create a new session for the user
92
- current_session = Lesli::User::SessionService.new(user).create(get_user_agent, request.remote_ip)
92
+ current_session = Lesli::UserSessionService.new(user)
93
+ .create(get_user_agent(false), request.remote_ip)
93
94
 
94
95
  # make session id globally available
95
96
  session[:user_session_id] = current_session[:id]
@@ -109,9 +110,6 @@ class Users::SessionsController < Devise::SessionsController
109
110
  # respond successful and send the path user should go
110
111
  #respond_with_successful({ default_path: user.has_role_with_default_path?() })
111
112
  respond_with_successful({ default_path: "/" })
112
-
113
- log_user_agent()
114
-
115
113
  end
116
114
 
117
115
  private