lesli 5.0.5 → 5.0.6

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/icons/lesli/cloud-letter.svg +1 -0
  3. data/app/assets/icons/readme.md +1 -1
  4. data/app/assets/javascripts/lesli/users/passwords.js +84 -118
  5. data/app/assets/javascripts/lesli/users/registrations.js +85 -119
  6. data/app/assets/javascripts/lesli/users/sessions.js +76 -130
  7. data/app/controllers/lesli/system_controllers_controller.rb +63 -0
  8. data/app/controllers/users/sessions_controller.rb +2 -1
  9. data/app/helpers/lesli/navigation_helper.rb +9 -9
  10. data/app/lib/lesli/system.rb +2 -1
  11. data/app/models/concerns/account_initializer.rb +27 -9
  12. data/app/models/concerns/user_extensions.rb +8 -6
  13. data/app/models/concerns/user_security.rb +1 -1
  14. data/app/models/lesli/account.rb +3 -1
  15. data/app/models/lesli/descriptor/privilege.rb +1 -0
  16. data/app/models/lesli/descriptor.rb +1 -4
  17. data/app/models/lesli/role/power.rb +3 -3
  18. data/app/models/lesli/user/session.rb +4 -27
  19. data/app/models/lesli/user.rb +2 -3
  20. data/app/operators/lesli/descriptor_privilege_operator.rb +1 -1
  21. data/app/operators/lesli/{role_power_operator.rb → role_descriptor_operator.rb} +24 -7
  22. data/app/views/lesli/partials/_application-data.html.erb +7 -0
  23. data/app/views/lesli/partials/_application-lesli-engines.html.erb +2 -2
  24. data/app/views/lesli/partials/_application-lesli-icons.html.erb +1 -1
  25. data/config/initializers/lesli.rb +2 -0
  26. data/config/locales/translations.en.yml +9 -2
  27. data/config/locales/translations.es.yml +9 -2
  28. data/config/routes.rb +2 -0
  29. data/db/migrate/v1.0/0010005010_create_lesli_descriptors.rb +1 -1
  30. data/db/migrate/v1.0/0010005510_create_lesli_role_powers.rb +7 -0
  31. data/lib/lesli/version.rb +1 -1
  32. data/lib/sass/lesli/components/editor-richtext.scss +10 -0
  33. data/lib/sass/lesli/templates/application.scss +4 -0
  34. data/lib/{tasks/lesli/privileges.rake → sass/lesli/templates/component.scss} +6 -21
  35. data/lib/tasks/lesli/db.rake +2 -1
  36. data/lib/tasks/lesli_tasks.rake +8 -0
  37. data/lib/vue/application.js +64 -62
  38. data/lib/vue/devise/sessions.js +1 -1
  39. data/lib/vue/layouts/application-header.vue +6 -7
  40. data/lib/vue/public.js +2 -5
  41. data/lib/vue/shared/stores/systemController.js +67 -0
  42. data/lib/vue/stores/translations.json +24 -2
  43. data/lib/vue/stores/users.js +2 -6
  44. data/lib/webpack/base.js +3 -2
  45. data/lib/webpack/core.js +1 -1
  46. data/readme.md +1 -1
  47. metadata +22 -5
  48. /data/app/assets/icons/lesli/{cloud-help.svg → cloud-support.svg} +0 -0
@@ -0,0 +1,63 @@
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
+
33
+ module Lesli
34
+ class SystemControllersController < ApplicationLesliController
35
+ before_action :set_system_controller, only: [:show, :update, :destroy]
36
+
37
+ # GET /system_controllers
38
+ def index
39
+ respond_to do |format|
40
+ format.html {}
41
+ format.json do
42
+ respond_with_successful(Lesli::SystemController.index())
43
+ end
44
+ end
45
+ end
46
+
47
+ def options
48
+ respond_to do |format|
49
+ format.html {}
50
+ format.json do
51
+ respond_with_successful(SystemController.options(current_user, @query))
52
+ end
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ # Only allow a list of trusted parameters through.
59
+ def system_controller_params
60
+ []
61
+ end
62
+ end
63
+ end
@@ -109,7 +109,8 @@ class Users::SessionsController < Devise::SessionsController
109
109
 
