Refactoring: Replaced home-rolled authorization logic in Controllers with Pundit.

This commit is contained in:
Ryan Lue 2020-03-19 10:39:51 +01:00 committed by Thorsten Eckel
parent 706e51d27b
commit becbdb1baa
153 changed files with 1168 additions and 939 deletions

View file

@ -220,7 +220,7 @@ Naming/MethodParameterName:
Checks for method parameter names that contain capital letters,
end in numbers, or do not meet a minimal length.
Enabled: true
AllowedNames: e, id, _, ip
AllowedNames: e, id, _, ip, to
Lint/BooleanSymbol:
Description: 'Check for `:true` and `:false` symbols.'

View file

@ -35,6 +35,9 @@ gem 'argon2'
# core - state machine
gem 'aasm'
# core - authorization
gem 'pundit'
# performance - Memcached
gem 'dalli'
@ -151,6 +154,9 @@ group :development, :test do
gem 'shoulda-matchers'
gem 'test-unit'
# for testing Pundit authorisation policies in RSpec
gem 'pundit-matchers'
# code coverage
gem 'coveralls', require: false
gem 'simplecov'

View file

@ -378,6 +378,10 @@ GEM
pry (>= 0.9.11)
public_suffix (3.0.3)
puma (3.12.4)
pundit (2.0.1)
activesupport (>= 3.0.0)
pundit-matchers (1.6.0)
rspec-rails (>= 3.0.0)
rack (2.2.2)
rack-livereload (0.3.17)
rack
@ -627,6 +631,8 @@ DEPENDENCIES
pry-rescue
pry-stack_explorer
puma (~> 3.12)
pundit
pundit-matchers
rack-livereload
rails (= 5.2.4.1)
rails-controller-testing

View file

@ -303,7 +303,7 @@ class App.User extends App.Model
Checks if requester has given access level on requested.
Possible access levels are: read, update and delete
See backend method User#access?
See backend policy UserPolicy
requester = App.User.find(1)
requested = App.User.find(3)

View file

@ -1,47 +0,0 @@
class ApplicationChannelController < ApplicationController
# Extending controllers has to define following constants:
# PERMISSION = "admin.channel_xyz"
# AREA = "XYZ::Account"
def index
render json: channels_data
end
def show
model_show_render(Channel, params)
end
def create
model_create_render(Channel, channel_params)
end
def update
model_update_render(Channel, channel_params)
end
def enable
channel.update!(active: true)
render json: channel
end
def disable
channel.update!(active: false)
render json: channel
end
def destroy
channel.destroy!
render json: {}
end
private
def channel
@channel ||= Channel.lookup(id: params[:id])
end
def channel_params
params.permit!.to_s
end
end

View file

@ -12,5 +12,5 @@ class ApplicationController < ActionController::Base
include ApplicationController::PreventsCsrf
include ApplicationController::HasSecureContentSecurityPolicyForDownloads
include ApplicationController::LogsHttpAccess
include ApplicationController::ChecksAccess
include ApplicationController::Authorizes
end

View file

