Maintenance: Add assets level to have different data sets based on permissions

This commit is contained in:
Rolf Schmidt 2021-09-22 16:57:27 +02:00 committed by Thorsten Eckel
parent acc93a23fb
commit 867b36baa8
11 changed files with 284 additions and 6 deletions

View file

@ -121,7 +121,7 @@ returns
key = "#{self.class}::aws::#{id}" key = "#{self.class}::aws::#{id}"
cache = Cache.read(key) cache = Cache.read(key)
return cache if cache return filter_unauthorized_attributes(cache) if cache
attributes = self.attributes attributes = self.attributes
relevant = %i[has_and_belongs_to_many has_many] relevant = %i[has_and_belongs_to_many has_many]
@ -160,7 +160,7 @@ returns
filter_attributes(attributes) filter_attributes(attributes)
Cache.write(key, attributes) Cache.write(key, attributes)
attributes filter_unauthorized_attributes(attributes)
end end
=begin =begin
@ -234,8 +234,7 @@ returns
end end
filter_attributes(attributes) filter_attributes(attributes)
filter_unauthorized_attributes(attributes)
attributes
end end
def filter_attributes(attributes) def filter_attributes(attributes)
@ -243,6 +242,10 @@ returns
attributes.except!('password', 'token', 'tokens', 'token_ids') attributes.except!('password', 'token', 'tokens', 'token_ids')
end end
def filter_unauthorized_attributes(attributes)
attributes
end
=begin =begin
reference if association id check reference if association id check

View file

@ -12,6 +12,8 @@ class Group < ApplicationModel
include HasTicketCreateScreenImpact include HasTicketCreateScreenImpact
include HasSearchIndexBackend include HasSearchIndexBackend
include Group::Assets
belongs_to :email_address, optional: true belongs_to :email_address, optional: true
belongs_to :signature, optional: true belongs_to :signature, optional: true

View file

@ -0,0 +1,14 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
class Group
module Assets
extend ActiveSupport::Concern
def filter_unauthorized_attributes(attributes)
return super if UserInfo.assets.blank? || UserInfo.assets.agent?
attributes = super
attributes.slice('id', 'name', 'active')
end
end
end

View file

@ -43,7 +43,7 @@ class ObjectManager::Element::Backend
end end
def screens def screens
attribute.screens.transform_values do |permission_options| @screens ||= attribute.screens.transform_values do |permission_options|
screen_value(permission_options) screen_value(permission_options)
end end
end end

View file

@ -70,5 +70,12 @@ returns
end end
data data
end end
def filter_unauthorized_attributes(attributes)
return super if UserInfo.assets.blank? || UserInfo.assets.agent?
attributes = super
attributes.slice('id', 'name', 'active')
end
end end
end end

View file

@ -60,5 +60,13 @@ returns
end end
data data
end end
def filter_unauthorized_attributes(attributes)
return super if UserInfo.assets.blank? || UserInfo.assets.agent?
attributes = super
attributes['name'] = "Role_#{id}"
attributes.slice('id', 'name', 'group_ids', 'permission_ids', 'active')
end
end end
end end

View file

@ -110,5 +110,20 @@ returns
end end
data data
end end
def filter_unauthorized_attributes(attributes)
return super if UserInfo.assets.blank? || UserInfo.assets.agent?
# customer assets for the user session
if UserInfo.current_user_id == id
attributes = super
attributes.except!('web', 'phone', 'mobile', 'fax', 'department', 'street', 'zip', 'city', 'country', 'address', 'note')
return attributes
end
# customer assets for other user
attributes = super
attributes.slice('id', 'firstname', 'lastname', 'image', 'image_source', 'active')
end
end end
end end

View file