110
110
  # respond successful and send the path user should go
111
111
  #respond_with_successful({ default_path: user.has_role_with_default_path?() })
112
- respond_with_successful({ default_path: "/" })
112
+ respond_with_successful({ default_path: Lesli.config.path_after_login || "/" })
113
+
113
114
  end
114
115
 
115
116
  private
@@ -140,12 +140,12 @@ module Lesli
140
140
  controller_path.include?("cloud_focus"))
141
141
  end
142
142
 
143
- # 03.05 Text engine
144
- def navigation_engine_text(title: "Text", subtitle: "cloud_text/text-logo.svg")
145
- return unless defined? CloudText
143
+ # 03.05 Letter engine
144
+ def navigation_engine_letter(title: "Letter", subtitle: "Notes & Notebooks")
145
+ return unless defined? LesliLetter
146
146
 
147
- navigation_engine_item(title, subtitle, "text", cloud_text.root_path,
148
- controller_path.include?("cloud_text"))
147
+ navigation_engine_item(title, subtitle, "letter", lesli_letter.root_path,
148
+ controller_path.include?("lesli_letter"))
149
149
  end
150
150
 
151
151
  # 03.07 Social engine
@@ -244,11 +244,11 @@ module Lesli
244
244
  end
245
245
 
246
246
  # 07.02 Help engine
247
- def navigation_engine_help(title: "Help", subtitle: "Support Ticket System")
248
- return unless defined? LesliHelp
247
+ def navigation_engine_support(title: "Support", subtitle: "Support Ticket System")
248
+ return unless defined? LesliSupport
249
249
 
250
- navigation_engine_item(title, subtitle, "help", lesli_help.root_path,
251
- controller_path.include?("lesli_help"))
250
+ navigation_engine_item(title, subtitle, "support", lesli_support.root_path,
251
+ controller_path.include?("lesli_support"))
252
252
  end
253
253
 
254
254
  # 07.03 Portal engine
@@ -89,7 +89,8 @@ module Lesli
89
89
  "LesliBell",
90
90
  "LesliDriver",
91
91
  "LesliGuard",
92
- "LesliHelp"
92
+ "LesliLetter",
93
+ "LesliSupport"
93
94
  ]
94
95
  end
95
96
  end
@@ -52,9 +52,9 @@ module AccountInitializer
52
52
  limited = self.roles.create({ name: "limited", active: true, object_level_permission: 10, path_default: "/administration/profile" })
53
53
 
54
54
  # assign descriptors with appropriate privileges
55
- owner.powers.create(:descriptor => descriptor_owner)
56
- sysadmin.powers.create(:descriptor => descriptor_sysadmin)
57
- limited.powers.create(:descriptor => descriptor_profile)
55
+ owner.powers.create(:descriptor => descriptor_owner, :plist => true, :pindex => true, :pshow => true, :pcreate => true, :pcreate => true, :pupdate => true, :pdestroy => true)
56
+ sysadmin.powers.create(:descriptor => descriptor_sysadmin, :plist => true, :pindex => true, :pshow => true, :pcreate => true, :pcreate => true, :pupdate => true, :pdestroy => true)
57
+ limited.powers.create(:descriptor => descriptor_profile, :plist => true, :pindex => true, :pshow => true, :pcreate => true, :pcreate => true, :pupdate => true, :pdestroy => true)
58
58
  end
59
59
 
60
60
 
@@ -79,6 +79,24 @@ module AccountInitializer
79
79
  end
80
80
  end
81
81
 
82
+ # 03.05 LesliNotes - Notes & Notebooks
83
+ if defined? LesliLetter
84
+ if self.letter.blank?
85
+ self.letter = LesliLetter::Account.new
86
+ self.letter.account = self
87
+ self.letter.save!
88
+ end
89
+ end
90
+
91
+ # 05.02 LesliAudit - System analytics
92
+ if defined? LesliAudit
93
+ if self.audit.blank?
94
+ self.audit = LesliAudit::Account.new
95
+ self.audit.account = self
96
+ self.audit.save!
97
+ end
98
+ end
99
+
82
100
  # 07.02 LesliHelp - Support Ticket System
83
101
  if defined? LesliHelp
84
102
  if self.help.blank?