@ -4,6 +4,8 @@ module ApplicationController::Authenticates
private
def permission_check(key)
ActiveSupport::Deprecation.warn("Method 'permission_check' is deprecated. Use Pundit policy and `authorize!` instead.")
if @_token_auth
user = Token.check(
action: 'api',
@ -76,6 +78,8 @@ module ApplicationController::Authenticates
inactive_user: true,
)
if user && auth_param[:permission]
ActiveSupport::Deprecation.warn("Paramter ':permission' is deprecated. Use Pundit policy and `authorize!` instead.")
user = Token.check(
action: 'api',
name: token_string,
@ -95,6 +99,8 @@ module ApplicationController::Authenticates
Time.zone.today >= token.expires_at
raise Exceptions::NotAuthorized, 'Not authorized (token expired)!'
end
@_token = token # remember for Pundit authorization / permit!
end
@_token_auth = token_string # remember for permission_check
@ -152,7 +158,14 @@ module ApplicationController::Authenticates
def authentication_check_prerequesits(user, auth_type, auth_param)
raise Exceptions::NotAuthorized, 'Maintenance mode enabled!' if in_maintenance_mode?(user)
raise Exceptions::NotAuthorized, 'User is inactive!' if !user.active
raise Exceptions::NotAuthorized, 'Not authorized (user)!' if auth_param[:permission] && !user.permissions?(auth_param[:permission])
if auth_param[:permission]
ActiveSupport::Deprecation.warn("Parameter ':permission' is deprecated. Use Pundit policy and `authorize!` instead.")
if !user.permissions?(auth_param[:permission])
raise Exceptions::NotAuthorized, 'Not authorized (user)!'
end
end
current_user_set(user, auth_type)
user_device_log(user, auth_type)

View file

@ -0,0 +1,61 @@
module ApplicationController::Authorizes
extend ActiveSupport::Concern
include Pundit
private
def authorize!(record = policy_record, query = nil)
authorize(record, query)
end
def authorized?(record = policy_record, query = nil)
authorize!(record, query)
true
rescue Exceptions::NotAuthorized, Pundit::NotAuthorizedError
false
end
def policy_record
# check permissions in matching Pundit policy
# Controllers namspace is used (See: https://github.com/varvet/pundit#policy-namespacing)
# [:controllers, self] => Controllers::RolesControllerPolicy
[: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
end

View file

@ -1,9 +0,0 @@
module ApplicationController::ChecksAccess
extend ActiveSupport::Concern
private
def access!(instance, access)
instance.access!(current_user, access)
end
end

View file

@ -11,6 +11,7 @@ module ApplicationController::HandlesErrors
rescue_from ArgumentError, with: :unprocessable_entity
rescue_from Exceptions::UnprocessableEntity, with: :unprocessable_entity
rescue_from Exceptions::NotAuthorized, with: :unauthorized
rescue_from Pundit::NotAuthorizedError, with: :pundit_not_authorized_error
end
def not_found(e)
@ -32,12 +33,22 @@ module ApplicationController::HandlesErrors
end
def unauthorized(e)
logger.info { e }
error = humanize_error(e)
response.headers['X-Failure'] = error.fetch(:error_human, error[:error])
respond_to_exception(e, :unauthorized)
http_log
end
def pundit_not_authorized_error(e)
logger.info { e }
# check if a special authorization_error should be shown in the result payload
# which was raised in one of the policies. Fall back to a simple "Not authorized"
# error to hide actual cause for security reasons.
exeption = e.policy.custom_exception || Exceptions::NotAuthorized.new
unauthorized(exeption)
end
private
def respond_to_exception(e, status)

View file

@ -95,10 +95,4 @@ module ApplicationController::HasUser
session[:user_agent] = request.env['HTTP_USER_AGENT']
end
def valid_session_with_user
return true if current_user
raise Exceptions::UnprocessableEntity, 'No session user!'
end
end

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class ApplicationsController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.api') }
prepend_before_action { authentication_check && authorize! }
def index
all = Doorkeeper::Application.all

View file

@ -1,6 +1,6 @@
# Copyright (C) 2012-2015 Zammad Foundation, http://zammad-foundation.org/
class CalendarSubscriptionsController < ApplicationController
prepend_before_action { authentication_check( { basic_auth_promt: true, permission: 'user_preferences.calendar' } ) }
prepend_before_action { authentication_check(basic_auth_promt: true) && authorize! }
# @path [GET] /calendar_subscriptions
#

View file

@ -1,8 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class CalendarsController < ApplicationController
prepend_before_action -> { authentication_check(permission: 'admin.calendar') }, only: %i[init index show create update destroy]
prepend_before_action -> { authentication_check(permission: 'admin') }, only: %i[timezones]
prepend_before_action { authentication_check && authorize! }
def init
assets = {}

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class ChannelsEmailController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.channel_email') }
prepend_before_action { authentication_check && authorize! }
def index
system_online_service = Setting.get('system_online_service')

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class ChannelsFacebookController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.channel_facebook') }
prepend_before_action { authentication_check && authorize! }
def index
assets = {}

View file

@ -1,8 +1,5 @@
class ChannelsSmsController < ApplicationChannelController
PERMISSION = 'admin.channel_sms'.freeze
AREA = ['Sms::Notification'.freeze, 'Sms::Account'.freeze].freeze
prepend_before_action -> { authentication_check(permission: self.class::PERMISSION) }, except: [:webhook]
class ChannelsSmsController < ApplicationController
prepend_before_action -> { authentication_check && authorize! }, except: [:webhook]
skip_before_action :verify_csrf_token, only: [:webhook]
def index
@ -15,6 +12,33 @@ class ChannelsSmsController < ApplicationChannelController
}
end
def show
model_show_render(Channel, params)
end
def create
model_create_render(Channel, channel_params)
end
def update
model_update_render(Channel, channel_params)
end
def enable
channel.update!(active: true)
render json: channel
end
def disable
channel.update!(active: false)
render json: channel
end
def destroy
channel.destroy!
render json: {}
end
def test
raise 'Missing parameter options.adapter' if params[:options][:adapter].blank?
@ -49,13 +73,17 @@ class ChannelsSmsController < ApplicationChannelController
private
def channel
@channel ||= Channel.lookup(id: params[:id])
end
def test_options
params.permit(:recipient, :message)
end
def channel_params
raise 'Missing area params' if params[:area].blank?
if !self.class::AREA.include?(params[:area])
if ['Sms::Notification', 'Sms::Account'].exclude?(params[:area])
raise "Invalid area '#{params[:area]}'!"
end
raise 'Missing options params' if params[:options].blank?

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class ChannelsTelegramController < ApplicationController
prepend_before_action -> { authentication_check(permission: 'admin.channel_telegram') }, except: [:webhook]
prepend_before_action -> { authentication_check && authorize! }, except: [:webhook]
skip_before_action :verify_csrf_token, only: [:webhook]
def index

View file

@ -2,7 +2,7 @@
require_dependency 'channel/driver/twitter'
class ChannelsTwitterController < ApplicationController
prepend_before_action -> { authentication_check(permission: 'admin.channel_twitter') }, except: %i[webhook_incoming webhook_verify]
prepend_before_action -> { authentication_check && authorize! }, except: %i[webhook_incoming webhook_verify]
skip_before_action :verify_csrf_token, only: %i[webhook_incoming webhook_verify]
before_action :validate_webhook_signature!, only: :webhook_incoming

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class ChatSessionsController < ApplicationController
prepend_before_action { authentication_check(permission: 'chat.agent') }
prepend_before_action { authentication_check && authorize! }
def show
model_show_render(Chat::Session, params)

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class ChatsController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.channel_chat') }
prepend_before_action { authentication_check && authorize! }
def index
chat_ids = []

View file

@ -4,12 +4,11 @@ module ChecksUserAttributesByCurrentUserPermission
private
def check_attributes_by_current_user_permission(params)
authorize!
# admins can do whatever they want
return true if current_user.permissions?('admin.user')
# non-agents (customers) can't set anything
raise Exceptions::NotAuthorized if !current_user.permissions?('ticket.agent')
# regular agents are not allowed to set Groups and Roles
%w[Role Group].each do |model|

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class CtiController < ApplicationController
prepend_before_action { authentication_check(permission: 'cti.agent') }
prepend_before_action { authentication_check && authorize! }
# list current caller log
# GET /api/v1/cti/log

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class EmailAddressesController < ApplicationController
prepend_before_action :authentication_check
prepend_before_action { authentication_check && authorize! }
=begin
@ -46,7 +46,6 @@ curl http://localhost/api/v1/email_addresses.json -v -u #{login}:#{password}
=end
def index
permission_check(['admin.channel_email', 'ticket.agent'])
model_index_render(EmailAddress, params)
end
@ -68,7 +67,6 @@ curl http://localhost/api/v1/email_addresses/#{id}.json -v -u #{login}:#{passwor
=end
def show
permission_check(['admin.channel_email', 'ticket.agent'])
model_show_render(EmailAddress, params)
end
@ -99,7 +97,6 @@ curl http://localhost/api/v1/email_addresses.json -v -u #{login}:#{password} -H
=end
def create
permission_check('admin.channel_email')
model_create_render(EmailAddress, params)
end
@ -130,7 +127,6 @@ curl http://localhost/api/v1/email_addresses/#{id}.json -v -u #{login}:#{passwor
=end
def update
permission_check('admin.channel_email')
model_update_render(EmailAddress, params)
end
@ -148,7 +144,6 @@ curl http://localhost/api/v1/email_addresses/#{id}.json -v -u #{login}:#{passwor
=end
def destroy
permission_check('admin.channel_email')
model_destroy_render(EmailAddress, params)
end
end

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class ExternalCredentialsController < ApplicationController
prepend_before_action :permission_check
prepend_before_action { authentication_check && authorize! }
def index
model_index_render(ExternalCredential, params)
@ -53,29 +53,4 @@ class ExternalCredentialsController < ApplicationController
def app_url(provider, channel_id)
ExternalCredential.app_url(provider, channel_id)
end
def permission_check
if params[:id].present? && ExternalCredential.exists?(params[:id])
external_credential = ExternalCredential.find(params[:id])
raise 'No such ExternalCredential!' if !external_credential
authentication_check(permission: ["admin.channel_#{external_credential.name}"])
return
end
if params[:name].present? || params[:provider].present?
if params[:name].present?
name = params[:name].downcase
elsif params[:provider].present?
name = params[:provider].downcase
else
raise 'Missing name/provider!'
end
authentication_check(permission: ["admin.channel_#{name}"])
return
end
authentication_check(permission: ['admin'])
end
end

View file

@ -3,9 +3,9 @@
class FirstStepsController < ApplicationController
prepend_before_action :authentication_check
def index
return if !access?
before_action -> { render json: [] }, if: -> { !authorized? }
def index
invite_agents = false
#if User.of_role('Agent').count > 2
# invite_agents = true
@ -169,8 +169,6 @@ class FirstStepsController < ApplicationController
end
def test_ticket
return if !access?
agent = current_user
customer = test_customer
from = "#{customer.fullname} <#{customer.email}>"
@ -221,13 +219,6 @@ class FirstStepsController < ApplicationController
User.find_by(login: 'nicole.braun@zammad.org')
end
def access?
return true if current_user.permissions?(['admin', 'ticket.agent'])
render json: []
false
end
def check_availability(result)
test_ticket_active = true
overview = test_overview

View file

@ -1,13 +1,14 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
class FormController < ApplicationController
prepend_before_action -> { authorize! }, only: %i[configuration submit]
skip_before_action :verify_csrf_token
before_action :cors_preflight_check
after_action :set_access_control_headers_execute
skip_before_action :user_device_check
def configuration
return if !enabled?
return if !fingerprint_exists?
return if limit_reached?
@ -23,7 +24,7 @@ class FormController < ApplicationController
token: token_gen(params[:fingerprint])
}
if params[:test] && current_user && current_user.permissions?('admin.channel_formular')
if authorized?(policy_record, :test?)
result[:enabled] = true
end
@ -31,7 +32,6 @@ class FormController < ApplicationController
end
def submit
return if !enabled?
return if !fingerprint_exists?
return if !token_valid?(params[:token], params[:fingerprint])
return if limit_reached?
@ -144,6 +144,14 @@ class FormController < ApplicationController
private
# we don't wann to tell what the cause for the authorization error is
# so we capture the exception and raise an anonymized one
def authorize!(*)
super
rescue Pundit::NotAuthorizedError
raise Exceptions::NotAuthorized
end
def token_gen(fingerprint)
crypt = ActiveSupport::MessageEncryptor.new(Setting.get('application_secret')[0, 32])
fingerprint = "#{Base64.strict_encode64(Setting.get('fqdn'))}:#{Time.zone.now.to_i}:#{Base64.strict_encode64(fingerprint)}"
@ -216,12 +224,4 @@ class FormController < ApplicationController
Rails.logger.info 'No fingerprint given!'
raise Exceptions::NotAuthorized
end
def enabled?
return true if params[:test] && current_user && current_user.permissions?('admin.channel_formular')
return true if Setting.get('form_ticket_create')
raise Exceptions::NotAuthorized
end
end

View file

@ -1,5 +1,6 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class GettingStartedController < ApplicationController
prepend_before_action -> { authorize! }, only: [:base]
=begin
@ -105,10 +106,6 @@ curl http://localhost/api/v1/getting_started -v -u #{login}:#{password}
end
def base
# check admin permissions
permission_check('admin.wizard')
# validate url
messages = {}
settings = {}

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class GroupsController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.group') }
prepend_before_action { authentication_check && authorize! }
=begin

View file

@ -1,11 +1,10 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class HttpLogsController < ApplicationController
prepend_before_action :authentication_check
prepend_before_action { authentication_check && authorize! }
# GET /http_logs/:facility
def index
permission_check('admin.*')
list = if params[:facility]
HttpLog.where(facility: params[:facility]).order(created_at: :desc).limit(params[:limit] || 50)
else
@ -16,7 +15,6 @@ class HttpLogsController < ApplicationController
# POST /http_logs
def create
permission_check('admin.*')
model_create_render(HttpLog, params)
end

View file

@ -3,7 +3,7 @@
class Integration::ExchangeController < ApplicationController
include Integration::ImportJobBase
prepend_before_action { authentication_check(permission: 'admin.integration.exchange') }
prepend_before_action { authentication_check && authorize! }
def autodiscover
answer_with do

