diff --git a/app/api/units_api.rb b/app/api/units_api.rb index 4dbc09cd1..7d11556cc 100644 --- a/app/api/units_api.rb +++ b/app/api/units_api.rb @@ -26,7 +26,7 @@ class UnitsApi < Grape::API optional :include_in_active, type: Boolean, desc: 'Include units that are not active' end get '/units' do - unless authorise? current_user, User, :convene_units + unless (authorise? current_user, User, :convene_units) || (authorise? current_user, User, :audit_units) error!({ error: 'Unable to list units' }, 403) end diff --git a/app/api/users_api.rb b/app/api/users_api.rb index 30f055df7..c21d23b72 100644 --- a/app/api/users_api.rb +++ b/app/api/users_api.rb @@ -30,7 +30,7 @@ class UsersApi < Grape::API desc 'Get convenors' get '/users/convenors' do - unless authorise? current_user, User, :convene_units + unless (authorise? current_user, User, :convene_units) || (authorise? current_user, User, :audit_units) error!({ error: 'Cannot list convenors - not authorised' }, 403) end @@ -39,7 +39,7 @@ class UsersApi < Grape::API desc 'Get tutors' get '/users/tutors' do - unless authorise? current_user, User, :convene_units + unless (authorise? current_user, User, :convene_units) || (authorise? current_user, User, :audit_units) error!({ error: 'Cannot list tutors - not authorised' }, 403) end @@ -55,7 +55,7 @@ class UsersApi < Grape::API optional :email, type: String, desc: 'New email address for user' optional :student_id, type: String, desc: 'New student_id for user' optional :nickname, type: String, desc: 'New nickname for user' - optional :system_role, type: String, desc: 'New role for user [Admin, Convenor, Tutor, Student]' + optional :system_role, type: String, desc: 'New role for user [Admin, Auditor, Convenor, Tutor, Student]' optional :receive_task_notifications, type: Boolean, desc: 'Allow user to be sent task notifications' optional :receive_portfolio_notifications, type: Boolean, desc: 'Allow user to be sent portfolio notifications' optional :receive_feedback_notifications, type: Boolean, desc: 'Allow user to be sent feedback notifications' @@ -141,7 +141,7 @@ class UsersApi < Grape::API optional :student_id, type: String, desc: 'New student_id for user' requires :username, type: String, desc: 'New username for user' requires :nickname, type: String, desc: 'New nickname for user' - requires :system_role, type: String, desc: 'New system role for user [Admin, Convenor, Tutor, Student]' + requires :system_role, type: String, desc: 'New system role for user [Admin, Auditor, Convenor, Tutor, Student]' end end post '/users' do diff --git a/app/models/group.rb b/app/models/group.rb index db4f766d8..e075c04b4 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -58,12 +58,17 @@ def self.permissions :can_exceed_capacity, :move_tutorial ] + # What can auditors do with groups? + auditor_role_permissions = [ + :get_members + ] # What can nil users do with groups? nil_role_permissions = [] # Return permissions hash { admin: admin_role_permissions, + auditor: auditor_role_permissions, convenor: convenor_role_permissions, tutor: tutor_role_permissions, student: student_role_permissions, diff --git a/app/models/project.rb b/app/models/project.rb index f7fc40f6d..dc5d5d5a9 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -70,6 +70,11 @@ def self.permissions :get, :get_submission ] + # What can auditors do with projects? + auditor_role_permissions = [ + :get, + :get_submission + ] # What can nil users do with projects? nil_role_permissions = [] @@ -78,6 +83,7 @@ def self.permissions student: student_role_permissions, tutor: tutor_role_permissions, admin: admin_role_permissions, + auditor: auditor_role_permissions, nil: nil_role_permissions } end @@ -229,6 +235,7 @@ def user_role(user) if user == student then :student elsif user.present? && unit.tutors.where(id: user.id).count != 0 then :tutor elsif user.present? && user.role.id == Role.admin_id then :admin + elsif user.present? && user.role.id == Role.auditor_id then :auditor else nil end end diff --git a/app/models/role.rb b/app/models/role.rb index c6ef76270..8a73f6a5d 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -9,11 +9,11 @@ def self.find(id) end def self.admin_staff_ids - [self.convenor_id, self.admin_id] + [self.convenor_id, self.admin_id, self.auditor_id] end def self.teaching_staff_ids - [self.tutor_id, self.convenor_id, self.admin_id] + [self.tutor_id, self.convenor_id, self.admin_id, self.auditor_id] end def self.student @@ -32,6 +32,10 @@ def self.admin Role.find(admin_id) end + def self.auditor + Role.find(auditor_id) + end + def to_sym name.downcase.to_sym end @@ -66,10 +70,16 @@ def self.admin_id 4 end + def self.auditor_id + 5 + end + def self.with_name(name) case name when /[Aa]dmin/ admin + when /[Aa]uditor/ + auditor when /[Cc]onvenor/ convenor when /[Tt]utor/ diff --git a/app/models/unit.rb b/app/models/unit.rb index 6e709baab..b07f010d4 100644 --- a/app/models/unit.rb +++ b/app/models/unit.rb @@ -69,6 +69,15 @@ def self.permissions :exceed_capacity ] + # What can auditors do with units? + auditor_role_permissions = [ + :get_unit, + :get_students, + :download_stats, + :download_unit_csv, + :download_grades + ] + # What can other users do with units? nil_role_permissions = [] @@ -78,6 +87,7 @@ def self.permissions tutor: tutor_role_permissions, convenor: convenor_role_permissions, admin: admin_role_permissions, + auditor: auditor_role_permissions, nil: nil_role_permissions } end @@ -89,6 +99,8 @@ def role_for(user) Role.tutor elsif active_projects.where('projects.user_id=:id', id: user.id).count == 1 Role.student + elsif user.has_auditor_capability? + Role.auditor elsif user.has_admin_capability? Role.admin else diff --git a/app/models/user.rb b/app/models/user.rb index 262b5d028..5a8681a0a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -147,9 +147,10 @@ def token_for_text?(a_token) validate :can_change_to_role?, if: :will_save_change_to_role_id? # Queries - scope :tutors, -> { joins(:role).where('roles.id = :tutor_role or roles.id = :convenor_role or roles.id = :admin_role', tutor_role: Role.tutor_id, convenor_role: Role.convenor_id, admin_role: Role.admin_id) } - scope :convenors, -> { joins(:role).where('roles.id = :convenor_role or roles.id = :admin_role', convenor_role: Role.convenor_id, admin_role: Role.admin_id) } - scope :admins, -> { joins(:role).where('roles.id = :admin_role', admin_role: Role.admin_id) } + scope :tutors, -> { joins(:role).where('roles.id = :tutor_role or roles.id = :convenor_role or roles.id = :admin_role or roles.id = :auditor_role', tutor_role: Role.tutor_id, convenor_role: Role.convenor_id, admin_role: Role.admin_id, auditor_role: Role.auditor_id) } + scope :convenors, -> { joins(:role).where('roles.id = :convenor_role or roles.id = :admin_role or roles.id = :auditor_role', convenor_role: Role.convenor_id, admin_role: Role.admin_id, auditor_role: Role.auditor_id) } + scope :admins, -> { joins(:role).where('roles.id = :admin_role or roles.id = :auditor_role', admin_role: Role.admin_id, auditor_role: Role.auditor_id) } + scope :auditors, -> { joins(:role).where('roles.id = :auditor_role', auditor_role: Role.auditor_id) } def self.teaching(unit) User.joins(:unit_roles).where('unit_roles.unit_id = :unit_id and ( unit_roles.role_id = :tutor_role_id or unit_roles.role_id = :convenor_role_id) ', unit_id: unit.id, tutor_role_id: Role.tutor_id, convenor_role_id: Role.convenor_id) @@ -167,7 +168,7 @@ def can_change_to_role? fail_if_in_unit_role = [Role.tutor, Role.convenor] if new_role == Role.student fail_if_in_unit_role = [Role.convenor] if new_role == Role.tutor - fail_if_in_unit_role = [] if new_role == Role.admin || new_role == Role.convenor + fail_if_in_unit_role = [] if new_role == Role.admin || new_role == Role.convenor || new_role == Role.auditor for check_role in fail_if_in_unit_role do if unit_roles.where('role_id = :role_id', role_id: check_role.id).count > 0 @@ -189,7 +190,11 @@ def has_convenor_capability? end def has_admin_capability? - role_id == Role.admin_id + role_id == Role.admin_id || has_auditor_capability? + end + + def has_auditor_capability? + role_id == Role.auditor_id end def self.get_change_role_perm_fn @@ -217,30 +222,42 @@ def self.permissions # An admin current_user can demote them to either a student, tutor or convenor admin: { student: [:demote_user], tutor: [:demote_user], - convenor: [:demote_user] }, + convenor: [:demote_user], + auditor: [:demote_user] }, + # User being assigned is an auditor? + # An admin current_user can demote them to either a student, tutor or convenor + # An admin current_user can promote them to an admin + auditor: { student: [:demote_user], + tutor: [:demote_user], + convenor: [:demote_user], + admin: [:promote_user] }, # User being assigned is a convenor? # An admin current_user can demote them to student or tutor - # An admin current_user can promote them to an admin + # An admin current_user can promote them to an admin or auditor convenor: { student: [:demote_user], tutor: [:demote_user], - admin: [:promote_user] }, + admin: [:promote_user], + auditor: [:promote_user] }, # User being assigned is a tutor? # An admin current_user can demote them to a student - # An admin current_user can promote them to a convenor or admin + # An admin current_user can promote them to a convenor, admin or auditor tutor: { student: [:demote_user], convenor: [:promote_user], - admin: [:promote_user] }, + admin: [:promote_user], + auditor: [:promote_user] }, # User being assigned is a student? - # An admin current_user can promote them to a tutor, convenor or admin + # An admin current_user can promote them to a tutor, convenor, admin or auditor student: { tutor: [:promote_user], convenor: [:promote_user], - admin: [:promote_user] }, + admin: [:promote_user], + auditor: [:promote_user] }, # User being assigned has no role? # An admin current_user can create user to any role nil: { student: [:create_user], tutor: [:create_user], convenor: [:create_user], - admin: [:create_user] } + admin: [:create_user], + auditor: [:create_user] } }, # The current_user's role is a Convenor convenor: { @@ -280,6 +297,19 @@ def self.permissions :use_overseer ] + # What can auditors do with users? + auditor_role_permissions = [ + :list_users, + :download_system_csv, + :download_unit_csv, + :act_tutor, + :admin_users, + :audit_units, + :download_stats, + :get_teaching_periods, + :use_overseer + ] + # What can convenors do with users? convenor_role_permissions = [ :promote_user, @@ -314,6 +344,7 @@ def self.permissions { change_role: change_role_permissions, admin: admin_role_permissions, + auditor: auditor_role_permissions, convenor: convenor_role_permissions, tutor: tutor_role_permissions, student: student_role_permissions diff --git a/lib/helpers/database_populator.rb b/lib/helpers/database_populator.rb index eaef8322c..223f9e822 100644 --- a/lib/helpers/database_populator.rb +++ b/lib/helpers/database_populator.rb @@ -288,6 +288,7 @@ def generate_fixed_data # Define fixed user data here @user_data = { acain: { first_name: "Andrew", last_name: "Cain", nickname: "Macite", role_id: Role.admin_id }, + aauditor: { first_name: "Auditor", last_name: "Auditor", nickname: "Auditor", role_id: Role.auditor_id }, aconvenor: { first_name: "Clinton", last_name: "Woodward", nickname: "The Giant", role_id: Role.convenor_id }, ajones: { first_name: "Allan", last_name: "Jones", nickname: "P-Jiddy", role_id: Role.admin_id }, rwilson: { first_name: "Reuben", last_name: "Wilson", nickname: "Reubs", role_id: Role.convenor_id }, diff --git a/lib/tasks/init.rake b/lib/tasks/init.rake index c00ead3d4..8368440f3 100644 --- a/lib/tasks/init.rake +++ b/lib/tasks/init.rake @@ -10,7 +10,8 @@ namespace :db do { name: 'Student', description: "Students are able to be enrolled into units, and to submit progress for their unit projects." }, { name: 'Tutor', description: "Tutors are able to supervise tutorial classes and provide feedback to students, they may also be students in other units" }, { name: 'Convenor', description: "Convenors are able to create and manage units, as well as act as tutors and students." }, - { name: 'Admin', description: "Admin are able to create convenors, and act as convenors, tutors, and students in units." } + { name: 'Admin', description: "Admin are able to create convenors, and act as convenors, tutors, and students in units." }, + { name: 'Auditor', description: "Auditors are able to view only everything an admin can." } ] roles.each do |role|