@@ -88,12 +106,12 @@ module AccountInitializer
88
106
  end
89
107
  end
90
108
 
91
- # 08.03 LesliAudit - System analytics
92
- if defined? LesliAudit
93
- if self.audit.blank?
94
- self.audit = LesliAudit::Account.new
95
- self.audit.account = self
96
- self.audit.save!
109
+ # 08.01 LesliGuard - Security Management Module
110
+ if defined? LesliGuard
111
+ if self.guard.blank?
112
+ self.guard = LesliGuard::Account.new
113
+ self.guard.account = self
114
+ self.guard.save!
97
115
  end
98
116
  end
99
117
  end
@@ -101,14 +101,16 @@ module UserExtensions
101
101
  # locale = User.last.locle
102
102
  # will print something like: :es
103
103
  def locale
104
- user_locale = settings.find_by(name: "locale")
104
+ user_locale = self.settings.find_by(name: "locale")
105
105
 
106
- if user_locale
107
- return user_locale.value.to_sym
108
- end
106
+ # return the desire locale by the user
107
+ return user_locale.value.to_sym if user_locale
108
+
109
+ # create a desire locale if the record does not exist
110
+ self.settings.create_with(:value => I18n.locale).find_or_create_by(:name => "locale")
109
111
 
110
- # return current locale
111
- I18n.locale
112
+ # reevaluate
113
+ self.locale()
112
114
  end
113
115
 
114
116
 
@@ -111,7 +111,7 @@ module UserSecurity
111
111
  def can_work_with_role?(role)
112
112
 
113
113
  # get the role if only id is given
114
- role = self.account.roles.find_by(:id => role) unless role.class.name == "Role"
114
+ role = self.account.roles.find_by(:id => role) unless role.class.name == "Lesli::Role"
115
115
 
116
116
  # false if role not found
117
117
  return false if role.blank?
@@ -32,7 +32,6 @@ Building a better future, one line of code at a time.
32
32
 
33
33
  module Lesli
34
34
  class Account < ApplicationLesliRecord
35
-
36
35
  include AccountInitializer
37
36
 
38
37
 
@@ -54,10 +53,13 @@ module Lesli
54
53
  has_many :currencies
55
54
  has_many :logs
56
55
 
56
+
57
57
  has_one :help, class_name: "LesliHelp::Account"
58
58
  has_one :audit, class_name: "LesliAudit::Account"
59
59
  has_one :admin, class_name: "LesliAdmin::Account"
60
60
  has_one :driver, class_name: "LesliDriver::Account"
61
+ has_one :letter, class_name: "LesliLetter::Account"
62
+ has_one :guard, class_name: "LesliGuard::Account"
61
63
 
62
64
 
63
65
  # account statuses
@@ -34,5 +34,6 @@ module Lesli
34
34
  class Descriptor::Privilege < ApplicationLesliRecord
35
35
  belongs_to :descriptor
36
36
  belongs_to :action, class_name: "SystemController::Action"
37
+ belongs_to :system_controller_action, class_name: "SystemController::Action", foreign_key: "action_id"
37
38
  end
38
39
  end
@@ -34,7 +34,6 @@ module Lesli
34
34
  class Descriptor < ApplicationLesliRecord
35
35
  belongs_to :account
36
36
  has_many :privileges
37
- #has_many :role_descriptors
38
37
 
39
38
  # this scope is needed to allow to join with deleted descriptors
40
39
  # join with deleted descriptors is needed to know which privileges we have to remove from the
@@ -43,14 +42,12 @@ module Lesli
43
42
 
44
43
  validates :name, presence: true
45
44
 
46
- after_create :initialize_descriptor_privileges
47
-
48
45
  def initialize_descriptor_privileges
49
46
 
50
47
  descriptor_operator = DescriptorPrivilegeOperator.new(self)
51
48
 
52
49
  descriptor_operator.add_profile_privileges(self) if self.name == "profile"
53
-
50
+
54
51
  descriptor_operator.add_owner_privileges(self) if ["owner", "sysadmin"].include?(self.name)
55
52
 
56
53
  end
@@ -35,11 +35,11 @@ module Lesli
35
35
  belongs_to :role
36
36
  belongs_to :descriptor
