role.rb 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. class Role < ApplicationModel
  3. include CanBeImported
  4. include HasActivityStreamLog
  5. include ChecksClientNotification
  6. include ChecksLatestChangeObserved
  7. include HasGroups
  8. include HasCollectionUpdate
  9. include HasTicketCreateScreenImpact
  10. include Role::Assets
  11. has_and_belongs_to_many :users, after_add: :cache_update, after_remove: :cache_update
  12. has_and_belongs_to_many :permissions,
  13. before_add: %i[validate_agent_limit_by_permission validate_permissions],
  14. after_add: :cache_update,
  15. before_remove: :last_admin_check_by_permission,
  16. after_remove: :cache_update
  17. validates :name, presence: true
  18. store :preferences
  19. before_create :check_default_at_signup_permissions
  20. before_update :last_admin_check_by_attribute, :validate_agent_limit_by_attributes, :check_default_at_signup_permissions
  21. # ignore Users because this will lead to huge
  22. # results for e.g. the Customer role
  23. association_attributes_ignored :users
  24. activity_stream_permission 'admin.role'
  25. =begin
  26. grant permission to role
  27. role.permission_grant('permission.key')
  28. =end
  29. def permission_grant(key)
  30. permission = Permission.lookup(name: key)
  31. raise "Invalid permission #{key}" if !permission
  32. return true if permission_ids.include?(permission.id)
  33. self.permission_ids = permission_ids.push permission.id
  34. true
  35. end
  36. =begin
  37. revoke permission of role
  38. role.permission_revoke('permission.key')
  39. =end
  40. def permission_revoke(key)
  41. permission = Permission.lookup(name: key)
  42. raise "Invalid permission #{key}" if !permission
  43. return true if !permission_ids.include?(permission.id)
  44. self.permission_ids = self.permission_ids -= [permission.id]
  45. true
  46. end
  47. =begin
  48. get signup roles
  49. Role.signup_roles
  50. returns
  51. [role1, role2, ...]
  52. =end
  53. def self.signup_roles
  54. Role.where(active: true, default_at_signup: true)
  55. end
  56. =begin
  57. get signup role ids
  58. Role.signup_role_ids
  59. returns
  60. [role1, role2, ...]
  61. =end
  62. def self.signup_role_ids
  63. signup_roles.map(&:id)
  64. end
  65. =begin
  66. get all roles with permission
  67. roles = Role.with_permissions('admin.session')
  68. get all roles with permission "admin.session" or "ticket.agent"
  69. roles = Role.with_permissions(['admin.session', 'ticket.agent'])
  70. returns
  71. [role1, role2, ...]
  72. =end
  73. def self.with_permissions(keys)
  74. permission_ids = Role.permission_ids_by_name(keys)
  75. Role.joins(:roles_permissions).joins(:permissions).where(
  76. 'permissions_roles.permission_id IN (?) AND roles.active = ? AND permissions.active = ?', permission_ids, true, true
  77. ).distinct()
  78. end
  79. =begin
  80. check if roles is with permission
  81. role = Role.find(123)
  82. role.with_permission?('admin.session')
  83. get if role has permission of "admin.session" or "ticket.agent"
  84. role.with_permission?(['admin.session', 'ticket.agent'])
  85. returns
  86. true | false
  87. =end
  88. def with_permission?(keys)
  89. permission_ids = Role.permission_ids_by_name(keys)
  90. return true if Role.joins(:roles_permissions).joins(:permissions).where(
  91. 'roles.id = ? AND permissions_roles.permission_id IN (?) AND permissions.active = ?', id, permission_ids, true
  92. ).distinct().count.nonzero?
  93. false
  94. end
  95. def self.permission_ids_by_name(keys)
  96. Array(keys).each_with_object([]) do |key, result|
  97. ::Permission.with_parents(key).each do |local_key|
  98. permission = ::Permission.lookup(name: local_key)
  99. next if !permission
  100. result.push permission.id
  101. end
  102. end
  103. end
  104. private
  105. def validate_permissions(permission)
  106. Rails.logger.debug { "self permission: #{permission.id}" }
  107. raise "Permission #{permission.name} is disabled" if permission.preferences[:disabled]
  108. permission.preferences[:not]
  109. &.find { |name| name.in?(permissions.map(&:name)) }
  110. &.tap { |conflict| raise "Permission #{permission} conflicts with #{conflict}" }
  111. permissions.find { |p| p.preferences[:not]&.include?(permission.name) }
  112. &.tap { |conflict| raise "Permission #{permission} conflicts with #{conflict}" }
  113. end
  114. def last_admin_check_by_attribute
  115. return true if !will_save_change_to_attribute?('active')
  116. return true if active != false
  117. return true if !with_permission?(['admin', 'admin.user'])
  118. raise Exceptions::UnprocessableEntity, 'Minimum one user needs to have admin permissions.' if last_admin_check_admin_count < 1
  119. true
  120. end
  121. def last_admin_check_by_permission(permission)
  122. return true if Setting.get('import_mode')
  123. return true if permission.name != 'admin' && permission.name != 'admin.user'
  124. raise Exceptions::UnprocessableEntity, 'Minimum one user needs to have admin permissions.' if last_admin_check_admin_count < 1
  125. true
  126. end
  127. def last_admin_check_admin_count
  128. admin_role_ids = Role.joins(:permissions).where(permissions: { name: ['admin', 'admin.user'], active: true }, roles: { active: true }).where.not(id: id).pluck(:id)
  129. User.joins(:roles).where(roles: { id: admin_role_ids }, users: { active: true }).distinct().count
  130. end
  131. def validate_agent_limit_by_attributes
  132. return true if Setting.get('system_agent_limit').blank?
  133. return true if !will_save_change_to_attribute?('active')
  134. return true if active != true
  135. return true if !with_permission?('ticket.agent')
  136. ticket_agent_role_ids = Role.joins(:permissions).where(permissions: { name: 'ticket.agent', active: true }, roles: { active: true }).pluck(:id)
  137. currents = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).distinct().pluck(:id)
  138. news = User.joins(:roles).where(roles: { id: id }, users: { active: true }).distinct().pluck(:id)
  139. count = currents.concat(news).uniq.count
  140. raise Exceptions::UnprocessableEntity, 'Agent limit exceeded, please check your account settings.' if count > Setting.get('system_agent_limit').to_i
  141. true
  142. end
  143. def validate_agent_limit_by_permission(permission)
  144. return true if Setting.get('system_agent_limit').blank?
  145. return true if active != true
  146. return true if permission.active != true
  147. return true if permission.name != 'ticket.agent'
  148. ticket_agent_role_ids = Role.joins(:permissions).where(permissions: { name: 'ticket.agent' }, roles: { active: true }).pluck(:id)
  149. ticket_agent_role_ids.push(id)
  150. count = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).distinct().count
  151. raise Exceptions::UnprocessableEntity, 'Agent limit exceeded, please check your account settings.' if count > Setting.get('system_agent_limit').to_i
  152. true
  153. end
  154. def check_default_at_signup_permissions
  155. all_permissions = Permission.all.pluck(:id)
  156. admin_permissions = Permission.where('name LIKE ? OR name = ?', 'admin%', 'ticket.agent').pluck(:id) # admin.*/ticket.agent permissions
  157. normal_permissions = (all_permissions - admin_permissions) | (admin_permissions - all_permissions) # all other permissions besides admin.*/ticket.agent
  158. return true if default_at_signup != true # means if default_at_signup = false, no need further checks
  159. return true if self.permission_ids.all? { |i| normal_permissions.include? i } # allow user to choose only normal permissions
  160. raise Exceptions::UnprocessableEntity, 'Cannot set default at signup when role has admin or ticket.agent permissions.'
  161. end
  162. end