View file

@ -1,9 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class Integration::IdoitController < ApplicationController
prepend_before_action -> { authentication_check(permission: ['agent.integration.idoit', 'admin.integration.idoit']) }, except: %i[verify query update]
prepend_before_action -> { authentication_check(permission: ['admin.integration.idoit']) }, only: [:verify]
prepend_before_action -> { authentication_check(permission: ['ticket.agent']) }, only: %i[query update]
prepend_before_action { authentication_check && authorize! }
def verify
response = ::Idoit.verify(params[:api_token], params[:endpoint], params[:client_id])
@ -39,7 +37,7 @@ class Integration::IdoitController < ApplicationController
params[:object_ids] ||= []
ticket = Ticket.find(params[:ticket_id])
ticket.with_lock do
access!(ticket, 'read')
authorize!(ticket, :show?)
ticket.preferences[:idoit] ||= {}
ticket.preferences[:idoit][:object_ids] = Array(params[:object_ids]).uniq
ticket.save!

View file

@ -6,7 +6,7 @@ require_dependency 'ldap/group'
class Integration::LdapController < ApplicationController
include Integration::ImportJobBase
prepend_before_action { authentication_check(permission: 'admin.integration.ldap') }
prepend_before_action { authentication_check && authorize! }
def discover
answer_with do

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class JobsController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.scheduler') }
prepend_before_action { authentication_check && authorize! }
def index
model_index_render(Job, params)

View file

@ -2,7 +2,7 @@
class KnowledgeBase::Answer::AttachmentsController < ApplicationController
prepend_before_action :authentication_check
prepend_before_action { permission_check('knowledge_base.editor') }
prepend_before_action :authorize!
before_action :fetch_answer

View file

@ -3,8 +3,6 @@
class KnowledgeBase::AnswersController < KnowledgeBase::BaseController
include HasPublishing
before_action :check_reader_access, only: :show
# accessible outside of specific Knowledge Base
# /api/v1/knowledge_bases/recent_answers
def recent_answers
@ -83,15 +81,4 @@ class KnowledgeBase::AnswersController < KnowledgeBase::BaseController
render json: { id: object.id, assets: assets }, status: :created
end
private
def check_reader_access
return if current_user.permissions? 'knowledge_base.editor'
object = klass.find params[:id]
return if object.can_be_published_aasm.internal? || object.can_be_published_aasm.published?
raise ActiveRecord::RecordNotFound
end
end

View file

@ -2,8 +2,7 @@
class KnowledgeBase::BaseController < ApplicationController
prepend_before_action :authentication_check
before_action :ensure_editor_or_reader
before_action :ensure_editor, only: %i[create update destroy]
before_action :authorize!
def show
model_show_render(klass, params_for_permission)
@ -21,21 +20,13 @@ class KnowledgeBase::BaseController < ApplicationController
model_destroy_render(klass, params_for_permission)
end
private
def klass
@klass ||= controller_path.classify.constantize
end
private
def params_for_permission
params.permit klass.agent_allowed_params
end
def ensure_editor
permission_check 'knowledge_base.editor'
end
def ensure_editor_or_reader
permission_check 'knowledge_base.*'
end
end

View file

@ -2,7 +2,6 @@
class KnowledgeBase::CategoriesController < KnowledgeBase::BaseController
before_action :load_knowledge_base, only: %i[reorder_root_categories reorder_categories reorder_answers]
before_action :check_reader_access, only: :show # rubocop:disable Rails/LexicallyScopedActionFilter
def reorder_root_categories
reorder @knowledge_base.categories.root, params[:ordered_ids], KnowledgeBase::Category
@ -46,14 +45,4 @@ class KnowledgeBase::CategoriesController < KnowledgeBase::BaseController
@knowledge_base = KnowledgeBase.find params[:knowledge_base_id]
@category = @knowledge_base.categories.find params[:id] if params.key? :id
end
def check_reader_access
return if current_user.permissions? 'knowledge_base.editor'
object = klass.find params[:id]
return if object.internal_content?
raise ActiveRecord::RecordNotFound
end
end

View file

@ -1,9 +1,5 @@
# Copyright (C) 2012-2017 Zammad Foundation, http://zammad-foundation.org/
class KnowledgeBase::ManageController < KnowledgeBase::BaseController
prepend_before_action { permission_check('admin.knowledge_base') }
skip_before_action :ensure_editor_or_reader
skip_before_action :ensure_editor
def init
render json: assets
end

View file

@ -1,20 +1,10 @@
# Copyright (C) 2012-2017 Zammad Foundation, http://zammad-foundation.org/
class KnowledgeBasesController < KnowledgeBase::BaseController
skip_before_action :ensure_editor_or_reader, only: :init
def init
render json: assets(params[:answer_translation_content_ids])
end
def create
raise Exceptions::NotAuthorized
end
def destroy
raise Exceptions::NotAuthorized
end
private
def assets(answer_translation_content_ids = nil)

View file

@ -1,7 +1,10 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class MonitoringController < ApplicationController
prepend_before_action -> { authentication_check(permission: 'admin.monitoring') }, except: %i[health_check status amount_check]
prepend_before_action { authorize! }
prepend_before_action -> { authentication_check }, except: %i[health_check status amount_check]
prepend_before_action -> { authentication_check_only }, only: %i[health_check status amount_check]
skip_before_action :verify_csrf_token
=begin
@ -27,8 +30,6 @@ curl http://localhost/api/v1/monitoring/health_check?token=XXX
=end
def health_check
token_or_permission_check
issues = []
actions = Set.new
@ -210,8 +211,6 @@ curl http://localhost/api/v1/monitoring/status?token=XXX
=end
def status
token_or_permission_check
last_login = nil
last_login_user = User.where('last_login IS NOT NULL').order(last_login: :desc).limit(1).first
if last_login_user
@ -298,8 +297,6 @@ curl http://localhost/api/v1/monitoring/amount_check?token=XXX&periode=1h
=end
def amount_check
token_or_permission_check
raise Exceptions::UnprocessableEntity, 'periode is missing!' if params[:periode].blank?
scale = params[:periode][-1, 1]
@ -370,7 +367,6 @@ curl http://localhost/api/v1/monitoring/amount_check?token=XXX&periode=1h
end
def token
access_check
token = SecureRandom.urlsafe_base64(40)
Setting.set('monitoring_token', token)
@ -381,27 +377,8 @@ curl http://localhost/api/v1/monitoring/amount_check?token=XXX&periode=1h
end
def restart_failed_jobs
access_check
Scheduler.restart_failed_jobs
render json: {}, status: :ok
end
private
def token_or_permission_check
user = authentication_check_only(permission: 'admin.monitoring')
return if user
return if Setting.get('monitoring_token') == params[:token]
raise Exceptions::NotAuthorized
end
def access_check
return if Permission.find_by(name: 'admin.monitoring', active: true)
raise Exceptions::NotAuthorized
end
end

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class ObjectManagerAttributesController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.object') }
prepend_before_action { authentication_check && authorize! }
# GET /object_manager_attributes_list
def list

View file

@ -1,6 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class OnlineNotificationsController < ApplicationController
prepend_before_action -> { authorize! }, only: %i[show update destroy]
prepend_before_action :authentication_check
=begin
@ -102,8 +103,6 @@ curl http://localhost/api/v1/online_notifications/#{id} -v -u #{login}:#{passwor
=end
def show
return if !access?
model_show_render(OnlineNotification, params)
end
@ -131,8 +130,6 @@ curl http://localhost/api/v1/online_notifications -v -u #{login}:#{password} -H
=end
def update
return if !access?
model_update_render(OnlineNotification, params)
end
@ -150,8 +147,6 @@ curl http://localhost/api/v1/online_notifications/{id}.json -v -u #{login}:#{pas
=end
def destroy
return if !access?
model_destroy_render(OnlineNotification, params)
end
@ -180,14 +175,4 @@ curl http://localhost/api/v1/online_notifications/mark_all_as_read -v -u #{login
end
render json: {}, status: :ok
end
private
def access?
notification = OnlineNotification.find(params[:id])
return true if notification.user_id == current_user.id
raise Exceptions::NotAuthorized
end
end

View file