37
37
 
38
- after_save :synchronize_privileges
39
- after_destroy :synchronize_privileges
38
+ after_commit :synchronize_privileges
39
+ #after_destroy :synchronize_privileges
40
40
 
41
41
  def synchronize_privileges
42
- RolePowerOperator.new(self.role.id).synchronize
42
+ RoleDescriptorOperator.new(self.role.id).synchronize
43
43
  end
44
44
 
45
45
  def self.index current_user, query, role
@@ -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 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
  require "bcrypt"
@@ -40,13 +40,13 @@ module Lesli
40
40
 
41
41
  enum session_sources: {
42
42
  dispatcher_standar_session: "dispatcher_standar_session",
43
- devise_standar_session: "devise_standar_session",
43
+ devise_standard_session: "devise_standar_session",
44
44
  cloud_shared_public: "cloud_shared_public",
45
45
  }
46
46
 
47
47
  def set_session_token
48
48
 
49
- return if self.session_source == "devise_standar_session"
49
+ return if self.session_source == "devise_standard_session"
50
50
 
51
51
  return unless self.session_token.blank?
52
52
 
@@ -67,29 +67,6 @@ module Lesli
67
67
 
68
68
  end
69
69
 
70
- def self.index(current_user, query, params, current_session_id)
71
- user_id = params[:user_id]
72
-
73
- User::Session.all
74
- .joins(:user)
75
- .where(user_id: user_id)
76
- .where("users.account_id = ?", current_user.account.id)
77
- .where("expiration_at > ? or expiration_at is ?", Time.now.utc, nil)
78
- .select(
79
- :id,
80
- :user_agent,
81
- :session_source,
82
- Date2.new.date_time.db_timestamps("user_sessions"),
83
- Date2.new.date_time.db_column("expiration_at"),
84
- Date2.new.date_time.db_column("last_used_at"),
85
- "case when #{current_session_id} = user_sessions.id then true else false end as current_session"
86
- )
87
- .page(query[:pagination][:page])
88
- .per(query[:pagination][:perPage])
89
- .order(updated_at: :desc)
90
-
91
- end
92
-
93
70
  def active?
94
71
  if self.deleted_at.present?
95
72
  return false
@@ -32,7 +32,6 @@ Building a better future, one line of code at a time.
32
32
 
33
33
  module Lesli
34
34
  class User < ApplicationLesliRecord
35
-
36
35
  include UserSecurity
37
36
  include UserExtensions
38
37
  #include UserActivities
@@ -88,7 +87,7 @@ module Lesli
88
87
 
89
88
  # callbacks
90
89
  before_create :before_create_user
91
- #after_create :after_confirmation_user, if: :confirmed?
90
+ after_create :after_confirmation_user, if: :confirmed?
92
91
  #after_create :after_account_assignation
93
92
  #after_update :update_associated_services
94
93
 
@@ -116,7 +115,7 @@ module Lesli
116
115
  self.set_alias
117
116
 
118
117
  # create user details
119
- #User::Detail.find_or_create_by({ user: self })
118
+ User::Detail.find_or_create_by({ user: self })
120
119
 
121
120
  # Minimum security settings required
122
121
  self.settings.create_with(:value => false).find_or_create_by(:name => "mfa_enabled")
@@ -65,7 +65,7 @@ module Lesli
65
65
  def add_owner_privileges(descriptor)
66
66
 
67
67
  # Adding default system actions for profile descriptor
68
- actions = SystemController::Action.all
68
+ actions = SystemController::Action.all
69
69
 
70
70
  actions.each do |action|
71
71
  descriptor.privileges.find_or_create_by(action: action)
@@ -31,7 +31,7 @@ Building a better future, one line of code at a time.
31
31
  =end
32
32
 
33
33
  module Lesli
34
- class RolePowerOperator < Lesli::ApplicationLesliService
34
+ class RoleDescriptorOperator < Lesli::ApplicationLesliService
35
35
 
36
36
  @roles;
37
37
 
@@ -48,6 +48,12 @@ module Lesli
48
48
  # is get the controllers and actions assigned to a descriptor through the
49
49
  # system_descriptor_privileges table and create an array of hashes with
50
50
  # all the raw privileges (this includes duplicated privileges)
