diff --git a/app/assets/javascripts/app/controllers/_application_controller_generic.coffee b/app/assets/javascripts/app/controllers/_application_controller_generic.coffee index 1c82a8d1e..6c8dfa547 100644 --- a/app/assets/javascripts/app/controllers/_application_controller_generic.coffee +++ b/app/assets/javascripts/app/controllers/_application_controller_generic.coffee @@ -87,6 +87,7 @@ class App.ControllerGenericEdit extends App.ControllerModal ui.close() fail: (settings, details) -> + App[ ui.genericObject ].fetch(id: @id) ui.log 'errors' ui.formEnable(e) ui.controller.showAlert(details.error_human || details.error || 'Unable to update object!') diff --git a/app/assets/javascripts/app/controllers/widget/translation_inline.coffee b/app/assets/javascripts/app/controllers/widget/translation_inline.coffee index 4a27407fd..b49757943 100644 --- a/app/assets/javascripts/app/controllers/widget/translation_inline.coffee +++ b/app/assets/javascripts/app/controllers/widget/translation_inline.coffee @@ -23,6 +23,7 @@ class Widget extends App.Controller if e.altKey && e.ctrlKey && !e.metaKey hotkeys = true if hotkeys && e.keyCode is 84 + e.preventDefault() @toogle() ) diff --git a/app/assets/javascripts/app/lib/base/jquery.contenteditable.js b/app/assets/javascripts/app/lib/base/jquery.contenteditable.js index 606402b01..cf32462c8 100644 --- a/app/assets/javascripts/app/lib/base/jquery.contenteditable.js +++ b/app/assets/javascripts/app/lib/base/jquery.contenteditable.js @@ -179,7 +179,7 @@ || e.keyCode == 76 || e.keyCode == 85 || e.keyCode == 86 - || e.keyCode == 87 + || e.keyCode == 88 || e.keyCode == 90 || e.keyCode == 89)) { e.preventDefault() @@ -219,7 +219,7 @@ if (e.keyCode == 86) { document.execCommand('strikeThrough') } - if (e.keyCode == 87) { + if (e.keyCode == 88) { document.execCommand('unlink') } if (e.keyCode == 89) { diff --git a/app/models/user.rb b/app/models/user.rb index 16d3071b9..93474015c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -45,7 +45,7 @@ class User < ApplicationModel after_destroy :avatar_destroy has_and_belongs_to_many :groups, after_add: :cache_update, after_remove: :cache_update, class_name: 'Group' - has_and_belongs_to_many :roles, after_add: [:cache_update, :check_notifications], after_remove: :cache_update, before_add: :validate_agent_limit, class_name: 'Role' + has_and_belongs_to_many :roles, after_add: [:cache_update, :check_notifications], after_remove: :cache_update, before_add: :validate_agent_limit, before_remove: :last_admin_check, class_name: 'Role' has_and_belongs_to_many :organizations, after_add: :cache_update, after_remove: :cache_update, class_name: 'Organization' #has_many :permissions, class_name: 'Permission', through: :roles, class_name: 'Role' has_many :tokens, after_add: :cache_update, after_remove: :cache_update @@ -860,6 +860,27 @@ returns } end +=begin + +checks if the current user is the last one +with admin permissions. + +Raises + +raise 'Minimum one user need to have admin permissions' + +=end + + def last_admin_check(role) + ticket_admin_role_ids = Role.joins(:permissions).where(permissions: { name: ['admin', 'admin.user'] }).pluck(:id) + count = User.joins(:roles).where(roles: { id: ticket_admin_role_ids }, users: { active: true }).count + if ticket_admin_role_ids.include?(role.id) + count -= 1 + end + + raise Exceptions::UnprocessableEntity, 'Minimum one user needs to have admin permissions.' if count < 1 + end + def validate_agent_limit(role) return if !Setting.get('system_agent_limit') diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index e193f6f4b..2fd0ca1d5 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -544,4 +544,72 @@ class UserTest < ActiveSupport::TestCase end + test 'min admin permission check' do + User.with_permissions('admin').each(&:destroy) + + # store current admin count + admin_count_inital = User.with_permissions('admin').count + assert_equal(0, admin_count_inital) + + # create two admin users + random = rand(999_999_999) + admin1 = User.create_or_update( + login: "1admin-role#{random}@example.com", + firstname: 'Role', + lastname: "Admin#{random}", + email: "admin-role#{random}@example.com", + password: 'adminpw', + active: true, + roles: Role.where(name: %w(Admin Agent)), + updated_by_id: 1, + created_by_id: 1, + ) + + random = rand(999_999_999) + admin2 = User.create_or_update( + login: "2admin-role#{random}@example.com", + firstname: 'Role', + lastname: "Admin#{random}", + email: "admin-role#{random}@example.com", + password: 'adminpw', + active: true, + roles: Role.where(name: %w(Admin Agent)), + updated_by_id: 1, + created_by_id: 1, + ) + + random = rand(999_999_999) + admin3 = User.create_or_update( + login: "2admin-role#{random}@example.com", + firstname: 'Role', + lastname: "Admin#{random}", + email: "admin-role#{random}@example.com", + password: 'adminpw', + active: true, + roles: Role.where(name: %w(Admin Agent)), + updated_by_id: 1, + created_by_id: 1, + ) + + admin_count_inital = User.with_permissions('admin').count + assert_equal(3, admin_count_inital) + + admin1.update_attribute(:roles, Role.where(name: %w(Agent))) + + admin_count_inital = User.with_permissions('admin').count + assert_equal(2, admin_count_inital) + + admin2.update_attribute(:roles, Role.where(name: %w(Agent))) + + admin_count_inital = User.with_permissions('admin').count + assert_equal(1, admin_count_inital) + + assert_raises(Exceptions::UnprocessableEntity) { + admin3.update_attribute(:roles, Role.where(name: %w(Agent))) + } + + admin_count_inital = User.with_permissions('admin').count + assert_equal(1, admin_count_inital) + end + end