app/models/ability.rb
# frozen_string_literal: true
# Defines permissions for controller actions.
class Ability
include CanCan::Ability
# Define abilities for user.
# @param [User] user
# @return [void]
def initialize(user)
# ======== Reset Actions ========
# clear all aliased actions - these mappings are removed:
# alias_action :index, :show, :to => :read
# alias_action :new, :to => :create
# alias_action :edit, :to => :update
clear_aliased_actions
# ======== Information about specifying `can` on controller actions ========
# | Can be used in |
# HTTP Verb | Path | Action | a block? | Purpose
#-------------|---------------------|-----------|----------------------------------------
# GET | /projects | :index | NO | display a list of all projects
# GET | /projects/new | :new | YES | return an HTML form/json properties for creating a new project
# POST | /projects | :create | YES | create a new project
# GET | /projects/:id | :show | YES | display a specific project
# GET | /projects/:id/edit | :edit | YES | return an HTML form for editing a project (not relevant to json API)
# PUT | /projects/:id | :update | YES | update a specific project
# DELETE | /projects/:id | :destroy | YES | delete a specific project
# POST or GET | /projects/filter | :filter | NO | advanced filtering endpoint (json API only)
# WARNING: If a block or hash of conditions exist they will be ignored
# when checking on a class, and it will return true.
# Think of it as asking "can the current user read *a* project?" when using a class,
# and "can the current user read *this* project?" when checking an instance.
# This is mainly relevant for :index and :filter
# since they do no have an instance of the model.
# WARNING: :manage represents ANY action on the object.
# DO NOT use :manage except for the admin user
# WARNING: instance variable in controller index action will not be set if using a block for can definitions
# because there is no way to determine which records to fetch from the database.
# WARNING: can't add .includes to permission checks
# it breaks when validating projects due to ActiveRecord::AssociationRelation
# .all would have worked. I tried .where(nil), that didn't work either :/
# https://github.com/rails/rails/issues/12756
# https://github.com/plataformatec/has_scope/issues/41
# ======== Conventions and Notes ========
# - index and filter permissions are checked as part of filter query
# - new is usually available publicly
# - never use `current_user`
# - `user` may not be the logged in user
# ======== Permissions Specification ========
# See specification description on baw-server wiki:
# https://github.com/QutBioacoustics/baw-server/wiki/Permissions
# either current logged in user or guest user (not logged in)
# an unconfirmed user is logged in and is not a guest
user = create_guest_user if user.blank?
# guest access is specified per project
is_guest = Access::Core.is_guest?(user)
# api security endpoints for logged in users
can [:show, :destroy], :api_security unless is_guest
to_cms(user, is_guest)
if Access::Core.is_admin?(user)
for_admin
elsif Access::Core.is_harvester?(user)
for_harvester
elsif Access::Core.is_standard_user?(user) || is_guest
# available models:
# Project, Permission, Site, AudioRecording,
# AudioEvent, AudioEventComment, Bookmark,
# AnalysisJob, SavedSearch, Script, Tag, Tagging,
# User
to_project(user, is_guest)
to_permission(user)
to_harvest(user, is_guest)
to_harvest_item(user, is_guest)
to_region(user, is_guest)
to_site(user, is_guest)
to_audio_recording(user, is_guest)
to_audio_event(user, is_guest)
to_audio_event_import(user, is_guest)
to_audio_event_comment(user, is_guest)
to_bookmark(user, is_guest)
to_analysis_job(user, is_guest)
to_analysis_jobs_item(user)
to_dataset(user, is_guest)
to_dataset_item(user, is_guest)
to_progress_event(user, is_guest)
to_saved_search(user, is_guest)
to_script(user, is_guest)
to_tag(user, is_guest)
to_tagging(user, is_guest)
to_user(user, is_guest)
to_analysis(user, is_guest)
to_media(user, is_guest)
to_error(user, is_guest)
to_public(user, is_guest)
to_study(user, is_guest)
to_question(user, is_guest)
to_response(user, is_guest)
else
raise ArgumentError, "Permissions are not defined for user '#{user.id}': #{user.role_symbols}"
end
# internal takes permissions away from admin, it has to be after all of the above
for_internal(is_guest)
end
private
def check_model(model)
raise ArgumentError, 'Must have an instance of the model.' if model.nil?
#fail CustomErrors::UnprocessableEntityError.new('Model was invalid.', model.errors) if model.invalid?
end
def to_cms(user, _is_guest)
alias_action :index, :show, to: :read
alias_action :create, :update, to: :manage
can [:read, :manage], 'Cms::Site' if Access::Core.is_admin?(user)
# anyone anytime can read cms blobs
can [:read], 'Cms::Site'
end
def for_internal(is_guest)
# internal endpoints for hooks explicitly require no user information to have been set
[
# add more here
:internal_sftpgo
].each do |subject|
if is_guest
can [:manage], subject do |_subject, remote_ip|
Settings.internal_allow_remote_ip?(remote_ip)
end
else
cannot [:manage], subject
end
end
end
def for_admin
# admin can access any action on any controller
can :manage, :all
# no one is allowed to change allow_audio_upload except an admin
can [:allow_audio_upload], Project
end
def for_harvester
# actions used for harvesting. See baw-workers.
# :original is the permission to download an original audio file
can [:new, :create, :check_uploader, :update_status, :update, :original], AudioRecording
can [:index], :downloader
# omitted: :new, :create,
# applied by default: :index, :show, :filter
can [:show, :update], AnalysisJobsItem
end
def create_guest_user
guest = User.new
guest.roles << :guest
guest
end
def check_audio_event(user, site, audio_event)
Access::Core.check_orphan_site!(site)
projects = site.projects
is_ref = audio_event.is_reference
Access::Core.can_any?(user, :reader, projects) || is_ref
end
def to_project(user, is_guest)
# cannot use block for #index, #filter, #new_access_request, #submit_access_request
# GET|POST /projects/filter projects#filter {:format=>"json"}
# POST /projects/:id/update_permissions projects#update_permissions
# GET /projects/:id/edit_sites projects#edit_sites
# PATCH|PUT /projects/:id/update_sites projects#update_sites
# GET /projects/new_access_request projects#new_access_request
# POST /projects/submit_access_request projects#submit_access_request
# GET /projects projects#index
# POST /projects projects#create
# GET /projects/new projects#new
# GET /projects/:id/edit projects#edit
# GET /projects/:id projects#show
# PATCH|PUT /projects/:id projects#update
# DELETE /projects/:id projects#destroy
# any user, including guest, with reader permissions can #show a project
can [:show], Project do |project|
check_model(project)
Access::Core.can?(user, :reader, project)
end
# only admin can #edit_sites, #update_sites (update_sites is html-only)
# below definition is redundant but added for clarity
can [:update_sites], Project do |project|
check_model(project)
Access::Core.is_admin?(user)
end
# TODO: update_sites will be merged with sites#orphans
# must be owner to do these actions
# :update_permissions is html-only
# :creates_sites: Can we create a site that belongs to this project? This is mainly used in views
can [:edit, :update, :update_permissions, :destroy, :create_sites], Project do |project|
check_model(project)
Access::Core.can?(user, :owner, project)
end
# actions any logged in user can access
can [:new_access_request, :submit_access_request], Project unless is_guest
# Restricted to Admin according to settings (admin has implicit access)
can [:create], Project unless is_guest || !Settings.permissions.any_user_can_create_projects
# available to any user, including guest
can [:index, :filter, :new], Project
end
def to_permission(user)
# cannot use block for #index
# #show, #create, #delete are only used by json api
# #edit and #update are done via project instead
# GET /projects/:project_id/permissions permissions#index
# POST /projects/:project_id/permissions permissions#create {:format=>"json"}
# GET /projects/:project_id/permissions/new permissions#new {:format=>"json"}
# GET /projects/:project_id/permissions/:id permissions#show {:format=>"json"}
# DELETE /projects/:project_id/permissions/:id permissions#destroy {:format=>"json"}
# only owners can show, change, or remove permissions
can [:show, :create, :update, :destroy], Permission do |permission|
check_model(permission)
Access::Core.can?(user, :owner, permission.project)
end
# available to any user, including guest
can [:index, :filter, :new], Permission
end
def to_harvest(user, _is_guest)
# POST /projects/:project_id/harvests harvests#create
# GET /projects/:project_id/harvests/new harvests#new
# GET /projects/:project_id/harvests/:id harvests#show
# PATCH|PUT /projects/:project_id/harvests/:id harvests#update
# DELETE /projects/:project_id/harvests/:id harvests#destroy
# GET /projects/:project_id/harvests harvests#index {:format=>"json"}
# GET|POST /projects/:project_id/harvests/filter harvests#filter {:format=>"json"}
# and all of the above again with the shallow route
# only owner can access these actions.
# Special action :harvest_audio used as validation in the harvester job
can [:create, :update, :destroy, :show, :harvest_audio], Harvest do |harvest|
check_model(harvest)
Access::Core.can_any?(user, :owner, harvest.project)
end
# available to any user, including guest
can [:index, :filter, :new], Harvest
end
def to_harvest_item(_user, _is_guest)
# available to any user, including guest
can [:index, :filter], HarvestItem
end
def to_region(user, _is_guest)
# POST /projects/:project_id/regions regions#create
# GET /projects/:project_id/regions/new regions#new
# GET /projects/:project_id/regions/:id regions#show
# PATCH|PUT /projects/:project_id/regions/:id regions#update
# DELETE /projects/:project_id/regions/:id regions#destroy
# GET /projects/:project_id/regions regions#index {:format=>"json"}
# GET|POST /regions/filter regions#filter {:format=>"json"}
# and all of the above again with the shallow route
# any user, including guest, with reader permissions on project can #show a region and access #new
can [:show], Region do |region|
check_model(region)
Access::Core.can_any?(user, :reader, region.project)
end
# only owner can access these actions.
can [:create, :update, :destroy], Region do |region|
check_model(region)
Access::Core.can_any?(user, :owner, region.project)
end
# available to any user, including guest
can [:index, :filter, :new], Region
end
def to_site(user, _is_guest)
# only admin can :destroy, :orphans
# cannot use block for #index, #filter, #orphans
# only admin can access #orphans
# GET /projects/:project_id/sites/:id/upload_instructions sites#upload_instructions
# GET /projects/:project_id/sites/:id/harvest sites#harvest
# POST /projects/:project_id/sites sites#create
# GET /projects/:project_id/sites/new sites#new
# GET /projects/:project_id/sites/:id/edit sites#edit
# GET /projects/:project_id/sites/:id sites#show
# PATCH|PUT /projects/:project_id/sites/:id sites#update
# DELETE /projects/:project_id/sites/:id sites#destroy
# GET /projects/:project_id/sites sites#index {:format=>"json"}
# GET|POST /sites/filter sites#filter {:format=>"json"}
# GET /sites/orphans sites#orphans
# GET /sites/:id sites#show_shallow {:format=>"json"}
# any user, including guest, with reader permissions on project can #show a site and access #new
can [:show, :show_shallow], Site do |site|
check_model(site)
Access::Core.check_orphan_site!(site)
# can't add .includes here - it breaks when validating projects due to ActiveRecord::AssociationRelation
Access::Core.can_any?(user, :reader, site.projects)
end
# only owner can access these actions.
# :create (create a new site in a project) requires an instance to be available before permissions are checked.
# This is done in controller action.
# Note: duplicate definition :create_sites in project abilities above used for rendering view capabilities.
can [:create, :edit, :update, :destroy, :upload_instructions, :harvest], Site do |site|
check_model(site)
Access::Core.check_orphan_site!(site)
Access::Core.can_any?(user, :owner, site.projects)
end
# available to any user, including guest
can [:index, :filter, :new], Site
end
def to_audio_recording(user, _is_guest)
# cannot use block for #index, #filter
# See permissions for harvester (#for_harvester)
# - Only admin and harvester can #create, #check_uploader, #update_status, #update
# permissions are also checked in controller actions
# GET /projects/:project_id/sites/:site_id/audio_recordings/check_uploader/:uploader_id audio_recordings#check_uploader {:format=>"json"}
# POST /projects/:project_id/sites/:site_id/audio_recordings audio_recordings#create {:format=>"json"}
# GET /projects/:project_id/sites/:site_id/audio_recordings/new audio_recordings#new {:format=>"json"}
# GET|POST /audio_recordings/filter audio_recordings#filter {:format=>"json"}
# GET /audio_recordings audio_recordings#index {:format=>"json"}
# GET /audio_recordings/new audio_recordings#new {:format=>"json"}
# GET /audio_recordings/:id audio_recordings#show {:format=>"json"}
# PATCH|PUT /audio_recordings/:id audio_recordings#update {:format=>"json"}
# PUT /audio_recordings/:id/update_status audio_recordings#update_status {:format=>"json"}
# any user, including guest, with reader permissions on project can #show an audio_recording
can [:show], AudioRecording do |audio_recording|
check_model(audio_recording)
Access::Core.check_orphan_site!(audio_recording.site)
Access::Core.can_any?(user, :reader, audio_recording.site.projects)
end
can [:new], AudioRecording do |audio_recording|
check_model(audio_recording)
if audio_recording.site.nil?
# allow #new for /audio_recordings/new
true
else
# require project reader for /projects/:project_id/sites/:site_id/audio_recordings/new
Access::Core.check_orphan_site!(audio_recording.site)
Access::Core.can_any?(user, :reader, audio_recording.site.projects)
end
end
# available to any user, including guest
can [:index, :filter], AudioRecording
# anyone can access the downloader script
can [:index], :downloader
end
def to_audio_event(user, is_guest)
# cannot use block for #index, #filter
# GET|POST /audio_events/filter audio_events#filter {:format=>"json"}
# GET /audio_recordings/:audio_recording_id/audio_events/download audio_events#download {:format=>"csv"}
# GET /audio_recordings/:audio_recording_id/audio_events audio_events#index {:format=>"json"}
# POST /audio_recordings/:audio_recording_id/audio_events audio_events#create {:format=>"json"}
# GET /audio_recordings/:audio_recording_id/audio_events/new audio_events#new {:format=>"json"}
# GET /audio_recordings/:audio_recording_id/audio_events/:id audio_events#show {:format=>"json"}
# PATCH|PUT /audio_recordings/:audio_recording_id/audio_events/:id audio_events#update {:format=>"json"}
# DELETE /audio_recordings/:audio_recording_id/audio_events/:id audio_events#destroy {:format=>"json"}
# GET /projects/:project_id/audio_events/download audio_events#download {:format=>"csv"}
# GET /projects/:project_id/sites/:site_id/audio_events/download audio_events#download {:format=>"csv"}
# GET /user_accounts/:user_id/audio_events/download audio_events#download {:format=>"csv"}
# any user, including guest, with reader permissions on project can #show an audio_event or access #new
can [:show, :new], AudioEvent do |audio_event|
check_model(audio_event)
check_audio_event(user, audio_event.audio_recording.site, audio_event)
end
# must have write permission or higher to create, update, destroy
can [:create, :update, :destroy], AudioEvent do |audio_event|
check_model(audio_event)
Access::Core.check_orphan_site!(audio_event.audio_recording.site)
Access::Core.can_any?(user, :writer, audio_event.audio_recording.site.projects)
end
# actions any logged in user can access
# has additional auth in the controller action
can [:download], AudioEvent unless is_guest
# available to any user, including guest
can [:index, :filter], AudioEvent
end
def to_audio_event_import(user, is_guest)
unless is_guest
can [:create], AudioEventImport do |audio_event_import|
check_model(audio_event_import)
# further permission checks are done for each audio_event import
# but that is not related to the permissions of this model
# (which is really just a tracking object)
true
end
# only creator can update, destroy, show their own audio_event_imports
can [:update, :destroy, :show], AudioEventImport, creator_id: user&.id
end
# available to any user
can [:index, :filter, :new], AudioEventImport
end
def to_audio_event_comment(user, is_guest)
# cannot use block for #index, #filter
# GET|POST /audio_event_comments/filter audio_event_comments#filter {:format=>"json"}
# GET /audio_events/:audio_event_id/comments audio_event_comments#index {:format=>"json"}
# POST /audio_events/:audio_event_id/comments audio_event_comments#create {:format=>"json"}
# GET /audio_events/:audio_event_id/comments/new audio_event_comments#new {:format=>"json"}
# GET /audio_events/:audio_event_id/comments/:id audio_event_comments#show {:format=>"json"}
# PATCH|PUT /audio_events/:audio_event_id/comments/:id audio_event_comments#update {:format=>"json"}
# DELETE /audio_events/:audio_event_id/comments/:id audio_event_comments#destroy {:format=>"json"}
# any user, including guest, with reader permissions on project, or for reference audio events, can #show an audio_event_comment or access #new
can [:new, :show], AudioEventComment do |audio_event_comment|
check_model(audio_event_comment)
check_audio_event(user, audio_event_comment.audio_event.audio_recording.site, audio_event_comment.audio_event)
end
# guest users can only access #new, #show, #index, or #filter
unless is_guest
# can also update flag, any other attribute is restricted to creator by custom auth in controller action
can [:create, :update], AudioEventComment do |audio_event_comment|
check_model(audio_event_comment)
check_audio_event(user, audio_event_comment.audio_event.audio_recording.site, audio_event_comment.audio_event)
end
# only logged in users can update or destroy their comments, which must be comments they created
can [:destroy, :update], AudioEventComment, creator_id: user.id
# available to any logged in user
can [:filter], AudioEventComment
end
# available to any user, including guest
can [:index], AudioEventComment
end
def to_bookmark(user, is_guest)
# GET|POST /bookmarks/filter bookmarks#filter {:format=>"json"}
# GET /bookmarks bookmarks#index
# POST /bookmarks bookmarks#create
# GET /bookmarks/new bookmarks#new
# GET /bookmarks/:id bookmarks#show
# PATCH|PUT /bookmarks/:id bookmarks#update
# DELETE /bookmarks/:id bookmarks#destroy
# guests have no access to bookmarks
return if is_guest
can [:create], Bookmark do |bookmark|
check_model(bookmark)
Access::Core.check_orphan_site!(bookmark.audio_recording.site)
Access::Core.can_any?(user, :reader, bookmark.audio_recording.site.projects)
end
# only creator can update, destroy, show their own bookmarks
can [:update, :destroy, :show], Bookmark, creator_id: user.id
# available to any logged in user
can [:index, :filter, :new], Bookmark
end
def to_analysis_job(user, _is_guest)
# must have read permission or higher on ANY saved_search.projects to create analysis job
can [:show, :create], AnalysisJob do |analysis_job|
check_model(analysis_job)
raise CustomErrors::BadRequestError, 'Analysis Job must have a saved search.' if analysis_job.saved_search.nil?
projects = analysis_job.saved_search.projects
raise CustomErrors::BadRequestError, 'Saved search must have at least one project.' if projects.empty?
# can_any? because AnalysisJobsItem and analysis results can be accessed via AudioRecording. Any AnalysisJobsItem
# can be accessed if they user has access to the AudioRecording (and thus any project). can_any? here makes access
# consistent with AnalysisJobsItem.
Access::Core.can_any?(user, :reader, projects)
end
# only creator can update, destroy their own analysis jobs
can [:update, :destroy], AnalysisJob, creator_id: user.id
# actions any logged in user can access
# AT: 2020 - disabled unless guest filter. Anyone should be able to new
# I'm unsure why it was being excluded to guest
#can [:new], AnalysisJob #unless is_guest
# available to any user, including guest
can [:index, :filter, :new], AnalysisJob
end
def to_analysis_jobs_item(user)
# Only harvester can update - see permissions for harvester in for_harvester.
can [:show], AnalysisJobsItem do |analysis_job_item|
check_model(analysis_job_item)
if analysis_job_item.audio_recording.nil?
raise CustomErrors::BadRequestError, 'Analysis Jobs Item must have a Audio Recording.'
end
Access::Core.can_any?(user, :reader, analysis_job_item.audio_recording.site.projects)
end
# actions any logged in user can access
can [:index, :filter], AnalysisJobsItem
end
def to_dataset(user, is_guest)
# only creator can update their own dataset
can [:update], Dataset, creator_id: user.id
# actions any logged in user can access
can [:create], Dataset unless is_guest
# available to any user, including guest
can [:new, :index, :filter, :show], Dataset
end
def to_dataset_item(user, _is_guest)
# only admin can update, delete
# only admin can create, unless it is the default dataset
# if default dataset, must have read permission or higher to create
can [:create], DatasetItem do |dataset_item|
if dataset_item.dataset_id == Dataset.default_dataset_id
check_model(dataset_item)
Access::Core.can_any?(user, :reader, dataset_item.audio_recording.site.projects)
else
false
end
end
# must have read permissions to show
can [:show], DatasetItem do |dataset_item|
check_model(dataset_item)
if dataset_item.audio_recording.nil?
raise CustomErrors::BadRequestError, 'Dataset Item must have a Audio Recording.'
end
Access::Core.check_orphan_site!(dataset_item.audio_recording.site)
Access::Core.can_any?(user, :reader, dataset_item.audio_recording.site.projects)
end
# actions any logged in user can access
can [:new, :index, :filter, :next_for_me], DatasetItem
end
def to_progress_event(user, _is_guest)
# anyone can create as long as they have read access on the ancestor project of the dataset item
can [:create], ProgressEvent do |progress_event|
check_model(progress_event)
# the dataset_item may not be valid and therefore may not be associated with a project
audio_recording = progress_event.dataset_item.try(:audio_recording)
if audio_recording
Access::Core.can_any?(user, :reader, audio_recording.site.projects)
else
raise CustomErrors::UnprocessableEntityError, 'Invalid dataset item'
end
end
# must have read permissions or be creator to view
can [:show, :index, :filter], ProgressEvent do |progress_event|
check_model(progress_event)
Access::Core.can_any?(user, :reader, progress_event.dataset_item.audio_recording.site.projects) ||
progress_event.creator_id === user.id
end
can :new, ProgressEvent
# update and edit are admin only
cannot [:update, :destroy], ProgressEvent
end
def to_saved_search(user, is_guest)
# cannot be updated
# must have read permission or higher on all projects to create saved search
can [:show, :create], SavedSearch do |saved_search|
check_model(saved_search)
projects = saved_search.projects
raise CustomErrors::BadRequestError, 'Saved Search must have at least one project.' if projects.empty?
Access::Core.can_all?(user, :reader, projects)
end
# only creator can destroy their own saved searches
can [:destroy], SavedSearch, creator_id: user.id
# actions any logged in user can access
can [:new], SavedSearch unless is_guest
# available to any user, including guest
can [:index, :filter], SavedSearch
end
def to_script(_user, is_guest)
# only admin can manipulate scripts
can [:show], Script unless is_guest
# available to any user, including guest
can [:index, :filter], Script
end
def to_tag(_user, is_guest)
# cannot be updated
# tag management controller is admin only (checked in before_action)
# actions any logged in user can access
can [:new, :create], Tag unless is_guest
# available to any user, including guest
can [:index, :show, :filter], Tag
end
def to_tagging(user, is_guest)
# must have read permission or higher to show
can [:show], Tagging do |tagging|
check_model(tagging)
Access::Core.check_orphan_site!(tagging.audio_event.audio_recording.site)
Access::Core.can_any?(user, :reader, tagging.audio_event.audio_recording.site.projects)
end
# must have write permission or higher to create, update, destroy
can [:create, :update, :destroy], Tagging do |tagging|
check_model(tagging)
Access::Core.check_orphan_site!(tagging.audio_event.audio_recording.site)
Access::Core.can_any?(user, :writer, tagging.audio_event.audio_recording.site.projects)
end
# actions any logged in user can access
can [:new, :user_index], Tagging unless is_guest
# available to any user, including guest
can [:index, :filter], Tagging
end
def to_user(user, is_guest)
# admin only: :index, :edit, :update
# :edit and :update are the Admin interface for editing any user
# normal users edit their profile using devise/registrations#edit
# users can only view their own:
can [:projects, :sites, :bookmarks, :audio_events, :audio_event_comments], User, id: user.id
# users get their own account and preferences from these actions
can [:my_account, :modify_preferences], User, id: user.id
# only logged in users can view a user's profile (read-only)
can [:show, :filter], User unless is_guest
end
def to_analysis(_user, is_guest)
# actions any logged in user can access
# skips CanCan auth
can [:show], :analysis unless is_guest
end
def to_media(user, is_guest)
# available to any user, including guest
# skips CanCan auth
can [:show], :media
# download original recording (#original)
#
# - admin and harvester can (see for_harvester and for_admin)
# - logged in users can if the project says so
# - anonymous users cannot
# GET /audio_recordings/:id/original media#original
return if is_guest
can [:original], AudioRecording do |audio_recording|
check_model(audio_recording)
Access::Core.check_orphan_site!(audio_recording.site)
projects = audio_recording.site.projects
# now extract the required permission levels needed to allow original downloads
requested_levels = projects.map(&:allow_original_download)
Access::Core.can_any?(user, requested_levels, projects)
end
end
def to_error(_user, _is_guest)
# available to any user, including guest
# skips CanCan auth
can [:route_error, :uncaught_error, :test_exceptions, :show], :error
# only available in Rails test env
can [:test_exceptions], :error if ENV.fetch('RAILS_ENV', nil) == 'test'
end
def to_public(_user, _is_guest)
# available to any user, including guest
# skips CanCan auth
can [
:index, :status,
:website_status,
:credits,
:disclaimers,
:ethics_statement,
:data_upload,
:new_contact_us, :create_contact_us,
:new_bug_report, :create_bug_report,
:new_data_request, :create_data_request,
:cors_preflight
], :public
end
def to_study(_user, _is_guest)
# only admin can create, update, delete
# all users including guest can access any get request
can [:new, :index, :filter, :show], Study
end
def to_question(_user, is_guest)
can [:new], Question
# only admin create, update, delete
# only logged in users can view questions
can [:index, :filter, :show], Question unless is_guest
end
def to_response(user, is_guest)
can [:new], Response
# must have read permission on dataset item to create a response for it
can [:create], Response do |response|
check_model(response)
if response.dataset_item
Access::Core.can_any?(user, :reader, response.dataset_item.audio_recording.site.projects)
else
false
end
end
# users can only view their own responses
# therefore guest can not view any responses
can [:index, :filter, :show], Response, creator_id: user.id unless is_guest
# only admin can update or delete responses
end
end