51
+ # IMPORTANT: A descriptor privilege is evaluated as active if:
52
+ # - the role has assigned the descriptor through the power association
53
+ # - the descriptor has assigned the privilege through the controller actions table
54
+ # - the power has active that group of actions, this means that, if the power has
55
+ # not marked as active the pshow, pindex, etc column the power is not active
56
+ # even if it is assigned and active to a descriptor
51
57
  records = Descriptor.joins(%(
52
58
  INNER JOIN lesli_descriptor_privileges
53
59
  ON lesli_descriptor_privileges.descriptor_id = lesli_descriptors.id
@@ -60,12 +66,23 @@ module Lesli
60
66
  )).joins(%(
61
67
  INNER JOIN lesli_role_powers
62
68
  ON lesli_role_powers.descriptor_id = lesli_descriptors.id
63
- )).select(
64
- "lesli_system_controllers.route as controller",
65
- "lesli_system_controller_actions.name as action",
66
- "case when lesli_role_powers.deleted_at is null then true else false end as active",
67
- "lesli_role_powers.role_id as role_id"
68
- ).with_deleted
69
+ )).select(%(
70
+ lesli_system_controllers.route as controller,
71
+ lesli_system_controller_actions.name as action,
72
+ case
73
+ when lesli_role_powers.deleted_at is not null then false
74
+ when NULLIF(lesli_system_controller_actions.name = 'list' and lesli_role_powers.plist = true, false) then true
75
+ when NULLIF(lesli_system_controller_actions.name = 'index' and lesli_role_powers.pindex = true, false) then true
76
+ when NULLIF(lesli_system_controller_actions.name = 'show' and lesli_role_powers.pshow = true, false) then true
77
+ when NULLIF(lesli_system_controller_actions.name = 'new' and lesli_role_powers.pcreate = true, false) then true
78
+ when NULLIF(lesli_system_controller_actions.name = 'create' and lesli_role_powers.pcreate = true, false) then true
79
+ when NULLIF(lesli_system_controller_actions.name = 'edit' and lesli_role_powers.pupdate = true, false) then true
80
+ when NULLIF(lesli_system_controller_actions.name = 'update' and lesli_role_powers.pupdate = true, false) then true
81
+ when NULLIF(lesli_system_controller_actions.name = 'destroy' and lesli_role_powers.pdestroy = true, false) then true
82
+ else false
83
+ end as active,
84
+ lesli_role_powers.role_id as role_id
85
+ )).with_deleted
69
86
 
70
87
 
71
88
  # get privileges only for the given role, this is needed to sync only modified roles
@@ -34,11 +34,18 @@ Building a better future, one line of code at a time.
34
34
 
35
35
  <%
36
36
 
37
+ # Should I move this to a base controller?
38
+
37
39
  # add company information (account)
38
40
  @lesli[:company] = {
39
41
  name: current_user.account.company_name,
40
42
  }
41
43
 
44
+ # set user information
45
+ @lesli[:current_user] = {
46
+ id: current_user.id
47
+ }
48
+
42
49
 
43
50
  # Include defaults to account
44
51
  @lesli[:instance] = Rails.application.credentials.dig(:instance) || lesli_instance_code
@@ -49,9 +49,9 @@ Building a better future, one line of code at a time.
49
49
 
50
50
  <%# Productivity & teamwork %>
51
51
  <%= navigation_engine_driver %>
52
+ <%= navigation_engine_letter %>
52
53
  <%= navigation_engine_work %>
53
54
  <%= navigation_engine_focus %>
54
- <%= navigation_engine_text %>
55
55
  <%= navigation_engine_social %>
56
56
  <%= navigation_engine_bell %>
57
57
  <%= navigation_engine_time %>
@@ -64,9 +64,9 @@ Building a better future, one line of code at a time.
64
64
 
65
65
  <%# IT & Help desk %>
66
66
  <%= navigation_engine_kb %>
67
- <%= navigation_engine_help %>
68
67
  <%= navigation_engine_portal %>
69
68
  <%= navigation_engine_shared %>
69
+ <%= navigation_engine_support %>
70
70
 
71
71
  <%# Security & privacy %>
72
72
  <%= navigation_engine_audit %>