app/models/ability.rb
class Ability
include CanCan::Ability
include AlaveteliFeatures::Helpers
attr_reader :user, :project, :public_token
def self.guest(**args)
new(nil, **args)
end
def initialize(user, project: nil, public_token: false)
# Define abilities for the passed in user here. For example:
#
# user ||= User.new # guest user (not logged in)
# if user.is_admin?
# can :manage, :all
# else
# can :read, :all
# end
#
# The first argument to `can` is the action you are giving the user
# permission to do.
# If you pass :manage it will apply to every action. Other common actions
# here are :read, :create, :update and :destroy.
#
# The second argument is the resource the user can perform the action on.
# If you pass :all it will apply to every resource. Otherwise pass a Ruby
# class of the resource.
#
# The third argument is an optional hash of conditions to further filter the
# objects.
# For example, here the user can only update published articles.
#
# can :update, Article, :published => true
#
# See the wiki for details:
# https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities
@user = user
@project = project
@public_token = public_token
# Updating request status
can :update_request_state, InfoRequest do |request|
can_update_request_state?(request)
end
# Viewing requests, messages & attachments as Pro admin
if user&.view_hidden_and_embargoed?
can :_read, InfoRequest
can :_read, OutgoingMessage
can :_read, IncomingMessage
can :_read, FoiAttachment
end
# Viewing requests, messages & attachments as admin
if user&.view_hidden?
can :_read, InfoRequest do |info_request|
!info_request.embargo
end
can :_read, [IncomingMessage, OutgoingMessage] do |message|
!message.info_request.embargo
end
can :_read, FoiAttachment do |attachment|
!attachment.info_request.embargo
end
end
can :_read, InfoRequest do |info_request|
!info_request.embargo &&
%w[normal backpage].include?(info_request.prominence)
end
can :_read, OutgoingMessage, prominence: 'normal'
can :_read, IncomingMessage, prominence: 'normal'
can :_read, FoiAttachment, prominence: 'normal'
if user
# Viewing their own embargoed requests with public prominence
can :_read, InfoRequest do |info_request|
info_request.embargo &&
info_request.user == user &&
%w[normal backpage].include?(info_request.prominence)
end
# Viewing their own request, messages & attachments with requester only prominence
can :_read, InfoRequest, user: user, prominence: 'requester_only'
can :_read, OutgoingMessage, info_request: { user: user }, prominence: 'requester_only'
can :_read, IncomingMessage, info_request: { user: user }, prominence: 'requester_only'
can :_read, FoiAttachment, incoming_message: { info_request: { user: user } }, prominence: 'requester_only'
end
# Reading attachments with prominence
can :read, FoiAttachment do |attachment|
can?(:_read, attachment) && can?(:read, attachment.incoming_message)
end
# Reading messages with prominence
can :read, [IncomingMessage, OutgoingMessage] do |message|
can?(:_read, message) && can?(:read, message.info_request)
end
# Reading requests with prominence or via a project or public token
can :read, InfoRequest do |info_request|
can?(:_read, info_request) ||
project&.member?(user) ||
public_token
end
can :manage, OutgoingMessage::Snippet do |_request|
user && user.is_admin?
end
# Viewing batch requests
can :read, InfoRequestBatch do |batch_request|
if batch_request.embargo_duration
user && (user == batch_request.user || user&.view_embargoed?)
else
true
end
end
# Downloading batch requests
can :download, InfoRequestBatch do |batch_request|
user && user == batch_request.user && user.is_pro?
end
# Updating batch requests
can :update, InfoRequestBatch do |batch_request|
if batch_request.embargo_duration
user && (user.is_pro_admin? ||
(user == batch_request.user && user.is_pro?))
else
user && requester_or_admin?(batch_request)
end
end
# Removing batch request embargoes
can :destroy_embargo, InfoRequestBatch do |batch_request|
if batch_request.embargo_duration
user && (user == batch_request.user || user.is_pro_admin?)
else
user && requester_or_admin?(batch_request)
end
end
if feature_enabled? :alaveteli_pro
# Accessing alaveteli professional
if user && (user.is_pro_admin? || user.is_pro?)
can :access, :alaveteli_pro
end
# Creating embargoes
can :create_embargo, InfoRequest do |info_request|
user && info_request.user &&
info_request.user.is_pro? &&
(user.is_pro_admin? || user == info_request.user) &&
!info_request.embargo &&
info_request.info_request_batch_id.nil?
end
# Extending embargoes
can :update, AlaveteliPro::Embargo do |embargo|
user && (user.is_pro_admin? ||
user == embargo.info_request.user && user.is_pro?)
end
# Removing embargoes
can :destroy, AlaveteliPro::Embargo do |embargo|
user && (user == embargo.info_request.user || user.is_pro_admin?)
end
end
can :admin, AlaveteliPro::Embargo if user && user.is_pro_admin?
can :admin, [InfoRequest, InfoRequestBatch] do |content|
if content.embargoed?
user && user.is_pro_admin?
else
user && user.is_admin?
end
end
can :create_citation, [InfoRequest, InfoRequestBatch] do |content|
user && (user.is_admin? || user.is_pro? || content.user == user)
end
can :share, InfoRequest do |info_request|
info_request.embargo &&
(user&.is_pro_admin? || info_request.is_actual_owning_user?(user))
end
can :admin, Comment do |comment|
if comment.info_request.embargo
user && user.is_pro_admin?
else
user && user.is_admin?
end
end
can :login_as, User do |target_user|
if user == target_user
false
elsif target_user.is_pro? || target_user.is_pro_admin?
user && user.is_pro_admin?
else
user && user.is_admin?
end
end
if feature_enabled? :alaveteli_pro
can :read, :api_key if user && user.is_pro_admin?
elsif user && user.is_admin?
can :read, :api_key
end
if feature_enabled? :projects
can :read, Project do |target_project|
user && (user.is_pro_admin? || target_project.member?(user))
end
can :edit, Project do |target_project|
user && (user.is_pro_admin? || target_project.owner?(user))
end
can :leave, Project do |target_project|
user && target_project.contributor?(user)
end
can :view, Dataset::KeySet do |dataset_key_set|
resource = dataset_key_set.resource
next false unless resource.is_a?(Project)
target_project = resource
next true if target_project.dataset_public?
next false unless user
next true if user&.is_pro_admin?
target_project.owner?(user)
end
end
end
private
def can_update_request_state?(request)
(user && request.is_old_unclassified?) || request.is_owning_user?(user) ||
(project && project.info_request?(request) && project.member?(user))
end
def requester_or_admin?(request)
user == request.user || user.is_admin?
end
end