role.rb 7.3 KB

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