@ -4,7 +4,7 @@ module SessionHelper
def self.json_hash(user) def self.json_hash(user)
collections, assets = default_collections(user) collections, assets = default_collections(user)
{ {
session: user.filter_attributes(user.attributes), session: user.filter_unauthorized_attributes(user.filter_attributes(user.attributes)),
models: models(user), models: models(user),
collections: collections, collections: collections,
assets: assets, assets: assets,

View file

@ -7,6 +7,11 @@ module UserInfo
def self.current_user_id=(user_id) def self.current_user_id=(user_id)
Thread.current[:user_id] = user_id Thread.current[:user_id] = user_id
Thread.current[:assets] = UserInfo::Assets.new(user_id)
end
def self.assets
Thread.current[:assets]
end end
def self.ensure_current_user_id def self.ensure_current_user_id

52
lib/user_info/assets.rb Normal file
View file

@ -0,0 +1,52 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
class UserInfo::Assets
LEVEL_CUSTOMER = 1
LEVEL_AGENT = 2
LEVEL_ADMIN = 3
attr_accessor :current_user_id, :level, :filter_attributes, :user
def initialize(current_user_id)
@current_user_id = current_user_id
@user = User.find_by(id: current_user_id) if current_user_id.present?
set_level
end
def admin?
check_level?(UserInfo::Assets::LEVEL_ADMIN)
end
def agent?
check_level?(UserInfo::Assets::LEVEL_AGENT)
end
def customer?
check_level?(UserInfo::Assets::LEVEL_CUSTOMER)
end
def set_level
if user.blank?
self.level = nil
return
end
self.level = UserInfo::Assets::LEVEL_CUSTOMER
Permission.where(id: user.permissions_with_child_ids).each do |permission|
case permission.name
when %r{^admin\.}
self.level = UserInfo::Assets::LEVEL_ADMIN
break
when 'ticket.agent'
self.level = UserInfo::Assets::LEVEL_AGENT
end
end
end
def check_level?(check)
return true if user.blank?
level >= check
end
end

View file

@ -0,0 +1,172 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'rails_helper'
RSpec.describe 'Assets', type: :system, db_strategy: :reset do
let(:organization) { create(:organization, note: 'hello') }
let(:customer) { create(:customer, organization: organization, note: 'hello', last_login: Time.zone.now, login_failed: 1) }
let(:agent) { create(:agent, groups: [Group.find_by(name: 'Users')], note: 'hello', last_login: Time.zone.now, login_failed: 1) }
let(:admin) { create(:admin, groups: [Group.find_by(name: 'Users')], note: 'hello', last_login: Time.zone.now, login_failed: 1) }
let(:ticket) { create(:ticket, owner: agent, group: Group.find_by(name: 'Users'), customer: customer, created_by: admin) }
context 'groups' do
def group_note
page.execute_script('return App.Group.first().note')
end
describe 'when customer', authenticated_as: :customer do
it 'can not access group details' do
expect(group_note).to be nil
end
end
describe 'when agent', authenticated_as: :agent do
it 'can access group details' do
expect(group_note).not_to be nil
end
end
describe 'when admin', authenticated_as: :admin do
it 'can access group details' do
expect(group_note).not_to be nil
end
end
end
context 'organizations' do
def organization_note
page.execute_script("return App.Organization.find(#{organization.id}).note")
end
before do
visit "#ticket/zoom/#{ticket.id}"
end
describe 'when customer', authenticated_as: :customer do
it 'can not access organization details' do
expect(organization_note).to be nil
end
end
describe 'when agent', authenticated_as: :agent do
it 'can access organization details' do
expect(organization_note).not_to be nil
end
end
describe 'when admin', authenticated_as: :admin do
it 'can access organization details' do
expect(organization_note).not_to be nil
end
end
end
context 'roles' do
def role_name
page.execute_script('return App.Role.first().name')
end
before do
visit "#ticket/zoom/#{ticket.id}"
end
describe 'when customer', authenticated_as: :customer do
it 'can not access role details' do
expect(role_name).to eq('Role_1')
end
end
describe 'when agent', authenticated_as: :agent do
it 'can access role details' do
expect(role_name).not_to eq('Role_1')
end
end
describe 'when admin', authenticated_as: :admin do
it 'can access role details' do
expect(role_name).not_to eq('Role_1')
end
end
end
context 'users' do
def customer_email
page.execute_script("return App.User.find(#{customer.id}).email")
end
def customer_note
page.execute_script("return App.User.find(#{customer.id}).note")
end
def owner_firstname
page.execute_script("return App.User.find(#{agent.id}).firstname")
end
def owner_details
[
page.execute_script("return App.User.find(#{agent.id}).last_login"),
page.execute_script("return App.User.find(#{agent.id}).login_failed"),
page.execute_script("return App.User.find(#{agent.id}).email"),
page.execute_script("return App.User.find(#{agent.id}).note"),
].compact
end
before do
visit "#ticket/zoom/#{ticket.id}"
end
describe 'when customer', authenticated_as: :customer do
it 'can access customer email' do
expect(customer_email).not_to be nil
end
it 'can not access customer note' do
expect(customer_note).to be nil
end
it 'can not access owner details' do
expect(owner_details).to be_empty
end
it 'can access owner firstname' do
expect(owner_firstname).not_to be nil
end
end
describe 'when agent', authenticated_as: :agent do
it 'can access customer email' do
expect(customer_email).not_to be nil
end
it 'can access customer note' do
expect(customer_note).not_to be nil
end
it 'can access owner details' do
expect(owner_details).not_to be_empty
end
it 'can access owner firstname' do
expect(owner_firstname).not_to be nil
end
end
describe 'when admin', authenticated_as: :admin do
it 'can access customer email' do
expect(customer_email).not_to be nil
end
it 'can access customer note' do
expect(customer_note).not_to be nil
end
it 'can access owner details' do
expect(owner_details).not_to be_empty
end
it 'can access owner firstname' do
expect(owner_firstname).not_to be nil
end
end
end
end