lesli 5.0.5 → 5.0.6

Sign up to get free protection for your applications and to get access to all the features.
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 %>