diff --git a/.reek b/.reek index 824a6a5ee..3c84a1114 100644 --- a/.reek +++ b/.reek @@ -1,5 +1,33 @@ +InstanceVariableAssumption: + exclude: + - Admin::ContactsController + - Admin::LocationsController + - Admin::OrganizationsController + - Admin::OrganizationContactsController + - Admin::ProgramsController + - Admin::ServiceContactsController + - Admin::ServicesController IrresponsibleModule: enabled: false +NestedIterators: + exclude: + - Admin::OrganizationsController#index +TooManyMethods: + exclude: + - Admin::CsvController + - Admin::ServicesController +TooManyStatements: + max_statements: 6 + exclude: + - Admin::ContactsController + - Admin::OrganizationsController + - Admin::OrganizationContactsController + - Admin::ServiceContactsController + - Admin::ServicesController +UtilityFunction: + exclude: + - Admin::ServicesController#program_ids_for + - Admin::CsvController#zip_file_name 'spec': DataClump: enabled: false diff --git a/.rubocop.yml b/.rubocop.yml index 2dcec6ce4..3bfde80a8 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -47,6 +47,7 @@ Metrics/ClassLength: Max: 100 Exclude: - spec/**/* + - 'app/controllers/admin/services_controller.rb' Metrics/LineLength: Description: Limit lines to 80 characters. diff --git a/app/controllers/admin/contacts_controller.rb b/app/controllers/admin/contacts_controller.rb index 041f2887c..91ba4028a 100644 --- a/app/controllers/admin/contacts_controller.rb +++ b/app/controllers/admin/contacts_controller.rb @@ -14,6 +14,8 @@ def update @contact = Contact.find(params[:id]) @location = Location.find(params[:location_id]) + authorize @location + if @contact.update(contact_params) flash[:notice] = 'Contact was successfully updated.' redirect_to [:admin, @location, @contact] @@ -34,6 +36,8 @@ def create @location = Location.find(params[:location_id]) @contact = @location.contacts.new(contact_params) + authorize @location + if @contact.save flash[:notice] = "Contact '#{@contact.name}' was successfully created." redirect_to admin_location_path(@location) @@ -44,8 +48,12 @@ def create def destroy contact = Contact.find(params[:id]) + location = contact.location + + authorize location + contact.destroy - redirect_to admin_location_path(contact.location), + redirect_to admin_location_path(location), notice: "Contact '#{contact.name}' was successfully deleted." end diff --git a/app/controllers/admin/csv_controller.rb b/app/controllers/admin/csv_controller.rb index ee598cec9..241600f77 100644 --- a/app/controllers/admin/csv_controller.rb +++ b/app/controllers/admin/csv_controller.rb @@ -1,5 +1,7 @@ class Admin class CsvController < ApplicationController + before_action :authenticate_admin! + before_action :authorize_admin # The CSV content for each action is defined in # app/views/admin/csv/{action_name}.csv.shaper @@ -45,6 +47,11 @@ def download_zip private + def authorize_admin + return if current_admin.super_admin? + user_not_authorized + end + def tmp_file_name @tmp_file_name ||= Rails.root.join('tmp', 'archive.zip') end diff --git a/app/controllers/admin/locations_controller.rb b/app/controllers/admin/locations_controller.rb index 38f2ec480..5e53b4592 100644 --- a/app/controllers/admin/locations_controller.rb +++ b/app/controllers/admin/locations_controller.rb @@ -19,6 +19,8 @@ def update @location = Location.find(params[:id]) @org = @location.organization + authorize @location + if @location.update(location_params) redirect_to [:admin, @location], notice: 'Location was successfully updated.' @@ -34,8 +36,9 @@ def new def create @location = Location.new(location_params) + org = @location.organization - assign_location_to_org(policy_scope(Organization)) + authorize org if org.present? if @location.save redirect_to [:admin, @location], notice: 'Location was successfully created.' @@ -46,20 +49,15 @@ def create def destroy location = Location.find(params[:id]) + + authorize location + location.destroy redirect_to admin_locations_path end private - def assign_location_to_org(admin_orgs) - org_id = location_params[:organization_id] - - if admin_orgs.select { |org| org[0] == org_id.to_i }.present? - @location.organization = Organization.find(org_id) - end - end - # rubocop:disable MethodLength def location_params params.require(:location).permit( diff --git a/app/controllers/admin/organization_contacts_controller.rb b/app/controllers/admin/organization_contacts_controller.rb index 28478fe38..ddf742bd5 100644 --- a/app/controllers/admin/organization_contacts_controller.rb +++ b/app/controllers/admin/organization_contacts_controller.rb @@ -7,13 +7,15 @@ def edit @organization = Organization.find(params[:organization_id]) @contact = Contact.find(params[:id]) - authorize @organization + authorize @contact end def update @contact = Contact.find(params[:id]) @organization = Organization.find(params[:organization_id]) + authorize @contact + if @contact.update(contact_params) flash[:notice] = 'Contact was successfully updated.' redirect_to [:admin, @organization, @contact] @@ -34,6 +36,8 @@ def create @organization = Organization.find(params[:organization_id]) @contact = @organization.contacts.new(contact_params) + authorize @contact + if @contact.save flash[:notice] = "Contact '#{@contact.name}' was successfully created." redirect_to admin_organization_path(@organization) @@ -44,6 +48,8 @@ def create def destroy contact = Contact.find(params[:id]) + authorize contact + contact.destroy redirect_to admin_organization_path(contact.organization), notice: "Contact '#{contact.name}' was successfully deleted." diff --git a/app/controllers/admin/organizations_controller.rb b/app/controllers/admin/organizations_controller.rb index 0c3c62458..d0a36e440 100644 --- a/app/controllers/admin/organizations_controller.rb +++ b/app/controllers/admin/organizations_controller.rb @@ -26,6 +26,7 @@ def edit def update @organization = Organization.find(params[:id]) + authorize @organization preprocess_organization_params if @organization.update(org_params) @@ -43,8 +44,8 @@ def new def create preprocess_organization_params - @organization = Organization.new(org_params) + authorize @organization if @organization.save redirect_to admin_organizations_url, @@ -56,6 +57,7 @@ def create def destroy organization = Organization.find(params[:id]) + authorize organization organization.destroy redirect_to admin_organizations_path end diff --git a/app/controllers/admin/programs_controller.rb b/app/controllers/admin/programs_controller.rb index b217a1bee..89cfc2e26 100644 --- a/app/controllers/admin/programs_controller.rb +++ b/app/controllers/admin/programs_controller.rb @@ -17,6 +17,8 @@ def edit def update @program = Program.find(params[:id]) + authorize @program + if @program.update(program_params) redirect_to [:admin, @program], notice: 'Program was successfully updated.' @@ -32,8 +34,9 @@ def new def create @program = Program.new(program_params) + org = @program.organization - add_org_to_program_if_authorized + authorize @program if org.present? if @program.save redirect_to admin_programs_url, @@ -45,20 +48,13 @@ def create def destroy program = Program.find(params[:id]) + authorize program program.destroy redirect_to admin_programs_path end private - def add_org_to_program_if_authorized - org_id = program_params[:organization_id] - - if policy_scope(Organization).select { |org| org[0] == org_id.to_i }.present? - @program.organization_id = org_id - end - end - def program_params params.require(:program).permit(:alternate_name, :name, :organization_id) end diff --git a/app/controllers/admin/service_contacts_controller.rb b/app/controllers/admin/service_contacts_controller.rb index 2e3a956f4..0ce3e5c8d 100644 --- a/app/controllers/admin/service_contacts_controller.rb +++ b/app/controllers/admin/service_contacts_controller.rb @@ -13,10 +13,13 @@ def edit def update @contact = Contact.find(params[:id]) @service = Service.find(params[:service_id]) + location = @service.location + + authorize location if @contact.update(contact_params) flash[:notice] = 'Contact was successfully updated.' - redirect_to [:admin, @service.location, @service, @contact] + redirect_to [:admin, location, @service, @contact] else render :edit end @@ -33,9 +36,12 @@ def new def create @service = Service.find(params[:service_id]) @contact = @service.contacts.new(contact_params) + location = @service.location + + authorize location if @contact.save - redirect_to admin_location_service_path(@service.location, @service), + redirect_to admin_location_service_path(location, @service), notice: "Contact '#{@contact.name}' was successfully created." else render :new @@ -44,8 +50,13 @@ def create def destroy contact = Contact.find(params[:id]) + service = contact.service + location = service.location + + authorize location + contact.destroy - redirect_to admin_location_service_path(contact.service.location, contact.service), + redirect_to admin_location_service_path(location, service), notice: "Contact '#{contact.name}' was successfully deleted." end diff --git a/app/controllers/admin/services_controller.rb b/app/controllers/admin/services_controller.rb index 988f8418d..3ccf2a1da 100644 --- a/app/controllers/admin/services_controller.rb +++ b/app/controllers/admin/services_controller.rb @@ -18,8 +18,8 @@ def edit def update assign_location_service_and_taxonomy_ids - preprocess_service_params + authorize @location preprocess_service if @service.update(service_params.except(:locations)) @@ -39,15 +39,8 @@ def new @service = Service.new end - # rubocop:disable Metrics/MethodLength def create - preprocess_service_params - - @location = Location.find(params[:location_id]) - @service = @location.services.new(service_params.except(:locations)) - @taxonomy_ids = [] - - preprocess_service + prepare_and_authorize_service_creation if @service.save redirect_to admin_location_path(@location), @@ -56,25 +49,36 @@ def create render :new end end - # rubocop:enable Metrics/MethodLength def destroy service = Service.find(params[:id]) + authorize service.location service.destroy redirect_to admin_locations_path end private - def preprocess_service - add_program_to_service_if_authorized - add_service_to_location_if_authorized + def prepare_and_authorize_service_creation + preprocess_service_params + + @location = Location.find(params[:location_id]) + @service = @location.services.new(service_params.except(:locations)) + @taxonomy_ids = [] + + authorize @location + preprocess_service end def preprocess_service_params shift_and_split_params(params[:service], :keywords) end + def preprocess_service + add_program_to_service_if_authorized + add_service_to_location_if_authorized + end + def add_program_to_service_if_authorized prog_id = service_params[:program_id] @service.program = nil and return if prog_id.blank? @@ -97,10 +101,9 @@ def add_service_to_location_if_authorized end def location_ids - return if service_params[:locations].blank? - service_params[:locations].select do |id| - location_ids_for(@service).include?(id.to_i) - end + locations = service_params[:locations] + return if locations.blank? + locations.select { |id| location_ids_for(@service).include?(id.to_i) } end def location_ids_for(service) diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb index 77725ab8e..da03eace3 100644 --- a/app/policies/application_policy.rb +++ b/app/policies/application_policy.rb @@ -6,7 +6,8 @@ def initialize(user, record) @record = record end - def edit? + def create? + return true if user.super_admin? scope.flatten.include?(record.id) end @@ -14,6 +15,21 @@ def scope Pundit.policy_scope!(user, record.class) end + alias new? create? + alias edit? create? + alias destroy? create? + alias update? create? + + private + + def orgs_user_can_access + @orgs_user_can_access ||= Pundit.policy_scope!(user, Organization) + end + + def can_access_at_least_one_organization? + orgs_user_can_access.present? + end + class Scope attr_reader :user, :scope diff --git a/app/policies/contact_policy.rb b/app/policies/contact_policy.rb new file mode 100644 index 000000000..dbf8bfac5 --- /dev/null +++ b/app/policies/contact_policy.rb @@ -0,0 +1,9 @@ +class ContactPolicy < ApplicationPolicy + delegate :create?, :destroy?, :edit?, :update?, to: :organization_policy + + private + + def organization_policy + @organization_policy ||= Pundit.policy!(user, record.organization) + end +end diff --git a/app/policies/location_policy.rb b/app/policies/location_policy.rb index fb2a3686f..f3606aa68 100644 --- a/app/policies/location_policy.rb +++ b/app/policies/location_policy.rb @@ -1,7 +1,8 @@ class LocationPolicy < ApplicationPolicy def new? return true if user.super_admin? - Pundit.policy_scope!(user, Organization).present? + return super if record.id.present? + can_access_at_least_one_organization? end class Scope < Scope diff --git a/app/policies/organization_policy.rb b/app/policies/organization_policy.rb index 5605a99f6..48e5d4344 100644 --- a/app/policies/organization_policy.rb +++ b/app/policies/organization_policy.rb @@ -1,8 +1,4 @@ class OrganizationPolicy < ApplicationPolicy - def new? - user.super_admin? - end - class Scope < Scope def resolve return scope.pluck(:id, :name, :slug).sort_by(&:second) if user.super_admin? diff --git a/app/policies/program_policy.rb b/app/policies/program_policy.rb index d609f98f3..7faafd86e 100644 --- a/app/policies/program_policy.rb +++ b/app/policies/program_policy.rb @@ -1,6 +1,14 @@ class ProgramPolicy < ApplicationPolicy + delegate :create?, to: :organization_policy + def new? - Pundit.policy_scope!(user, Organization).present? + can_access_at_least_one_organization? + end + + private + + def organization_policy + @organization_policy ||= Pundit.policy!(user, record.organization) end class Scope < Scope diff --git a/config/locales/en.yml b/config/locales/en.yml index 616416577..f09f36131 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -158,13 +158,6 @@ en: delete_symbol: 'x' download_zip_file: 'Download zip file' generate_zip_file: 'Generate zip file' - not_authorized: 'You are not authorized to perform this action.' - notices: - zip_file_generation: > - Your zip file is being generated. Please refresh the page in a few - seconds. Once it's ready, the button at the bottom will change from - 'Generate zip file' to 'Download zip file'. - wait_for_zip_file: 'Please wait while the zip file is being generated.' locations: forms: @@ -206,6 +199,15 @@ en: virtual: description: 'Does this location have a physical address?' + not_authorized: 'You are not authorized to perform this action.' + + notices: + zip_file_generation: > + Your zip file is being generated. Please refresh the page in a few + seconds. Once it's ready, the button at the bottom will change from + 'Generate zip file' to 'Download zip file'. + wait_for_zip_file: 'Please wait while the zip file is being generated.' + organizations: forms: accreditations: diff --git a/spec/controllers/admin/contacts_controller_spec.rb b/spec/controllers/admin/contacts_controller_spec.rb index 067747b26..4b1913c19 100644 --- a/spec/controllers/admin/contacts_controller_spec.rb +++ b/spec/controllers/admin/contacts_controller_spec.rb @@ -3,7 +3,7 @@ describe Admin::ContactsController do describe 'GET edit' do before(:each) do - @loc = create(:nearby_loc) + @loc = create(:location_with_admin) @contact = @loc.contacts.create!(attributes_for(:contact)) end @@ -19,6 +19,7 @@ context 'when admin is regular admin without privileges' do it 'redirects to admin dashboard' do + create(:location_for_org_admin) log_in_as_admin(:admin) get :edit, location_id: @loc.id, id: @contact.id @@ -27,11 +28,21 @@ expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) end end + + context 'when admin is regular admin with privileges' do + it 'allows access' do + log_in_as_admin(:location_admin) + + get :edit, location_id: @loc.id, id: @contact.id + + expect(response).to render_template(:edit) + end + end end describe 'GET new' do before(:each) do - @loc = create(:nearby_loc) + @loc = create(:location_with_admin) end context 'when admin is super admin' do @@ -46,6 +57,7 @@ context 'when admin is regular admin without privileges' do it 'redirects to admin dashboard' do + create(:location_for_org_admin) log_in_as_admin(:admin) get :new, location_id: @loc.id @@ -54,5 +66,136 @@ expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) end end + + context 'when admin is regular admin with privileges' do + it 'allows access' do + log_in_as_admin(:location_admin) + + get :new, location_id: @loc.id + + expect(response).to render_template(:new) + end + end + end + + describe 'create' do + before(:each) do + @loc = create(:location_with_admin) + end + + context 'when admin is super admin' do + it 'allows access to create contact' do + log_in_as_admin(:super_admin) + + post :create, location_id: @loc.id, contact: { name: 'John' } + + expect(response).to redirect_to "/admin/locations/#{@loc.friendly_id}" + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + log_in_as_admin(:admin) + + post :create, location_id: @loc.id, contact: { name: 'John' } + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@loc.contacts).to be_empty + end + end + + context 'when admin is regular admin allowed to create a contact' do + it 'creates the contact' do + log_in_as_admin(:location_admin) + + post :create, location_id: @loc.id, contact: { name: 'John' } + + expect(response).to redirect_to "/admin/locations/#{@loc.friendly_id}" + expect(@loc.contacts.last.name).to eq 'John' + end + end + end + + describe 'update' do + before(:each) do + @loc = create(:location_with_admin) + @contact = @loc.contacts.create!(attributes_for(:contact)) + end + + context 'when admin is super admin' do + it 'allows access to update contact' do + log_in_as_admin(:super_admin) + + post :update, location_id: @loc.id, id: @contact.id, contact: { name: 'John' } + + expect(response). + to redirect_to "/admin/locations/#{@loc.friendly_id}/contacts/#{@contact.id}" + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + log_in_as_admin(:admin) + + post :update, location_id: @loc.id, id: @contact.id, contact: { name: 'John' } + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@contact.reload.name).to_not eq 'John' + end + end + + context 'when admin is regular admin allowed to edit this contact' do + it 'updates the contact' do + log_in_as_admin(:location_admin) + + post :update, location_id: @loc.id, id: @contact.id, contact: { name: 'John' } + + expect(response). + to redirect_to "/admin/locations/#{@loc.friendly_id}/contacts/#{@contact.id}" + expect(@contact.reload.name).to eq 'John' + end + end + end + + describe 'destroy' do + before(:each) do + @loc = create(:location_with_admin) + @contact = @loc.contacts.create!(attributes_for(:contact)) + end + + context 'when admin is super admin' do + it 'allows access to destroy contact' do + log_in_as_admin(:super_admin) + + delete :destroy, location_id: @loc.id, id: @contact.id + + expect(response).to redirect_to "/admin/locations/#{@loc.friendly_id}" + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + log_in_as_admin(:admin) + + delete :destroy, location_id: @loc.id, id: @contact.id + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@contact.reload.name).to eq 'Moncef Belyamani' + end + end + + context 'when admin is regular admin allowed to destroy this contact' do + it 'destroys the contact' do + log_in_as_admin(:location_admin) + + delete :destroy, location_id: @loc.id, id: @contact.id + + expect(response).to redirect_to "/admin/locations/#{@loc.friendly_id}" + expect(Contact.find_by(id: @contact.id)).to be_nil + end + end end end diff --git a/spec/controllers/admin/csv_controller_spec.rb b/spec/controllers/admin/csv_controller_spec.rb index 6829cc914..045cb166c 100644 --- a/spec/controllers/admin/csv_controller_spec.rb +++ b/spec/controllers/admin/csv_controller_spec.rb @@ -14,6 +14,24 @@ get :all end + + it 'denies access if not a super admin' do + log_in_as_admin(:admin) + + actions = %i[ + addresses contacts holiday_schedules locations mail_addresses + organizations phones programs regular_schedules services all download_zip + ] + actions.each do |action| + expect(ZipDownloadJob).to_not receive(:perform_in) + expect(ZipDeleteJob).to_not receive(:perform_in) + + get action + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + end + end end describe 'GET download_zip' do diff --git a/spec/controllers/admin/locations_controller_spec.rb b/spec/controllers/admin/locations_controller_spec.rb new file mode 100644 index 000000000..0a1936ba7 --- /dev/null +++ b/spec/controllers/admin/locations_controller_spec.rb @@ -0,0 +1,210 @@ +require 'rails_helper' + +describe Admin::LocationsController do + describe 'create' do + before(:each) do + location = create(:location_with_admin) + @org = location.organization + end + + context 'when admin is super admin' do + it 'allows access to create location' do + log_in_as_admin(:super_admin) + + post :create, location: { + name: 'New Location', description: 'New description', virtual: true, + organization_id: @org.id + } + + expect(response).to redirect_to '/admin/locations/new-location' + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + location_params = { + name: 'New Location', description: 'New description', virtual: true, + organization_id: @org.id + } + + expect { post :create, location: location_params }.to_not change(Location, :count) + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + end + end + + context 'when admin is regular admin with privileges' do + it 'allows location creation' do + log_in_as_admin(:location_admin) + + post :create, location: { + name: 'New Location', + description: 'New description', + virtual: true, + admin_emails: %w[moncef@smcgov.org], + organization_id: @org.id + } + + expect(response).to redirect_to '/admin/locations/new-location' + end + end + end + + describe 'update' do + before(:each) do + @loc = create(:location_with_admin) + end + + context 'when admin is super admin' do + it 'allows access to update location' do + log_in_as_admin(:super_admin) + + post :update, id: @loc.id, location: { name: 'Updated location' } + + expect(response).to redirect_to "/admin/locations/#{@loc.reload.friendly_id}" + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + post :update, id: @loc.id, location: { name: 'Updated location' } + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@loc.reload.name).to_not eq 'Updated location' + end + end + + context 'when admin is regular admin allowed to edit this location' do + it 'updates the location' do + log_in_as_admin(:location_admin) + + post :update, id: @loc.id, location: { name: 'Updated location' } + + expect(response).to redirect_to "/admin/locations/#{@loc.reload.friendly_id}" + expect(@loc.reload.name).to eq 'Updated location' + end + end + end + + describe 'destroy' do + before(:each) do + @location = create(:location_with_admin) + end + + context 'when admin is super admin' do + it 'allows access to destroy location' do + log_in_as_admin(:super_admin) + + delete :destroy, id: @location.id + + expect(response).to redirect_to '/admin/locations' + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + expect { delete :destroy, id: @location.id }.to_not change(Location, :count) + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + end + end + + context 'when admin is regular admin allowed to destroy this location' do + it 'destroys the location' do + log_in_as_admin(:location_admin) + + delete :destroy, id: @location.id + + expect(response).to redirect_to '/admin/locations' + expect(Location.find_by(id: @location.id)).to be_nil + end + end + end + + describe 'edit' do + before(:each) do + @location = create(:location_with_admin) + end + + context 'when admin is super admin' do + it 'allows access to edit location' do + log_in_as_admin(:super_admin) + + get :edit, id: @location.id + + expect(response).to render_template(:edit) + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + get :edit, id: @location.id + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + end + end + + context 'when admin is regular admin with privileges' do + it 'allows access to edit location' do + log_in_as_admin(:location_admin) + + get :edit, id: @location.id + + expect(response).to render_template(:edit) + end + end + end + + describe 'new' do + before(:each) do + location = create(:location_with_admin) + @org = location.organization + end + + context 'when admin is super admin' do + it 'allows access to add location' do + log_in_as_admin(:super_admin) + + get :new + + expect(response).to render_template(:new) + end + end + + context 'when admin does not have access to any locations' do + it 'redirects to admin dashboard' do + log_in_as_admin(:admin) + + get :new + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + end + end + + context 'when admin is regular admin with privileges' do + it 'allows access to add new location' do + log_in_as_admin(:location_admin) + + get :new + + expect(response).to render_template(:new) + end + end + end +end diff --git a/spec/controllers/admin/organization_contacts_controller_spec.rb b/spec/controllers/admin/organization_contacts_controller_spec.rb index 8718ea43c..20915a701 100644 --- a/spec/controllers/admin/organization_contacts_controller_spec.rb +++ b/spec/controllers/admin/organization_contacts_controller_spec.rb @@ -3,7 +3,8 @@ describe Admin::OrganizationContactsController do describe 'GET edit' do before(:each) do - @org = create(:organization) + location = create(:location_with_admin) + @org = location.organization @contact = @org.contacts.create!(attributes_for(:contact)) end @@ -17,8 +18,9 @@ end end - context 'when admin is regular admin without privileges' do + context 'when admin is regular admin without privileges to the associated organization' do it 'redirects to admin dashboard' do + create(:location_for_org_admin) log_in_as_admin(:admin) get :edit, organization_id: @org.id, id: @contact.id @@ -27,11 +29,22 @@ expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) end end + + context 'when admin is regular admin with privileges' do + it 'allows access to edit contact' do + log_in_as_admin(:location_admin) + + get :edit, organization_id: @org.id, id: @contact.id + + expect(response).to render_template(:edit) + end + end end describe 'GET new' do before(:each) do - @org = create(:organization) + location = create(:location_with_admin) + @org = location.organization end context 'when admin is super admin' do @@ -46,6 +59,7 @@ context 'when admin is regular admin without privileges' do it 'redirects to admin dashboard' do + create(:location_for_org_admin) log_in_as_admin(:admin) get :new, organization_id: @org.id @@ -54,5 +68,144 @@ expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) end end + + context 'when admin is regular admin with privileges' do + it 'allows access to create a new contact' do + log_in_as_admin(:location_admin) + + get :new, organization_id: @org.id + + expect(response).to render_template(:new) + end + end + end + + describe 'create' do + before(:each) do + loc = create(:location) + @org = loc.organization + end + + context 'when admin is super admin' do + it 'allows access to create contact' do + log_in_as_admin(:super_admin) + + post :create, organization_id: @org.id, contact: { name: 'Jane' } + + expect(response).to redirect_to "/admin/organizations/#{@org.friendly_id}" + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + post :create, organization_id: @org.id, contact: { name: 'Jane' } + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@org.contacts).to be_empty + end + end + + context 'when admin is regular admin allowed to create a contact' do + it 'creates the contact' do + location = create(:location_with_admin) + organization = location.organization + log_in_as_admin(:location_admin) + + post :create, organization_id: organization.id, contact: { name: 'Jane' } + + expect(response).to redirect_to "/admin/organizations/#{organization.friendly_id}" + expect(organization.contacts.last.name).to eq 'Jane' + end + end + end + + describe 'update' do + before(:each) do + @loc = create(:location_with_admin) + @org = @loc.organization + @contact = @org.contacts.create!(attributes_for(:contact)) + end + + context 'when admin is super admin' do + it 'allows access to update contact' do + log_in_as_admin(:super_admin) + + post :update, organization_id: @org.id, id: @contact.id, contact: { name: 'Jane' } + + expect(response). + to redirect_to "/admin/organizations/#{@org.friendly_id}/contacts/#{@contact.id}" + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + post :update, organization_id: @org.id, id: @contact.id, contact: { name: 'Jane' } + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@contact.reload.name).to_not eq 'Jane' + end + end + + context 'when admin is regular admin allowed to edit this contact' do + it 'updates the contact' do + log_in_as_admin(:location_admin) + + post :update, organization_id: @org.id, id: @contact.id, contact: { name: 'Jane' } + + expect(response). + to redirect_to "/admin/organizations/#{@org.friendly_id}/contacts/#{@contact.id}" + expect(@contact.reload.name).to eq 'Jane' + end + end + end + + describe 'destroy' do + before(:each) do + @loc = create(:location_with_admin) + @org = @loc.organization + @contact = @org.contacts.create!(attributes_for(:contact)) + end + + context 'when admin is super admin' do + it 'allows access to destroy contact' do + log_in_as_admin(:super_admin) + + delete :destroy, organization_id: @org.id, id: @contact.id + + expect(response).to redirect_to "/admin/organizations/#{@org.friendly_id}" + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + delete :destroy, organization_id: @org.id, id: @contact.id + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@contact.reload.name).to eq 'Moncef Belyamani' + end + end + + context 'when admin is regular admin allowed to destroy this contact' do + it 'destroys the contact' do + log_in_as_admin(:location_admin) + + delete :destroy, organization_id: @org.id, id: @contact.id + + expect(response).to redirect_to "/admin/organizations/#{@org.friendly_id}" + expect(Contact.find_by(id: @contact.id)).to be_nil + end + end end end diff --git a/spec/controllers/admin/organizations_controller_spec.rb b/spec/controllers/admin/organizations_controller_spec.rb new file mode 100644 index 000000000..62261a703 --- /dev/null +++ b/spec/controllers/admin/organizations_controller_spec.rb @@ -0,0 +1,187 @@ +require 'rails_helper' + +describe Admin::OrganizationsController do + describe 'create' do + let(:attrs) do + { + name: 'New org', + description: 'New description', + licenses: [''], + accreditations: [''] + } + end + + context 'when admin is super admin' do + it 'allows access to create organization' do + log_in_as_admin(:super_admin) + + expect { post :create, organization: attrs }.to change(Organization, :count) + + expect(response).to redirect_to '/admin/organizations' + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + log_in_as_admin(:admin) + + expect { post :create, organization: attrs }.to_not change(Organization, :count) + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + end + end + end + + describe 'update' do + let(:attrs) do + { + name: 'Updated org', + description: 'Updated description', + licenses: [''], + accreditations: [''] + } + end + + before(:each) do + loc = create(:location_with_admin) + @org = loc.organization + end + + context 'when admin is super admin' do + it 'allows access to update organization' do + log_in_as_admin(:super_admin) + + post :update, id: @org.id, organization: attrs + + expect(response).to redirect_to "/admin/organizations/#{@org.reload.friendly_id}" + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + post :update, id: @org.id, organization: attrs + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@org.reload.name).to_not eq 'Updated organization' + end + end + + context 'when admin is regular admin allowed to edit this organization' do + it 'updates the organization' do + log_in_as_admin(:location_admin) + + post :update, id: @org.id, organization: attrs + + expect(response).to redirect_to "/admin/organizations/#{@org.reload.friendly_id}" + expect(@org.reload.name).to eq 'Updated org' + end + end + end + + describe 'destroy' do + before(:each) do + location = create(:location_with_admin) + @organization = location.organization + end + + context 'when admin is super admin' do + it 'allows access to destroy organization' do + log_in_as_admin(:super_admin) + + delete :destroy, id: @organization.id + + expect(response).to redirect_to '/admin/organizations' + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + expect { delete :destroy, id: @organization.id }.to_not change(Organization, :count) + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + end + end + + context 'when admin is regular admin allowed to destroy this organization' do + it 'destroys the organization' do + log_in_as_admin(:location_admin) + + delete :destroy, id: @organization.id + + expect(response).to redirect_to '/admin/organizations' + expect(Organization.find_by(id: @organization.id)).to be_nil + end + end + end + + describe 'edit' do + before(:each) do + location = create(:location_with_admin) + @organization = location.organization + end + + context 'when admin is super admin' do + it 'allows access to destroy organization' do + log_in_as_admin(:super_admin) + + get :edit, id: @organization.id + + expect(response).to render_template(:edit) + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + get :edit, id: @organization.id + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + end + end + + context 'when admin is regular admin allowed to destroy this organization' do + it 'destroys the organization' do + log_in_as_admin(:location_admin) + + get :edit, id: @organization.id + + expect(response).to render_template(:edit) + end + end + end + + describe 'new' do + context 'when admin is super admin' do + it 'allows access to create a new organization' do + log_in_as_admin(:super_admin) + + get :new + + expect(response).to render_template(:new) + end + end + + context 'when admin is not a super_admin' do + it 'redirects to admin dashboard' do + log_in_as_admin(:admin) + + get :new + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + end + end + end +end diff --git a/spec/controllers/admin/programs_controller_spec.rb b/spec/controllers/admin/programs_controller_spec.rb index a541b457a..f5f4de069 100644 --- a/spec/controllers/admin/programs_controller_spec.rb +++ b/spec/controllers/admin/programs_controller_spec.rb @@ -3,7 +3,8 @@ describe Admin::ProgramsController do describe 'GET edit' do before(:each) do - org = create(:organization) + location = create(:location_with_admin) + org = location.organization @program = org.programs.create!(attributes_for(:program)) end @@ -17,8 +18,9 @@ end end - context 'when admin does not have access' do + context 'when admin is regular admin without privileges' do it 'redirects to admin dashboard' do + create(:location_for_org_admin) log_in_as_admin(:admin) get :edit, id: @program.id @@ -27,11 +29,21 @@ expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) end end + + context 'when admin is regular admin with privileges' do + it 'allows access to edit program' do + log_in_as_admin(:location_admin) + + get :edit, id: @program.id + + expect(response).to render_template(:edit) + end + end end describe 'GET new' do before(:each) do - create(:location) + create(:location_with_admin) end context 'when admin is super admin' do @@ -44,14 +56,148 @@ end end - context 'when admin does not have access' do - it 'redirects to admin dashboard' do + context 'when admin is regular admin without privileges' do + it 'allows access to create a program' do + create(:location_for_org_admin) log_in_as_admin(:admin) get :new + expect(response).to render_template(:new) + end + end + + context 'when admin is regular admin with privileges' do + it 'allows access to create a program' do + log_in_as_admin(:location_admin) + + get :new + + expect(response).to render_template(:new) + end + end + end + + describe 'create' do + before(:each) do + loc = create(:location_with_admin) + @org = loc.organization + end + + context 'when admin is super admin' do + it 'allows access to create program' do + log_in_as_admin(:super_admin) + + post :create, program: { name: 'New program', organization_id: @org.id } + + expect(response).to redirect_to '/admin/programs' + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + expect { post :create, program: { name: 'New program', organization_id: @org.id } }. + to_not change(Program, :count) + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@org.programs).to be_empty + end + end + + context 'when admin is regular admin included in location admin_emails' do + it 'allows program creation' do + log_in_as_admin(:location_admin) + + post :create, program: { name: 'New program', organization_id: @org.id } + + expect(response).to redirect_to '/admin/programs' + end + end + end + + describe 'update' do + before(:each) do + loc = create(:location_with_admin) + org = loc.organization + @program = org.programs.create!(name: 'New Program') + end + + context 'when admin is super admin' do + it 'allows access to update program' do + log_in_as_admin(:super_admin) + + post :update, id: @program.id, program: { name: 'Updated program' } + + expect(response).to redirect_to "/admin/programs/#{@program.id}" + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + post :update, id: @program.id, program: { name: 'Updated program' } + expect(response).to redirect_to admin_dashboard_path expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@program.reload.name).to_not eq 'Updated program' + end + end + + context 'when admin is regular admin allowed to edit this program' do + it 'updates the program' do + log_in_as_admin(:location_admin) + + post :update, id: @program.id, program: { name: 'Updated program' } + + expect(response).to redirect_to "/admin/programs/#{@program.id}" + expect(@program.reload.name).to eq 'Updated program' + end + end + end + + describe 'destroy' do + before(:each) do + loc = create(:location_with_admin) + org = loc.organization + @program = org.programs.create!(name: 'New Program') + end + + context 'when admin is super admin' do + it 'allows access to destroy program' do + log_in_as_admin(:super_admin) + + delete :destroy, id: @program.id + + expect(response).to redirect_to '/admin/programs' + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + expect { delete :destroy, id: @program.id }.to_not change(Program, :count) + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + end + end + + context 'when admin is a regular admin who is allowed to destroy this program' do + it 'destroys the program' do + log_in_as_admin(:location_admin) + + delete :destroy, id: @program.id + + expect(response).to redirect_to '/admin/programs' + expect(Program.find_by(id: @program.id)).to be_nil end end end diff --git a/spec/controllers/admin/service_contacts_controller_spec.rb b/spec/controllers/admin/service_contacts_controller_spec.rb index 57b495eeb..4289768c7 100644 --- a/spec/controllers/admin/service_contacts_controller_spec.rb +++ b/spec/controllers/admin/service_contacts_controller_spec.rb @@ -3,7 +3,8 @@ describe Admin::ServiceContactsController do describe 'GET edit' do before(:each) do - create_service + @location = create(:location_with_admin) + @service = @location.services.create!(attributes_for(:service)) @contact = @service.contacts.create!(attributes_for(:contact)) end @@ -19,6 +20,7 @@ context 'when admin is regular admin without privileges' do it 'redirects to admin dashboard' do + create(:location_for_org_admin) log_in_as_admin(:admin) get :edit, location_id: @location.id, service_id: @service.id, id: @contact.id @@ -27,15 +29,26 @@ expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) end end + + context 'when admin is regular admin with privileges' do + it 'redirects to admin dashboard' do + log_in_as_admin(:location_admin) + + get :edit, location_id: @location.id, service_id: @service.id, id: @contact.id + + expect(response).to render_template(:edit) + end + end end describe 'GET new' do before(:each) do - create_service + @location = create(:location_with_admin) + @service = @location.services.create!(attributes_for(:service)) end context 'when admin is super admin' do - it 'allows access to edit contact' do + it 'allows access to create contact' do log_in_as_admin(:super_admin) get :new, location_id: @location.id, service_id: @service.id @@ -46,6 +59,7 @@ context 'when admin is regular admin without privileges' do it 'redirects to admin dashboard' do + create(:location_for_org_admin) log_in_as_admin(:admin) get :new, location_id: @location.id, service_id: @service.id @@ -54,5 +68,160 @@ expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) end end + + context 'when admin is regular admin with privileges' do + it 'allows access to create contact' do + log_in_as_admin(:location_admin) + + get :new, location_id: @location.id, service_id: @service.id + + expect(response).to render_template(:new) + end + end + end + + describe 'create' do + before(:each) do + @location = create(:location_with_admin) + @service = @location.services.create!(attributes_for(:service)) + end + + context 'when admin is super admin' do + it 'allows access to create contact' do + log_in_as_admin(:super_admin) + + post :create, location_id: @location.id, service_id: @service.id, contact: { name: 'Jane' } + + expect(response). + to redirect_to "/admin/locations/#{@location.friendly_id}/services/#{@service.id}" + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + post :create, location_id: @location.id, service_id: @service.id, contact: { name: 'Jane' } + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@service.contacts).to be_empty + end + end + + context 'when admin is regular admin allowed to create a contact' do + it 'creates the contact' do + log_in_as_admin(:location_admin) + + post :create, location_id: @location.id, service_id: @service.id, contact: { name: 'Jane' } + + expect(response). + to redirect_to "/admin/locations/#{@location.friendly_id}/services/#{@service.id}" + expect(@service.contacts.last.name).to eq 'Jane' + end + end + end + + describe 'update' do + before(:each) do + @location = create(:location_with_admin) + @service = @location.services.create!(attributes_for(:service)) + @contact = @service.contacts.create!(attributes_for(:contact)) + end + + context 'when admin is super admin' do + it 'allows access to update contact' do + log_in_as_admin(:super_admin) + + post( + :update, + location_id: @location.id, service_id: @service.id, + id: @contact.id, contact: { name: 'Jane' } + ) + + path_prefix = "/admin/locations/#{@location.friendly_id}/services/#{@service.id}/contacts" + + expect(response).to redirect_to "#{path_prefix}/#{@contact.id}" + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + post( + :update, + location_id: @location.id, service_id: @service.id, + id: @contact.id, contact: { name: 'Jane' } + ) + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@contact.reload.name).to_not eq 'Jane' + end + end + + context 'when admin is regular admin allowed to edit this contact' do + it 'updates the contact' do + log_in_as_admin(:location_admin) + + post( + :update, + location_id: @location.id, service_id: @service.id, + id: @contact.id, contact: { name: 'Jane' } + ) + + path_prefix = "/admin/locations/#{@location.friendly_id}/services/#{@service.id}/contacts" + + expect(response).to redirect_to "#{path_prefix}/#{@contact.id}" + expect(@contact.reload.name).to eq 'Jane' + end + end + end + + describe 'destroy' do + before(:each) do + @location = create(:location_with_admin) + @service = @location.services.create!(attributes_for(:service)) + @contact = @service.contacts.create!(attributes_for(:contact)) + end + + context 'when admin is super admin' do + it 'allows access to destroy contact' do + log_in_as_admin(:super_admin) + + delete :destroy, location_id: @location.id, service_id: @service.id, id: @contact.id + + expect(response). + to redirect_to "/admin/locations/#{@location.friendly_id}/services/#{@service.id}" + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + delete :destroy, location_id: @location.id, service_id: @service.id, id: @contact.id + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@contact.reload.name).to eq 'Moncef Belyamani' + end + end + + context 'when admin is regular admin allowed to destroy this contact' do + it 'destroys the contact' do + log_in_as_admin(:location_admin) + + delete :destroy, location_id: @location.id, service_id: @service.id, id: @contact.id + + expect(response). + to redirect_to "/admin/locations/#{@location.friendly_id}/services/#{@service.id}" + expect(Contact.find_by(id: @contact.id)).to be_nil + end + end end end diff --git a/spec/controllers/admin/services_controller_spec.rb b/spec/controllers/admin/services_controller_spec.rb index 5ff1a3a1c..288b64e04 100644 --- a/spec/controllers/admin/services_controller_spec.rb +++ b/spec/controllers/admin/services_controller_spec.rb @@ -3,7 +3,7 @@ describe Admin::ServicesController do describe 'GET edit' do before(:each) do - @loc = create(:nearby_loc) + @loc = create(:location_with_admin) @service = @loc.services.create!(attributes_for(:service)) end @@ -17,8 +17,9 @@ end end - context 'when admin is regular admin' do + context 'when admin is regular admin without privileges' do it 'redirects to admin dashboard' do + create(:location_for_org_admin) log_in_as_admin(:admin) get :edit, location_id: @loc.id, id: @service.id @@ -27,15 +28,25 @@ expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) end end + + context 'when admin is regular admin with privileges' do + it 'allows access to edit service' do + log_in_as_admin(:location_admin) + + get :edit, location_id: @loc.id, id: @service.id + + expect(response).to render_template(:edit) + end + end end describe 'GET new' do before(:each) do - @loc = create(:nearby_loc) + @loc = create(:location_with_admin) end context 'when admin is super admin' do - it 'allows access to edit service' do + it 'allows access to create service' do log_in_as_admin(:super_admin) get :new, location_id: @loc.id @@ -44,8 +55,9 @@ end end - context 'when admin is regular admin' do + context 'when admin is regular admin without privileges' do it 'redirects to admin dashboard' do + create(:location_for_org_admin) log_in_as_admin(:admin) get :new, location_id: @loc.id @@ -54,6 +66,16 @@ expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) end end + + context 'when admin is regular admin with privileges' do + it 'allows access to create service' do + log_in_as_admin(:location_admin) + + get :new, location_id: @loc.id + + expect(response).to render_template(:new) + end + end end describe 'PATCH update' do @@ -95,4 +117,146 @@ end end end + + describe 'create' do + before(:each) do + @location = create(:location_with_admin) + end + + context 'when admin is super admin' do + it 'allows access to create service' do + log_in_as_admin(:super_admin) + + post :create, location_id: @location.id, service: { + name: 'New Service', description: 'new service', status: 'active', keywords: [''] + } + + expect(response). + to redirect_to "/admin/locations/#{@location.friendly_id}" + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + expect do + post :create, location_id: @location.id, service: { + name: 'New Service', description: 'new service', status: 'active', keywords: [''] + } + end.to_not change(Service, :count) + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + end + end + + context 'when admin is regular admin allowed to create a service' do + it 'creates the service' do + log_in_as_admin(:location_admin) + + expect do + post :create, location_id: @location.id, service: { + name: 'New Service', description: 'new service', status: 'active', keywords: [''] + } + end.to change(Service, :count).by(1) + + expect(response). + to redirect_to "/admin/locations/#{@location.friendly_id}" + end + end + end + + describe 'update' do + before(:each) do + @location = create(:location_with_admin) + @service = @location.services.create!(attributes_for(:service)) + @attrs = { + name: 'Updated Service', + description: 'Updated Description', + keywords: [''] + } + end + + context 'when admin is super admin' do + it 'allows access to update service' do + log_in_as_admin(:super_admin) + + post(:update, location_id: @location.id, id: @service.id, service: @attrs) + + path = "/admin/locations/#{@location.friendly_id}/services/#{@service.id}" + + expect(response).to redirect_to path + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + post(:update, location_id: @location.id, id: @service.id, service: @attrs) + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + expect(@service.reload.name).to_not eq 'Updated Service' + end + end + + context 'when admin is regular admin allowed to edit this service' do + it 'updates the service' do + log_in_as_admin(:location_admin) + + post(:update, location_id: @location.id, id: @service.id, service: @attrs) + + path = "/admin/locations/#{@location.friendly_id}/services/#{@service.id}" + + expect(response).to redirect_to path + end + end + end + + describe 'destroy' do + before(:each) do + @location = create(:location_with_admin) + @service = @location.services.create!(attributes_for(:service)) + end + + context 'when admin is super admin' do + it 'allows access to destroy service' do + log_in_as_admin(:super_admin) + + delete :destroy, location_id: @location.id, id: @service.id + + expect(response). + to redirect_to '/admin/locations' + end + end + + context 'when admin is regular admin without privileges' do + it 'redirects to admin dashboard' do + create(:location_for_org_admin) + log_in_as_admin(:admin) + + expect { delete :destroy, location_id: @location.id, id: @service.id }. + to_not change(Service, :count) + + expect(response).to redirect_to admin_dashboard_path + expect(flash[:error]).to eq(I18n.t('admin.not_authorized')) + end + end + + context 'when admin is regular admin allowed to destroy this service' do + it 'destroys the service' do + log_in_as_admin(:location_admin) + + delete :destroy, location_id: @location.id, id: @service.id + + expect(response). + to redirect_to '/admin/locations' + expect(Service.find_by(id: @service.id)).to be_nil + end + end + end end diff --git a/spec/factories/admins.rb b/spec/factories/admins.rb index 6895c2bf3..8f9dad7f9 100644 --- a/spec/factories/admins.rb +++ b/spec/factories/admins.rb @@ -27,4 +27,12 @@ password_confirmation 'ohanatest' confirmed_at Time.zone.now end + + factory :location_admin, class: :admin do + name 'Moncef Belyamani' + email 'moncef@smcgov.org' + password 'ohanatest' + password_confirmation 'ohanatest' + confirmed_at Time.zone.now + end end diff --git a/spec/features/admin/csv/download_addresses_csv_spec.rb b/spec/features/admin/csv/download_addresses_csv_spec.rb index 1f329223a..d1fd929ef 100644 --- a/spec/features/admin/csv/download_addresses_csv_spec.rb +++ b/spec/features/admin/csv/download_addresses_csv_spec.rb @@ -2,6 +2,7 @@ feature 'Downloading Addresses CSV' do before do + login_super_admin @address = create(:address, location_id: 1) visit admin_csv_addresses_path(format: 'csv') end diff --git a/spec/features/admin/csv/download_contacts_csv_spec.rb b/spec/features/admin/csv/download_contacts_csv_spec.rb index 7b5eb9e43..9a56d836d 100644 --- a/spec/features/admin/csv/download_contacts_csv_spec.rb +++ b/spec/features/admin/csv/download_contacts_csv_spec.rb @@ -2,6 +2,7 @@ feature 'Downloading Contacts CSV' do before do + login_super_admin @service = create(:service) @location = @service.location @org_id = @location.organization_id diff --git a/spec/features/admin/csv/download_holiday_schedules_csv_spec.rb b/spec/features/admin/csv/download_holiday_schedules_csv_spec.rb index d8a43e677..e3ab6cfca 100644 --- a/spec/features/admin/csv/download_holiday_schedules_csv_spec.rb +++ b/spec/features/admin/csv/download_holiday_schedules_csv_spec.rb @@ -1,6 +1,8 @@ require 'rails_helper' feature 'Downloading Holiday Schedules CSV' do + before { login_super_admin } + context 'when holiday_schedule contains nil date attributes' do before do create_service diff --git a/spec/features/admin/csv/download_locations_csv_spec.rb b/spec/features/admin/csv/download_locations_csv_spec.rb index 75ee221c8..0eda3de3d 100644 --- a/spec/features/admin/csv/download_locations_csv_spec.rb +++ b/spec/features/admin/csv/download_locations_csv_spec.rb @@ -1,6 +1,8 @@ require 'rails_helper' feature 'Downloading Locations CSV' do + before { login_super_admin } + context 'location has non-empty array attributes' do before do @loc = create( diff --git a/spec/features/admin/csv/download_mail_addresses_csv_spec.rb b/spec/features/admin/csv/download_mail_addresses_csv_spec.rb index 38ae24105..374250ac0 100644 --- a/spec/features/admin/csv/download_mail_addresses_csv_spec.rb +++ b/spec/features/admin/csv/download_mail_addresses_csv_spec.rb @@ -2,6 +2,7 @@ feature 'Downloading Mail Addresses CSV' do before do + login_super_admin @mail_address = create(:mail_address) visit admin_csv_mail_addresses_path(format: 'csv') end diff --git a/spec/features/admin/csv/download_organizations_csv_spec.rb b/spec/features/admin/csv/download_organizations_csv_spec.rb index 62a5ac010..05e546e4b 100644 --- a/spec/features/admin/csv/download_organizations_csv_spec.rb +++ b/spec/features/admin/csv/download_organizations_csv_spec.rb @@ -1,6 +1,8 @@ require 'rails_helper' feature 'Downloading Organizations CSV' do + before { login_super_admin } + context 'organization has non-empty array attributes' do before do @org = create(:org_with_extra_whitespace) diff --git a/spec/features/admin/csv/download_phones_csv_spec.rb b/spec/features/admin/csv/download_phones_csv_spec.rb index 38a6ab45e..dd71a0f7e 100644 --- a/spec/features/admin/csv/download_phones_csv_spec.rb +++ b/spec/features/admin/csv/download_phones_csv_spec.rb @@ -2,6 +2,7 @@ feature 'Downloading Phones CSV' do before do + login_super_admin @service = create(:service) @location = @service.location @org_id = @location.organization_id diff --git a/spec/features/admin/csv/download_programs_csv_spec.rb b/spec/features/admin/csv/download_programs_csv_spec.rb index 1f8c0074c..6696988ec 100644 --- a/spec/features/admin/csv/download_programs_csv_spec.rb +++ b/spec/features/admin/csv/download_programs_csv_spec.rb @@ -2,6 +2,7 @@ feature 'Downloading Programs CSV' do before do + login_super_admin @program = create(:program) visit admin_csv_programs_path(format: 'csv') end diff --git a/spec/features/admin/csv/download_regular_schedules_csv_spec.rb b/spec/features/admin/csv/download_regular_schedules_csv_spec.rb index ed1ee968d..0dd33153e 100644 --- a/spec/features/admin/csv/download_regular_schedules_csv_spec.rb +++ b/spec/features/admin/csv/download_regular_schedules_csv_spec.rb @@ -2,6 +2,7 @@ feature 'Downloading Regular Schedules CSV' do before do + login_super_admin create_service @regular_schedule = @location.regular_schedules. create!(attributes_for(:regular_schedule)) diff --git a/spec/features/admin/csv/download_services_csv_spec.rb b/spec/features/admin/csv/download_services_csv_spec.rb index 06e3bbefd..114df0596 100644 --- a/spec/features/admin/csv/download_services_csv_spec.rb +++ b/spec/features/admin/csv/download_services_csv_spec.rb @@ -1,6 +1,8 @@ require 'rails_helper' feature 'Downloading Services CSV' do + before { login_super_admin } + context 'services has non-empty array attributes' do before do @food = create(:category)