2016-10-19 03:11:36 +00:00
|
|
|
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
2013-06-12 15:59:58 +00:00
|
|
|
|
2012-04-16 11:57:33 +00:00
|
|
|
class Role < ApplicationModel
|
2017-05-02 15:21:13 +00:00
|
|
|
include HasActivityStreamLog
|
|
|
|
include ChecksClientNotification
|
|
|
|
include ChecksLatestChangeObserved
|
2017-06-16 20:43:09 +00:00
|
|
|
include HasGroups
|
|
|
|
|
|
|
|
load 'role/assets.rb'
|
|
|
|
include Role::Assets
|
2017-01-31 17:13:45 +00:00
|
|
|
|
2016-08-12 16:39:09 +00:00
|
|
|
has_and_belongs_to_many :users, after_add: :cache_update, after_remove: :cache_update
|
2017-10-20 11:32:52 +00:00
|
|
|
has_and_belongs_to_many :permissions, after_add: :cache_update, after_remove: :cache_update, before_add: :validate_agent_limit_by_permission, before_remove: :last_admin_check_by_permission
|
2016-08-12 16:39:09 +00:00
|
|
|
validates :name, presence: true
|
|
|
|
store :preferences
|
2013-12-26 21:51:25 +00:00
|
|
|
|
2016-08-12 16:39:09 +00:00
|
|
|
before_create :validate_permissions
|
2017-10-20 11:32:52 +00:00
|
|
|
before_update :validate_permissions, :last_admin_check_by_attribute, :validate_agent_limit_by_attributes
|
2016-08-12 16:39:09 +00:00
|
|
|
|
2017-06-16 20:43:09 +00:00
|
|
|
association_attributes_ignored :users
|
2017-01-31 17:13:45 +00:00
|
|
|
|
|
|
|
activity_stream_permission 'admin.role'
|
2016-08-12 16:39:09 +00:00
|
|
|
|
|
|
|
=begin
|
|
|
|
|
2017-02-24 13:47:55 +00:00
|
|
|
grant permission to role
|
2016-08-12 16:39:09 +00:00
|
|
|
|
2017-02-24 13:47:55 +00:00
|
|
|
role.permission_grant('permission.key')
|
2016-08-12 16:39:09 +00:00
|
|
|
|
|
|
|
=end
|
|
|
|
|
2017-02-24 13:47:55 +00:00
|
|
|
def permission_grant(key)
|
2016-08-12 16:39:09 +00:00
|
|
|
permission = Permission.lookup(name: key)
|
|
|
|
raise "Invalid permission #{key}" if !permission
|
|
|
|
return true if permission_ids.include?(permission.id)
|
|
|
|
self.permission_ids = permission_ids.push permission.id
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
revoke permission of role
|
|
|
|
|
|
|
|
role.permission_revoke('permission.key')
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def permission_revoke(key)
|
|
|
|
permission = Permission.lookup(name: key)
|
|
|
|
raise "Invalid permission #{key}" if !permission
|
|
|
|
return true if !permission_ids.include?(permission.id)
|
|
|
|
self.permission_ids = self.permission_ids -= [permission.id]
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
get signup roles
|
|
|
|
|
|
|
|
Role.signup_roles
|
|
|
|
|
2016-12-08 14:06:54 +00:00
|
|
|
returns
|
2016-08-12 16:39:09 +00:00
|
|
|
|
|
|
|
[role1, role2, ...]
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.signup_roles
|
|
|
|
Role.where(active: true, default_at_signup: true)
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
get signup role ids
|
|
|
|
|
|
|
|
Role.signup_role_ids
|
|
|
|
|
2016-12-08 14:06:54 +00:00
|
|
|
returns
|
2016-08-12 16:39:09 +00:00
|
|
|
|
|
|
|
[role1, role2, ...]
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.signup_role_ids
|
|
|
|
Role.where(active: true, default_at_signup: true).map(&:id)
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
get all roles with permission
|
|
|
|
|
|
|
|
roles = Role.with_permissions('admin.session')
|
|
|
|
|
|
|
|
get all roles with permission "admin.session" or "ticket.agent"
|
|
|
|
|
|
|
|
roles = Role.with_permissions(['admin.session', 'ticket.agent'])
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
2017-02-15 12:29:25 +00:00
|
|
|
[role1, role2, ...]
|
2016-08-12 16:39:09 +00:00
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.with_permissions(keys)
|
2017-10-20 11:32:52 +00:00
|
|
|
permission_ids = Role.permission_ids_by_name(keys)
|
|
|
|
Role.joins(:roles_permissions).joins(:permissions).where(
|
|
|
|
'permissions_roles.permission_id IN (?) AND roles.active = ? AND permissions.active = ?', permission_ids, true, true
|
|
|
|
).distinct()
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
check if roles is with permission
|
|
|
|
|
|
|
|
role = Role.find(123)
|
|
|
|
role.with_permission?('admin.session')
|
|
|
|
|
|
|
|
get if role has permission of "admin.session" or "ticket.agent"
|
|
|
|
|
|
|
|
role.with_permission?(['admin.session', 'ticket.agent'])
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
true | false
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def with_permission?(keys)
|
|
|
|
permission_ids = Role.permission_ids_by_name(keys)
|
|
|
|
return true if Role.joins(:roles_permissions).joins(:permissions).where(
|
|
|
|
'roles.id = ? AND permissions_roles.permission_id IN (?) AND permissions.active = ?', id, permission_ids, true
|
|
|
|
).distinct().count.nonzero?
|
|
|
|
false
|
|
|
|
end
|
|
|
|
|
|
|
|
private_class_method
|
|
|
|
|
|
|
|
def self.permission_ids_by_name(keys)
|
2016-08-12 16:39:09 +00:00
|
|
|
if keys.class != Array
|
|
|
|
keys = [keys]
|
|
|
|
end
|
|
|
|
permission_ids = []
|
2017-10-01 12:25:52 +00:00
|
|
|
keys.each do |key|
|
2017-10-20 11:32:52 +00:00
|
|
|
::Permission.with_parents(key).each do |local_key|
|
|
|
|
permission = ::Permission.lookup(name: local_key)
|
2016-08-12 16:39:09 +00:00
|
|
|
next if !permission
|
|
|
|
permission_ids.push permission.id
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
|
|
|
end
|
2017-10-20 11:32:52 +00:00
|
|
|
permission_ids
|
2016-08-12 16:39:09 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def validate_permissions
|
2017-06-16 22:53:20 +00:00
|
|
|
return true if !self.permission_ids
|
2017-10-01 12:25:52 +00:00
|
|
|
permission_ids.each do |permission_id|
|
2016-08-12 16:39:09 +00:00
|
|
|
permission = Permission.lookup(id: permission_id)
|
|
|
|
raise "Unable to find permission for id #{permission_id}" if !permission
|
|
|
|
raise "Permission #{permission.name} is disabled" if permission.preferences[:disabled] == true
|
|
|
|
next unless permission.preferences[:not]
|
2017-10-01 12:25:52 +00:00
|
|
|
permission.preferences[:not].each do |local_permission_name|
|
2016-08-12 16:39:09 +00:00
|
|
|
local_permission = Permission.lookup(name: local_permission_name)
|
|
|
|
next if !local_permission
|
|
|
|
raise "Permission #{permission.name} conflicts with #{local_permission.name}" if permission_ids.include?(local_permission.id)
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
|
|
|
end
|
2017-06-16 22:53:20 +00:00
|
|
|
true
|
2016-08-12 16:39:09 +00:00
|
|
|
end
|
|
|
|
|
2017-10-20 11:32:52 +00:00
|
|
|
def last_admin_check_by_attribute
|
|
|
|
return true if !will_save_change_to_attribute?('active')
|
|
|
|
return true if active != false
|
|
|
|
return true if !with_permission?(['admin', 'admin.user'])
|
|
|
|
raise Exceptions::UnprocessableEntity, 'Minimum one user needs to have admin permissions.' if last_admin_check_admin_count < 1
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
def last_admin_check_by_permission(permission)
|
|
|
|
return true if Setting.get('import_mode')
|
|
|
|
return true if permission.name != 'admin' && permission.name != 'admin.user'
|
|
|
|
raise Exceptions::UnprocessableEntity, 'Minimum one user needs to have admin permissions.' if last_admin_check_admin_count < 1
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
def last_admin_check_admin_count
|
|
|
|
admin_role_ids = Role.joins(:permissions).where(permissions: { name: ['admin', 'admin.user'], active: true }, roles: { active: true }).where.not(id: id).pluck(:id)
|
|
|
|
User.joins(:roles).where(roles: { id: admin_role_ids }, users: { active: true }).count
|
|
|
|
end
|
|
|
|
|
|
|
|
def validate_agent_limit_by_attributes
|
|
|
|
return true if !Setting.get('system_agent_limit')
|
|
|
|
return true if !will_save_change_to_attribute?('active')
|
|
|
|
return true if active != true
|
|
|
|
return true if !with_permission?('ticket.agent')
|
|
|
|
ticket_agent_role_ids = Role.joins(:permissions).where(permissions: { name: 'ticket.agent', active: true }, roles: { active: true }).pluck(:id)
|
|
|
|
currents = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).pluck(:id)
|
|
|
|
news = User.joins(:roles).where(roles: { id: id }, users: { active: true }).pluck(:id)
|
|
|
|
count = currents.concat(news).uniq.count
|
|
|
|
raise Exceptions::UnprocessableEntity, 'Agent limit exceeded, please check your account settings.' if count > Setting.get('system_agent_limit')
|
|
|
|
true
|
|
|
|
end
|
|
|
|
|
|
|
|
def validate_agent_limit_by_permission(permission)
|
2017-06-16 22:53:20 +00:00
|
|
|
return true if !Setting.get('system_agent_limit')
|
2017-10-20 11:32:52 +00:00
|
|
|
return true if active != true
|
|
|
|
return true if permission.active != true
|
2017-06-16 22:53:20 +00:00
|
|
|
return true if permission.name != 'ticket.agent'
|
2017-10-20 11:32:52 +00:00
|
|
|
ticket_agent_role_ids = Role.joins(:permissions).where(permissions: { name: 'ticket.agent' }, roles: { active: true }).pluck(:id)
|
2017-04-18 07:38:53 +00:00
|
|
|
ticket_agent_role_ids.push(id)
|
|
|
|
count = User.joins(:roles).where(roles: { id: ticket_agent_role_ids }, users: { active: true }).count
|
|
|
|
raise Exceptions::UnprocessableEntity, 'Agent limit exceeded, please check your account settings.' if count > Setting.get('system_agent_limit')
|
2017-06-16 22:53:20 +00:00
|
|
|
true
|
2017-04-18 07:38:53 +00:00
|
|
|
end
|
|
|
|
|
2015-04-27 14:15:29 +00:00
|
|
|
end
|