@ -1,7 +1,8 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class OrganizationsController < ApplicationController
prepend_before_action :authentication_check
prepend_before_action -> { authorize! }, except: %i[index show]
prepend_before_action { authentication_check }
=begin
@ -59,15 +60,7 @@ curl http://localhost/api/v1/organizations -v -u #{login}:#{password}
per_page = 500
end
# only allow customer to fetch his own organization
organizations = []
if !current_user.permissions?(['admin.organization', 'ticket.agent'])
if current_user.organization_id
organizations = Organization.where(id: current_user.organization_id).order(id: :asc).offset(offset).limit(per_page)
end
else
organizations = Organization.all.order(id: :asc).offset(offset).limit(per_page)
end
organizations = policy_scope(Organization).order(id: :asc).offset(offset).limit(per_page)
if response_expand?
list = []
@ -117,14 +110,17 @@ curl http://localhost/api/v1/organizations/#{id} -v -u #{login}:#{password}
=end
def show
begin
authorize!
rescue Pundit::NotAuthorizedError
# we have a special case here where Users that have no
# organization can request any organization_id but get
# an empty response. However, users with an organization_id
# get that error
raise if current_user.organization_id
# only allow customer to fetch his own organization
if !current_user.permissions?(['admin.organization', 'ticket.agent'])
if !current_user.organization_id
render json: {}
return
end
raise Exceptions::NotAuthorized if params[:id].to_i != current_user.organization_id
render json: {}
return
end
if response_expand?
@ -168,7 +164,6 @@ curl http://localhost/api/v1/organizations -v -u #{login}:#{password} -H "Conten
=end
def create
permission_check(['admin.organization', 'ticket.agent'])
model_create_render(Organization, params)
end
@ -199,7 +194,6 @@ curl http://localhost/api/v1/organizations -v -u #{login}:#{password} -H "Conten
=end
def update
permission_check(['admin.organization', 'ticket.agent'])
model_update_render(Organization, params)
end
@ -217,15 +211,12 @@ curl http://localhost/api/v1/organization/{id} -v -u #{login}:#{password} -H "Co
=end
def destroy
permission_check(['admin.organization', 'ticket.agent'])
model_references_check(Organization, params)
model_destroy_render(Organization, params)
end
# GET /api/v1/organizations/search
def search
raise Exceptions::NotAuthorized if !current_user.permissions?(['admin.organization', 'ticket.agent'])
per_page = params[:per_page] || params[:limit] || 100
per_page = per_page.to_i
if per_page > 500
@ -301,8 +292,6 @@ curl http://localhost/api/v1/organization/{id} -v -u #{login}:#{password} -H "Co
# GET /api/v1/organizations/history/1
def history
raise Exceptions::NotAuthorized if !current_user.permissions?(['admin.organization', 'ticket.agent'])
# get organization data
organization = Organization.find(params[:id])
@ -319,7 +308,6 @@ curl http://localhost/api/v1/organization/{id} -v -u #{login}:#{password} -H "Co
# @response_message 200 File download.
# @response_message 401 Invalid session.
def import_example
permission_check('admin.organization')
send_data(
Organization.csv_example,
filename: 'organization-example.csv',
@ -338,7 +326,6 @@ curl http://localhost/api/v1/organization/{id} -v -u #{login}:#{password} -H "Co
# @response_message 201 Import started.
# @response_message 401 Invalid session.
def import_start
permission_check('admin.user')
string = params[:data]
if string.blank? && params[:file].present?
string = params[:file].read.force_encoding('utf-8')

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class OverviewsController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.overview') }
prepend_before_action { authentication_check && authorize! }
=begin

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class PackagesController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.package') }
prepend_before_action { authentication_check && authorize! }
# GET /api/v1/packages
def index

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class PostmasterFiltersController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.channel_email') }
prepend_before_action { authentication_check && authorize! }
=begin

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class ProxyController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.system') }
prepend_before_action { authentication_check && authorize! }
# POST /api/v1/proxy
def test

View file

@ -1,5 +1,5 @@
class ReportProfilesController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.report_profile') }
prepend_before_action { authentication_check && authorize! }
=begin

View file

@ -1,6 +1,6 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class ReportsController < ApplicationController
prepend_before_action { authentication_check(permission: 'report') }
prepend_before_action { authentication_check && authorize! }
# GET /api/reports/config
def reporting_config

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class RolesController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.role') }
prepend_before_action { authentication_check && authorize! }
=begin

View file

@ -7,10 +7,6 @@ class SearchController < ApplicationController
# GET|POST /api/v1/search/:objects
def search_generic
# enable search only for users with valid session
raise Exceptions::NotAuthorized if !current_user
# get params
query = params[:query]
if query.respond_to?(:permit!)

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class SessionsController < ApplicationController
prepend_before_action :authentication_check, only: %i[switch_to_user list delete]
prepend_before_action -> { authentication_check && authorize! }, only: %i[switch_to_user list delete]
skip_before_action :verify_csrf_token, only: %i[show destroy create_omniauth failure_omniauth]
skip_before_action :user_device_check, only: %i[create_sso]
@ -97,8 +97,6 @@ class SessionsController < ApplicationController
# "switch" to user
def switch_to_user
permission_check(['admin.session', 'admin.user'])
# check user
if !params[:id]
render(
@ -176,7 +174,6 @@ class SessionsController < ApplicationController
end
def list
permission_check('admin.session')
assets = {}
sessions_clean = []
SessionHelper.list.each do |session|
@ -197,7 +194,6 @@ class SessionsController < ApplicationController
end
def delete
permission_check('admin.session')
SessionHelper.destroy(params[:id])
render json: {}
end

View file

@ -1,13 +1,13 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class SettingsController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.*') }
prepend_before_action { authentication_check && authorize! }
# GET /settings
def index
list = []
Setting.all.each do |setting|
next if setting.preferences[:permission] && !current_user.permissions?(setting.preferences[:permission])
next if !authorized?(setting, :show?)
list.push setting
end
@ -16,7 +16,6 @@ class SettingsController < ApplicationController
# GET /settings/1
def show
check_access('read')
model_show_render(Setting, params)
end
@ -27,14 +26,12 @@ class SettingsController < ApplicationController
# PUT /settings/1
def update
check_access('write')
clean_params = keep_certain_attributes
model_update_render(Setting, clean_params)
end
# PUT /settings/image/:id
def update_image
check_access('write')
clean_params = keep_certain_attributes
if !clean_params[:logo]
@ -105,20 +102,4 @@ class SettingsController < ApplicationController
end
params
end
def check_access(type)
setting = Setting.lookup(id: params[:id])
if setting.preferences[:permission] && !current_user.permissions?(setting.preferences[:permission])
raise Exceptions::NotAuthorized, "Not authorized (required #{setting.preferences[:permission].inspect})"
end
if type == 'write'
return true if !Setting.get('system_online_service')
if setting.preferences && setting.preferences[:online_service_disable]
raise Exceptions::NotAuthorized, 'Not authorized (service disabled)'
end
end
true
end
end

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class SignaturesController < ApplicationController
prepend_before_action :authentication_check
prepend_before_action { authentication_check && authorize! }
=begin
@ -47,7 +47,6 @@ curl http://localhost/api/v1/signatures.json -v -u #{login}:#{password}
=end
def index
permission_check(['admin.channel_email', 'ticket.agent'])
model_index_render(Signature, params)
end
@ -69,7 +68,6 @@ curl http://localhost/api/v1/signatures/#{id}.json -v -u #{login}:#{password}
=end
def show
permission_check(['admin.channel_email', 'ticket.agent'])
model_show_render(Signature, params)
end
@ -98,7 +96,6 @@ curl http://localhost/api/v1/signatures.json -v -u #{login}:#{password} -H "Cont
=end
def create
permission_check(['admin.channel_email'])
model_create_render(Signature, params)
end
@ -127,7 +124,6 @@ curl http://localhost/api/v1/signatures.json -v -u #{login}:#{password} -H "Cont
=end
def update
permission_check(['admin.channel_email'])
model_update_render(Signature, params)
end
@ -142,7 +138,6 @@ Test:
=end
def destroy
permission_check(['admin.channel_email'])
model_destroy_render(Signature, params)
end
end

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class SlasController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.sla') }
prepend_before_action { authentication_check && authorize! }
=begin

View file

@ -1,7 +1,8 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class TagsController < ApplicationController
prepend_before_action :authentication_check
prepend_before_action -> { authorize! }, only: %i[admin_list admin_create admin_rename admin_delete]
prepend_before_action { authentication_check }
# GET /api/v1/tag_search?term=abc
def search
@ -60,7 +61,6 @@ class TagsController < ApplicationController
# GET /api/v1/tag_list
def admin_list
permission_check('admin.tag')
list = Tag::Item.order(name: :asc).limit(params[:limit] || 1000)
results = []
list.each do |item|
@ -76,14 +76,12 @@ class TagsController < ApplicationController
# POST /api/v1/tag_list
def admin_create
permission_check('admin.tag')
Tag::Item.lookup_by_name_and_create(params[:name])
render json: {}
end
# PUT /api/v1/tag_list/:id
def admin_rename
permission_check('admin.tag')
Tag::Item.rename(
id: params[:id],
name: params[:name],
@ -93,7 +91,6 @@ class TagsController < ApplicationController
# DELETE /api/v1/tag_list/:id
def admin_delete
permission_check('admin.tag')
Tag::Item.remove(params[:id])
render json: {}
end

View file

@ -1,45 +1,35 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class TaskbarController < ApplicationController
prepend_before_action -> { authorize! }, only: %i[show update destroy]
prepend_before_action :authentication_check
before_action :set_task_user_param, only: %i[create update]
def index
current_user_tasks = Taskbar.where(user_id: current_user.id)
model_index_render_result(current_user_tasks)
end
def show
taskbar = Taskbar.find(params[:id])
access_to_taskbar(taskbar)
model_create_render(Taskbar, params)
end
def create
task_user(params)
model_create_render(Taskbar, params)
end
def update
taskbar = Taskbar.find(params[:id])
access_to_taskbar(taskbar)
task_user(params)
model_update_render(Taskbar, params)
end
def destroy
taskbar = Taskbar.find(params[:id])
access_to_taskbar(taskbar)
model_destroy_render(Taskbar, params)
end
private
def access_to_taskbar(taskbar)
raise Exceptions::UnprocessableEntity, 'Not allowed to access this task.' if taskbar.user_id != current_user.id
end
def task_user(params)
def set_task_user_param
params[:user_id] = current_user.id
end
end

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class TemplatesController < ApplicationController
prepend_before_action :authentication_check
prepend_before_action { authentication_check && authorize! }
=begin
@ -47,7 +47,6 @@ curl http://localhost/api/v1/templates.json -v -u #{login}:#{password}
=end
def index
permission_check(['admin.template', 'ticket.agent'])
model_index_render(Template, params)
end
@ -69,7 +68,6 @@ curl http://localhost/api/v1/templates/#{id}.json -v -u #{login}:#{password}
=end
def show
permission_check(['admin.template', 'ticket.agent'])
model_show_render(Template, params)
end
@ -97,7 +95,6 @@ curl http://localhost/api/v1/templates.json -v -u #{login}:#{password} -H "Conte
=end
def create
permission_check(['admin.template', 'ticket.agent'])
model_create_render(Template, params)
end
@ -125,7 +122,6 @@ curl http://localhost/api/v1/templates.json -v -u #{login}:#{password} -H "Conte
=end
def update
permission_check(['admin.template', 'ticket.agent'])
model_update_render(Template, params)
end
@ -143,7 +139,6 @@ curl http://localhost/api/v1/templates.json -v -u #{login}:#{password} -H "Conte
=end
def destroy
permission_check(['admin.template', 'ticket.agent'])
model_destroy_render(Template, params)
end
end

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class TextModulesController < ApplicationController
prepend_before_action :authentication_check
prepend_before_action { authentication_check && authorize! }
=begin
@ -49,7 +49,6 @@ curl http://localhost/api/v1/text_modules.json -v -u #{login}:#{password}
=end
def index
permission_check(['admin.text_module', 'ticket.agent'])
model_index_render(TextModule, params)
end
@ -71,7 +70,6 @@ curl http://localhost/api/v1/text_modules/#{id}.json -v -u #{login}:#{password}
=end
def show
permission_check(['admin.text_module', 'ticket.agent'])
model_show_render(TextModule, params)
end
@ -101,7 +99,6 @@ curl http://localhost/api/v1/text_modules.json -v -u #{login}:#{password} -H "Co
=end
def create
permission_check('admin.text_module')
model_create_render(TextModule, params)
end
@ -131,7 +128,6 @@ curl http://localhost/api/v1/text_modules.json -v -u #{login}:#{password} -H "Co
=end
def update
permission_check('admin.text_module')
model_update_render(TextModule, params)
end
@ -149,7 +145,6 @@ curl http://localhost/api/v1/text_modules.json -v -u #{login}:#{password} -H "Co
=end
def destroy
permission_check('admin.text_module')
model_destroy_render(TextModule, params)
end
@ -162,7 +157,6 @@ curl http://localhost/api/v1/text_modules.json -v -u #{login}:#{password} -H "Co
# @response_message 200 File download.
# @response_message 401 Invalid session.
def import_example
permission_check('admin.text_module')
csv_string = TextModule.csv_example(
col_sep: params[:col_sep] || ',',
)
@ -185,7 +179,6 @@ curl http://localhost/api/v1/text_modules.json -v -u #{login}:#{password} -H "Co
# @response_message 201 Import started.
# @response_message 401 Invalid session.
def import_start
permission_check('admin.text_module')
string = params[:data]
if string.blank? && params[:file].present?
string = params[:file].read.force_encoding('utf-8')

View file

@ -4,18 +4,18 @@ class TicketArticlesController < ApplicationController
include CreatesTicketArticles
include ClonesTicketArticleAttachments
prepend_before_action -> { authorize! }, only: %i[index import_example import_start]
prepend_before_action :authentication_check
# GET /articles
def index
permission_check('admin')
model_index_render(Ticket::Article, params)
end
# GET /articles/1
def show
article = Ticket::Article.find(params[:id])
access!(article, 'read')
authorize!(article)
if response_expand?
result = article.attributes_with_association_names
@ -35,15 +35,13 @@ class TicketArticlesController < ApplicationController
# GET /ticket_articles/by_ticket/1
def index_by_ticket
ticket = Ticket.find(params[:id])
access!(ticket, 'read')
authorize!(ticket, :show?)
articles = []
if response_expand?
ticket.articles.each do |article|
# ignore internal article if customer is requesting
next if article.internal == true && current_user.permissions?('ticket.customer')
next if !authorized?(article, :show?)
result = article.attributes_with_association_names
articles.push result
@ -57,9 +55,7 @@ class TicketArticlesController < ApplicationController
assets = {}
record_ids = []
ticket.articles.each do |article|
# ignore internal article if customer is requesting
next if article.internal == true && current_user.permissions?('ticket.customer')
next if !authorized?(article, :show?)
record_ids.push article.id
assets = article.assets({})
@ -72,9 +68,7 @@ class TicketArticlesController < ApplicationController
end
ticket.articles.each do |article|
# ignore internal article if customer is requesting
next if article.internal == true && current_user.permissions?('ticket.customer')
next if !authorized?(article, :show?)
articles.push article.attributes_with_association_names
end
@ -84,7 +78,7 @@ class TicketArticlesController < ApplicationController
# POST /articles
def create
ticket = Ticket.find(params[:ticket_id])
access!(ticket, 'create')
authorize!(ticket)
article = article_create(ticket, params)
if response_expand?
@ -105,11 +99,7 @@ class TicketArticlesController < ApplicationController
# PUT /articles/1
def update
article = Ticket::Article.find(params[:id])
access!(article, 'change')
if !current_user.permissions?('ticket.agent') && !current_user.permissions?('admin')
raise Exceptions::NotAuthorized, 'Not authorized (ticket.agent or admin permission required)!'
end
authorize!(article)
clean_params = Ticket::Article.association_name_to_id_convert(params)
clean_params = Ticket::Article.param_cleanup(clean_params, true)
@ -137,34 +127,15 @@ class TicketArticlesController < ApplicationController
# DELETE /api/v1/ticket_articles/:id
def destroy
article = Ticket::Article.find(params[:id])
access!(article, 'delete')
if current_user.permissions?('admin')
article.destroy!
render json: {}, status: :ok
return
end
article_deletable =
current_user.permissions?('ticket.agent') &&
article.created_by_id == current_user.id &&
!article.type.communication?
raise Exceptions::NotAuthorized, 'Not authorized (admin permission required)!' if !article_deletable
if article_deletable && article.created_at >= 10.minutes.ago
article.destroy!
render json: {}, status: :ok
return
end
raise Exceptions::NotAuthorized, 'Articles can only be deleted within 10 minutes after creation.'
authorize!(article)
article.destroy!
render json: {}, status: :ok
end
# POST /ticket_attachment_upload_clone_by_article
def ticket_attachment_upload_clone_by_article
article = Ticket::Article.find(params[:article_id])
access!(article.ticket, 'read')
authorize!(article.ticket, :show?)
render json: {
attachments: article_attachments_clone(article),
@ -174,7 +145,7 @@ class TicketArticlesController < ApplicationController
# GET /ticket_attachment/:ticket_id/:article_id/:id
def attachment
ticket = Ticket.lookup(id: params[:ticket_id])
access!(ticket, 'read')
authorize!(ticket, :show?)
article = Ticket::Article.find(params[:article_id])
if ticket.id != article.ticket_id
@ -185,7 +156,7 @@ class TicketArticlesController < ApplicationController
end
ticket = article.ticket
access!(ticket, 'read')
authorize!(ticket, :show?)
end
list = article.attachments || []
@ -226,7 +197,7 @@ class TicketArticlesController < ApplicationController
# GET /ticket_article_plain/1
def article_plain
article = Ticket::Article.find(params[:id])
access!(article, 'read')
authorize!(article, :show?)
file = article.as_raw
@ -250,7 +221,6 @@ class TicketArticlesController < ApplicationController
# @response_message 200 File download.
# @response_message 401 Invalid session.
def import_example
permission_check('admin')
csv_string = Ticket::Article.csv_example(
col_sep: ',',
)
@ -273,7 +243,6 @@ class TicketArticlesController < ApplicationController
# @response_message 201 Import started.
# @response_message 401 Invalid session.
def import_start
permission_check('admin')
if Setting.get('import_mode') != true
raise 'Only can import tickets if system is in import mode.'
end

View file

@ -1,35 +1,30 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class TicketPrioritiesController < ApplicationController
prepend_before_action :authentication_check
prepend_before_action { authentication_check && authorize! }
# GET /ticket_priorities
def index
permission_check(['admin.object', 'ticket.agent', 'ticket.customer'])
model_index_render(Ticket::Priority, params)
end
# GET /ticket_priorities/1
def show
permission_check(['admin.object', 'ticket.agent', 'ticket.customer'])
model_show_render(Ticket::Priority, params)
end
# POST /ticket_priorities
def create
permission_check('admin.object')
model_create_render(Ticket::Priority, params)
end
# PUT /ticket_priorities/1
def update
permission_check('admin.object')
model_update_render(Ticket::Priority, params)
end
# DELETE /ticket_priorities/1
def destroy
permission_check('admin.object')
model_references_check(Ticket::Priority, params)
model_destroy_render(Ticket::Priority, params)
end

View file

@ -1,37 +1,31 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class TicketStatesController < ApplicationController
prepend_before_action :authentication_check
prepend_before_action { authentication_check && authorize! }
# GET /ticket_states
def index
permission_check(['admin.object', 'ticket.agent', 'ticket.customer'])
model_index_render(Ticket::State, params)
end
# GET /ticket_states/1
def show
permission_check(['admin.object', 'ticket.agent', 'ticket.customer'])
model_show_render(Ticket::State, params)
end
# POST /ticket_states
def create
permission_check('admin.object')
model_create_render(Ticket::State, params)
end
# PUT /ticket_states/1
def update
permission_check('admin.object')
model_update_render(Ticket::State, params)
end
# DELETE /ticket_states/1
def destroy
permission_check('admin.object')
return if model_references_check(Ticket::State, params)
model_references_check(Ticket::State, params)
model_destroy_render(Ticket::State, params)
end
end

View file

@ -6,8 +6,8 @@ class TicketsController < ApplicationController
include ChecksUserAttributesByCurrentUserPermission
include TicketStats
prepend_before_action -> { authorize! }, only: %i[selector import_example import_start]
prepend_before_action :authentication_check
before_action :follow_up_possible_check, only: :update
# GET /api/v1/tickets
def index
@ -55,7 +55,7 @@ class TicketsController < ApplicationController
# GET /api/v1/tickets/1
def show
ticket = Ticket.find(params[:id])
access!(ticket, 'read')
authorize!(ticket)
if response_expand?
result = ticket.attributes_with_association_names
@ -221,7 +221,8 @@ class TicketsController < ApplicationController
# PUT /api/v1/tickets/1
def update
ticket = Ticket.find(params[:id])
access!(ticket, 'change')
authorize!(ticket, :follow_up?)
authorize!(ticket)
clean_params = Ticket.association_name_to_id_convert(params)
clean_params = Ticket.param_cleanup(clean_params, true)
@ -269,9 +270,7 @@ class TicketsController < ApplicationController
# DELETE /api/v1/tickets/1
def destroy
ticket = Ticket.find(params[:id])
access!(ticket, 'delete')
raise Exceptions::NotAuthorized, 'Not authorized (admin permission required)!' if !current_user.permissions?('admin')
authorize!(ticket)
ticket.destroy!
@ -296,7 +295,7 @@ class TicketsController < ApplicationController
# get ticket data
ticket = Ticket.find(params[:id])
access!(ticket, 'read')
authorize!(ticket, :show?)
# get history of ticket
render json: ticket.history_get(true)
@ -385,7 +384,7 @@ class TicketsController < ApplicationController
}
return
end
access!(ticket_master, 'change')
authorize!(ticket_master, :update?)
# check slave ticket
ticket_slave = Ticket.find_by(id: params[:slave_ticket_id])
@ -396,7 +395,7 @@ class TicketsController < ApplicationController
}
return
end
access!(ticket_slave, 'change')
authorize!(ticket_slave, :update?)
# merge ticket
ticket_slave.merge_to(
@ -415,11 +414,11 @@ class TicketsController < ApplicationController
# GET /api/v1/ticket_split
def ticket_split
ticket = Ticket.find(params[:ticket_id])
access!(ticket, 'read')
authorize!(ticket, :show?)
assets = ticket.assets({})
article = Ticket::Article.find(params[:article_id])
access!(article.ticket, 'read')
authorize!(article.ticket, :show?)
assets = article.assets(assets)
render json: {
@ -497,8 +496,6 @@ class TicketsController < ApplicationController
# GET /api/v1/tickets/selector
def selector
permission_check('admin.*')
ticket_count, tickets = Ticket.selectors(params[:condition], limit: 6, execution_time: true)
assets = {}
@ -627,7 +624,6 @@ class TicketsController < ApplicationController
# @response_message 200 File download.
# @response_message 401 Invalid session.
def import_example
permission_check('admin')
csv_string = Ticket.csv_example(
col_sep: ',',
)
@ -650,7 +646,6 @@ class TicketsController < ApplicationController
# @response_message 201 Import started.
# @response_message 401 Invalid session.
def import_start
permission_check('admin')
if Setting.get('import_mode') != true
raise 'Only can import tickets if system is in import mode.'
end
@ -673,16 +668,6 @@ class TicketsController < ApplicationController
private
def follow_up_possible_check
ticket = Ticket.find(params[:id])
return true if current_user.permissions?('ticket.agent') # agents can always reopen tickets, regardless of group configuration
return true if ticket.group.follow_up_possible != 'new_ticket' # check if the setting for follow_up_possible is disabled
return true if ticket.state.name != 'closed' # check if the ticket state is already closed
raise Exceptions::UnprocessableEntity, 'Cannot follow-up on a closed ticket. Please create a new ticket.'
end
def ticket_all(ticket)
# get attributes to update
@ -698,9 +683,7 @@ class TicketsController < ApplicationController
# get related users
article_ids = []
ticket.articles.each do |article|
# ignore internal article if customer is requesting
next if article.internal == true && current_user.permissions?('ticket.customer')
next if !authorized?(article, :show?)
article_ids.push article.id
assets = article.assets(assets)

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class TimeAccountingsController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.time_accounting') }
prepend_before_action { authentication_check && authorize! }
def by_ticket

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class TranslationsController < ApplicationController
prepend_before_action :authentication_check, except: [:lang]
prepend_before_action -> { authentication_check && authorize! }, except: [:lang]
# GET /translations/lang/:locale
def lang
@ -10,7 +10,6 @@ class TranslationsController < ApplicationController
# PUT /translations/push
def push
permission_check('admin.translation')
start = Time.zone.now
Translation.push(params[:locale])
if start > Time.zone.now - 4.seconds
@ -21,51 +20,43 @@ class TranslationsController < ApplicationController
# POST /translations/sync/:locale
def sync
permission_check('admin.translation')
Translation.load(params[:locale])
render json: { message: 'ok' }, status: :ok
end
# POST /translations/reset
def reset
permission_check('admin.translation')
Translation.reset(params[:locale])
render json: { message: 'ok' }, status: :ok
end
# GET /translations/admin/lang/:locale
def admin
permission_check('admin.translation')
render json: Translation.lang(params[:locale], true)
end
# GET /translations
def index
permission_check('admin.translation')
model_index_render(Translation, params)
end
# GET /translations/1
def show
permission_check('admin.translation')
model_show_render(Translation, params)
end
# POST /translations
def create
permission_check('admin.translation')
model_create_render(Translation, params)
end
# PUT /translations/1
def update
permission_check('admin.translation')
model_update_render(Translation, params)
end
# DELETE /translations/1
def destroy
permission_check('admin.translation')
model_destroy_render(Translation, params)
end
end

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class TriggersController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.trigger') }
prepend_before_action { authentication_check && authorize! }
def index
model_index_render(Trigger, params)

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class UserAccessTokenController < ApplicationController
prepend_before_action { authentication_check(permission: 'user_preferences.access_token') }
prepend_before_action { authentication_check && authorize! }
=begin

View file

@ -1,7 +1,7 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class UserDevicesController < ApplicationController
prepend_before_action { authentication_check(permission: 'user_preferences.device') }
prepend_before_action { authentication_check && authorize! }
def index
devices = UserDevice.where(user_id: current_user.id).order(updated_at: :desc, name: :asc)

View file

@ -3,6 +3,7 @@
class UsersController < ApplicationController
include ChecksUserAttributesByCurrentUserPermission
prepend_before_action -> { authorize! }, only: %i[import_example import_start search history]
prepend_before_action :authentication_check, except: %i[create password_reset_send password_reset_verify image]
prepend_before_action :authentication_check_only, only: [:create]
@ -27,12 +28,7 @@ class UsersController < ApplicationController
per_page = 500
end
# only allow customer to fetch him self
users = if !current_user.permissions?(['admin.user', 'ticket.agent'])
User.where(id: current_user.id).order(id: :asc).offset(offset).limit(per_page)
else
User.all.order(id: :asc).offset(offset).limit(per_page)
end
users = policy_scope(User).order(id: :asc).offset(offset).limit(per_page)
if response_expand?
list = []
@ -78,7 +74,7 @@ class UsersController < ApplicationController
# @response_message 401 Invalid session.
def show
user = User.find(params[:id])
access!(user, 'read')
authorize!(user)
if response_expand?
result = user.attributes_with_association_names
@ -263,7 +259,7 @@ class UsersController < ApplicationController
# @response_message 401 Invalid session.
def update
user = User.find(params[:id])
access!(user, 'change')
authorize!(user)
# permission check
check_attributes_by_current_user_permission(params)
@ -312,7 +308,7 @@ class UsersController < ApplicationController
# @response_message 401 Invalid session.
def destroy
user = User.find(params[:id])
access!(user, 'delete')
authorize!(user)
model_references_check(User, params)
model_destroy_render(User, params)
@ -367,8 +363,6 @@ class UsersController < ApplicationController
# @response_message 200 [Array<User>] A list of User records matching the search term.
# @response_message 401 Invalid session.
def search
raise Exceptions::NotAuthorized if !current_user.permissions?(['ticket.agent', 'admin.user'])
per_page = params[:per_page] || params[:limit] || 100
per_page = per_page.to_i
if per_page > 500
@ -472,8 +466,6 @@ class UsersController < ApplicationController
# @response_message 200 [History] The History records of the requested User record.
# @response_message 401 Invalid session.
def history
raise Exceptions::NotAuthorized if !current_user.permissions?(['admin.user', 'ticket.agent'])
# get user data
user = User.find(params[:id])
@ -775,8 +767,6 @@ curl http://localhost/api/v1/users/preferences -v -u #{login}:#{password} -H "Co
=end
def preferences
raise Exceptions::UnprocessableEntity, 'No current user!' if !current_user
preferences_params = params.except(:controller, :action)
if preferences_params.present?
@ -816,8 +806,6 @@ curl http://localhost/api/v1/users/out_of_office -v -u #{login}:#{password} -H "
=end
def out_of_office
raise Exceptions::UnprocessableEntity, 'No current user!' if !current_user
user = User.find(current_user.id)
user.with_lock do
user.assign_attributes(
@ -854,8 +842,6 @@ curl http://localhost/api/v1/users/account -v -u #{login}:#{password} -H "Conten
=end
def account_remove
raise Exceptions::UnprocessableEntity, 'No current user!' if !current_user
# provider + uid to remove
raise Exceptions::UnprocessableEntity, 'provider needed!' if !params[:provider]
raise Exceptions::UnprocessableEntity, 'uid needed!' if !params[:uid]
@ -934,8 +920,6 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content
=end
def avatar_new
return if !valid_session_with_user
# get & validate image
file_full = StaticAssets.data_url_attributes(params[:avatar_full])
file_resize = StaticAssets.data_url_attributes(params[:avatar_resize])
@ -963,8 +947,6 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content
end
def avatar_set_default
return if !valid_session_with_user
# get & validate image
raise Exceptions::UnprocessableEntity, 'No id of avatar!' if !params[:id]
@ -979,8 +961,6 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content
end
def avatar_destroy
return if !valid_session_with_user
# get & validate image
raise Exceptions::UnprocessableEntity, 'No id of avatar!' if !params[:id]
@ -996,8 +976,6 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content
end
def avatar_list
return if !valid_session_with_user
# list of avatars
result = Avatar.list('User', current_user.id)
render json: { avatars: result }, status: :ok
@ -1012,7 +990,6 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content
# @response_message 200 File download.
# @response_message 401 Invalid session.
def import_example
permission_check('admin.user')
send_data(
User.csv_example,
filename: 'user-example.csv',
@ -1031,7 +1008,6 @@ curl http://localhost/api/v1/users/avatar -v -u #{login}:#{password} -H "Content
# @response_message 201 Import started.
# @response_message 401 Invalid session.
def import_start
permission_check('admin.user')
string = params[:data]
if string.blank? && params[:file].present?
string = params[:file].read.force_encoding('utf-8')

View file

@ -1,7 +1,8 @@
# Copyright (C) 2012-2017 Zammad Foundation, http://zammad-foundation.org/
class VersionController < ApplicationController
prepend_before_action { authentication_check(permission: 'admin.version') }
prepend_before_action { authentication_check && authorize! }
# GET /api/v1/version
def index

View file

@ -10,7 +10,6 @@ class Organization < ApplicationModel
include ChecksHtmlSanitized
include HasObjectManagerAttributesValidation
include Organization::ChecksAccess
include Organization::Assets
include Organization::Search
include Organization::SearchIndex

View file

@ -1,51 +0,0 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class Organization
module ChecksAccess
extend ActiveSupport::Concern
# Checks the given access of a given user for an organization.
#
# @param [User] The user that will be checked for given access.
# @param [String] The access that should get checked.
#
# @example
# organization.access?(user, 'read')
# #=> true
#
# @return [Boolean]
def access?(user, access)
# check customer
if user.permissions?('ticket.customer')
# access ok if its own organization
return false if access != 'read'
return false if !user.organization_id
return id == user.organization_id
end
# check agent
return true if user.permissions?('admin')
return true if user.permissions?('ticket.agent')
false
end
# Checks the given access of a given user for an organization and fails with an exception.
#
# @param (see Organization#access?)
#
# @example
# organization.access!(user, 'read')
#
# @raise [NotAuthorized] Gets raised if given user doesn't have the given access.
#
# @return [nil]
def access!(user, access)
return if access?(user, access)
raise Exceptions::NotAuthorized
end
end
end

View file

@ -76,12 +76,11 @@ class RecentView < ApplicationModel
end
def self.access(object, o_id, user)
object.to_s
.constantize
.try(:lookup, { id: o_id })
.try(:access?, user, 'read')
rescue NameError
false
record = object.to_s
.safe_constantize
.try(:lookup, { id: o_id })
Pundit.policy(user, record).try(:show?)
end
=begin

View file

@ -13,7 +13,6 @@ class Ticket < ApplicationModel
include HasOnlineNotifications
include HasKarmaActivityLog
include HasLinks
include Ticket::ChecksAccess
include HasObjectManagerAttributesValidation
include Ticket::Escalation

View file

@ -8,7 +8,6 @@ class Ticket::Article < ApplicationModel
include CanCsvImport
include HasObjectManagerAttributesValidation
include Ticket::Article::ChecksAccess
include Ticket::Article::Assets
belongs_to :ticket, optional: true

View file

@ -1,43 +0,0 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class Ticket
class Article
module ChecksAccess
extend ActiveSupport::Concern
# Checks the given access of a given user for a ticket article.
#
# @param [User] The user that will be checked for given access.
# @param [String] The access that should get checked.
#
# @example
# article.access?(user, 'read')
# #=> true
#
# @return [Boolean]
def access?(user, access)
if user.permissions?('ticket.customer')
return false if internal == true
end
ticket = Ticket.lookup(id: ticket_id)
ticket.access?(user, access)
end
# Checks the given access of a given user for a ticket article and fails with an exception.
#
# @param (see Ticket::Article#access?)
#
# @example
# article.access!(user, 'read')
#
# @raise [NotAuthorized] Gets raised if given user doesn't have the given access.
#
# @return [nil]
def access!(user, access)
return if access?(user, access)
raise Exceptions::NotAuthorized
end
end
end
end

View file

@ -1,57 +0,0 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class Ticket
module ChecksAccess
extend ActiveSupport::Concern
# Checks the given access of a given user for a ticket.
#
# @param [User] The user that will be checked for given access.
# @param [String] The access that should get checked.
#
# @example
# ticket.access?(user, 'read')
# #=> true
#
# @return [Boolean]
def access?(user, access)
# check customer
if user.permissions?('ticket.customer')
# access ok if its own ticket
return true if customer_id == user.id
# check organization ticket access
return false if organization_id.blank?
return false if user.organization_id.blank?
return false if organization_id != user.organization_id
return organization.shared?
end
# check agent
# access if requestor is owner
return true if owner_id == user.id
# access if requestor is in group
user.group_access?(group.id, access)
end
# Checks the given access of a given user for a ticket and fails with an exception.
#
# @param (see Ticket#access?)
#
# @example
# ticket.access!(user, 'read')
#
# @raise [NotAuthorized] Gets raised if given user doesn't have the given access.
#
# @return [nil]
def access!(user, access)
return if access?(user, access)
raise Exceptions::NotAuthorized
end
end
end

View file

@ -79,27 +79,7 @@ returns
# add permission check
if data[:permission]
return if !user.permissions?(data[:permission])
return if !token.preferences[:permission]
local_permissions = data[:permission]
if data[:permission].class != Array
local_permissions = [data[:permission]]
end
match = false
local_permissions.each do |local_permission|
local_permissions = Permission.with_parents(local_permission)
local_permissions.each do |local_permission_name|
next if !token.preferences[:permission].include?(local_permission_name)
match = true
break
end
next if !match
break
end
return if !match
return if !token.permissions?(data[:permission])
end
# return token user
@ -119,6 +99,17 @@ cleanup old token
true
end
def permissions?(permissions)
return false if !user.permissions?(permissions)
return false if preferences[:permission].blank?
Array(permissions).any? do |parentless|
Permission.with_parents(parentless).any? do |permission|
preferences[:permission].include?(permission)
end
end
end
private
def generate_token

View file

@ -14,7 +14,6 @@ class User < ApplicationModel
include HasObjectManagerAttributesValidation
include HasTicketCreateScreenImpact
include User::HasTicketCreateScreenImpact
include User::ChecksAccess
include User::Assets
include User::Search
include User::SearchIndex
@ -421,14 +420,10 @@ returns
=end
def permissions?(key)
keys = key
if key.class == String
keys = [key]
end
keys.each do |local_key|
Array(key).each do |local_key|
list = []
if local_key.match?(/\.\*$/)
local_key.sub!('.*', '.%')
local_key = local_key.sub('.*', '.%')
permissions = ::Permission.with_parents(local_key)
list = ::Permission.select('preferences').joins(:roles).where('roles.id IN (?) AND roles.active = ? AND (permissions.name IN (?) OR permissions.name LIKE ?) AND permissions.active = ?', role_ids, true, permissions, local_key, true).pluck(:preferences)
else

View file

@ -1,74 +0,0 @@
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
class User
module ChecksAccess
extend ActiveSupport::Concern
# Checks the given access of a given user for another user.
#
# @param [User] The user that will be checked for given access.
# @param [String] The access that should get checked.
#
# @example
# user.access?(user, 'read')
# #=> true
#
# @return [Boolean]
def access?(requester, access)
# full admins can do whatever they want
return true if requester.permissions?('admin')
send("#{access}able_by?".to_sym, requester)
end
# Checks the given access of a given user for another user and fails with an exception.
#
# @param (see User#access?)
#
# @example
# user.access!(user, 'read')
#
# @raise [NotAuthorized] Gets raised if given user doesn't have the given access.
#
# @return [nil]
def access!(user, access)
return if access?(user, access)
raise Exceptions::NotAuthorized
end
private
def readable_by?(requester)
return true if own_account?(requester)
return true if requester.permissions?('admin.*')
return true if requester.permissions?('ticket.agent')
# check same organization for customers
return false if !requester.permissions?('ticket.customer')
same_organization?(requester)
end
def changeable_by?(requester)
return true if requester.permissions?('admin.user')
# allow agents to change customers
return false if !requester.permissions?('ticket.agent')
permissions?('ticket.customer')
end
def deleteable_by?(requester)
requester.permissions?('admin.user')
end
def own_account?(requester)
id == requester.id
end
def same_organization?(requester)
return false if organization_id.blank?
return false if requester.organization_id.blank?
organization_id == requester.organization_id
end
end
end

View file

@ -0,0 +1,19 @@
class ApplicationPolicy
include PunditPolicy
attr_reader :record
def initialize_context(record)
@record = record
end
class Scope
include PunditPolicy
attr_reader :scope
def initialize_context(scope)
@scope = scope
end
end
end

View file

@ -0,0 +1,33 @@
class Controllers::ApplicationControllerPolicy < ApplicationPolicy
class_attribute(:action_permissions_map, default: {})
def self.inherited(subclass)
subclass.action_permissions_map = action_permissions_map.deep_dup
end
def self.default_permit!(permissions)
action_permissions_map.default = permissions
end
def self.permit!(actions, to:)
Array(actions).each do |action|
action_permissions_map[:"#{action}?"] = to
end
end
def method_missing(missing_method, *)
case (permission = action_permissions_map[missing_method])
when String, Array
user.permissions!(permission) || true
when Proc
user.permissions!(instance_exec(&permission)) || true
else
super
end
end
def respond_to_missing?(missing_method)
action_permissions_map[missing_method] || super
end
end

View file

@ -0,0 +1,3 @@
class Controllers::ApplicationsControllerPolicy < Controllers::ApplicationControllerPolicy
default_permit!('admin.api')
end

View file

@ -0,0 +1,3 @@
class Controllers::CalendarSubscriptionsControllerPolicy < Controllers::ApplicationControllerPolicy
default_permit!('user_preferences.calendar')
end

View file

@ -0,0 +1,4 @@
class Controllers::CalendarsControllerPolicy < Controllers::ApplicationControllerPolicy
permit! :timezones, to: 'admin'
default_permit!('admin.calendar')
end

View file

@ -0,0 +1,3 @@
class Controllers::ChannelsEmailControllerPolicy < Controllers::ApplicationControllerPolicy
default_permit!('admin.channel_email')
end

View file

@ -0,0 +1,3 @@
class Controllers::ChannelsFacebookControllerPolicy < Controllers::ApplicationControllerPolicy
default_permit!('admin.channel_facebook')
end

View file

@ -0,0 +1,3 @@
class Controllers::ChannelsSmsControllerPolicy < Controllers::ApplicationControllerPolicy
default_permit!('admin.channel_sms')
end

View file

@ -0,0 +1,3 @@
class Controllers::ChannelsTelegramControllerPolicy < Controllers::ApplicationControllerPolicy
default_permit!('admin.channel_telegram')
end

View file

@ -0,0 +1,3 @@
class Controllers::ChannelsTwitterControllerPolicy < Controllers::ApplicationControllerPolicy
default_permit!('admin.channel_twitter')
end

View file

@ -0,0 +1,3 @@
class Controllers::ChatSessionsControllerPolicy < Controllers::ApplicationControllerPolicy
default_permit!('chat.agent')
end

View file

@ -0,0 +1,3 @@
class Controllers::ChatsControllerPolicy < Controllers::ApplicationControllerPolicy
default_permit!('admin.channel_chat')
end

View file

@ -0,0 +1,3 @@
class Controllers::CtiControllerPolicy < Controllers::ApplicationControllerPolicy
default_permit!('cti.agent')
end

View file

@ -0,0 +1,4 @@
class Controllers::EmailAddressesControllerPolicy < Controllers::ApplicationControllerPolicy
permit! %i[index show], to: ['ticket.agent', 'admin.channel_email']
default_permit!('admin.channel_email')
end

View file

@ -0,0 +1,16 @@
class Controllers::ExternalCredentialsControllerPolicy < Controllers::ApplicationControllerPolicy
permit! :index, to: 'admin'
default_permit! -> { "admin.channel_#{provider_name}" }
private
def provider_name
@provider_name ||= begin
if record.params[:id].present?
ExternalCredential.find(record.params[:id]).name
else
record.params[:provider] || record.params[:name]
end
end
end
end

View file

@ -0,0 +1,3 @@
class Controllers::FirstStepsControllerPolicy < Controllers::ApplicationControllerPolicy
permit! %i[index test_ticket], to: ['ticket.agent', 'admin']
end

View file

@ -0,0 +1,28 @@
class Controllers::FormControllerPolicy < Controllers::ApplicationControllerPolicy
def configuration?
authorized?
end
def submit?
authorized?
end
def test?
record.params[:test] && user&.permissions?('admin.channel_formular')
end
private
def authorized?
test? || enabled?
end
def user_required?
false
end
def enabled?
Setting.get('form_ticket_create')
end
end

View file

@ -0,0 +1,3 @@
class Controllers::GettingStartedControllerPolicy < Controllers::ApplicationControllerPolicy
permit! :base, to: 'admin.wizard'
end

View file

@ -0,0 +1,3 @@
class Controllers::GroupsControllerPolicy < Controllers::ApplicationControllerPolicy
default_permit!('admin.group')
end

Some files were not shown because too many files have changed in this diff Show more