Fixes #3186 - Endpoint api/v1/ticket_articles/by_ticket ignores X-On-Behalf-Of
This commit is contained in:
parent
3af0e35821
commit
5dde117a14
5 changed files with 78 additions and 34 deletions
|
@ -22,39 +22,6 @@ module ApplicationController::Authorizes
|
|||
[:controllers, self]
|
||||
end
|
||||
|
||||
# We need a special UserContext when authorizing in controller context
|
||||
# because of Token authentication which has it's own permissions
|
||||
# See: https://github.com/varvet/pundit#additional-context
|
||||
# We use a Delegator here to have transparent / DuckType access
|
||||
# to the underlying User instance in the Policy
|
||||
class UserContext < Delegator
|
||||
|
||||
def initialize(user, token)
|
||||
@user = user
|
||||
@token = token
|
||||
end
|
||||
|
||||
def __getobj__
|
||||
@user
|
||||
end
|
||||
|
||||
def permissions!(permissions)
|
||||
raise Exceptions::NotAuthorized, 'authentication failed' if !@user
|
||||
raise Exceptions::NotAuthorized, 'Not authorized (user)!' if !@user.permissions?(permissions)
|
||||
return if !@token
|
||||
return if @token.permissions?(permissions)
|
||||
|
||||
raise Exceptions::NotAuthorized, 'Not authorized (token)!'
|
||||
end
|
||||
|
||||
def permissions?(permissions)
|
||||
permissions!(permissions)
|
||||
true
|
||||
rescue Exceptions::NotAuthorized
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def pundit_user
|
||||
@pundit_user ||= UserContext.new(current_user, @_token)
|
||||
end
|
||||
|
|
|
@ -109,11 +109,22 @@ cleanup old token
|
|||
end
|
||||
|
||||
def permissions?(names)
|
||||
return false if !user.permissions?(names)
|
||||
return false if !effective_user.permissions?(names)
|
||||
|
||||
super(names)
|
||||
end
|
||||
|
||||
# allows to evaluate token permissions in context of given user instead of owner
|
||||
# @param [User] user to use as context for the given block
|
||||
# @param block to evaluate in given context
|
||||
def with_context(user:, &block)
|
||||
@effective_user = user
|
||||
|
||||
instance_eval(&block) if block_given?
|
||||
ensure
|
||||
@effective_user = nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_token
|
||||
|
@ -123,4 +134,9 @@ cleanup old token
|
|||
end
|
||||
true
|
||||
end
|
||||
|
||||
# token owner or user set by #with_context
|
||||
def effective_user
|
||||
@effective_user || user
|
||||
end
|
||||
end
|
||||
|
|
32
lib/user_context.rb
Normal file
32
lib/user_context.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
# We need a special UserContext when authorizing in controller context
|
||||
# because of Token authentication which has it's own permissions
|
||||
# See: https://github.com/varvet/pundit#additional-context
|
||||
# We use a Delegator here to have transparent / DuckType access
|
||||
# to the underlying User instance in the Policy
|
||||
class UserContext < Delegator
|
||||
|
||||
def initialize(user, token)
|
||||
@user = user
|
||||
@token = token
|
||||
end
|
||||
|
||||
def __getobj__
|
||||
@user
|
||||
end
|
||||
|
||||
def permissions!(permissions)
|
||||
raise Exceptions::NotAuthorized, 'authentication failed' if !@user
|
||||
raise Exceptions::NotAuthorized, 'Not authorized (user)!' if !@user.permissions?(permissions)
|
||||
return if !@token
|
||||
return if @token.with_context(user: @user) { permissions?(permissions) }
|
||||
|
||||
raise Exceptions::NotAuthorized, 'Not authorized (token)!'
|
||||
end
|
||||
|
||||
def permissions?(permissions)
|
||||
permissions!(permissions)
|
||||
true
|
||||
rescue Exceptions::NotAuthorized
|
||||
false
|
||||
end
|
||||
end
|
|
@ -7,5 +7,9 @@ FactoryBot.define do
|
|||
factory :agent_role do
|
||||
permissions { Permission.where(name: 'ticket.agent') }
|
||||
end
|
||||
|
||||
trait :admin do
|
||||
permissions { Permission.where(name: 'admin') }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
25
spec/lib/user_context_spec.rb
Normal file
25
spec/lib/user_context_spec.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe UserContext do
|
||||
subject(:user_context) { described_class.new(user, token) }
|
||||
|
||||
describe '#permissions?' do
|
||||
context 'when user with ticket.agent permission' do
|
||||
let(:user) { create(:user, roles: [create(:agent_role)]) }
|
||||
let(:token) { nil }
|
||||
|
||||
it { is_expected.to be_permissions('ticket.agent') }
|
||||
it { is_expected.not_to be_permissions('admin') }
|
||||
end
|
||||
|
||||
# https://github.com/zammad/zammad/issues/3186
|
||||
context 'when user with ticket.agent permission and token created by user who doesn\'t' do
|
||||
let(:user) { create(:user, roles: [create(:agent_role)]) }
|
||||
let(:token_owner) { create(:user, roles: [create(:role, :admin)]) }
|
||||
let(:token) { create(:token, user: token_owner, preferences: { permission: %w[ticket.agent] }) }
|
||||
|
||||
it { is_expected.to be_permissions('ticket.agent') }
|
||||
it { is_expected.not_to be_permissions('admin') }
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue