diff --git a/app/controllers/admin/roles_controller.rb b/app/controllers/admin/roles_controller.rb index 1e045b74..d68b0883 100644 --- a/app/controllers/admin/roles_controller.rb +++ b/app/controllers/admin/roles_controller.rb @@ -2,11 +2,13 @@ module Admin class RolesController < Admin::BaseController load_and_authorize_resource :conference, find_by: :short_title before_action :set_selection + authorize_resource :role, except: :index # Show flash message with ajax calls after_action :prepare_unobtrusive_flash, only: :toggle_user def index @roles = Role.where(resource: @conference) + authorize! :index, @role end def show diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 149d5874..b3d32bec 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -278,7 +278,7 @@ module ApplicationHelper end def can_manage_volunteers(conference) - if (current_user.has_role? :organizer, conference) || (current_user.has_role? :volunteer_coordinator, conference) + if (current_user.has_role? :organizer, conference) || (current_user.has_role? :volunteers_coordinator, conference) true else false diff --git a/app/models/ability.rb b/app/models/ability.rb index ef569ec7..b54f8ab0 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -9,7 +9,7 @@ class Ability # user.is_organizer? or user.has_role? :organizer # user.is_cfp_of? Conference or user.has_role? :cfp, Conference # user.is_info_desk_of? Conference - # user.is_volunteer_coordinator_of? Conference + # user.is_volunteers_coordinator_of? Conference # user.is_attendee_of? Conference # The following is wrong because a user will only have 'cfp' role for a specific conference # user.is_cfp? # This is always false @@ -104,7 +104,7 @@ class Ability signed_in_with_organizer_role(user) if user.has_role? :organizer, :any signed_in_with_cfp_role(user) if user.has_role? :cfp, :any signed_in_with_info_desk_role(user) if user.has_role? :info_desk, :any - signed_in_with_volunteers_coordinator_role(user) if user.has_role? :volunteer_coordinator, :any + signed_in_with_volunteers_coordinator_role(user) if user.has_role? :volunteers_coordinator, :any # for users with any role can :access, Admin @@ -123,9 +123,7 @@ class Ability def signed_in_with_organizer_role(user) # ids of all the conferences for which the user has the 'organizer' role - conf_ids_for_organizer = [] - conf_ids_for_organizer = - Conference.with_role(:organizer, user).pluck(:id) if user.has_role? :organizer, :any + conf_ids_for_organizer = Conference.with_role(:organizer, user).pluck(:id) can [:new, :create], Conference if user.has_role?(:organizer, :any) can :manage, Conference, id: conf_ids_for_organizer @@ -162,24 +160,15 @@ class Ability commentable_id: Event.where(program_id: Program.where(conference_id: conf_ids_for_organizer).pluck(:id)).pluck(:id) # Abilities for Role (Conference resource) - can :index, Role - can :manage, Role do |role| + can [:index, :show], Role + can [:edit, :update, :toggle_user], Role do |role| role.resource_type == 'Conference' && (conf_ids_for_organizer.include? role.resource_id) end - - # Can add or remove users from role, when user has that same role for the conference - # Eg. If you are member of the CfP team, you can add more CfP team members (add users to the role 'CfP') - can :toggle_user, Role do |role| - role.resource_type == 'Conference' && - (Conference.with_role(role.name.parameterize.underscore.to_sym, user).pluck(:id).include? role.resource_id) - end end def signed_in_with_cfp_role(user) # ids of all the conferences for which the user has the 'cfp' role - conf_ids_for_cfp = [] - conf_ids_for_cfp = - Conference.with_role(:cfp, user).pluck(:id) if user.has_role? :cfp, :any + conf_ids_for_cfp = Conference.with_role(:cfp, user).pluck(:id) can :manage, Event, program: { conference_id: conf_ids_for_cfp } can :manage, EventType, program: { conference_id: conf_ids_for_cfp } @@ -196,66 +185,52 @@ class Ability commentable_id: Event.where(program_id: Program.where(conference_id: conf_ids_for_cfp).pluck(:id)).pluck(:id) # Abilities for Role (Conference resource) - can :index, Role - - can :manage, Role do |role| - role.resource_type == 'Conference' && (conf_ids_for_cfp.include? role.resource_id) - end + can [:index, :show], Role # Can add or remove users from role, when user has that same role for the conference # Eg. If you are member of the CfP team, you can add more CfP team members (add users to the role 'CfP') can :toggle_user, Role do |role| - role.resource_type == 'Conference' && - (Conference.with_role(role.name.parameterize.underscore.to_sym, user).pluck(:id).include? role.resource_id) + role.resource_type == 'Conference' && role.name == 'cfp' && + (Conference.with_role(:cfp, user).pluck(:id).include? role.resource_id) end end def signed_in_with_info_desk_role(user) # ids of all the conferences for which the user has the 'info_desk' role - conf_ids_for_info_desk = [] - conf_ids_for_info_desk = - Conference.with_role(:info_desk, user).pluck(:id) if user.has_role? :info_desk, :any + conf_ids_for_info_desk = Conference.with_role(:info_desk, user).pluck(:id) can :manage, Registration, conference_id: conf_ids_for_info_desk can :manage, Question, conference_id: conf_ids_for_info_desk can :manage, Question do |question| !(question.conferences.pluck(:id) & conf_ids_for_info_desk).empty? end - # Abilities for Role (Conference resource) - can :index, Role - can :manage, Role do |role| - role.resource_type == 'Conference' && (conf_ids_for_info_desk.include? role.resource_id) - end + # Abilities for Role (Conference resource) + can [:index, :show], Role # Can add or remove users from role, when user has that same role for the conference # Eg. If you are member of the CfP team, you can add more CfP team members (add users to the role 'CfP') can :toggle_user, Role do |role| - role.resource_type == 'Conference' && - (Conference.with_role(role.name.parameterize.underscore.to_sym, user).pluck(:id).include? role.resource_id) + role.resource_type == 'Conference' && role.name == 'info_desk' && + (Conference.with_role(:info_desk, user).pluck(:id).include? role.resource_id) end end def signed_in_with_volunteers_coordinator_role(user) # ids of all the conferences for which the user has the 'volunteers_coordinator' role - conf_ids_for_volunteers_coordinator = [] - conf_ids_for_volunteers_coordinator = - Conference.with_role(:volunteer_coordinator, user).pluck(:id) if user.has_role? :volunteer_coordinator, :any + conf_ids_for_volunteers_coordinator = Conference.with_role(:volunteers_coordinator, user).pluck(:id) can :manage, Vposition, conference_id: conf_ids_for_volunteers_coordinator can :manage, Vday, conference_id: conf_ids_for_volunteers_coordinator - # Abilities for Role (Conference resource) - can :index, Role - can :manage, Role do |role| - role.resource_type == 'Conference' && (conf_ids_for_volunteers_coordinator.include? role.resource_id) - end + # Abilities for Role (Conference resource) + can [:index, :show], Role # Can add or remove users from role, when user has that same role for the conference # Eg. If you are member of the CfP team, you can add more CfP team members (add users to the role 'CfP') can :toggle_user, Role do |role| - role.resource_type == 'Conference' && - (Conference.with_role(role.name.parameterize.underscore.to_sym, user).pluck(:id).include? role.resource_id) + role.resource_type == 'Conference' && role.name == 'volunteers_coordinator' && + (Conference.with_role(:volunteers_coordinator, user).pluck(:id).include? role.resource_id) end end end diff --git a/app/views/admin/roles/_users.html.haml b/app/views/admin/roles/_users.html.haml index f73af1b8..dbfbe76a 100644 --- a/app/views/admin/roles/_users.html.haml +++ b/app/views/admin/roles/_users.html.haml @@ -3,16 +3,18 @@ - if users.present? %table.table.table-striped.table-bordered.table-hover.datatable#users %thead - %th.col-md-1 + - if ( can? :toggle_user, @role ) + %th.col-md-1 %th ID %th Name %th Email %tbody - users.each do |user| %tr - %td.text-right - = hidden_field_tag "role[user_ids][]", nil - = check_box_tag @conference.short_title, @role.id, (@role.user_ids.include? user.id), method: :post, url: "/admin/conference/#{@conference.short_title}/roles/#{@role.name}/toggle_user?user[email]=#{user.email}&user[state]=", class: 'switch-checkbox', data: { size: 'small', off_color: 'warning', on_text: 'Yes', off_text: 'No' } + - if ( can? :toggle_user, @role ) + %td.text-right + = hidden_field_tag "role[user_ids][]", nil + = check_box_tag @conference.short_title, @role.id, (@role.user_ids.include? user.id), method: :post, url: "/admin/conference/#{@conference.short_title}/roles/#{@role.name}/toggle_user?user[email]=#{user.email}&user[state]=", class: 'switch-checkbox', data: { size: 'small', off_color: 'warning', on_text: 'Yes', off_text: 'No' } %td= user.id %td= user.name %td= user.email diff --git a/spec/features/ability_spec.rb b/spec/features/ability_spec.rb index fac2e4e7..60248c30 100644 --- a/spec/features/ability_spec.rb +++ b/spec/features/ability_spec.rb @@ -11,13 +11,13 @@ feature 'Has correct abilities' do let(:role_organizer) { Role.find_by(name: 'organizer', resource: conference1) } let(:role_cfp) { Role.find_by(name: 'cfp', resource: conference2) } let(:role_info_desk) { Role.find_by(name: 'info_desk', resource: conference3) } - let(:role_volunteer_coordinator) { Role.find_by(name: 'volunteers_coordinator', resource: conference4) } + let(:role_volunteers_coordinator) { Role.find_by(name: 'volunteers_coordinator', resource: conference4) } let(:user) { create(:user) } let(:user_organizer) { create(:user, role_ids: [role_organizer.id]) } let(:user_cfp) { create(:user, role_ids: [role_cfp.id]) } let(:user_info_desk) { create(:user, role_ids: [role_info_desk.id]) } - let(:user_volunteer_coordinator) { create(:user, role_ids: [role_volunteer_coordinator.id]) } + let(:user_volunteers_coordinator) { create(:user, role_ids: [role_volunteers_coordinator.id]) } scenario 'when user has no role' do sign_in user diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index 91937cfb..71884e48 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -126,6 +126,34 @@ describe 'User' do it{ should_not be_able_to(:destroy, my_venue) } end + shared_examples 'user with any role' do + before do + @other_conference = create(:conference) + end + + %w(organizer cfp info_desk volunteers_coordinator).each do |role| + it{ should_not be_able_to(:toggle_user, Role.find_by(name: role, resource: @other_conference)) } + it{ should_not be_able_to(:update, Role.find_by(name: role, resource: @other_conference)) } + it{ should_not be_able_to(:edit, Role.find_by(name: role, resource: @other_conference)) } + it{ should be_able_to(:show, Role.find_by(name: role, resource: @other_conference)) } + it{ should be_able_to(:index, Role.find_by(name: role, resource: @other_conference)) } + end + end + + shared_examples 'user with non-organizer role' do |role_name| + %w(organizer cfp info_desk volunteers_coordinator).each do |role| + if role == role_name + it{ should be_able_to(:toggle_user, Role.find_by(name: role, resource: my_conference)) } + else + it{ should_not be_able_to(:toggle_user, Role.find_by(name: role, resource: my_conference)) } + end + it{ should_not be_able_to(:update, Role.find_by(name: role, resource: my_conference)) } + it{ should_not be_able_to(:edit, Role.find_by(name: role, resource: my_conference)) } + it{ should be_able_to(:show, Role.find_by(name: role, resource: my_conference)) } + it{ should be_able_to(:index, Role.find_by(name: role, resource: my_conference)) } + end + end + context 'when user has the role organizer' do let!(:my_conference) { create(:full_conference) } let(:role) { Role.find_by(name: 'organizer', resource: my_conference) } @@ -190,6 +218,16 @@ describe 'User' do it{ should_not be_able_to(:manage, other_event.commercials.first) } it{ should be_able_to(:index, my_event.comment_threads.first) } it{ should_not be_able_to(:index, other_event.comment_threads.first) } + + %w(organizer cfp info_desk volunteers_coordinator).each do |role| + it{ should be_able_to(:toggle_user, Role.find_by(name: role, resource: my_conference)) } + it{ should be_able_to(:edit, Role.find_by(name: role, resource: my_conference)) } + it{ should be_able_to(:update, Role.find_by(name: role, resource: my_conference)) } + it{ should be_able_to(:show, Role.find_by(name: role, resource: my_conference)) } + it{ should be_able_to(:index, Role.find_by(name: role, resource: my_conference)) } + end + + it_behaves_like 'user with any role' end context 'when user has the role cfp' do @@ -245,6 +283,9 @@ describe 'User' do it{ should_not be_able_to(:manage, other_event.commercials.first) } it{ should be_able_to(:index, my_event.comment_threads.first) } it{ should_not be_able_to(:index, other_event.comment_threads.first) } + + it_behaves_like 'user with any role' + it_behaves_like 'user with non-organizer role', 'cfp' end context 'when user has the role info_desk' do @@ -300,6 +341,9 @@ describe 'User' do it{ should_not be_able_to(:manage, other_event.commercials.first) } it{ should_not be_able_to(:index, my_event.comment_threads.first) } it{ should_not be_able_to(:index, other_event.comment_threads.first) } + + it_behaves_like 'user with any role' + it_behaves_like 'user with non-organizer role', 'info_desk' end context 'when user has the role volunteers_coordinator' do @@ -357,6 +401,9 @@ describe 'User' do it{ should_not be_able_to(:index, other_event.comment_threads.first) } it 'should be_able to :manage Vposition' it 'should be_able to :manage Vday' + + it_behaves_like 'user with any role' + it_behaves_like 'user with non-organizer role', 'volunteers_coordinator' end end end