From e2fb434dc70a988c6cbc618ae7d9e505a2fad612 Mon Sep 17 00:00:00 2001 From: Stella Rouzi Date: Tue, 12 Aug 2014 11:51:59 +0300 Subject: [PATCH] Implement role authorization --- Gemfile | 2 + Gemfile.lock | 2 + .../admin/callforpapers_controller.rb | 6 +- app/controllers/admin/campaigns_controller.rb | 18 +- .../admin/commercials_controller.rb | 12 +- .../admin/conference_controller.rb | 6 +- app/controllers/admin/contacts_controller.rb | 45 ++- .../admin/dietchoices_controller.rb | 7 +- .../admin/difficulty_levels_controller.rb | 13 +- app/controllers/admin/emails_controller.rb | 4 +- .../admin/event_types_controller.rb | 25 ++ app/controllers/admin/events_controller.rb | 5 +- app/controllers/admin/lodgings_controller.rb | 7 +- app/controllers/admin/questions_controller.rb | 42 ++- .../admin/registrations_controller.rb | 10 +- app/controllers/admin/rooms_controller.rb | 7 +- app/controllers/admin/schedules_controller.rb | 7 +- .../admin/social_events_controller.rb | 7 +- app/controllers/admin/speakers_controller.rb | 8 +- app/controllers/admin/sponsors_controller.rb | 7 +- .../admin/sponsorship_levels_controller.rb | 7 +- app/controllers/admin/stats_controller.rb | 3 +- .../admin/supporter_levels_controller.rb | 7 +- .../admin/supporters_controller.rb | 3 +- app/controllers/admin/targets_controller.rb | 6 +- app/controllers/admin/tracks_controller.rb | 7 +- app/controllers/admin/users_controller.rb | 32 ++- app/controllers/admin/venue_controller.rb | 3 +- .../admin/volunteers_controller.rb | 35 ++- app/controllers/application_controller.rb | 38 ++- app/controllers/commercials_controller.rb | 14 +- app/controllers/conference_controller.rb | 6 +- .../conference_registration_controller.rb | 28 +- .../event_attachments_controller.rb | 36 ++- app/controllers/home_controller.rb | 1 + app/controllers/proposal_controller.rb | 24 +- app/controllers/schedule_controller.rb | 6 +- .../users/omniauth_callbacks_controller.rb | 1 + app/helpers/application_helper.rb | 8 - app/models/ability.rb | 144 +++++++++- app/models/call_for_papers.rb | 2 +- app/models/campaign.rb | 4 +- app/models/conference.rb | 1 + app/models/difficulty_level.rb | 4 +- app/models/event_attachment.rb | 1 + app/models/event_type.rb | 5 +- app/models/lodging.rb | 2 +- app/models/question.rb | 10 +- app/models/role.rb | 8 +- app/models/room.rb | 2 +- app/models/sponsor.rb | 3 +- app/models/sponsorship_level.rb | 2 +- app/models/supporter_level.rb | 2 +- app/models/target.rb | 2 +- app/models/track.rb | 2 +- app/models/user.rb | 35 ++- app/views/admin/commercials/index.html.haml | 11 +- app/views/admin/conference/_roles.html.haml | 29 ++ .../admin/conference/_todo_list.html.haml | 40 ++- app/views/admin/conference/roles.html.haml | 22 ++ app/views/admin/conference/roles.js.erb | 1 + .../_event_type_fields.html.erb | 0 .../index.html.haml | 2 +- .../admin/questions/_questions.html.haml | 14 +- app/views/admin/registrations/index.html.haml | 16 +- app/views/admin/users/_form.html.haml | 16 +- app/views/admin/users/index.html.haml | 53 ++-- app/views/admin/users/show.html.haml | 8 +- app/views/conference/_registration.html.haml | 2 +- .../register.html.haml | 4 +- app/views/home/_conference_details.html.haml | 4 +- app/views/home/index.html.haml | 2 +- app/views/layouts/_admin_sidebar.html.haml | 206 ++++++++------ .../layouts/_admin_sidebar_index.html.haml | 29 +- app/views/layouts/_user_menu.html.haml | 4 +- app/views/proposal/_form.html.haml | 13 +- app/views/proposal/_proposal_form.html.haml | 12 +- app/views/proposal/index.html.haml | 4 +- app/views/proposal/new.html.haml | 2 +- app/views/proposal/show.html.haml | 4 +- config/initializers/rolify.rb | 8 + config/routes.rb | 17 +- ...1_add_description_and_resource_to_roles.rb | 10 + .../20140718103856_add_is_admin_to_users.rb | 5 + db/schema.rb | 9 + db/seeds.rb | 18 +- .../admin/conferences_controller_spec.rb | 73 ++--- .../admin/users_controller_spec.rb | 6 +- .../controllers/conference_controller_spec.rb | 5 +- spec/factories/commercials.rb | 8 + spec/factories/roles.rb | 12 +- spec/factories/users.rb | 8 +- spec/features/ability_spec.rb | 266 ++++++++++++++++++ spec/features/campaign_spec.rb | 10 +- spec/features/cfp_spec.rb | 8 +- spec/features/commercials_spec.rb | 17 +- spec/features/conference_spec.rb | 10 +- spec/features/difficulty_levels_spec.rb | 9 +- spec/features/email_spec.rb | 9 +- spec/features/event_types_spec.rb | 13 +- spec/features/lodgings_spec.rb | 9 +- spec/features/omniauth_spec.rb | 1 - spec/features/proposal_spec.rb | 11 +- spec/features/rooms_spec.rb | 9 +- spec/features/sponsor_spec.rb | 9 +- spec/features/sponsorship_level_spec.rb | 11 +- spec/features/supporter_levels_spec.rb | 21 +- spec/features/tracks_spec.rb | 9 +- spec/features/user_spec.rb | 22 +- spec/features/venue_spec.rb | 9 +- spec/features/volunteers_spec.rb | 13 +- spec/models/ability_spec.rb | 146 +++++++++- spec/models/conference_spec.rb | 21 +- spec/models/user_spec.rb | 71 ++--- spec/support/sidebar.rb | 2 +- .../admin/conference/edit.html.haml_spec.rb | 2 +- .../admin/conference/index.html.haml_spec.rb | 6 +- .../admin/conference/show.html.haml_spec.rb | 2 +- .../index.html.haml_spec.rb | 2 +- .../social_events/index.html.haml_spec.rb | 2 +- .../admin/volunteers/show.html.haml_spec.rb | 2 +- spec/views/conference/show.html.haml_spec.rb | 4 +- 122 files changed, 1386 insertions(+), 751 deletions(-) create mode 100644 app/controllers/admin/event_types_controller.rb create mode 100644 app/views/admin/conference/_roles.html.haml create mode 100644 app/views/admin/conference/roles.html.haml create mode 100644 app/views/admin/conference/roles.js.erb rename app/views/admin/{eventtypes => event_types}/_event_type_fields.html.erb (100%) rename app/views/admin/{eventtypes => event_types}/index.html.haml (76%) create mode 100644 config/initializers/rolify.rb create mode 100644 db/migrate/20140711072651_add_description_and_resource_to_roles.rb create mode 100644 db/migrate/20140718103856_add_is_admin_to_users.rb create mode 100644 spec/factories/commercials.rb create mode 100644 spec/features/ability_spec.rb rename spec/views/admin/{eventtypes => event_types}/index.html.haml_spec.rb (89%) diff --git a/Gemfile b/Gemfile index 01c8a4f0..98896e29 100644 --- a/Gemfile +++ b/Gemfile @@ -22,6 +22,8 @@ gem 'omniauth-google-oauth2' # Use cancancan as authorization framework gem 'cancancan' +# Use rolify to set roles +gem 'rolify' # Use transitions as state machine gem 'transitions', :require => %w( transitions active_record/transitions ) diff --git a/Gemfile.lock b/Gemfile.lock index 5c4b58ac..7152bfcb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -296,6 +296,7 @@ GEM request_store (1.0.6) rest-client (1.6.7) mime-types (>= 1.16) + rolify (3.4.0) rspec (3.0.0) rspec-core (~> 3.0.0) rspec-expectations (~> 3.0.0) @@ -441,6 +442,7 @@ DEPENDENCIES rails-observers rdoc-generator-fivefish redcarpet + rolify rspec-activemodel-mocks rspec-rails rubocop diff --git a/app/controllers/admin/callforpapers_controller.rb b/app/controllers/admin/callforpapers_controller.rb index 7d4ac3d2..4e238027 100644 --- a/app/controllers/admin/callforpapers_controller.rb +++ b/app/controllers/admin/callforpapers_controller.rb @@ -1,8 +1,10 @@ module Admin class CallforpapersController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title +# load_and_authorize_resource :cfp, class: 'CallForPapers', through: :conference def show + authorize! :show, CallForPapers.new(conference_id: @conference.id) @cfp = @conference.call_for_papers if @cfp.nil? @cfp = CallForPapers.new @@ -10,6 +12,7 @@ module Admin end def update + authorize! :update, @conference.call_for_papers @cfp = @conference.call_for_papers @cfp.assign_attributes(params[:call_for_papers]) send_mail_on_schedule_public = @cfp.notify_on_schedule_public? @@ -30,6 +33,7 @@ module Admin end def create + authorize! :update, CallForPapers.new(conference_id: @conference.id) @cfp = CallForPapers.new(params[:call_for_papers]) if @cfp.valid? @cfp.save diff --git a/app/controllers/admin/campaigns_controller.rb b/app/controllers/admin/campaigns_controller.rb index 68c4521d..b3add716 100644 --- a/app/controllers/admin/campaigns_controller.rb +++ b/app/controllers/admin/campaigns_controller.rb @@ -1,16 +1,15 @@ module Admin class CampaignsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource :campaign, through: :conference def index - @conference = Conference.find_by(short_title: params[:conference_id]) + authorize! :show, Campaign.new(conference_id: @conference.id) @campaigns = @conference.campaigns end def create - @conference = Conference.find_by(short_title: params[:conference_id]) - @campaign = @conference.campaigns.new(params[:campaign]) - @campaign.conference_id = @conference.id + @campaign.attributes = params[:campaign] if @conference.save redirect_to(admin_conference_campaigns_path(conference_id: @conference.short_title), @@ -23,19 +22,12 @@ module Admin end def new - @conference = Conference.find_by(short_title: params[:conference_id]) - @campaign = @conference.campaigns.new end def edit - @conference = Conference.find_by(short_title: params[:conference_id]) - @campaign = Campaign.find(params[:id]) end def update - @conference = Conference.find_by(short_title: params[:conference_id]) - @campaign = Campaign.find(params[:id]) - if @campaign.update_attributes(params[:campaign]) redirect_to(admin_conference_campaigns_path( conference_id: @conference.short_title), @@ -50,8 +42,6 @@ module Admin end def destroy - @conference = Conference.find_by(short_title: params[:conference_id]) - @campaign = Campaign.find(params[:id]) if @campaign.destroy redirect_to(admin_conference_campaigns_path(conference_id: @conference.short_title), notice: "Campaign '#{@campaign.name}' successfully deleted.") diff --git a/app/controllers/admin/commercials_controller.rb b/app/controllers/admin/commercials_controller.rb index a624a191..9e4e29a5 100644 --- a/app/controllers/admin/commercials_controller.rb +++ b/app/controllers/admin/commercials_controller.rb @@ -1,7 +1,7 @@ module Admin class CommercialsController < ApplicationController - before_action :set_conference - before_action :set_commercial, only: [:edit, :update, :destroy] + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource through: :conference def index @commercials = @conference.commercials @@ -43,14 +43,6 @@ module Admin private - def set_commercial - @commercial = @conference.commercials.find(params[:id]) - end - - def set_conference - @conference = Conference.find_by(short_title: params[:conference_id]) - end - def commercial_params #params.require(:commercial).permit(:commercial_id, :commercial_type) params[:commercial] diff --git a/app/controllers/admin/conference_controller.rb b/app/controllers/admin/conference_controller.rb index d463076f..0f2ed4c6 100644 --- a/app/controllers/admin/conference_controller.rb +++ b/app/controllers/admin/conference_controller.rb @@ -1,6 +1,6 @@ module Admin class ConferenceController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title def index # Redirect to new form if there is no conference @@ -63,8 +63,11 @@ module Admin def create @conference = Conference.new(params[:conference]) + if @conference.valid? @conference.save + # user that creates the conference becomes organizer of that conference + current_user.add_role :organizer, @conference redirect_to(admin_conference_path(id: @conference.short_title), notice: 'Conference was successfully created.') else @@ -108,6 +111,7 @@ module Admin if @conference.update_attributes(params[:conference]) Mailbot.delay.conference_date_update_mail(@conference) if notify_on_conf_dates_updates Mailbot.delay.conference_registration_date_update_mail(@conference) if notify_on_conf_reg_dates_updates + redirect_to(edit_admin_conference_path(id: @conference.short_title), notice: 'Conference was successfully updated.') else diff --git a/app/controllers/admin/contacts_controller.rb b/app/controllers/admin/contacts_controller.rb index 6d97db98..30de5967 100644 --- a/app/controllers/admin/contacts_controller.rb +++ b/app/controllers/admin/contacts_controller.rb @@ -1,33 +1,30 @@ module Admin class ContactsController < ApplicationController - before_action :set_conference - before_action :set_conference - before_action :set_contact, only: [:edit, :update] + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource through: :conference, singleton: true - # GET /:conference/contact/edit - def edit + # GET /:conference/contact + def show; end + + # GET /:conference/contact/edit + def edit; end + + # PATCH/PUT /:conference/contact + def update + if @contact.update(contact_params) + redirect_to admin_conference_contact_path, notice: 'Contact details were successfully updated.' + else + render :edit end + end - # PATCH/PUT /:conference/contact - def update - if @contact.update(contact_params) - redirect_to edit_admin_conference_contact_path, notice: 'Contact details were successfully updated.' - else - render :edit - end - end - - private - - # Use callbacks to share common setup or constraints between actions. - def set_contact - @contact = @conference.contact - end - - def set_conference - @conference = Conference.find_by(short_title: params[:conference_id]) - end + # DELETE /:conference/contact + def destroy + @contact.destroy + redirect_to admin_conference_contacts_url, notice: 'Contact details were successfully destroyed.' + end + private # Only allow a trusted parameter "white list" through. def contact_params # params.require(:contact).permit(:social_tag, :email, :facebook, :googleplus, :twitter, :instagram, :public) diff --git a/app/controllers/admin/dietchoices_controller.rb b/app/controllers/admin/dietchoices_controller.rb index 043a6577..9ec934f0 100644 --- a/app/controllers/admin/dietchoices_controller.rb +++ b/app/controllers/admin/dietchoices_controller.rb @@ -1,6 +1,7 @@ module Admin class DietchoicesController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource :dietary_choice, through: :conference def show render :diets_list @@ -9,9 +10,9 @@ module Admin def update begin @conference.update_attributes!(params[:conference]) - redirect_to(admin_conference_dietary_list_path(conference_id: @conference.short_title), notice: 'Dietary choices were successfully updated.') + redirect_to(admin_conference_dietary_list_path(:conference_id => @conference.short_title), :notice => 'Dietary choices were successfully updated.') rescue => e - redirect_to(admin_conference_dietary_list_path(conference_id: @conference.short_title), alert: "Dietary choices update failed: #{e.message}") + redirect_to(admin_conference_dietary_list_path(:conference_id => @conference.short_title), :alert => "Dietary choices update failed: #{e.message}") end end end diff --git a/app/controllers/admin/difficulty_levels_controller.rb b/app/controllers/admin/difficulty_levels_controller.rb index f32dc8d9..53280434 100644 --- a/app/controllers/admin/difficulty_levels_controller.rb +++ b/app/controllers/admin/difficulty_levels_controller.rb @@ -1,9 +1,10 @@ module Admin class DifficultyLevelsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + authorize_resource through: :conference def index - @conference = Conference.find_by(short_title: params[:conference_id]) + authorize! :index, DifficultyLevel.new(conference_id: @conference.id) end def update @@ -13,18 +14,18 @@ module Admin @conference.use_difficulty_levels = false @conference.save! flash[:error] = "You cannot enable the usage of difficulty levels without having set any levels." - redirect_to(admin_conference_difficulty_levels_path(conference_id: @conference.short_title)) + redirect_to(admin_conference_difficulty_levels_path(:conference_id => @conference.short_title)) rescue ActiveRecord::RecordInvalid flash[:error] = "Something went wrong. Difficulty Levels update failed." - redirect_to(admin_conference_difficulty_levels_path(conference_id: @conference.short_title)) + redirect_to(admin_conference_difficulty_levels_path(:conference_id => @conference.short_title)) end else flash[:notice] = "Difficulty Levels were successfully updated." - redirect_to(admin_conference_difficulty_levels_path(conference_id: @conference.short_title)) + redirect_to(admin_conference_difficulty_levels_path(:conference_id => @conference.short_title)) end else flash[:error] = "Difficulty Levels update failed." - redirect_to(admin_conference_difficulty_levels_path(conference_id: @conference.short_title)) + redirect_to(admin_conference_difficulty_levels_path(:conference_id => @conference.short_title)) end end end diff --git a/app/controllers/admin/emails_controller.rb b/app/controllers/admin/emails_controller.rb index e4489180..bff82c49 100644 --- a/app/controllers/admin/emails_controller.rb +++ b/app/controllers/admin/emails_controller.rb @@ -1,6 +1,7 @@ module Admin class EmailsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource class: EmailSettings def update @conference.email_settings.update_attributes(params[:email_settings]) @@ -10,6 +11,7 @@ module Admin end def index + authorize! :index, @conference.email_settings @settings = @conference.email_settings end end diff --git a/app/controllers/admin/event_types_controller.rb b/app/controllers/admin/event_types_controller.rb new file mode 100644 index 00000000..4c687021 --- /dev/null +++ b/app/controllers/admin/event_types_controller.rb @@ -0,0 +1,25 @@ +module Admin + class EventTypesController < ApplicationController + load_and_authorize_resource :conference, find_by: :short_title + authorize_resource :event_type, through: :conference + + def index + authorize! :index, EventType.new(conference_id: @conference.id) + end + + def show + render :eventtypes + end + + def update + @conference.update_attributes!(params[:conference]) + redirect_to(admin_conference_event_types_path( + conference_id: @conference.short_title), + notice: 'Event types were successfully updated.') + rescue Exception => e + redirect_to(admin_conference_event_types_path( + conference_id: @conference.short_title), + alert: "Event types update failed: #{e.message}") + end + end +end diff --git a/app/controllers/admin/events_controller.rb b/app/controllers/admin/events_controller.rb index 99dbfbc2..a807ac5d 100644 --- a/app/controllers/admin/events_controller.rb +++ b/app/controllers/admin/events_controller.rb @@ -1,6 +1,7 @@ module Admin class EventsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource :event, through: :conference before_action :get_event, except: [:index, :create] @@ -13,6 +14,8 @@ module Admin end def index + authorize! :index, @conference.events.build + @conference = Conference.find_by(short_title: params[:conference_id]) @events = @conference.events @tracks = @conference.tracks @machine_states = @events.state_machine.states.map diff --git a/app/controllers/admin/lodgings_controller.rb b/app/controllers/admin/lodgings_controller.rb index 34dfa628..992d7921 100644 --- a/app/controllers/admin/lodgings_controller.rb +++ b/app/controllers/admin/lodgings_controller.rb @@ -1,16 +1,17 @@ module Admin class LodgingsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource :venue, through: :conference, singleton: true + authorize_resource :lodging, through: :venue def index - @venue = @conference.venue + authorize! :update, Lodging.new(venue_id: @venue.id) end def show end def update - @venue = @conference.venue if @venue.update_attributes(params[:venue]) redirect_to(admin_conference_lodgings_path(conference_id: @conference.short_title), notice: 'Lodgings were successfully updated.') diff --git a/app/controllers/admin/questions_controller.rb b/app/controllers/admin/questions_controller.rb index 240909cd..d2f63cf2 100644 --- a/app/controllers/admin/questions_controller.rb +++ b/app/controllers/admin/questions_controller.rb @@ -1,23 +1,24 @@ module Admin class QuestionsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource through: :conference, except: [:new, :create] def index - @conference = Conference.find_by(short_title: params[:conference_id]) - @questions = Question.where(global: true).all | Question.where(conference_id: @conference.id) + authorize! :update, Question.new(conference_id: @conference.id) + @questions = Question.where(:global => true).all | Question.where(:conference_id => @conference.id) @questions_conference = @conference.questions @new_question = @conference.questions.new end def new - @conference = Conference.find_by(short_title: params[:conference_id]) - @new_question = @conference.questions.new + @question = Question.new(conference_id: @conference.id) + authorize! :create, @question end def create - @conference = Conference.find_by(short_title: params[:conference_id]) @question = @conference.questions.new(params[:question]) @question.conference_id = @conference.id + authorize! :create, @question respond_to do |format| if @conference.save @@ -31,42 +32,33 @@ module Admin # GET questions/1/edit def edit - @conference = Conference.find_by(short_title: params[:conference_id]) - @question = Question.find(params[:id]) - - if @question.global == true && !has_role?(current_user, "Admin") - redirect_to(admin_conference_questions_path(conference_id: @conference.short_title), alert: "Sorry, you cannot edit global questions. Create a new one.") + if @question.global == true && !(current_user.has_role? :organizer, @conference) + redirect_to(admin_conference_questions_path(:conference_id => @conference.short_title), :alert => "Sorry, you cannot edit global questions. Create a new one.") end end # PUT questions/1 def update - @conference = Conference.find_by(short_title: params[:conference_id]) - @question = Question.find(params[:id]) - if @question.update_attributes(params[:question]) - redirect_to(admin_conference_questions_path(conference_id: @conference.short_title), notice: "Question '#{@question.title}' for #{@conference.short_title} successfully updated.") + redirect_to(admin_conference_questions_path(:conference_id => @conference.short_title), :notice => "Question '#{@question.title}' for #{@conference.short_title} successfully updated.") else - redirect_to(admin_conference_questions_path(conference_id: @conference.short_title), notice: "Update of questions for #{@conference.short_title} failed.") + redirect_to(admin_conference_questions_path(:conference_id => @conference.short_title), :notice => "Update of questions for #{@conference.short_title} failed.") end end # Update questions used for the conference def update_conference - @conference = Conference.find_by(short_title: params[:conference_id]) - if @conference.update_attributes(params[:conference]) - redirect_to(admin_conference_questions_path(conference_id: @conference.short_title), notice: "Questions for #{@conference.short_title} successfully updated.") + redirect_to(admin_conference_questions_path(:conference_id => @conference.short_title), :notice => "Questions for #{@conference.short_title} successfully updated.") else - redirect_to(admin_conference_questions_path(conference_id: @conference.short_title), notice: "Update of questions for #{@conference.short_title} failed.") + redirect_to(admin_conference_questions_path(:conference_id => @conference.short_title), :notice => "Update of questions for #{@conference.short_title} failed.") end end # DELETE questions/1 def destroy - if has_role?(current_user, "Admin") - @question = Question.find(params[:id]) + if can? :destroy, @question # Do not delete global questions if @question.global == false @@ -74,12 +66,12 @@ module Admin begin Question.transaction do - @question.delete + @question.destroy @question.answers.each do |a| a.delete end flash[:notice] = "Deleted question: #{@question.title} and its answers: #{@question.answers.map {|a| a.title}.join ','}" - end + end rescue ActiveRecord::RecordInvalid flash[:error] = "Could not delete question." end @@ -90,7 +82,7 @@ module Admin flash[:error] = "You must be an admin to delete a question." end - @questions = Question.where(global: true).all | Question.where(conference_id: @conference.id) + @questions = Question.where(:global => true).all | Question.where(:conference_id => @conference.id) @questions_conference = @conference.questions end end diff --git a/app/controllers/admin/registrations_controller.rb b/app/controllers/admin/registrations_controller.rb index 6ebe3db0..677cb701 100644 --- a/app/controllers/admin/registrations_controller.rb +++ b/app/controllers/admin/registrations_controller.rb @@ -1,8 +1,10 @@ module Admin class RegistrationsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource through: :conference def index + authorize! :show, Registration.new(conference_id: @conference.id) session[:return_to] ||= request.referer @pdf_filename = "#{@conference.title}.pdf" @registrations = @conference.registrations.includes(:user) @@ -12,7 +14,6 @@ module Admin end def change_field - @registration = Registration.find(params[:id]) field = params[:view_field] if @registration.send(field.to_sym) @registration.update_attribute(:"#{field}", 0) @@ -26,12 +27,10 @@ module Admin end def edit - @registration = @conference.registrations.where('id = ?', params[:id]).first @user = User.where('id = ?', @registration.user_id).first end def update - @registration = @conference.registrations.where('id = ?', params[:id]).first @user = User.where('id = ?', @registration.user_id).first begin @user.update_attributes!(params[:registration][:user_attributes]) @@ -55,6 +54,7 @@ module Admin def new @user = User.new @registration = @user.registrations.new + @registration.conference_id = @conference.id @supporter_registration = @conference.supporter_registrations.new end @@ -97,7 +97,7 @@ module Admin end def destroy - if has_role?(current_user, 'Admin') + if can? :destroy, @registration registration = @conference.registrations.where(id: params[:id]).first user = User.where('id = ?', registration.user_id).first diff --git a/app/controllers/admin/rooms_controller.rb b/app/controllers/admin/rooms_controller.rb index ea2cd3f5..f9ed42e0 100644 --- a/app/controllers/admin/rooms_controller.rb +++ b/app/controllers/admin/rooms_controller.rb @@ -1,6 +1,11 @@ module Admin class RoomsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + authorize_resource through: :conference + + def index + authorize! :index, Room.new(conference_id: @conference.id) + end def show render :rooms_list diff --git a/app/controllers/admin/schedules_controller.rb b/app/controllers/admin/schedules_controller.rb index cd7fff2b..bf04d453 100644 --- a/app/controllers/admin/schedules_controller.rb +++ b/app/controllers/admin/schedules_controller.rb @@ -1,10 +1,14 @@ module Admin class SchedulesController < ApplicationController - before_filter :verify_organizer + # By authorizing 'conference' resource, we can ensure there will be no unauthorized access to + # the schedule of a conference, which should not be accessed in the first place + load_and_authorize_resource :conference, find_by: :short_title + skip_before_filter :verify_authenticity_token, only: [:update] layout 'schedule' def show + authorize! :update, @conference.events.new if @conference.nil? redirect_to admin_conference_index_path return @@ -14,6 +18,7 @@ module Admin end def update + authorize! :update, @conference.events.new event = Event.where(guid: params[:event]).first error_message = nil if event.nil? diff --git a/app/controllers/admin/social_events_controller.rb b/app/controllers/admin/social_events_controller.rb index c3f82ee8..05881371 100644 --- a/app/controllers/admin/social_events_controller.rb +++ b/app/controllers/admin/social_events_controller.rb @@ -1,6 +1,7 @@ module Admin class SocialEventsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + authorize_resource :social_event, through: :conference def show render :social_events_list @@ -8,9 +9,9 @@ module Admin def update if @conference.update_attributes(params[:conference]) - redirect_to(admin_conference_social_events_path(conference_id: @conference.short_title), notice: 'Social events were successfully updated.') + redirect_to(admin_conference_social_events_path(:conference_id => @conference.short_title), :notice => 'Social events were successfully updated.') else - redirect_to(admin_conference_social_events_path(conference_id: @conference.short_title), notice: 'Social events update failed.') + redirect_to(admin_conference_social_events_path(:conference_id => @conference.short_title), :notice => 'Social events update failed.') end end end diff --git a/app/controllers/admin/speakers_controller.rb b/app/controllers/admin/speakers_controller.rb index 76fd40ce..019cb24b 100644 --- a/app/controllers/admin/speakers_controller.rb +++ b/app/controllers/admin/speakers_controller.rb @@ -1,15 +1,17 @@ module Admin class SpeakersController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource :event + respond_to :js, :html def edit - @event = @conference.events.find(params[:event_id]) + authorize! :update, @conference.events.new @speaker = @event.event_users.where(event_role: 'speaker').first end def update - @event = @conference.events.find(params[:event_id]) + authorize! :update, @conference.events.new @speaker = @event.event_users.where(event_role: 'speaker').first @speaker.user_id = params[:speaker][:user_id] @speaker.save diff --git a/app/controllers/admin/sponsors_controller.rb b/app/controllers/admin/sponsors_controller.rb index d37c1cb4..9db33120 100644 --- a/app/controllers/admin/sponsors_controller.rb +++ b/app/controllers/admin/sponsors_controller.rb @@ -1,6 +1,11 @@ module Admin class SponsorsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + authorize_resource :sponsor, through: :conference + + def index + authorize! :index, Sponsor.new(conference_id: @conference.id) + end def update if @conference.update_attributes(params[:conference]) diff --git a/app/controllers/admin/sponsorship_levels_controller.rb b/app/controllers/admin/sponsorship_levels_controller.rb index 1d0a61bc..bef6af72 100644 --- a/app/controllers/admin/sponsorship_levels_controller.rb +++ b/app/controllers/admin/sponsorship_levels_controller.rb @@ -1,6 +1,11 @@ module Admin class SponsorshipLevelsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + authorize_resource through: :conference + + def index + authorize! :index, SponsorshipLevel.new(conference_id: @conference.id) + end def update if @conference.update_attributes(params[:conference]) diff --git a/app/controllers/admin/stats_controller.rb b/app/controllers/admin/stats_controller.rb index c98b9892..99bee919 100644 --- a/app/controllers/admin/stats_controller.rb +++ b/app/controllers/admin/stats_controller.rb @@ -1,6 +1,7 @@ module Admin class StatsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource + load_and_authorize_resource :conference, find_by: :short_title def index @registrations = @conference.registrations.includes(:user) diff --git a/app/controllers/admin/supporter_levels_controller.rb b/app/controllers/admin/supporter_levels_controller.rb index bc799c3d..686f16dc 100644 --- a/app/controllers/admin/supporter_levels_controller.rb +++ b/app/controllers/admin/supporter_levels_controller.rb @@ -1,6 +1,11 @@ module Admin class SupporterLevelsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + authorize_resource through: :conference + + def index + authorize! :update, SupporterLevel.new(conference_id: @conference.id) + end def show render :supporter_levels diff --git a/app/controllers/admin/supporters_controller.rb b/app/controllers/admin/supporters_controller.rb index 2ee69e6c..99dcefb3 100644 --- a/app/controllers/admin/supporters_controller.rb +++ b/app/controllers/admin/supporters_controller.rb @@ -1,6 +1,7 @@ module Admin class SupportersController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource through: :conference def index respond_to do |format| diff --git a/app/controllers/admin/targets_controller.rb b/app/controllers/admin/targets_controller.rb index 94562de3..6253459e 100644 --- a/app/controllers/admin/targets_controller.rb +++ b/app/controllers/admin/targets_controller.rb @@ -1,11 +1,15 @@ module Admin class TargetsController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + authorize_resource through: :conference def index + authorize! :index, Target.new(conference_id: @conference.id) end def update + authorize! :update, @conference => Target + if @conference.update_attributes(params[:conference]) redirect_to(admin_conference_targets_path( conference_id: @conference.short_title), diff --git a/app/controllers/admin/tracks_controller.rb b/app/controllers/admin/tracks_controller.rb index 284d7165..14f375f7 100644 --- a/app/controllers/admin/tracks_controller.rb +++ b/app/controllers/admin/tracks_controller.rb @@ -1,6 +1,11 @@ module Admin class TracksController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + authorize_resource through: :conference + + def index + authorize! :index, Track.new(conference_id: @conference.id) + end def show respond_to do |format| diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index cbd8300d..7d2faaa0 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -1,6 +1,7 @@ module Admin class UsersController < ApplicationController - before_filter :verify_admin + load_and_authorize_resource + def new @user = User.new end @@ -10,34 +11,37 @@ module Admin end def show - @user = User.find(params[:id]) - # Variable @show_attributes holds the attributes that are visible for the 'show' action # If you want to change the attributes that are shown in the 'show' action of users # add/remove the attributes in the following string array - @show_attributes = %w(name email affiliation biography registered attended created_at + @show_attributes = %w(name email affiliation biography registered attended roles created_at updated_at sign_in_count current_sign_in_at last_sign_in_at current_sign_in_ip last_sign_in_ip) end def update - user = User.find(params[:id]) - user.update_attributes!(params[:user]) - redirect_to admin_users_path, notice: "Updated #{user.email}" + params[:user].delete :roles_attributes if params[:user] + @user.update_attributes!(params[:user]) + redirect_to admin_users_path, notice: "Updated #{@user.email}" + end + + def add_role + role = params[:user][:roles_attributes][:"0"] + @user.add_role role['name'].parameterize.underscore.to_sym, Conference.find(role['resource_id']) + + respond_to do |format| + format.html + format.js + end + end def edit - @user = User.find(params[:id]) - end - - def delete - @user = User.find(params[:id]) end def destroy - @user = User.find(params[:id]) @user.destroy - redirect_to admin_users_path, notice: 'User got deleted' + redirect_to admin_users_path, notice: "User #{@user.name} (#{@user.email})got deleted" end end end diff --git a/app/controllers/admin/venue_controller.rb b/app/controllers/admin/venue_controller.rb index 59379a09..e308fc7e 100644 --- a/app/controllers/admin/venue_controller.rb +++ b/app/controllers/admin/venue_controller.rb @@ -1,6 +1,7 @@ module Admin class VenueController < ApplicationController - before_filter :verify_organizer + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource :venue, through: :conference, singleton: true def index end diff --git a/app/controllers/admin/volunteers_controller.rb b/app/controllers/admin/volunteers_controller.rb index 5713845f..fb34f78e 100644 --- a/app/controllers/admin/volunteers_controller.rb +++ b/app/controllers/admin/volunteers_controller.rb @@ -1,26 +1,37 @@ module Admin class VolunteersController < ApplicationController + load_and_authorize_resource :conference, find_by: :short_title + def index - @conference = Conference.find_by(short_title: params[:conference_id]) - render :index + if (current_user.has_role? :organizer, @conference) || (current_user.has_role? :volunteer_coordinator, @conference) + render :index + else + authorize! :index, :volunteer + end end def show - @conference = Conference.find_by(short_title: params[:conference_id]) - if @conference.use_vpositions - @volunteers = @conference.registrations.joins(:vchoices).uniq + if (current_user.has_role? :organizer, @conference) || (current_user.has_role? :volunteer_coordinator, @conference) + if @conference.use_vpositions + @volunteers = @conference.registrations.joins(:vchoices).uniq + else + @volunteers = @conference.registrations.where(:volunteer => true) + end else - @volunteers = @conference.registrations.where(volunteer: true) + authorize! :index, :volunteer end end def update - @conference = Conference.find_by(short_title: params[:conference_id]) - begin - @conference.update_attributes!(params[:conference]) - redirect_to(admin_conference_volunteers_info_path(conference_id: params[:conference_id]), notice: "Volunteering options were successfully updated.") - rescue => e - redirect_to(admin_conference_volunteers_info_path(conference_id: params[:conference_id]), alert: "Volunteering options update failed: #{e.message}") + if (current_user.has_role? :organizer, @conference) || (current_user.has_role? :volunteer_coordinator, @conference) + begin + @conference.update_attributes!(params[:conference]) + redirect_to(admin_conference_volunteers_info_path(:conference_id => params[:conference_id]), :notice => "Volunteering options were successfully updated.") + rescue Exception => e + redirect_to(admin_conference_volunteers_info_path(:conference_id => params[:conference_id]), :alert => "Volunteering options update failed: #{e.message}") + end + else + authorize! :index, :volunteer end end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0219a4ca..cec431c2 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,14 +3,17 @@ class ApplicationController < ActionController::Base protect_from_forgery before_filter :get_conferences before_filter :store_location + before_filter :verify_user_admin helper_method :date_string + # Ensure every controller authorizes resource or skips authorization (skip_authorization_check) + check_authorization unless: :devise_controller? def store_location session[:return_to] = request.fullpath if request.get? && controller_name != "user_sessions" && controller_name != "sessions" end def after_sign_in_path_for(resource) - if organizer_or_admin? && + if (can? :view, Conference) && (!session[:return_to] || session[:return_to] && session[:return_to] == root_path) @@ -31,6 +34,16 @@ class ApplicationController < ActionController::Base @conferences =Conference.all end + def verify_user_admin + if self.class.to_s.split('::').first == 'Admin' && verify_user + unless (current_user.has_role? :organizer, :any) || (current_user.has_role? :cfp, :any) || + (current_user.has_role? :info_desk, :any) || + (current_user.has_role? :volunteers_coordinator, :any) || current_user.is_admin + raise CanCan::AccessDenied.new('You are not authorized to access this area!') + end + end + end + def verify_user :authenticate_user! @@ -39,36 +52,17 @@ class ApplicationController < ActionController::Base return false end - @conference = Conference.find_by(short_title: params[:conference_id]) true end - def organizer_or_admin? - has_role?(current_user, 'admin') || has_role?(current_user, 'organizer') - end - - def verify_organizer - if !verify_user - return - end - - ## Todo simplify this - redirect_to root_path unless has_role?(current_user, 'admin') || has_role?(current_user, 'organizer') - end - - def verify_admin - if !verify_user - return - end - - redirect_to root_path unless has_role?(current_user, 'admin') + def current_ability + @current_ability ||= Ability.new(current_user) end rescue_from CanCan::AccessDenied do |exception| Rails.logger.debug("Access denied!") redirect_to root_path, alert: exception.message end - helper_method :organizer_or_admin? def not_found raise ActionController::RoutingError.new('Not Found') diff --git a/app/controllers/commercials_controller.rb b/app/controllers/commercials_controller.rb index fd9d6d88..fdf71b37 100644 --- a/app/controllers/commercials_controller.rb +++ b/app/controllers/commercials_controller.rb @@ -1,10 +1,11 @@ class CommercialsController < ApplicationController - before_action :set_conference + load_and_authorize_resource :conference, find_by: :short_title before_action :set_event - before_action :set_commercial, only: [:edit, :update, :destroy] + load_and_authorize_resource through: @event, except: [:new, :create] def new @commercial = @event.commercials.build + authorize! :new, @commercial end def edit @@ -12,6 +13,7 @@ class CommercialsController < ApplicationController def create @commercial = @event.commercials.build(commercial_params) + authorize! :create, @commercial if @commercial.save redirect_to edit_conference_proposal_path(conference_id: @conference.short_title, id: @event.id), @@ -40,14 +42,6 @@ class CommercialsController < ApplicationController private - def set_commercial - @commercial = @event.commercials.find(params[:id]) - end - - def set_conference - @conference = Conference.find_by(short_title: params[:conference_id]) - end - def set_event @event = @conference.events.find(params[:proposal_id]) end diff --git a/app/controllers/conference_controller.rb b/app/controllers/conference_controller.rb index afd35ce6..f809c225 100644 --- a/app/controllers/conference_controller.rb +++ b/app/controllers/conference_controller.rb @@ -1,7 +1,7 @@ class ConferenceController < ApplicationController + load_and_authorize_resource find_by: :short_title + def show - @conference = Conference.find_by_short_title(params[:id]) - redirect_to root_path, notice: "Conference not ready yet!!" unless @conference.make_conference_public? end def subscribe @@ -41,7 +41,7 @@ class ConferenceController < ApplicationController end def gallery_photos - @photos = Conference.find_by_short_title(params[:id]).photos + @photos = @conference.photos render "photos", formats: [:js] end end diff --git a/app/controllers/conference_registration_controller.rb b/app/controllers/conference_registration_controller.rb index ee4bc677..69e97261 100644 --- a/app/controllers/conference_registration_controller.rb +++ b/app/controllers/conference_registration_controller.rb @@ -1,9 +1,9 @@ class ConferenceRegistrationController < ApplicationController before_filter :verify_user + load_resource :conference, find_by: :short_title + authorize_resource :conference_registration, class: Registration def register - # TODO Figure out how to change the route's id from :id to :conference_id - @conference = Conference.find_by(short_title: params[:id]) @workshops = @conference.events.where('require_registration = ? AND state LIKE ?', true, 'confirmed') @user = current_user @@ -23,9 +23,8 @@ class ConferenceRegistrationController < ApplicationController # TODO this is ugly def update - conference = Conference.find_by(short_title: params[:id]) user = current_user - registration = user.registrations.where(conference_id: conference.id).first + registration = user.registrations.where(conference_id: @conference.id).first update_registration = true # First verify that the supporter code is legit if !params[:registration][:supporter_registration_attributes].nil? && @@ -35,7 +34,7 @@ class ConferenceRegistrationController < ApplicationController if regs.count != 0 if regs.where(email: user.email).count == 0 - redirect_to(register_conference_path(id: conference.short_title), + redirect_to(conference_register_path(conference_id: @conference.short_title), alert: "This code is already in use. Please contact #{conference.contact.email} for assistance.") return @@ -50,7 +49,7 @@ class ConferenceRegistrationController < ApplicationController supporter_reg = params[:registration][:supporter_registration_attributes] params[:registration].delete :supporter_registration_attributes registration = user.registrations.new(registration_params) - if conference.use_supporter_levels? && !supporter_reg.nil? + if @conference.use_supporter_levels? && !supporter_reg.nil? if !supporter_reg[:id].blank? # Means that their supporter registration was entered ahead of time, by an admin registration.supporter_registration = SupporterRegistration.find(supporter_reg[:id]) @@ -58,12 +57,12 @@ class ConferenceRegistrationController < ApplicationController raise 'Invalid code' end else - registration.supporter_registration = conference. + registration.supporter_registration = @conference. supporter_registrations.new(registration_params[:supporter_registration_attributes]) end end - registration.conference_id = conference.id + registration.conference_id = @conference.id registration.save! if user.subscriptions.where(conference: conference).blank? subscription = Subscription.new(conference_id: conference.id, user_id: user.id) @@ -74,7 +73,7 @@ class ConferenceRegistrationController < ApplicationController end rescue => e Rails.logger.debug e.backtrace.join('\n') - redirect_to(register_conference_path(id: conference.short_title), + redirect_to(conference_register_path(conference_id: @conference.short_title), alert: 'Registration failed:' + e.message) return end @@ -84,19 +83,18 @@ class ConferenceRegistrationController < ApplicationController else # Track ahoy event ahoy.track 'Registered', title: 'New registration' - if conference.email_settings.send_on_registration? - Mailbot.delay.registration_mail(conference, current_user) + if @conference.email_settings.send_on_registration? + Mailbot.delay.registration_mail(@conference, current_user) end end - redirect_to(register_conference_path(id: conference.short_title), + redirect_to(conference_register_path(conference_id: @conference.short_title), notice: redirect_message) end def unregister - conference = Conference.find_by(short_title: params[:id]) user = current_user - registration = user.registrations.where(conference_id: conference.id).first - subscription = user.subscriptions.where(conference: conference) + registration = user.registrations.where(conference_id: @conference.id).first + subscription = user.subscriptions.where(conference: @conference) unless subscription.blank? subscription.first.destroy end diff --git a/app/controllers/event_attachments_controller.rb b/app/controllers/event_attachments_controller.rb index 9c366eb5..c8bf54c1 100644 --- a/app/controllers/event_attachments_controller.rb +++ b/app/controllers/event_attachments_controller.rb @@ -1,9 +1,11 @@ class EventAttachmentsController < ApplicationController + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource :proposal, class: Event + load_and_authorize_resource :upload, class: EventAttachment, through: :proposal before_filter :verify_user skip_before_filter :verify_user, only: [:show] def index - @proposal = Event.find(params[:proposal_id]) @uploads = @proposal.event_attachments @uploads = @uploads.map{|upload| upload.to_jq_upload } @@ -14,9 +16,9 @@ class EventAttachmentsController < ApplicationController end def show - upload = EventAttachment.find(params[:id]) - if upload.public? - send_file upload.attachment.path + + if @upload.public? + send_file @upload.attachment.path return end @@ -26,7 +28,7 @@ class EventAttachmentsController < ApplicationController end if organizer_or_admin? || current_user == upload.event.submitter - send_file upload.attachment.path + send_file @upload.attachment.path else raise ActionController::RoutingError.new('Not Found') end @@ -42,7 +44,6 @@ class EventAttachmentsController < ApplicationController end def edit - @upload = EventAttachment.find(params[:id]) end def create @@ -50,7 +51,7 @@ class EventAttachmentsController < ApplicationController params[:event_attachment][:public] = false params[:event_attachment][:event_id] = params[:proposal_id] - if !organizer_or_admin? + if cannot? :create, EventAttachment begin current_user.events.find(params[:proposal_id]) rescue @@ -66,6 +67,7 @@ class EventAttachmentsController < ApplicationController respond_to do |format| if @upload.save +<<<<<<< HEAD format.html do render json: [@upload.to_jq_upload].to_json, content_type: 'text/html', @@ -75,6 +77,15 @@ class EventAttachmentsController < ApplicationController render json: [@upload.to_jq_upload].to_json, status: :created, location: conference_proposal_event_attachment_path(@upload.event.conference.short_title, @upload.event, @upload) end +======= + format.html { + render :json => [@upload.to_jq_upload].to_json, + :content_type => 'text/html', + :layout => false + } + format.json { render json: {files: [@upload.to_jq_upload]}, status: :created, + location: conference_proposal_event_attachment_path(@upload.event.conference.short_title, @upload.event, @upload) } +>>>>>>> authorization with cancancan else format.html { render action: "new" } format.json { render json: @upload.errors, status: :unprocessable_entity } @@ -83,8 +94,6 @@ class EventAttachmentsController < ApplicationController end def update - @proposal = current_user.events.find(params[:proposal_id]) - @upload = @proposal.event_attachments.find(params[:proposal_id]) respond_to do |format| if @upload.update_attributes(params[:upload]) @@ -98,14 +107,13 @@ class EventAttachmentsController < ApplicationController end def destroy - @proposal = Event.find(params[:proposal_id]) - - if organizer_or_admin? || current_user == @proposal.submitter + + if can? :destroy, @proposal @upload = @proposal.event_attachments.find(params[:id]) end - + @upload.destroy if !@upload.nil? - + respond_to do |format| format.html { redirect_back_or_to conference_proposal_index_path(@conference.short_title), notice: "Deleted successfully attachment '#{@upload.title}' for proposal '#{@proposal.title}'" } diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 1b6a0373..8da4883f 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -1,5 +1,6 @@ class HomeController < ApplicationController before_filter :respond_to_options + skip_authorization_check def index @today = Date.current diff --git a/app/controllers/proposal_controller.rb b/app/controllers/proposal_controller.rb index dd2bf657..31c8299b 100644 --- a/app/controllers/proposal_controller.rb +++ b/app/controllers/proposal_controller.rb @@ -1,22 +1,19 @@ class ProposalController < ApplicationController before_filter :verify_user, except: [:show] - before_action :set_conference, only: [:show] - before_action :set_event, only: [:show, :edit, :update, :destroy, :confirm, :restart] + load_resource :conference, find_by: :short_title + load_and_authorize_resource :event, parent: false, through: :conference def index @events = current_user.proposals(@conference) end def show - authorize! :show, @event # FIXME: We should show more than the first speaker @speaker = @event.speakers.first || @event.submitter end def new - authorize! :new, Event @url = conference_proposal_index_path(@conference.short_title) - @event = Event.new end def edit @@ -26,7 +23,6 @@ class ProposalController < ApplicationController end def create - authorize! :create, Event @url = conference_proposal_index_path(@conference.short_title) params[:event].delete :user @@ -53,7 +49,7 @@ class ProposalController < ApplicationController registration = current_user.registrations.where(conference_id: @conference.id).first ahoy.track 'Event submission', title: 'New submission' if registration.nil? - redirect_to(register_conference_path(@conference.short_title), + redirect_to(conference_register_path(@conference.short_title), alert: 'Event was successfully submitted. You should register for the conference now.') else @@ -120,7 +116,7 @@ class ProposalController < ApplicationController end if !@conference.user_registered?(current_user) - redirect_to(register_conference_path(@conference.short_title), + redirect_to(conference_register_path(@conference.short_title), alert: 'The proposal was confirmed. Please register to attend the conference.') return end @@ -131,7 +127,7 @@ class ProposalController < ApplicationController def restart authorize! :update, @event @url = conference_proposal_path(@conference.short_title, params[:id]) - + begin @event.restart rescue Transitions::InvalidTransition @@ -149,14 +145,4 @@ class ProposalController < ApplicationController redirect_to(conference_proposal_index_path(conference_id: @conference.short_title), notice: "The proposal was re-submitted. The #{@conference.short_title} organizers will review it again.") end - - private - - def set_conference - @conference = Conference.find_by(short_title: params[:conference_id]) - end - - def set_event - @event = Event.find(params[:id]) - end end diff --git a/app/controllers/schedule_controller.rb b/app/controllers/schedule_controller.rb index 84a861b8..f5fc9914 100644 --- a/app/controllers/schedule_controller.rb +++ b/app/controllers/schedule_controller.rb @@ -1,6 +1,10 @@ class ScheduleController < ApplicationController +<<<<<<< HEAD +======= + authorize_resource class: false +>>>>>>> authorization with cancancan layout "application" - + def index @conference = Conference.includes(:rooms, events: [:speakers, :track, :event_type]).where("conferences.short_title" => params[:conference_id]).first @rooms = @conference.rooms diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb index aca14642..4412a8ae 100644 --- a/app/controllers/users/omniauth_callbacks_controller.rb +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -1,6 +1,7 @@ module Users class OmniauthCallbacksController < Devise::OmniauthCallbacksController skip_before_filter :verify_authenticity_token + skip_authorization_check User.omniauth_providers.each do |provider| define_method(provider) { handle(provider) } diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 44deebd4..e4f0e09a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -137,14 +137,6 @@ module ApplicationHelper render "shared/dynamic_association", association_name: association_name, title: title, f: form_builder, hint: options[:hint] end - def has_role?(current_user, role) - if current_user.nil? - return false - end - - return !!current_user.role?(role.to_s.camelize) - end - # Same as redirect_to(:back) if there is a valid HTTP referer, otherwise redirect_to() def redirect_back_or_to(options = {}, response_status = {}) if request.env["HTTP_REFERER"] diff --git a/app/models/ability.rb b/app/models/ability.rb index 8c09734e..98bb265e 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -2,16 +2,144 @@ class Ability include CanCan::Ability def initialize(user) - # guest user (not logged in) - user ||= User.new - if user.admin? || user.organizer? - # An admin can manage everything - can :manage, :all + # The first argument to `can` is the action you are giving the user permission to do. + # If you pass :manage it will apply to every action. Other common actions here are + # :read, :create, :update and :destroy. + # + # The second argument is the resource the user can perform the action on. If you pass + # :all it will apply to every resource. Otherwise pass a Ruby class of the resource. + # + # The third argument is an optional hash of conditions to further filter the objects. + # For example, here the user can only update published articles. + # + # can :update, Article, :published => true + # + # See the wiki for details: https://github.com/ryanb/cancan/wiki/Defining-Abilities + + # Order Abilities + # (Check https://github.com/CanCanCommunity/cancancan/wiki/Ability-Precedence) + # Check roles of user, using rolify. Role name is *case sensitive* + # 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_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 + + + user ||= User.new # guest user (not logged in) + + if user.new_record? + guest(user) else - can [:update, :destroy], Event do |event| - event.users.include?(user) + roles = Role::ACTIONABLES.map {|i| i.parameterize.underscore} + if (user.roles.pluck(:name) & roles).empty? && !user.is_admin # User has no roles + signed_in(user) + else + user_with_roles(user) end - can [:create, :read], Event end end + + def user_with_roles(user) + conf_ids_for_organizer = [] + venue_ids_for_organizer = [] + conf_ids_for_cfp = [] + venue_ids_for_cfp = [] + conf_ids_for_info_desk = [] + conf_ids_for_volunteer_coordinator = [] + + # Ids of all the conferences for which the user has an 'organizer' role + conf_ids_for_organizer = + Conference.with_role(:organizer, user).pluck(:id) if user.has_role? :organizer, :any + venue_ids_for_organizer = + Conference.with_role(:organizer, user).pluck(:venue_id) if user.has_role? :organizer, :any + conf_ids_for_cfp = + Conference.with_role(:cfp, user).pluck(:id) if user.has_role? :cfp, :any + venue_ids_for_cfp = + Conference.with_role(:cfp, user).pluck(:venue_id) if user.has_role? :cfp, :any + # Ids of all the conferences for which the user has an 'info_desk' role + conf_ids_for_info_desk = + Conference.with_role(:info_desk, user).pluck(:id) if user.has_role? :info_desk, :any + # Ids of all the conferences for which the user has a 'volunteer_coordinator' role + conf_ids_for_volunteer_coordinator = + Conference.with_role(:volunteer_coordinator, user).pluck(:id) if user.has_role? :volunteer_coordinator, :any + + signed_in(user) # Inherit abilities from signed user + # User with role + can :manage, User if user.is_admin # ??? || (user.has_role? :organizer, :any) + can [:new, :create], Conference if user.is_admin || (user.has_role? :organizer, :any) + can [:index, :show, :gallery_photos], Conference + can :manage, Conference, id: conf_ids_for_organizer +# can :manage, Conference do |conference| +# conference.id = conf_ids_for_organizer +# end + can :manage, Venue, id: venue_ids_for_organizer + can :index, Venue, id: venue_ids_for_cfp + can :manage, Registration, conference_id: conf_ids_for_organizer + conf_ids_for_info_desk + can :manage, Question, conference_id: conf_ids_for_organizer + conf_ids_for_info_desk + can :manage, Vposition, conference_id: conf_ids_for_organizer + conf_ids_for_volunteer_coordinator + can :manage, Vday, conference_id: conf_ids_for_organizer + conf_ids_for_volunteer_coordinator + # The ability to manage an Event means that: + # the user can also edit the schedule and that + # the user can also vote + can :manage, Event, conference_id: conf_ids_for_organizer + conf_ids_for_cfp + can :create, Event + can :manage, CallForPapers, conference_id: conf_ids_for_organizer + conf_ids_for_cfp + can :manage, EventType, conference_id: conf_ids_for_organizer + conf_ids_for_cfp + can :manage, Track, conference_id: conf_ids_for_organizer + conf_ids_for_cfp + can :manage, DifficultyLevel, conference_id: conf_ids_for_organizer + conf_ids_for_cfp + can :manage, EmailSettings, conference_id: conf_ids_for_organizer + conf_ids_for_cfp + can :manage, Campaign, conference_id: conf_ids_for_organizer + can :manage, Lodging, venue_id: venue_ids_for_organizer + can :manage, Photo, conference_id: conf_ids_for_organizer + can :manage, Room, conference_id: conf_ids_for_organizer + conf_ids_for_cfp + can :manage, Sponsor, conference_id: conf_ids_for_organizer + can :manage, SponsorshipLevel, conference_id: conf_ids_for_organizer + can :manage, SupporterLevel, conference_id: conf_ids_for_organizer + can :manage, Target, conference_id: conf_ids_for_organizer + can :manage, Commercial#, commercialable_type: 'Conference', commercialable_id: conf_ids_for_organizer + can :index, Commercial, commercialable_type: 'Conference' + # Manage commercials for events that belong to a conference of which user is organizer + can :manage, Commercial, commercialable_type: 'Event', commercialable_id: Event.where(conference_id: conf_ids_for_organizer + conf_ids_for_cfp).pluck(:id) + can :manage, Contact, conference_id: conf_ids_for_organizer + can :manage, Campaign, conference_id: conf_ids_for_organizer + end + + def guest(user) + ## Abilities for everyone, even guests (not logged in users) + can [:show, :gallery_photos], Conference do |conference| + conference.make_conference_public == true + end + + can :show, Event do |event| + event.state == 'confirmed' + end + + can :index, :schedule # show? + end + + def signed_in(user) + guest(user) # Inherits abilities of guest + + # Conference Registration + can :manage, Registration, user_id: user.id + + ## Proposals + # Users can manage their own proposals + can :manage, Event, id: user.events.pluck(:id) + + # Submit proposals only for conferences that are not over yet + can :create, Event, conference_id: Conference.where('end_date >= ?', Date.today).pluck(:id) + # Users can manage their own commercials + can :manage, Commercial, commercialable_type: 'Event', commercialable_id: user.events.pluck(:id) + # View commercials of confirmed events + can :show, Commercial, commercialable_type: 'Event', commercialable_id: Event.where(state: 'confirmed').pluck(:id) + + can :manage, EventAttachment do |ea| + Event.find(ea.event_id).event_users.where(user_id: user.id).present? + end + can :create, EventAttachment + end end diff --git a/app/models/call_for_papers.rb b/app/models/call_for_papers.rb index 569939c3..7876efa2 100644 --- a/app/models/call_for_papers.rb +++ b/app/models/call_for_papers.rb @@ -1,7 +1,7 @@ class CallForPapers < ActiveRecord::Base attr_accessible :start_date, :end_date, :description, :schedule_changes, :rating, - :schedule_public, :include_cfp_in_splash + :schedule_public, :include_cfp_in_splash, :conference_id belongs_to :conference validates_presence_of :start_date, :end_date diff --git a/app/models/campaign.rb b/app/models/campaign.rb index 0228406b..5d9ab7ed 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -1,6 +1,6 @@ class Campaign < ActiveRecord::Base - attr_accessible :name, :utm_source, :utm_medium, :utm_term, - :utm_content, :utm_campaign, :target_ids + attr_accessible :name, :target_ids, :conference_id, + :utm_source, :utm_medium, :utm_term, :utm_content, :utm_campaign validates :name, :utm_campaign, presence: true diff --git a/app/models/conference.rb b/app/models/conference.rb index 01a8d8b4..552d5248 100644 --- a/app/models/conference.rb +++ b/app/models/conference.rb @@ -4,6 +4,7 @@ class Conference < ActiveRecord::Base require 'uri' serialize :events_per_week, Hash + resourcify # Needed to call 'Conference.with_role' in /models/ability.rb attr_accessible :title, :short_title, :timezone, :html_export_path, :start_date, :end_date, :rooms_attributes, :tracks_attributes, diff --git a/app/models/difficulty_level.rb b/app/models/difficulty_level.rb index ac8306ae..b230c07f 100644 --- a/app/models/difficulty_level.rb +++ b/app/models/difficulty_level.rb @@ -1,6 +1,6 @@ class DifficultyLevel < ActiveRecord::Base - attr_accessible :title, :description, :color - + attr_accessible :title, :description, :color, :conference_id + belongs_to :conference has_many :events diff --git a/app/models/event_attachment.rb b/app/models/event_attachment.rb index 41915248..819f3b6d 100644 --- a/app/models/event_attachment.rb +++ b/app/models/event_attachment.rb @@ -6,6 +6,7 @@ class EventAttachment < ActiveRecord::Base has_attached_file :attachment, path: ":rails_root/storage/:rails_env/attachments/:id/:style/:basename.:extension" include Rails.application.routes.url_helpers + do_not_validate_attachment_file_type :attachment def to_jq_upload { diff --git a/app/models/event_type.rb b/app/models/event_type.rb index 81db86da..a2204985 100644 --- a/app/models/event_type.rb +++ b/app/models/event_type.rb @@ -1,10 +1,11 @@ class EventType < ActiveRecord::Base - attr_accessible :title, :length, :minimum_abstract_length, :maximum_abstract_length, :color + attr_accessible :title, :length, :minimum_abstract_length, :maximum_abstract_length, :color, + :conference_id belongs_to :conference validates :title, presence: true - validates :length, numericality: {greater_than: 0} + validates :length, numericality: {greater_than: 0} validates :minimum_abstract_length, presence: true validates :maximum_abstract_length, presence: true diff --git a/app/models/lodging.rb b/app/models/lodging.rb index 296ff0b1..9871f35c 100644 --- a/app/models/lodging.rb +++ b/app/models/lodging.rb @@ -1,5 +1,5 @@ class Lodging < ActiveRecord::Base - attr_accessible :name, :description, :photo, :website_link + attr_accessible :name, :description, :photo, :website_link, :venue_id belongs_to :venue has_attached_file :photo, styles: { thumb: '100x100>', large: '300x300>' } diff --git a/app/models/question.rb b/app/models/question.rb index 1a6302c1..96a5b8db 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -1,14 +1,14 @@ class Question < ActiveRecord::Base - attr_accessible :title, :global, :answers_attributes, :answer_ids, :question_type_id - + attr_accessible :title, :global, :answers_attributes, :answer_ids, :question_type_id, :conference_id + belongs_to :question_type has_and_belongs_to_many :conferences - + has_many :qanswers, dependent: :delete_all has_many :answers, through: :qanswers, dependent: :delete_all - + validates :title, presence: true validates :answers, presence: true - + accepts_nested_attributes_for :answers, allow_destroy: true end diff --git a/app/models/role.rb b/app/models/role.rb index e6d7cb0a..fc2f1e50 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,4 +1,10 @@ class Role < ActiveRecord::Base - attr_accessible :name + attr_accessible :name, :description has_and_belongs_to_many :users + belongs_to :resource, polymorphic: true + + scopify + + LABELS = ['Attendee', 'Volunteer', 'Speaker', 'Sponsor', 'Press', 'Keynote Speaker'] + ACTIONABLES = ['Organizer', 'CfP', 'Info Desk', 'Volunteers Coordinator'] end diff --git a/app/models/room.rb b/app/models/room.rb index f4611a7d..3244ff54 100644 --- a/app/models/room.rb +++ b/app/models/room.rb @@ -1,5 +1,5 @@ class Room < ActiveRecord::Base - attr_accessible :name, :size, :public + attr_accessible :name, :size, :public, :conference_id belongs_to :conference has_many :events diff --git a/app/models/sponsor.rb b/app/models/sponsor.rb index 93244c0e..e6acad75 100644 --- a/app/models/sponsor.rb +++ b/app/models/sponsor.rb @@ -1,6 +1,5 @@ class Sponsor < ActiveRecord::Base - attr_accessible :name, :description, :website_url, :logo, - :sponsorship_level_id + attr_accessible :name, :description, :website_url, :logo, :sponsorship_level_id, :conference_id belongs_to :sponsorship_level belongs_to :conference has_attached_file :logo, diff --git a/app/models/sponsorship_level.rb b/app/models/sponsorship_level.rb index 4cbe3a7c..174a440d 100644 --- a/app/models/sponsorship_level.rb +++ b/app/models/sponsorship_level.rb @@ -1,5 +1,5 @@ class SponsorshipLevel < ActiveRecord::Base - attr_accessible :title + attr_accessible :title, :conference_id validates_presence_of :title belongs_to :conference has_many :sponsors diff --git a/app/models/supporter_level.rb b/app/models/supporter_level.rb index 02c56f61..deb12aa8 100644 --- a/app/models/supporter_level.rb +++ b/app/models/supporter_level.rb @@ -2,5 +2,5 @@ class SupporterLevel < ActiveRecord::Base belongs_to :conference has_many :supporter_registrations - attr_accessible :conference, :title, :url, :description, :ticket_price + attr_accessible :conference, :title, :url, :description, :ticket_price, :conference_id end diff --git a/app/models/target.rb b/app/models/target.rb index 6a7990a8..8c994522 100644 --- a/app/models/target.rb +++ b/app/models/target.rb @@ -1,7 +1,7 @@ class Target < ActiveRecord::Base include ActionView::Helpers::TextHelper - attr_accessible :due_date, :target_count, :unit + attr_accessible :due_date, :target_count, :unit, :conference_id default_scope { order('due_date ASC') } diff --git a/app/models/track.rb b/app/models/track.rb index beb033c9..4e7deba7 100644 --- a/app/models/track.rb +++ b/app/models/track.rb @@ -1,5 +1,5 @@ class Track < ActiveRecord::Base - attr_accessible :name, :description, :color + attr_accessible :name, :description, :color, :conference_id belongs_to :conference diff --git a/app/models/user.rb b/app/models/user.rb index 88cd34f7..08541de8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,7 +1,10 @@ class User < ActiveRecord::Base + rolify include Gravtastic gravtastic size: 32 + before_create :setup_role + # Include default devise modules. Others available are: # :token_authenticatable, :confirmable, # :lockable, :timeoutable and :omniauthable @@ -13,7 +16,7 @@ class User < ActiveRecord::Base has_many :openids attr_accessible :email, :password, :password_confirmation, :remember_me, :role_id, :role_ids, - :name, :email_public, :biography, :nickname, :affiliation + :name, :email_public, :biography, :nickname, :affiliation, :is_admin has_many :event_users, dependent: :destroy has_many :events, -> { uniq }, through: :event_users @@ -23,8 +26,6 @@ class User < ActiveRecord::Base has_many :subscriptions, dependent: :destroy accepts_nested_attributes_for :roles - before_create :setup_role - validates :name, presence: true # Searches for user based on email. Returns found user or new user. @@ -47,26 +48,24 @@ class User < ActiveRecord::Base user end - def role?(role) - Rails.logger.debug('Checking role in user') - !!roles.find_by_name(role.to_s.downcase.camelize) - end - - def admin? - role?('Admin') - end - - def organizer? - role?('Organizer') - end - def get_roles roles end def setup_role - roles << Role.where(name: 'Admin') if User.count == 0 - roles << Role.where(name: 'Participant') if roles.empty? + self.is_admin = true if User.count == 0 + end + + # Gets the roles of the user, groups them by role.name and returns the resource(s) of each role + # ====Returns + # * +Hash+ * -> e.g. 'organizer' => "(conf1, conf2)" + def show_roles + result = {} + Role::ACTIONABLES.each do |role| + resources = self.roles.where(name: role.parameterize.underscore).map{ |myrole| Conference.find(myrole.resource_id).short_title }.join ', ' + result[role.parameterize.underscore] = "(#{ resources })" unless resources.blank? + end + result end def self.prepare(params) diff --git a/app/views/admin/commercials/index.html.haml b/app/views/admin/commercials/index.html.haml index 002398b1..e8f72d53 100644 --- a/app/views/admin/commercials/index.html.haml +++ b/app/views/admin/commercials/index.html.haml @@ -14,8 +14,11 @@ = commercial.commercial_type .flexvideo = render partial: 'shared/media_item', locals: { commercial_type: commercial.commercial_type, commercial_id: commercial.commercial_id } - = link_to 'Edit', edit_admin_conference_commercial_path(@conference.short_title, commercial.id), class: 'btn btn-primary' - = link_to 'Delete', admin_conference_commercial_path(@conference.short_title, commercial.id), - method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger' -%br + - if can? :update, commercial + = link_to 'Edit', edit_admin_conference_commercial_path(@conference.short_title, commercial.id), class: 'btn btn-primary' + - if can? :destroy, commercial + = link_to 'Delete', admin_conference_commercial_path(@conference.short_title, commercial.id), + method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger' +- if can? :create, @conference.commercials.new + %br = link_to 'New Commercial', new_admin_conference_commercial_path, class: 'btn btn-primary' diff --git a/app/views/admin/conference/_roles.html.haml b/app/views/admin/conference/_roles.html.haml new file mode 100644 index 00000000..fb7af48b --- /dev/null +++ b/app/views/admin/conference/_roles.html.haml @@ -0,0 +1,29 @@ +.roles{ id: 'myroles' } + - unless @role.blank? + %p.text-muted + = @role.first.description + + %hr + .row + .col-md-6 + = semantic_form_for(:user, url: add_user_admin_conference_path(@conference.short_title, role: @selected), remote: true) do |f| + %h4 + = f.input :email, label: "Add role '#{@selected}' to user: ", placeholder: "User's email" + = f.action :submit, as: :button, label: "Add User", button_html: {value: 'Add', class: 'btn btn-primary'} + .row + .col-md-12 + %h3 Users with role #{@selected} + %table.table.table-striped.table-bordered.table-hover + %thead + %th ID + %th Name + %th Email + %tbody + - @role_users[@selection].each do |user| + %tr + %td + = link_to remove_user_admin_conference_path(@conference.short_title, user: user, role: @selected), method: :delete, remote: true, title: 'Remove user' do + %i{class: 'fa fa-times'} + = user.id + %td= user.name + %td= user.email diff --git a/app/views/admin/conference/_todo_list.html.haml b/app/views/admin/conference/_todo_list.html.haml index 3f87ecbd..acb0155e 100644 --- a/app/views/admin/conference/_todo_list.html.haml +++ b/app/views/admin/conference/_todo_list.html.haml @@ -8,25 +8,49 @@ = conference_progress['process'] + '%' %li{'class'=>class_for_todo(conference_progress['registration'])} %span{'class'=>icon_for_todo(conference_progress['registration'])} - = link_to 'Set up registration period', edit_admin_conference_path(conference_progress['short_title'], :anchor => 'conference-end-datepicker') + - if can? :update, @conference.registrations.build + = link_to 'Set up registration period', edit_admin_conference_path(conference_progress['short_title'], :anchor => 'conference-end-datepicker') + - else + Set up registration period %li{'class'=>class_for_todo(conference_progress['cfp'])} %span{'class'=>icon_for_todo(conference_progress['cfp'])} - = link_to 'Set up call for papers', admin_conference_callforpapers_path(conference_progress['short_title']) + - if can? :update, CallForPapers.new(conference_id: @conference.id) + = link_to 'Set up call for papers', admin_conference_callforpapers_path(conference_progress['short_title']) + - else + Set up call for papers %li{'class'=>class_for_todo(conference_progress['venue'])} %span{'class'=>icon_for_todo(conference_progress['venue'])} - = link_to 'Add venue', admin_conference_venue_info_path(conference_progress['short_title']) + - if can? :update, @conference.venue + = link_to 'Add venue', admin_conference_venue_info_path(conference_progress['short_title']) + - else + Add venue %li{'class'=>class_for_todo(conference_progress['rooms'])} %span{'class'=>icon_for_todo(conference_progress['rooms'])} - = link_to 'Add rooms', admin_conference_rooms_path(conference_progress['short_title']) + - if can? :update, @conference.rooms.build + = link_to 'Add rooms', admin_conference_rooms_path(conference_progress['short_title']) + - else + Add rooms %li{'class'=>class_for_todo(conference_progress['tracks'])} %span{'class'=>icon_for_todo(conference_progress['tracks'])} - = link_to 'Add tracks', admin_conference_tracks_path(conference_progress['short_title']) + - if can? :update, @conference.tracks.build + = link_to 'Add tracks', admin_conference_tracks_path(conference_progress['short_title']) + - else + Add tracks %li{'class'=>class_for_todo(conference_progress['event_types'])} %span{'class'=>icon_for_todo(conference_progress['event_types'])} - = link_to 'Add event types', admin_conference_eventtypes_path(conference_progress['short_title']) + - if can? :update, @conference.event_types.build + = link_to 'Add event types', admin_conference_event_types_path(conference_progress['short_title']) + - else + Add event types %li{'class'=>class_for_todo(conference_progress['difficulty_levels'])} %span{'class'=>icon_for_todo(conference_progress['difficulty_levels'])} - = link_to 'Add difficulty levels', admin_conference_difficulty_levels_path(conference_progress['short_title']) + - if can? :update, @conference.difficulty_levels.build + = link_to 'Add difficulty levels', admin_conference_difficulty_levels_path(conference_progress['short_title']) + - else + Add difficulty levels %li{class: class_for_todo(conference_progress['make_conference_public'])} %span{'class'=>icon_for_todo(conference_progress['make_conference_public'])} - = link_to 'Make Splash Page Public for Visitors', edit_admin_conference_path(conference_progress['short_title']) + - if can? :update, @conference + = link_to 'Make Splash Page Public for Visitors', edit_admin_conference_path(conference_progress['short_title']) + - else + Make Splash Page Public for Visitors diff --git a/app/views/admin/conference/roles.html.haml b/app/views/admin/conference/roles.html.haml new file mode 100644 index 00000000..a49bb17d --- /dev/null +++ b/app/views/admin/conference/roles.html.haml @@ -0,0 +1,22 @@ +.row + .col-md-6 + = semantic_form_for(:user, url: roles_admin_conference_path(@conference.short_title), remote: true) do |f| + %h4 + = f.input :roles, collection: @roles, label: 'Show users for role: ' + += render partial: 'roles' + +:javascript + + $("#user_roles_input").change(function () { + + var url = document.forms[0].action; + var selected_role = $(this).find('option:selected').attr('value'); + + $.ajax({ + url: url, + type: "POST", + data: {user: { roles: selected_role } }, + dataType: "script" + }); + }); diff --git a/app/views/admin/conference/roles.js.erb b/app/views/admin/conference/roles.js.erb new file mode 100644 index 00000000..15ac7237 --- /dev/null +++ b/app/views/admin/conference/roles.js.erb @@ -0,0 +1 @@ +$('#myroles').html("<%= escape_javascript(render partial: 'roles').html_safe %>"); diff --git a/app/views/admin/eventtypes/_event_type_fields.html.erb b/app/views/admin/event_types/_event_type_fields.html.erb similarity index 100% rename from app/views/admin/eventtypes/_event_type_fields.html.erb rename to app/views/admin/event_types/_event_type_fields.html.erb diff --git a/app/views/admin/eventtypes/index.html.haml b/app/views/admin/event_types/index.html.haml similarity index 76% rename from app/views/admin/eventtypes/index.html.haml rename to app/views/admin/event_types/index.html.haml index ad9256d1..c225bd66 100644 --- a/app/views/admin/eventtypes/index.html.haml +++ b/app/views/admin/event_types/index.html.haml @@ -1,5 +1,5 @@ .row .col-md-8 - = semantic_form_for(@conference, url: admin_conference_eventtypes_path(@conference.short_title, @conference.event_types)) do |f| + = semantic_form_for(@conference, url: admin_conference_event_types_path(@conference.short_title, @conference.event_types)) do |f| = dynamic_association :event_types, "Event Types", f = f.action :submit, :as => :button, :button_html => {:class => "btn btn-primary"} diff --git a/app/views/admin/questions/_questions.html.haml b/app/views/admin/questions/_questions.html.haml index 9feda3aa..46da49cd 100644 --- a/app/views/admin/questions/_questions.html.haml +++ b/app/views/admin/questions/_questions.html.haml @@ -18,11 +18,11 @@ = ',' = label_tag dom_id(q), "Answers: #{q.answers.map {|a| a.title}.join(', ')}" - %td= link_to 'Edit', edit_admin_conference_question_path(@conference.short_title, q), - class: 'btn btn-primary', - disabled: q.global == true && !has_role?(current_user, 'Admin') + - if can? :update, q + %td= link_to 'Edit', edit_admin_conference_question_path(@conference.short_title, q), + class: 'btn btn-primary', disabled: q.global == true - %td= link_to 'Delete', admin_conference_question_path(@conference.short_title, q), - method: :delete, remote: true, class: 'btn btn-danger', - confirm: "Delete question '#{q.title}'?", - disabled: q.global == true && !has_role?(current_user, "Admin") + - if can? :destroy, q + %td= link_to 'Delete', admin_conference_question_path(@conference.short_title, q), + method: :delete, remote: true, class: 'btn btn-danger', + confirm: "Delete question '#{q.title}'?", disabled: q.global == true diff --git a/app/views/admin/registrations/index.html.haml b/app/views/admin/registrations/index.html.haml index 78aa4db7..a0590a59 100644 --- a/app/views/admin/registrations/index.html.haml +++ b/app/views/admin/registrations/index.html.haml @@ -7,9 +7,11 @@ = "(#{@registrations.length})" = " - Attended (#{@attended})" .btn-group.pull-right - = link_to "New", new_admin_conference_registration_path(@conference.short_title), :class => "btn btn-default" - = link_to "Export PDF", admin_conference_registrations_path(@conference.short_title, :format => :pdf), :class => "btn btn-default" - = link_to "Export XLS", {:format => :xlsx}, :class => "btn btn-default" + - if can? :create, Registration + = link_to "New", new_admin_conference_registration_path(@conference.short_title), :class => "btn btn-default" + - if can? :read, Registration + = link_to "Export PDF", admin_conference_registrations_path(@conference.short_title, :format => :pdf), :class => "btn btn-default" + = link_to "Export XLS", {:format => :xlsx}, :class => "btn btn-default" %table.table.table-bordered.table-striped.table-hover#registrations %thead %th @@ -21,7 +23,7 @@ %th %th %th - - counter = 0 + - counter = 0 - @registrations.each do |registration| %tr %td @@ -33,7 +35,7 @@ - if registration.supporter_level && registration.supporter_level.title != 'Free' %p{:style => "color:red"} = registration.supporter_level.title - + -elsif field == 'attended' = link_to "#{registration.send(field.to_sym)}", admin_conference_registrations_change_field_path(@conference.short_title, :id => registration.id, :view_field => "#{field}"), :method => :patch, ":#{field}" => registration.send(field.to_sym), :class => "btn btn-success" @@ -64,11 +66,11 @@ "bLengthChange": false } ); } ); - + function toggle(rowid) { if( document.getElementById(rowid).style.display=='none' ){ document.getElementById(rowid).style.display = ''; }else{ document.getElementById(rowid).style.display = 'none'; } - }; \ No newline at end of file + }; diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index ddd33cf8..f8278bee 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -1,8 +1,14 @@ = semantic_form_for [:admin, @user] do |f| - = f.inputs "Basic Information" do + = f.inputs 'Basic Information' do + = f.input :is_admin, hint: 'An admin can create a new conference, manage users and make other users admins.' = f.input :name, :as => :string = f.input :email - = f.input :affiliation, :as => :string - = f.input :biography, :input_html => {:rows => 10} - = f.actions do - = f.action :submit, :button_html => {:class => "btn btn-primary"} + = f.input :affiliation, as: :string + = f.input :biography, input_html: { rows: 5, "onkeyup" => "word_count(this, 'biography-count', 150)" } + You have used + %span#biography-count #{@user.biography_word_count} + words. Biographies are limited to 150 words. + %br + %br + = f.actions do + = f.action :submit, button_html: { class: 'btn btn-primary' } diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index d66a475d..a6fa2c99 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -5,7 +5,7 @@ - if @users = "(#{@users.length})" - = link_to "New User", new_admin_user_path, :class => "btn btn-success pull-right" + = link_to "New User", new_admin_user_path, class: 'btn btn-success pull-right' .well %table.table.table-striped.table-bordered.table-hover#users %thead @@ -18,7 +18,7 @@ %th %b Name %th - %b # of Conference Registrations + %b Attended Conferences %th %b Roles %th @@ -38,39 +38,24 @@ %td = user.name %td - = user.registrations.count + = user.registrations.where(attended: true).count %td - .modal.fade{:id => "user-role-selection-#{user.id}", "role" => "dialog", "aria-hidden" => "true"} - .modal-dialog - .modal-content - .modal-header - %button{"type"=>"button", :class=>"close", "data-dismiss"=>"modal", "aria-hidden"=>"true"} - × - %h3{:id => "role-selector-header-#{user.id}"} - Modifying Roles - .modal-body - - if current_user == user - You cannot modify your own role! - %br - %button{:class=> "btn btn-danger", "data-dismiss"=> "modal", "aria-hidden"=>"true"} - Cancel - - else - = "Give #{user.name} (#{user.email}) the following roles:" - = semantic_form_for(user, :url => admin_user_path(user), :method => :put) do |f| - = f.input :roles, :label => false - %button{:class=> "btn btn-danger", "data-dismiss"=> "modal", "aria-hidden"=>"true"} - Cancel - = f.action :submit, :as => :button, :button_html => {:value => "Save", :class => "btn btn-primary"} - =link_to "#{user.roles.map { |role| role.name }.join ', '}", "#", "data-toggle" => "modal", "data-target" => "#user-role-selection-#{user.id}",id: "user-modify-role-#{user.id}" - %td - = link_to "Edit", edit_admin_user_path(user) - %td - = link_to "View", admin_user_path(user) - %td - - if current_user.id == user.id or user.role_ids.include? 3 - =link_to 'Delete',admin_user_path(user), :method => :delete , :data => {:confirm => 'Are you sure ?'}, :disabled => true,:class => "btn btn-primary disabled btn-danger",:role => "button" - - else - =link_to 'Delete',admin_user_path(user), :method=> :delete , :data=> {:confirm => 'Are you sure ?'},:class => "btn btn-primary btn-danger" + - unless user.show_roles.blank? + = user.show_roles.first(2).map { |x| x[0].titleize + ' ' + x[1] }.join ', ' + - if user.show_roles.count > 2 + = '...' + - if can? :show, user + %td + = link_to "View", admin_user_path(user), class: 'btn btn-success' + - if can? :update, user + %td + = link_to "Edit", edit_admin_user_path(user), class: 'btn btn-primary' + - if can? :destroy, user + %td + - if current_user.id == user.id or user.role_ids.include? 3 + =link_to 'Delete',admin_user_path(user), :method => :delete , :data => {:confirm => 'Are you sure ?'}, :disabled => true,:class => "btn btn-primary disabled btn-danger",:role => "button" + - else + =link_to 'Delete',admin_user_path(user), :method=> :delete , :data=> {:confirm => 'Are you sure ?'},:class => "btn btn-primary btn-danger" :javascript diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index c41a6b3b..25cd9d80 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -1,7 +1,11 @@ %table.table - @show_attributes.each do |attr| %tr - %td + %td{style: 'width:20%'} %b = attr.capitalize.gsub('_', ' ') - %td= @user.send(attr) + - if attr == 'roles' + %td + = @user.show_roles.map { |x| x[0].titleize + ' ' + x[1] }.join ', ' + - else + %td= @user.send(attr) diff --git a/app/views/conference/_registration.html.haml b/app/views/conference/_registration.html.haml index acee2262..6b91ad77 100644 --- a/app/views/conference/_registration.html.haml +++ b/app/views/conference/_registration.html.haml @@ -13,7 +13,7 @@ -else %h4 Registration is Closed, it was from #{ date_string(@conference.registration_start_date, @conference.registration_end_date) } - if @conference.registration_open? - = link_to "Register for #{@conference.short_title}", register_conference_path(@conference.short_title), :class =>"btn btn-success btn-lg", target: '_blank' + = link_to "Register for #{@conference.short_title}", conference_register_path(@conference.short_title), :class =>"btn btn-success btn-lg", target: '_blank' - if @conference.use_supporter_levels? - if @conference.include_tickets_in_splash? = render 'tickets' diff --git a/app/views/conference_registration/register.html.haml b/app/views/conference_registration/register.html.haml index 13b6b568..4019ed01 100644 --- a/app/views/conference_registration/register.html.haml +++ b/app/views/conference_registration/register.html.haml @@ -1,6 +1,6 @@ .row .col-md-12 - = semantic_form_for(@registration, :url => register_conference_path(@conference.short_title), :html => { :method => :patch }) do |f| + = semantic_form_for(@registration, :url => conference_register_path(@conference.short_title), :html => { :method => :patch }) do |f| .tabbable %ul.nav.nav-tabs %li.active @@ -16,7 +16,7 @@ = render 'conference_registration/volunteer', :f => f - if @registered = f.action :submit, :button_html => { :value => "Update Registration", :class => "btn btn-primary" } - = link_to "Unregister", register_conference_path(@conference.short_title),:method => :delete, :class => "btn btn-danger", + = link_to "Unregister", conference_register_path(@conference.short_title),:method => :delete, :class => "btn btn-danger", :confirm => "Are you sure you want to unregister?" - else = f.action :submit, :button_html => { :value => "Register", :class => "btn btn-primary", id: 'register' } diff --git a/app/views/home/_conference_details.html.haml b/app/views/home/_conference_details.html.haml index 6b20c75d..22aa89ee 100644 --- a/app/views/home/_conference_details.html.haml +++ b/app/views/home/_conference_details.html.haml @@ -31,9 +31,9 @@ = link_to "View Conference", conference_path(conference.short_title), :class =>"btn btn-default" - if conference.registration_open? - if conference.user_registered?(current_user) - = link_to "Modify Registration", register_conference_path(conference.short_title), :class =>"btn btn-default" + = link_to "Modify Registration", conference_register_path(conference.short_title), :class =>"btn btn-default" - else - = link_to "Register", register_conference_path(conference.short_title), :class =>"btn btn-success" + = link_to "Register", conference_register_path(conference.short_title), :class =>"btn btn-success" = link_to "Schedule", conference_schedule_path(conference.short_title), :class =>"btn btn-default" if conference.call_for_papers and conference.call_for_papers.schedule_public - if !current_user.nil? && current_user.proposal_count(conference) > 0 = link_to "View My Proposals", conference_proposal_index_path(conference.short_title), :class =>"btn btn-default" diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml index f9b27f71..2df959ce 100644 --- a/app/views/home/index.html.haml +++ b/app/views/home/index.html.haml @@ -2,4 +2,4 @@ .col-md-12.page-header %h2.text-center Upcoming Conferences - @current.each do |conference| - = render :partial => "conference_details", :locals => {:conference => conference} \ No newline at end of file + = render :partial => "conference_details", :locals => {:conference => conference} diff --git a/app/views/layouts/_admin_sidebar.html.haml b/app/views/layouts/_admin_sidebar.html.haml index 31f8397b..2d716ebb 100644 --- a/app/views/layouts/_admin_sidebar.html.haml +++ b/app/views/layouts/_admin_sidebar.html.haml @@ -10,97 +10,129 @@ %span.glyphicon.glyphicon-home All Conferences - @conferences.each do |conference| + - if can? :show, conference + %li + = link_to(admin_conference_path(conference.short_title)) do + %span.glyphicon.glyphicon-cog + Manage + = conference.short_title + - if (current_user.is_admin) || (current_user.has_role? :organizer, :any) %li - = link_to(admin_conference_path(conference.short_title)) do - %span.glyphicon.glyphicon-cog - Manage - = conference.short_title - %li - = link_to(new_admin_conference_path) do - %span.glyphicon.glyphicon-plus - New Conference + = link_to(new_admin_conference_path) do + %span.glyphicon.glyphicon-plus + New Conference %hr - %li{:class=> "#{active_nav_li(admin_conference_path(@conference.short_title))} nav-header nav-header-bigger"} - = link_to(admin_conference_path(@conference.short_title)) do - %span.fa.fa-tachometer - Dashboard - %li{:class=> "#{active_nav_li(edit_admin_conference_path(@conference.short_title))}"} - = link_to(edit_admin_conference_path(@conference.short_title)) do - %span.fa.fa-home - Basics - %ul - %li{:class=> "#{active_nav_li(edit_admin_conference_contact_path(@conference.short_title))}"} - = link_to(edit_admin_conference_contact_path(@conference.short_title)) do - %span.fa.fa-envelope-o - Contact - %li{:class=> "#{active_nav_li(admin_conference_commercials_path(@conference.short_title))}"} - = link_to(admin_conference_commercials_path(@conference.short_title)) do - %span.fa.fa-film - Commercials - %li{:class=> "#{active_nav_li(admin_conference_photos_path(@conference.short_title))}"} - = link_to(admin_conference_photos_path(@conference.short_title)) do - %span.fa.fa-picture-o - Photos - %li{:class=> active_nav_li(admin_conference_events_path(@conference.short_title))} - = link_to(admin_conference_events_path(@conference.short_title)) do - %span.glyphicon.glyphicon-comment - Events - %li{:class=> active_nav_li(admin_conference_registrations_path(@conference.short_title))} - = link_to(admin_conference_registrations_path(@conference.short_title)) do - %span.glyphicon.glyphicon-user - Registrations - %li{class: active_nav_li(admin_conference_schedule_path(@conference.short_title))} - = link_to(admin_conference_schedule_path(@conference.short_title), target: '_blank') do - %span.glyphicon.glyphicon-calendar - Schedule - %li{class: active_nav_li(admin_conference_campaigns_path(@conference.short_title))} - = link_to(admin_conference_campaigns_path(@conference.short_title)) do - %span.glyphicon.glyphicon-bullhorn - Campaigns + - if can? :show, @conference + %li{:class=> "#{active_nav_li(admin_conference_path(@conference.short_title))} nav-header nav-header-bigger"} + = link_to(admin_conference_path(@conference.short_title)) do + %span.fa.fa-tachometer + Dashboard + - if can? :update, @conference + %li{:class=> "#{active_nav_li(edit_admin_conference_path(@conference.short_title))}"} + = link_to(edit_admin_conference_path(@conference.short_title)) do + %span.fa.fa-home + Basics + - if can? :update, Contact.new(conference_id: @conference.id) + %ul + %li{:class=> "#{active_nav_li(edit_admin_conference_contact_path(@conference.short_title))}"} + = link_to(edit_admin_conference_contact_path(@conference.short_title)) do + %span.fa.fa-envelope-o + Contact + - if can? :index, @conference.commercials.build + %li{:class=> "#{active_nav_li(admin_conference_commercials_path(@conference.short_title))}"} + = link_to(admin_conference_commercials_path(@conference.short_title)) do + %span.fa.fa-film + Commercials + - if can? :update, @conference.photos.build + %li{:class=> "#{active_nav_li(admin_conference_photos_path(@conference.short_title))}"} + = link_to(admin_conference_photos_path(@conference.short_title)) do + %span.fa.fa-picture-o + Photos + - if can? :update, @conference.events.build + %li{:class=> active_nav_li(admin_conference_events_path(@conference.short_title))} + = link_to(admin_conference_events_path(@conference.short_title)) do + %span.glyphicon.glyphicon-comment + Events + - if can? :update, Registration.new(conference_id: @conference.id) + %li{:class=> active_nav_li(admin_conference_registrations_path(@conference.short_title))} + = link_to(admin_conference_registrations_path(@conference.short_title)) do + %span.glyphicon.glyphicon-user + Registrations + - if can? :update, @conference.events.build + %li{class: active_nav_li(admin_conference_schedule_path(@conference.short_title))} + = link_to(admin_conference_schedule_path(@conference.short_title), target: '_blank') do + %span.glyphicon.glyphicon-calendar + Schedule + - if can? :update, @conference + %li{class: active_nav_li(admin_conference_campaigns_path(@conference.short_title))} + = link_to(admin_conference_campaigns_path(@conference.short_title)) do + %span.glyphicon.glyphicon-bullhorn + Campaigns %hr - %li{:class=> "#{active_nav_li(admin_conference_targets_path(@conference.short_title))}"} - = link_to(admin_conference_targets_path(@conference.short_title)) do - %span.glyphicon.glyphicon-flag - Targets - %li{:class=> "#{active_nav_li(admin_conference_venue_info_path(@conference.short_title))} myAccordion"} - = link_to(admin_conference_venue_info_path(@conference.short_title)) do - %span.glyphicon.glyphicon-road - Venue - %span.small.glyphicon.glyphicon-chevron-right - %ul.nav.nav-stacked.nav-pills.small.collapse.subNav - %li{:class=> active_nav_li(admin_conference_rooms_path(@conference.short_title))} - = link_to 'Rooms', admin_conference_rooms_path(@conference.short_title) - %li{ class: active_nav_li(admin_conference_lodgings_path(@conference.short_title)) } - = link_to 'Lodgings', admin_conference_lodgings_path(@conference.short_title) - %li{:class=> "#{active_nav_li(admin_conference_sponsorship_levels_path(@conference.short_title))} myAccordion" } - = link_to(admin_conference_sponsorship_levels_path(@conference.short_title)) do - %span.glyphicon.glyphicon-star - Sponsorship - %span.small.glyphicon.glyphicon-chevron-right - %ul.nav.nav-stacked.nav-pills.small.collapse.subNav - %li{:class=> active_nav_li(admin_conference_sponsors_path(@conference.short_title))} - = link_to 'Sponsors', admin_conference_sponsors_path(@conference.short_title) - %li{ class: active_nav_li(admin_conference_supporter_levels_path(@conference.short_title)) } - = link_to(admin_conference_supporter_levels_path(@conference.short_title)) do - %span.glyphicon.glyphicon-usd - Supporter Levels - %li{:class=> active_nav_li(admin_conference_emails_path(@conference.short_title))} - = link_to(admin_conference_emails_path(@conference.short_title)) do - %span.glyphicon.glyphicon-envelope - E-Mails - %li{:class=> "#{active_nav_li(admin_conference_callforpapers_path(@conference.short_title))} myAccordion"} - = link_to(admin_conference_callforpapers_path(@conference.short_title)) do - %span.glyphicon.glyphicon-comment - Call for papers - %span.small.glyphicon.glyphicon-chevron-right - %ul.nav.nav-stacked.nav-pills.small.collapse.subNav - %li{:class=> active_nav_li(admin_conference_tracks_path(@conference.short_title))} - = link_to 'Tracks', admin_conference_tracks_path(@conference.short_title) - %li{:class=> active_nav_li(admin_conference_eventtypes_path(@conference.short_title))} - = link_to 'Event types', admin_conference_eventtypes_path(@conference.short_title) - %li{:class=> active_nav_li(admin_conference_difficulty_levels_path(@conference.short_title))} - = link_to 'Difficulty levels', admin_conference_difficulty_levels_path(@conference.short_title) + - if can? :update, @conference + %li{:class=> "#{active_nav_li(edit_admin_conference_path(@conference.short_title))} nav-header nav-header-bigger"} + = link_to(edit_admin_conference_path(@conference.short_title)) do + %span.glyphicon.glyphicon-cog + Settings + - if can? :update, @conference.targets.build + %li{:class=> "#{active_nav_li(admin_conference_targets_path(@conference.short_title))}"} + = link_to(admin_conference_targets_path(@conference.short_title)) do + %span.glyphicon.glyphicon-flag + Targets + - if can? :index, @conference.venue + %li{:class=> "#{active_nav_li(admin_conference_venue_info_path(@conference.short_title))} myAccordion"} + = link_to(admin_conference_venue_info_path(@conference.short_title)) do + %span.glyphicon.glyphicon-road + Venue + %span.small.glyphicon.glyphicon-chevron-right + %ul.nav.nav-stacked.nav-pills.small.collapse.subNav + - if can? :update, @conference.rooms.build + %li{:class=> active_nav_li(admin_conference_rooms_path(@conference.short_title))} + = link_to 'Rooms', admin_conference_rooms_path(@conference.short_title) + - if can? :update, @conference.venue.lodgings.build + %li{ class: active_nav_li(admin_conference_lodgings_path(@conference.short_title)) } + = link_to 'Lodgings', admin_conference_lodgings_path(@conference.short_title) + - if can? :update, @conference.sponsorship_levels.build + %li{:class=> "#{active_nav_li(admin_conference_sponsorship_levels_path(@conference.short_title))} myAccordion" } + = link_to(admin_conference_sponsorship_levels_path(@conference.short_title)) do + %span.glyphicon.glyphicon-star + Sponsorship + %span.small.glyphicon.glyphicon-chevron-right + %ul.nav.nav-stacked.nav-pills.small.collapse.subNav + - if can? :update, @conference.sponsors.build + %li{:class=> active_nav_li(admin_conference_sponsors_path(@conference.short_title))} + = link_to 'Sponsors', admin_conference_sponsors_path(@conference.short_title) + - if can? :update, @conference.supporter_levels.build + %li{ class: active_nav_li(admin_conference_supporter_levels_path(@conference.short_title)) } + = link_to(admin_conference_supporter_levels_path(@conference.short_title)) do + %span.glyphicon.glyphicon-usd + Supporter Levels + - if can? :update, @conference.email_settings + %li{:class=> active_nav_li(admin_conference_emails_path(@conference.short_title))} + = link_to(admin_conference_emails_path(@conference.short_title)) do + %span.glyphicon.glyphicon-envelope + E-Mails + - if can? :update, CallForPapers.new(conference_id: @conference.id) + %li{:class=> "#{active_nav_li(admin_conference_callforpapers_path(@conference.short_title))} myAccordion"} + = link_to(admin_conference_callforpapers_path(@conference.short_title)) do + %span.glyphicon.glyphicon-comment + Call for papers + %span.small.glyphicon.glyphicon-chevron-right + %ul.nav.nav-stacked.nav-pills.small.collapse.subNav + - if can? :update, @conference.tracks.build + %li{:class=> active_nav_li(admin_conference_tracks_path(@conference.short_title))} + = link_to 'Tracks', admin_conference_tracks_path(@conference.short_title) + - if can? :update, @conference.event_types.build + %li{:class=> active_nav_li(admin_conference_event_types_path(@conference.short_title))} + = link_to 'Event types', admin_conference_event_types_path(@conference.short_title) + - if can? :update, @conference.difficulty_levels.build, conference_id: @conference.id + %li{:class=> active_nav_li(admin_conference_difficulty_levels_path(@conference.short_title))} + = link_to 'Difficulty levels', admin_conference_difficulty_levels_path(@conference.short_title) + - if can? :update, Question.new(conference_id: @conference.id) %li{:class=> active_nav_li(admin_conference_questions_path(@conference.short_title))} = link_to(admin_conference_questions_path(@conference.short_title)) do %span.glyphicon.glyphicon-question-sign Questions + - if can? :manage, @conference + %li{:class=> active_nav_li(roles_admin_conference_path(@conference.short_title))} + = link_to 'Roles', roles_admin_conference_path(@conference.short_title) diff --git a/app/views/layouts/_admin_sidebar_index.html.haml b/app/views/layouts/_admin_sidebar_index.html.haml index a5f4191c..219d0a56 100644 --- a/app/views/layouts/_admin_sidebar_index.html.haml +++ b/app/views/layouts/_admin_sidebar_index.html.haml @@ -10,17 +10,20 @@ %span.glyphicon.glyphicon-home All Conferences - @conferences.each do |conference| + - if can? :show, conference + %li + = link_to(admin_conference_path(conference.short_title)) do + %span.glyphicon.glyphicon-cog + Manage + = conference.short_title + - if (current_user.is_admin) || (current_user.has_role? :organizer, :any) %li - = link_to(admin_conference_path(conference.short_title)) do - %span.glyphicon.glyphicon-cog - Manage - = conference.short_title - %li - = link_to(new_admin_conference_path) do - %span.glyphicon.glyphicon-plus - New Conference - %hr - %li - = link_to(admin_users_path) do - %span.glyphicon.glyphicon-user - Users + = link_to(new_admin_conference_path) do + %span.glyphicon.glyphicon-plus + New Conference + - if can? :index, User + %hr + %li + = link_to(admin_users_path) do + %span.glyphicon.glyphicon-user + Users diff --git a/app/views/layouts/_user_menu.html.haml b/app/views/layouts/_user_menu.html.haml index bfcbfa6f..3662a129 100644 --- a/app/views/layouts/_user_menu.html.haml +++ b/app/views/layouts/_user_menu.html.haml @@ -11,13 +11,13 @@ = link_to(destroy_user_session_path, :method=>'delete') do %span.glyphicon.glyphicon-minus Sign out --if has_role?(current_user, "admin") || has_role?(current_user, "organizer") +- if can? :index, Conference %li.divider %li = link_to(admin_conference_index_path()) do %span.glyphicon.glyphicon-home Administration - -if @conference and @conference.id + -if @conference and @conference.id and can? :show, @conference %li = link_to(admin_conference_path(@conference.short_title)) do %span.glyphicon.glyphicon-cog diff --git a/app/views/proposal/_form.html.haml b/app/views/proposal/_form.html.haml index 1a088ed7..b30497e4 100644 --- a/app/views/proposal/_form.html.haml +++ b/app/views/proposal/_form.html.haml @@ -26,11 +26,14 @@ = commercial.commercial_type .flexvideo = render partial: 'shared/media_item', locals: { commercial_type: commercial.commercial_type, commercial_id: commercial.commercial_id } - = link_to 'Edit', edit_conference_proposal_commercial_path(@conference.short_title, @event.id, commercial.id), class: 'btn btn-primary' - = link_to 'Delete', conference_proposal_commercial_path(@conference.short_title, @event.id, commercial.id), + - if can? :update, commercial + = link_to 'Edit', edit_conference_proposal_commercial_path(@conference.short_title, @event.id, commercial.id), class: 'btn btn-primary' + - if can? :destrooy, commercial + = link_to 'Delete', conference_proposal_commercial_path(@conference.short_title, @event.id, commercial.id), :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-danger' - %hr - = link_to 'Add Commercial', new_conference_proposal_commercial_path(@conference.short_title, @event.id), class: 'btn btn-primary' + - if can? :create, @event.commercials.new + %hr + = link_to 'Add Commercial', new_conference_proposal_commercial_path(@conference.short_title, @event.id), class: 'btn btn-primary' #attachment-content.tab-pane = form_for EventAttachment.new, :url => conference_proposal_event_attachment_index_path(@conference.short_title, @event), :html => { :multipart => true, :id => "fileupload" } do |f| @@ -68,7 +71,7 @@ data.formData = inputs.serializeArray(); }); $.getJSON($('#fileupload').prop('action'), function (files) { - var fu = $('#fileupload').data('fileupload'), + var fu = $('#fileupload').data('blueimpFileupload'), template; fu._adjustMaxNumberOfFiles(-files.length); template = fu._renderDownload(files) diff --git a/app/views/proposal/_proposal_form.html.haml b/app/views/proposal/_proposal_form.html.haml index 748bd445..d1174766 100644 --- a/app/views/proposal/_proposal_form.html.haml +++ b/app/views/proposal/_proposal_form.html.haml @@ -1,20 +1,20 @@ = semantic_form_for(@event, :url => @url) do |f| %section#basic = f.inputs :name => "Session Information" do - - if !@conference.call_for_papers.schedule_changes && @event.state == "confirmed" && !organizer_or_admin? + - if can? :update, @event or can? :create, @event + = f.input :title, :as => :string, :required => true + - else Title: #{@event.title} %br %br - - else - = f.input :title, :as => :string, :required => true = f.input :subtitle, :as => :string %section#details - - if (@event.state === "unconfirmed" || @event.state === "confirmed") && !organizer_or_admin? && !@conference.call_for_papers.schedule_changes + - if can? :update, @event or can? :create, @event + = f.input :event_type_id,:as => :select, :collection => @conference.event_types.map {|x| ["#{x.title} - #{show_time(x.length)}", x.id]}, :include_blank => false, :label => "Session Type" + - else Event type: #{@event.event_type.title} %br %br - - else - = f.input :event_type_id,:as => :select, :collection => @conference.event_types.map {|x| ["#{x.title} - #{show_time(x.length)}", x.id]}, :include_blank => false, :label => "Session Type" = f.input :difficulty_level, :as => :select, :collection => @conference.difficulty_levels, :include_blank => "(Please select)" if @conference.use_difficulty_levels = f.input :require_registration = f.input :abstract, :input_html => {:rows => 5, :class => "span11"}, diff --git a/app/views/proposal/index.html.haml b/app/views/proposal/index.html.haml index 96c8a4fc..bf53ab15 100644 --- a/app/views/proposal/index.html.haml +++ b/app/views/proposal/index.html.haml @@ -2,7 +2,7 @@ .col-md-12.page-header %h1 = "My Proposals for #{@conference.title}" - - if @conference.cfp_open? || organizer_or_admin? + - if @conference.cfp_open? || (current_user.has_role? :organizer, @conference) = link_to "New Proposal", new_conference_proposal_path(@conference.short_title), :class => "btn btn-success pull-right" - if current_user.proposal_count(@conference) > 0 .row @@ -27,7 +27,7 @@ (Pre-registered: #{pre_registered(event).count}) - if event.confirmed? && !@conference.user_registered?(current_user) %br - = link_to "Register to attend", register_conference_path(@conference.short_title), :style => "font-size:10px;" + = link_to "Register to attend", conference_register_path(@conference.short_title), :style => "font-size:10px;" %td .pull-right - if event.transition_possible? :confirm diff --git a/app/views/proposal/new.html.haml b/app/views/proposal/new.html.haml index a6325a98..69e5bf4e 100644 --- a/app/views/proposal/new.html.haml +++ b/app/views/proposal/new.html.haml @@ -1,6 +1,6 @@ .row .col-md-12 - = simple_format(@conference.call_for_papers.description) + = simple_format(@conference.call_for_papers.description) if @conference.call_for_papers .row .col-md-12 = render 'proposal_form' diff --git a/app/views/proposal/show.html.haml b/app/views/proposal/show.html.haml index 167976db..26e474d8 100644 --- a/app/views/proposal/show.html.haml +++ b/app/views/proposal/show.html.haml @@ -7,7 +7,7 @@ %small = @event.subtitle = link_to "Schedule", conference_schedule_path(@conference.short_title), :class =>"btn btn-success pull-right" - - if has_role?(current_user, "admin") + - if can? :edit, @event = link_to "Edit", edit_admin_conference_event_path(@conference.short_title, @event), :class => "btn btn-mini btn-primary pull-right" .row .col-md-3 @@ -37,7 +37,7 @@ %span.label{:style =>"background-color: #{@event.difficulty_level.color};"} = @event.difficulty_level.title - if @event.require_registration - = link_to "Registration required!", register_conference_path(@conference.short_title), :class => "btn btn-xs btn-warning" + = link_to "Registration required!", conference_register_path(@conference.short_title), :class => "btn btn-xs btn-warning" .col-md-9 .row .col-md-12 diff --git a/config/initializers/rolify.rb b/config/initializers/rolify.rb new file mode 100644 index 00000000..30651dd0 --- /dev/null +++ b/config/initializers/rolify.rb @@ -0,0 +1,8 @@ +Rolify.configure do |config| + # By default ORM adapter is ActiveRecord. uncomment to use mongoid + # config.use_mongoid + + # Dynamic shortcuts for User class (user.is_admin? like methods). Default is: false + # Enable this feature _after_ running rake db:migrate as it relies on the roles table + config.use_dynamic_shortcuts +end diff --git a/config/routes.rb b/config/routes.rb index bce18686..9e84de26 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,8 +8,13 @@ Osem::Application.routes.draw do resources :users resources :people resources :conference do - resource :contact, except: [:index, :new, :create, :show, :destroy] - resources :photos, except: [:show] + member do + get :roles + post :roles + post :add_user + delete :remove_user + end + resource :contact, except: [:index, :new, :create] resource :schedule, only: [:show, :update] resources :commercials, except: [:show] get '/stats' => 'stats#index' @@ -40,7 +45,7 @@ Osem::Application.routes.draw do resources :campaigns - resources :eventtypes, only: [:show, :index] do + resources :event_types, only: [:show, :index] do collection do patch :update end @@ -92,10 +97,10 @@ Osem::Application.routes.draw do resource :schedule, only: [] do get "/" => "schedule#index" end + get "/register" => "conference_registration#register" + patch "/register" => "conference_registration#update" + delete "/register" => "conference_registration#unregister" member do - get "/register" => "conference_registration#register" - patch "/register" => "conference_registration#update" - delete "/register" => "conference_registration#unregister" get "gallery_photos" patch "subscription" => "conference#subscribe" delete "subscription" => "conference#unsubscribe" diff --git a/db/migrate/20140711072651_add_description_and_resource_to_roles.rb b/db/migrate/20140711072651_add_description_and_resource_to_roles.rb new file mode 100644 index 00000000..8e5a16ec --- /dev/null +++ b/db/migrate/20140711072651_add_description_and_resource_to_roles.rb @@ -0,0 +1,10 @@ +class AddDescriptionAndResourceToRoles < ActiveRecord::Migration + def change + add_column :roles, :description, :string + add_reference :roles, :resource, polymorphic: true + + add_index(:roles, :name) + add_index(:roles, [:name, :resource_type, :resource_id]) + add_index(:roles_users, [:user_id, :role_id]) + end +end diff --git a/db/migrate/20140718103856_add_is_admin_to_users.rb b/db/migrate/20140718103856_add_is_admin_to_users.rb new file mode 100644 index 00000000..def2bbb0 --- /dev/null +++ b/db/migrate/20140718103856_add_is_admin_to_users.rb @@ -0,0 +1,5 @@ +class AddIsAdminToUsers < ActiveRecord::Migration + def change + add_column :users, :is_admin, :boolean + end +end diff --git a/db/schema.rb b/db/schema.rb index b21c54c0..8cbc8109 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -363,15 +363,23 @@ ActiveRecord::Schema.define(version: 20140801170430) do create_table "roles", force: true do |t| t.string "name" + t.string "description" + t.integer "resource_id" + t.string "resource_type" t.datetime "created_at" t.datetime "updated_at" end + add_index "roles", ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id" + add_index "roles", ["name"], name: "index_roles_on_name" + create_table "roles_users", id: false, force: true do |t| t.integer "role_id" t.integer "user_id" end + add_index "roles_users", ["user_id", "role_id"], name: "index_roles_users_on_user_id_and_role_id" + create_table "rooms", force: true do |t| t.string "guid", null: false t.integer "conference_id" @@ -484,6 +492,7 @@ ActiveRecord::Schema.define(version: 20140801170430) do t.string "tshirt" t.string "languages" t.text "volunteer_experience" + t.boolean "is_admin" end add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true diff --git a/db/seeds.rb b/db/seeds.rb index 92d873a8..8294f19c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -5,18 +5,18 @@ # # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) # Mayor.create(name: 'Emanuel', city: cities.first) -Role.create(name: "Participant") -Role.create(name: "Organizer") -Role.create(name: "Admin") -qtype_yesno = QuestionType.create(title: "Yes/No") -QuestionType.create(title: "Single Choice") -QuestionType.create(title: "Multiple Choice") +# Questions +qtype_yesno = QuestionType.create(title: 'Yes/No') +qtype_single = QuestionType.create(title: 'Single Choice') +qtype_multiple = QuestionType.create(title: 'Multiple Choice') -answer_yes = Answer.create(title: "Yes") -answer_no = Answer.create(title: "No") +answer_yes = Answer.create(title: 'Yes') +answer_no = Answer.create(title: 'No') -questions_yes_no = ["Do you need handicapped access to the venue?", "Are you attending with partner?", "Will you attend the social event(s)?", "Will you stay at suggested hotel?"] +questions_yes_no = ['Do you need handicapped access to the venue?', + 'Are you attending with partner?', 'Will you attend the social event(s)?', + 'Will you stay at suggested hotel?'] questions_yes_no.each do |i| q = Question.create(title: i, question_type_id: qtype_yesno.id, global: true) diff --git a/spec/controllers/admin/conferences_controller_spec.rb b/spec/controllers/admin/conferences_controller_spec.rb index e3286fa0..18eba58a 100644 --- a/spec/controllers/admin/conferences_controller_spec.rb +++ b/spec/controllers/admin/conferences_controller_spec.rb @@ -3,16 +3,15 @@ require 'spec_helper' describe Admin::ConferenceController do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } - let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } - let(:conference) { create(:conference) } - let(:admin) { create(:admin) } - let(:organizer) { create(:organizer) } + let!(:first_user) { create(:user) } + let!(:participant_role) { create(:participant_role) } + let!(:organizer_role) { create(:role, name: 'organizer', resource: conference) } + + let(:organizer) { create(:user, role_ids: organizer_role.id, is_admin: true) } let(:participant) { create(:participant) } - shared_examples 'access as administration or organizer' do + shared_examples 'access as administration' do describe 'PATCH #update' do @@ -45,8 +44,7 @@ describe Admin::ConferenceController do mailer = double allow(mailer).to receive(:deliver) conference.email_settings = create(:email_settings) - patch :update, id: conference.short_title, conference: - attributes_for(:conference, start_date: Date.today + 2.days, end_date: Date.today + 4.days) + patch :update, id: conference.short_title#, conference: attributes_for(:conference, start_date: Date.today + 2.days, end_date: Date.today + 4.days) conference.reload allow(Mailbot).to receive(:conference_date_update_mail).and_return(mailer) end @@ -193,8 +191,12 @@ describe Admin::ConferenceController do context 'no conferences' do it 'redirect to new conference' do + Conference.all.each do |c| + c.destroy + end + sign_in create(:admin) get :index - expect(response).to redirect_to(redirect_to new_admin_conference_path) + expect(response).to redirect_to new_admin_conference_path end end end @@ -215,59 +217,64 @@ describe Admin::ConferenceController do describe 'administrator access' do before do - sign_in(admin) - end - - it_behaves_like 'access as administration or organizer' - - end - - describe 'organizer access' do - - before(:each) do sign_in(organizer) end - it_behaves_like 'access as administration or organizer' + it_behaves_like 'access as administration' end - shared_examples 'access as participant or guest' do |success_path| + shared_examples 'access as participant or guest' do |path, message| describe 'GET #show' do - it 'requires admin privileges' do + it 'requires organizer privileges' do get :show, id: conference.short_title - expect(response).to redirect_to(send(success_path)) + expect(response).to redirect_to(send(path)) + if message + expect(flash[:alert]).to match(/#{message}/) + end end end describe 'GET #index' do - it 'requires admin privileges' do + it 'requires organizer privileges' do get :index - expect(response).to redirect_to(send(success_path)) + expect(response).to redirect_to(send(path)) + if message + expect(flash[:alert]).to match(/#{message}/) + end end end describe 'GET #new' do - it 'requires admin privileges' do + it 'requires organizer privileges' do get :new - expect(response).to redirect_to(send(success_path)) + expect(response).to redirect_to(send(path)) + if message + expect(flash[:alert]).to match(/#{message}/) + end end end describe 'POST #create' do - it 'requires admin privileges' do + it 'requires organizer privileges' do post :create, conference: attributes_for(:conference, short_title: 'ExCon') - expect(response).to redirect_to(send(success_path)) + expect(response).to redirect_to(send(path)) + if message + expect(flash[:alert]).to match(/#{message}/) + end end end describe 'PATCH #update' do - it 'requires admin privileges' do + it 'requires organizer privileges' do patch :update, id: conference.short_title, conference: attributes_for(:conference, short_title: 'ExCon') - expect(response).to redirect_to(send(success_path)) + expect(response).to redirect_to(send(path)) + if message + expect(flash[:alert]).to match(/#{message}/) + end end end end @@ -277,7 +284,7 @@ describe Admin::ConferenceController do sign_in(participant) end - it_behaves_like 'access as participant or guest', :root_path + it_behaves_like 'access as participant or guest', :root_path, 'You are not authorized to access this area!' end diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index e3f64829..97d11d81 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -1,7 +1,5 @@ require 'spec_helper' describe Admin::UsersController do - let!(:admin_role) { create(:admin_role) } - let!(:participant_role) { create(:participant_role) } let(:admin) { create(:admin) } let(:user) { create(:user) } before(:each) do @@ -31,13 +29,13 @@ describe Admin::UsersController do :user, email: 'example@incoherent.de', id: user.id).email). to eq('example@incoherent.de') end - it "redirects to the updated user" do + it 'redirects to the updated user' do patch :update, id: user.id expect(response).to redirect_to admin_users_path end end end - describe 'DELETE #destroy' do + describe 'DELETE #destroy' do before :each do @user = create(:user) end diff --git a/spec/controllers/conference_controller_spec.rb b/spec/controllers/conference_controller_spec.rb index 23454ec5..90747dd3 100644 --- a/spec/controllers/conference_controller_spec.rb +++ b/spec/controllers/conference_controller_spec.rb @@ -1,7 +1,8 @@ require 'spec_helper' describe ConferenceController do - let(:conference) { create(:conference) } + let(:conference) { create(:conference, make_conference_public: true) } + describe 'GET #show' do context 'conference made public' do it 'assigns the requested conference to conference' do @@ -24,7 +25,7 @@ describe ConferenceController do it 'renders flash saying conference not ready' do get :show, id: conference.short_title - expect(flash[:notice]).to eq("Conference not ready yet!!") + expect(flash[:alert]).to eq('You are not authorized to access this page.') end end context 'gallery photos for splash' do diff --git a/spec/factories/commercials.rb b/spec/factories/commercials.rb new file mode 100644 index 00000000..7ebfd744 --- /dev/null +++ b/spec/factories/commercials.rb @@ -0,0 +1,8 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :commercial do + commercial_type 'YouTube' + commercial_id 'test' + end +end diff --git a/spec/factories/roles.rb b/spec/factories/roles.rb index 6d56375f..19ec8969 100644 --- a/spec/factories/roles.rb +++ b/spec/factories/roles.rb @@ -1,16 +1,18 @@ FactoryGirl.define do factory :role do - factory :admin_role do - name 'Admin' + factory :participant_role do + name 'participant' end factory :organizer_role do - name 'Organizer' + name 'organizer' end - factory :participant_role do - name 'Participant' + factory :organizer_conference_1_role do + name 'organizer' + resource_type 'Conference' + resource_id 1 end end end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 7ab2b62c..5b029441 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -19,12 +19,12 @@ FactoryGirl.define do after(:create) { |user| user.role_ids = create(:participant_role).id } end - factory :admin do - after(:create) { |user| user.role_ids = create(:admin_role).id } + factory :organizer_conference_1 do + after(:create) { |user| user.role_ids = create(:organizer_conference_1_role).id } end - factory :organizer do - after(:create) { |user| user.role_ids = create(:organizer_role).id } + factory :admin do + is_admin true end end end diff --git a/spec/features/ability_spec.rb b/spec/features/ability_spec.rb new file mode 100644 index 00000000..75679ee2 --- /dev/null +++ b/spec/features/ability_spec.rb @@ -0,0 +1,266 @@ +require 'spec_helper' + +feature 'Has correct abilities' do + # It is necessary to use bang version of let to build roles before user + let(:conference1) { create(:conference) } # user is organizer + let(:conference2) { create(:conference) } # user is cfp + let(:conference3) { create(:conference) } # user is info_desk + let(:conference4) { create(:conference) } # user is volunteer coordinator + let(:conference5) { create(:conference) } # user has no role + + let(:role_organizer) { create(:role, name: 'organizer', resource: conference1) } + let(:role_cfp) { create(:role, name: 'cfp', resource: conference2) } + let(:role_info_desk) { create(:role, name: 'info_desk', resource: conference3) } + let(:role_volunteer_coordinator) { create(:role, name: 'volunteer_coordinator', resource: conference4) } + + let(:user) { create(:user, role_ids: [role_organizer.id, role_cfp.id, role_info_desk.id, role_volunteer_coordinator.id]) } + + scenario 'when user is organizer' do + sign_in user + visit admin_conference_path(conference1.short_title) + + expect(page.has_content?('Settings')).to be true + expect(page.has_content?('Manage')).to be true + expect(page.has_content?('Registrations')).to be true + expect(page.has_content?('Events')).to be true + expect(page.has_content?('Schedule')).to be true + expect(page.has_content?('Campaigns')).to be true + expect(page.has_content?('Targets')).to be true + expect(page.has_content?('Venue')).to be true + expect(page.has_content?('Sponsorship')).to be true + expect(page.has_content?('Supporter Levels')).to be true + expect(page.has_content?('E-Mails')).to be true + expect(page.has_content?('Call for papers')).to be true + expect(page.has_content?('Questions')).to be true + expect(page.has_content?('Commercials')).to be true + + visit edit_admin_conference_path(conference1.short_title) + expect(current_path).to eq(edit_admin_conference_path(conference1.short_title)) + + visit admin_conference_path(conference1.short_title) + expect(current_path).to eq(admin_conference_path(conference1.short_title)) + + visit admin_conference_registrations_path(conference1.short_title) + expect(current_path).to eq(admin_conference_registrations_path(conference1.short_title)) + + visit admin_conference_events_path(conference1.short_title) + expect(current_path).to eq(admin_conference_events_path(conference1.short_title)) + + visit admin_conference_schedule_path(conference1.short_title) + expect(current_path).to eq(admin_conference_schedule_path(conference1.short_title)) + + visit admin_conference_campaigns_path(conference1.short_title) + expect(current_path).to eq(admin_conference_campaigns_path(conference1.short_title)) + + visit admin_conference_targets_path(conference1.short_title) + expect(current_path).to eq(admin_conference_targets_path(conference1.short_title)) + + visit admin_conference_venue_info_path(conference1.short_title) + expect(current_path).to eq(admin_conference_venue_info_path(conference1.short_title)) + + visit admin_conference_sponsorship_levels_path(conference1.short_title) + expect(current_path).to eq(admin_conference_sponsorship_levels_path(conference1.short_title)) + + visit admin_conference_supporter_levels_path(conference1.short_title) + expect(current_path).to eq(admin_conference_supporter_levels_path(conference1.short_title)) + + visit admin_conference_emails_path(conference1.short_title) + expect(current_path).to eq(admin_conference_emails_path(conference1.short_title)) + + visit admin_conference_callforpapers_path(conference1.short_title) + expect(current_path).to eq(admin_conference_callforpapers_path(conference1.short_title)) + + visit admin_conference_questions_path(conference1.short_title) + expect(current_path).to eq(admin_conference_questions_path(conference1.short_title)) + + visit admin_conference_commercials_path(conference1.short_title) + expect(current_path).to eq(admin_conference_commercials_path(conference1.short_title)) + end + + scenario 'when user is cfp' do + sign_in user + visit admin_conference_path(conference2.short_title) + + expect(page.has_content?('Settings')).to be false + expect(page.has_content?('Manage')).to be true +# expect(page.has_content?('Registrations')).to be false + expect(page.has_content?('Events')).to be true + expect(page.has_content?('Schedule')).to be true +# expect(page.has_content?('Campaigns')).to be false + expect(page.has_content?('Targets')).to be false + expect(page.has_content?('Venue')).to be true + expect(page.has_content?('Sponsorship')).to be false + expect(page.has_content?('Supporter Levels')).to be false + expect(page.has_content?('E-Mails')).to be true + expect(page.has_content?('Call for papers')).to be true + expect(page.has_content?('Questions')).to be false + expect(page.has_content?('Commercials')).to be true + + visit edit_admin_conference_path(conference2.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_path(conference2.short_title) + expect(current_path).to eq(admin_conference_path(conference2.short_title)) + + visit admin_conference_registrations_path(conference2.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_events_path(conference2.short_title) + expect(current_path).to eq(admin_conference_events_path(conference2.short_title)) + + visit admin_conference_schedule_path(conference2.short_title) + expect(current_path).to eq(admin_conference_schedule_path(conference2.short_title)) + + visit admin_conference_campaigns_path(conference2.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_targets_path(conference2.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_venue_info_path(conference2.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_sponsorship_levels_path(conference2.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_supporter_levels_path(conference2.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_emails_path(conference2.short_title) + expect(current_path).to eq(admin_conference_emails_path(conference2.short_title)) + + visit admin_conference_callforpapers_path(conference2.short_title) + expect(current_path).to eq(admin_conference_callforpapers_path(conference2.short_title)) + + visit admin_conference_questions_path(conference2.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_commercials_path(conference3.short_title) + expect(current_path).to eq(admin_conference_commercials_path(conference3.short_title)) + end + + scenario 'when user is info desk' do + sign_in user + visit admin_conference_path(conference3.short_title) + + expect(page.has_content?('Settings')).to be false + expect(page.has_content?('Manage')).to be true + expect(page.has_content?('Registrations')).to be true + expect(page.has_content?('Events')).to be false + expect(page.has_content?('Schedule')).to be false +# expect(page.has_content?('Campaigns')).to be false + expect(page.has_content?('Targets')).to be false + expect(page.has_content?('Venue')).to be false + expect(page.has_content?('Sponsorship')).to be false + expect(page.has_content?('Supporter Levels')).to be false + expect(page.has_content?('E-Mails')).to be false + expect(page.has_content?('Call for papers')).to be false + expect(page.has_content?('Questions')).to be true + expect(page.has_content?('Commercials')).to be true + + visit edit_admin_conference_path(conference3.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_path(conference3.short_title) + expect(current_path).to eq(admin_conference_path(conference3.short_title)) + + visit admin_conference_registrations_path(conference3.short_title) + expect(current_path).to eq(admin_conference_registrations_path(conference3.short_title)) + + visit admin_conference_events_path(conference3.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_schedule_path(conference3.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_campaigns_path(conference3.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_targets_path(conference3.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_venue_info_path(conference3.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_sponsorship_levels_path(conference3.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_supporter_levels_path(conference3.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_emails_path(conference3.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_callforpapers_path(conference3.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_questions_path(conference3.short_title) + expect(current_path).to eq(admin_conference_questions_path(conference3.short_title)) + + visit admin_conference_commercials_path(conference3.short_title) + expect(current_path).to eq(admin_conference_commercials_path(conference3.short_title)) + + end + + scenario 'when user is volunteer coordinator' do + sign_in user + visit admin_conference_path(conference4.short_title) + + expect(page.has_content?('Settings')).to be false + expect(page.has_content?('Manage')).to be true +# expect(page.has_content?('Registrations')).to be false + expect(page.has_content?('Events')).to be false + expect(page.has_content?('Schedule')).to be false +# expect(page.has_content?('Campaigns')).to be false + expect(page.has_content?('Targets')).to be false + expect(page.has_content?('Venue')).to be false + expect(page.has_content?('Sponsorship')).to be false + expect(page.has_content?('Supporter Levels')).to be false + expect(page.has_content?('E-Mails')).to be false + expect(page.has_content?('Call for papers')).to be false + expect(page.has_content?('Questions')).to be false + expect(page.has_content?('Commercials')).to be true + + visit edit_admin_conference_path(conference4.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_path(conference4.short_title) + expect(current_path).to eq(admin_conference_path(conference4.short_title)) + + visit admin_conference_registrations_path(conference4.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_events_path(conference4.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_schedule_path(conference4.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_campaigns_path(conference4.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_targets_path(conference4.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_venue_info_path(conference4.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_sponsorship_levels_path(conference4.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_supporter_levels_path(conference4.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_emails_path(conference4.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_callforpapers_path(conference4.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_questions_path(conference4.short_title) + expect(current_path).to eq(root_path) + + visit admin_conference_commercials_path(conference3.short_title) + expect(current_path).to eq(admin_conference_commercials_path(conference3.short_title)) + end +end diff --git a/spec/features/campaign_spec.rb b/spec/features/campaign_spec.rb index 9c71a759..6580d736 100644 --- a/spec/features/campaign_spec.rb +++ b/spec/features/campaign_spec.rb @@ -3,9 +3,8 @@ require 'spec_helper' feature Campaign do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } shared_examples 'add and update campaign' do |user| scenario 'adds and update a campaign', feature: true, js: true do @@ -42,7 +41,7 @@ feature Campaign do expect(Campaign.count).to eq(expected_count) - campaign = Campaign.where('name'=> 'Test Campaign').first + campaign = Campaign.where('name' => 'Test Campaign').first visit edit_admin_conference_campaign_path(conference.short_title, campaign.id) fill_in 'campaign_name', with: 'Test Campaign 42' @@ -52,8 +51,7 @@ feature Campaign do end end - describe 'admin' do - it_behaves_like 'add and update campaign', :admin - it_behaves_like 'add and update campaign', :organizer + describe 'organizer' do + it_behaves_like 'add and update campaign', :organizer_conference_1 end end diff --git a/spec/features/cfp_spec.rb b/spec/features/cfp_spec.rb index 4c185872..e024e11b 100644 --- a/spec/features/cfp_spec.rb +++ b/spec/features/cfp_spec.rb @@ -3,9 +3,8 @@ require 'spec_helper' feature Conference do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } shared_examples 'add and update cfp' do |user| scenario 'adds a new cfp', feature: true, js: true do @@ -87,8 +86,7 @@ feature Conference do end end - describe 'admin' do - it_behaves_like 'add and update cfp', :admin - it_behaves_like 'add and update cfp', :organizer + describe 'organizer' do + it_behaves_like 'add and update cfp', :organizer_conference_1 end end diff --git a/spec/features/commercials_spec.rb b/spec/features/commercials_spec.rb index e180443d..39b69ad0 100644 --- a/spec/features/commercials_spec.rb +++ b/spec/features/commercials_spec.rb @@ -2,18 +2,17 @@ require 'spec_helper' feature Commercial do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } - let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:conference) { create(:conference) } + let!(:organizer_role) { create(:role, name: 'organizer', resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } - shared_examples 'adds and updates a commercial' do |user| + shared_examples 'adds and updates a commercial' do scenario 'of a conference', feature: true, js: true do - conference = create(:conference) expected_count = conference.commercials.count + 1 - sign_in create(user) + sign_in organizer visit admin_conference_commercials_path(conference.short_title) @@ -61,11 +60,7 @@ feature Commercial do end end - describe 'admin' do - it_behaves_like 'adds and updates a commercial', :admin - end - describe 'organizer' do - it_behaves_like 'adds and updates a commercial', :organizer + it_behaves_like 'adds and updates a commercial' end end diff --git a/spec/features/conference_spec.rb b/spec/features/conference_spec.rb index feed1eb8..fdd37748 100644 --- a/spec/features/conference_spec.rb +++ b/spec/features/conference_spec.rb @@ -3,9 +3,8 @@ require 'spec_helper' feature Conference do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } shared_examples 'add and update conference' do |user| scenario 'adds a new conference', feature: true, js: true do @@ -36,7 +35,7 @@ feature Conference do scenario 'update conference', feature: true, js: true do conference = create(:conference) expected_count = Conference.count - sign_in create(user) + sign_in create(:organizer_conference_1) visit edit_admin_conference_path(conference.short_title) click_link 'Edit' @@ -65,9 +64,4 @@ feature Conference do describe 'admin' do it_behaves_like 'add and update conference', :admin end - - describe 'organizer' do - it_behaves_like 'add and update conference', :organizer - end - end diff --git a/spec/features/difficulty_levels_spec.rb b/spec/features/difficulty_levels_spec.rb index 6dcfb990..c5ef30a4 100644 --- a/spec/features/difficulty_levels_spec.rb +++ b/spec/features/difficulty_levels_spec.rb @@ -2,9 +2,8 @@ require 'spec_helper' feature DifficultyLevel do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } shared_examples 'difficulty levels' do |user| scenario 'adds and updates difficulty level', feature: true, js: true do @@ -50,11 +49,7 @@ feature DifficultyLevel do end end - describe 'admin' do - it_behaves_like 'difficulty levels', :admin - end - describe 'organizer' do - it_behaves_like 'difficulty levels', :organizer + it_behaves_like 'difficulty levels', :organizer_conference_1 end end diff --git a/spec/features/email_spec.rb b/spec/features/email_spec.rb index c5838f31..0918e67f 100644 --- a/spec/features/email_spec.rb +++ b/spec/features/email_spec.rb @@ -2,9 +2,8 @@ require 'spec_helper' feature EmailSettings do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } shared_examples 'email settings' do |user| scenario 'updates email settings', @@ -91,11 +90,7 @@ feature EmailSettings do end end - describe 'admin' do - it_behaves_like 'email settings', :admin - end - describe 'organizer' do - it_behaves_like 'email settings', :organizer + it_behaves_like 'email settings', :organizer_conference_1 end end diff --git a/spec/features/event_types_spec.rb b/spec/features/event_types_spec.rb index c900c65d..f417ac34 100644 --- a/spec/features/event_types_spec.rb +++ b/spec/features/event_types_spec.rb @@ -2,18 +2,17 @@ require 'spec_helper' feature EventType do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } shared_examples 'event types' do |user| scenario 'adds and updates event type', feature: true, js: true do conference = create(:conference) sign_in create(user) - visit admin_conference_eventtypes_path( + visit admin_conference_event_types_path( conference_id: conference.short_title) - expect(page.all('div.nested-fields').count == 2).to be true + expect(page.all('div.nested-fields').count == 2).to be true # Add event type click_link 'Add event_type' expect(page.all('div.nested-fields').count == 3).to be true @@ -55,11 +54,7 @@ feature EventType do end end - describe 'admin' do - it_behaves_like 'event types', :admin - end - describe 'organizer' do - it_behaves_like 'event types', :organizer + it_behaves_like 'event types', :organizer_conference_1 end end diff --git a/spec/features/lodgings_spec.rb b/spec/features/lodgings_spec.rb index 10576cc9..a52d8ed4 100644 --- a/spec/features/lodgings_spec.rb +++ b/spec/features/lodgings_spec.rb @@ -2,9 +2,8 @@ require 'spec_helper' feature Lodging do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } shared_examples 'lodgings' do |user| scenario 'adds and updates lodgings', feature: true, js: true do @@ -56,11 +55,7 @@ feature Lodging do end end - describe 'admin' do - it_behaves_like 'lodgings', :admin - end - describe 'organizer' do - it_behaves_like 'lodgings', :organizer + it_behaves_like 'lodgings', :organizer_conference_1 end end diff --git a/spec/features/omniauth_spec.rb b/spec/features/omniauth_spec.rb index 41cbb76e..206060d1 100644 --- a/spec/features/omniauth_spec.rb +++ b/spec/features/omniauth_spec.rb @@ -2,7 +2,6 @@ require 'spec_helper' feature Openid do let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } shared_examples 'sign in with openid' do diff --git a/spec/features/proposal_spec.rb b/spec/features/proposal_spec.rb index 68c5f9e0..dd7f9adf 100644 --- a/spec/features/proposal_spec.rb +++ b/spec/features/proposal_spec.rb @@ -2,16 +2,15 @@ require 'spec_helper' feature Event do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } shared_examples 'proposal workflow' do scenario 'submitts a proposal, accepts and confirms', feature: true, js: true do - admin = create(:admin, email: 'admin@example.com') - participant = create(:participant, email: 'participant@example.com', biography: "") + organizer = create(:organizer_conference_1, email: 'admin@example.com') + participant = create(:user, email: 'participant@example.com', biography: '') expected_count = Event.count + 1 conference = create(:conference) @@ -38,7 +37,7 @@ feature Event do click_button 'Create Event' expect(flash).to eq('Event was successfully submitted. You should register for the conference now.') - expect(current_path).to eq(register_conference_path(conference.short_title)) + expect(current_path).to eq(conference_register_path(conference.short_title)) expect(Event.count).to eq(expected_count) @@ -99,7 +98,7 @@ feature Event do expect(event.commercials.count).to eq(expected_count_commercial - 1) sign_out - sign_in admin + sign_in organizer # Reject proposal visit admin_conference_events_path(conference.short_title) diff --git a/spec/features/rooms_spec.rb b/spec/features/rooms_spec.rb index dc88f9bd..0025267e 100644 --- a/spec/features/rooms_spec.rb +++ b/spec/features/rooms_spec.rb @@ -2,9 +2,8 @@ require 'spec_helper' feature Room do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } shared_examples 'rooms' do |user| scenario 'adds and updates rooms', feature: true, js: true do @@ -43,11 +42,7 @@ feature Room do end end - describe 'admin' do - it_behaves_like 'rooms', :admin - end - describe 'organizer' do - it_behaves_like 'rooms', :organizer + it_behaves_like 'rooms', :organizer_conference_1 end end diff --git a/spec/features/sponsor_spec.rb b/spec/features/sponsor_spec.rb index 24998340..c09a093e 100644 --- a/spec/features/sponsor_spec.rb +++ b/spec/features/sponsor_spec.rb @@ -2,9 +2,8 @@ require 'spec_helper' feature Sponsor do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } shared_examples 'sponsors' do |user| scenario 'adds and updates sponsors', feature: true, js: true do @@ -69,11 +68,7 @@ feature Sponsor do end end - describe 'admin' do - it_behaves_like 'sponsors', :admin - end - describe 'organizer' do - it_behaves_like 'sponsors', :organizer + it_behaves_like 'sponsors', :organizer_conference_1 end end diff --git a/spec/features/sponsorship_level_spec.rb b/spec/features/sponsorship_level_spec.rb index c6f75ce4..0974d770 100644 --- a/spec/features/sponsorship_level_spec.rb +++ b/spec/features/sponsorship_level_spec.rb @@ -1,10 +1,9 @@ require 'spec_helper' feature SponsorshipLevel do -# It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } + # It is necessary to use bang version of let to build roles before user let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } shared_examples 'sponsorship levels' do |user| scenario 'adds and updates sponsorship level', feature: true, js: true do @@ -36,11 +35,7 @@ feature SponsorshipLevel do end end - describe 'admin' do - it_behaves_like 'sponsorship levels', :admin - end - describe 'organizer' do - it_behaves_like 'sponsorship levels', :organizer + it_behaves_like 'sponsorship levels', :organizer_conference_1 end end diff --git a/spec/features/supporter_levels_spec.rb b/spec/features/supporter_levels_spec.rb index ee55a385..692d13ff 100644 --- a/spec/features/supporter_levels_spec.rb +++ b/spec/features/supporter_levels_spec.rb @@ -1,17 +1,14 @@ require 'spec_helper' feature SupporterLevel do - # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } - let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:user) { create(:user, role_ids: [organizer_role.id]) } - shared_examples 'supporter levels' do |user| + shared_examples 'supporter levels' do scenario 'adds and updates supporter level', feature: true, js: true do - conference = create(:conference) - sign_in create(user) - visit admin_conference_supporter_levels_path( - conference_id: conference.short_title) + sign_in user + visit admin_conference_supporter_levels_path(conference_id: conference.short_title) # Add supporter level click_link 'Add supporter_level' @@ -43,11 +40,7 @@ feature SupporterLevel do end end - describe 'admin' do - it_behaves_like 'supporter levels', :admin - end - describe 'organizer' do - it_behaves_like 'supporter levels', :organizer + it_behaves_like 'supporter levels' end end diff --git a/spec/features/tracks_spec.rb b/spec/features/tracks_spec.rb index b1ff4925..d625bbae 100644 --- a/spec/features/tracks_spec.rb +++ b/spec/features/tracks_spec.rb @@ -2,9 +2,8 @@ require 'spec_helper' feature Track do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } shared_examples 'tracks' do |user| scenario 'adds and updates tracks', feature: true, js: true do @@ -50,11 +49,7 @@ feature Track do end end - describe 'admin' do - it_behaves_like 'tracks', :admin - end - describe 'organizer' do - it_behaves_like 'tracks', :organizer + it_behaves_like 'tracks', :organizer_conference_1 end end diff --git a/spec/features/user_spec.rb b/spec/features/user_spec.rb index 5e5a57df..6a7b12f6 100644 --- a/spec/features/user_spec.rb +++ b/spec/features/user_spec.rb @@ -1,14 +1,10 @@ require 'spec_helper' + feature User do - # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } - let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } - let(:admin) { create(:admin) } shared_examples 'admin ability' do scenario 'deletes a user', feature: true, js: true do - sign_in(admin) + sign_in(create(:admin)) visit admin_users_path expected_count = User.count - 1 page.all('btn btn-primary btn-danger') do @@ -20,20 +16,6 @@ feature User do end sign_out end - scenario 'can modify roles', feature: true, js: true do - @user = create(:user) - sign_in(admin) - visit admin_users_path - find("#user-modify-role-#{@user.id}").click - if find("#user-role-selection-#{@user.id}").visible? - page.find('#user_role_ids').find(:xpath, 'option[2]').select_option do - find('#user_submit_action').click - expect(flash).to eq("Updated #{@user.email}") - expect(@user.role_ids).to match_array([2]) - end - end - sign_out - end end describe 'admin' do diff --git a/spec/features/venue_spec.rb b/spec/features/venue_spec.rb index 7f2e82a3..3c838312 100644 --- a/spec/features/venue_spec.rb +++ b/spec/features/venue_spec.rb @@ -3,9 +3,8 @@ require 'spec_helper' feature Conference do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_role) { create(:organizer_conference_1_role) } shared_examples 'venue' do |user| scenario 'adds and updates venue' do @@ -59,12 +58,8 @@ feature Conference do end end - describe 'admin' do - it_behaves_like 'venue', :admin - end - describe 'organizer' do - it_behaves_like 'venue', :organizer + it_behaves_like 'venue', :organizer_conference_1 end end diff --git a/spec/features/volunteers_spec.rb b/spec/features/volunteers_spec.rb index bb82c468..907e4e69 100644 --- a/spec/features/volunteers_spec.rb +++ b/spec/features/volunteers_spec.rb @@ -2,15 +2,14 @@ require 'spec_helper' feature Conference do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } - let(:admin) { create(:admin) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } + let(:organizer) { create(:organizer_conference_1) } let(:conference) { create(:conference) } shared_examples 'volunteer' do scenario 'adds and updates vdays', feature: true, js: true do - sign_in(admin) + sign_in(organizer) visit admin_conference_volunteers_info_path( conference_id: conference.short_title) check('Enable Volunteering') @@ -54,7 +53,7 @@ feature Conference do end scenario 'adds and updates vpositions', feature: true, js: true do - sign_in(admin) + sign_in(organizer) visit admin_conference_volunteers_info_path( conference_id: conference.short_title) @@ -119,10 +118,6 @@ feature Conference do end end - describe 'admin' do - it_behaves_like 'volunteer', :admin - end - describe 'organizer' do it_behaves_like 'volunteer', :organizer end diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index e8a801f2..bf543fb1 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -1,39 +1,163 @@ require 'spec_helper' -require "cancan/matchers" +require 'cancan/matchers' -describe "User" do - describe "abilities" do +describe 'User' do + describe 'Abilities' do subject(:ability){ Ability.new(user) } + let!(:first_user) { create(:user) } # automatically becomes admin let(:user){ nil } + let(:conference_not_public) { create(:conference, make_conference_public: false) } + let(:conference_public) { create(:conference, make_conference_public: true)} + let(:event_confirmed) { create(:event, state: 'confirmed') } + let(:someevent) { create(:event) } - context "when is an admin" do - let!(:user) { create(:admin) } + context 'when user is a guest' do # Test abilities for guest users - it{ should be_able_to(:manage, Event.new) } + it{ should be_able_to(:show, conference_public)} + it{ should_not be_able_to(:show, conference_not_public)} + + it{ should be_able_to(:show, event_confirmed)} + it{ should_not be_able_to(:show, someevent)} + + it{ should be_able_to(:index, :schedule)} + + it{ should_not be_able_to(:create, Event)} + it{ should_not be_able_to(:manage, Event)} + it{ should_not be_able_to(:manage, Conference)} + it{ should_not be_able_to(:manage, :any)} end - context "when is an participant" do - let(:user) { build(:participant) } + context 'when user is a Signed In User' do # Test abilities for signed in users (without any role) + let(:user) { create(:participant) } + let(:registration1) { create(:registration, conference: conference_public, user: user) } + let(:registration2) { create(:registration, conference: conference_not_public, user: user) } + it{ should be_able_to(:create, Event) } + it{ should be_able_to(:index, Event) } it{ should_not be_able_to(:manage, Event.new) } - it{ should be_able_to(:create, Event.new) } - it{ should be_able_to(:read, Event.new) } + it{ should be_able_to(:show, event_confirmed) } + + it{ should be_able_to(:manage, registration1) } + it{ should be_able_to(:manage, registration2) } + + it{ should be_able_to(:show, conference_public)} + it{ should_not be_able_to(:show, conference_not_public)} + it{ should_not be_able_to(:manage, Conference) } end - context "when is an event owner" do + context 'user #is_admin?' do + let(:user) { create(:admin) } + it{ should be_able_to(:manage, User) } + it{ should be_able_to(:create, Conference) } + end + + context 'signed in users can manage their events' do let(:user) { create(:participant) } let(:user2) { create(:participant) } let(:myevent) { create(:event, users: [user]) } let(:someevent) { create(:event, users: [user2]) } + let(:commercial_myevent) { create(:commercial, commercialable: myevent) } + let(:commercial_someevent) { create(:commercial, commercialable: someevent) } # Users are able to update and destroy their own events it{ should be_able_to(:update, myevent) } it{ should be_able_to(:destroy, myevent) } + it{ should be_able_to(:manage, myevent) } + it{ should be_able_to(:create, myevent.commercials.new) } + it{ should be_able_to(:manage, commercial_myevent) } # Users are not able to update and destroy other users events it{ should_not be_able_to(:update, someevent) } it{ should_not be_able_to(:destroy, someevent) } + it{ should_not be_able_to(:manage, someevent) } + it{ should_not be_able_to(:manage, commercial_someevent) } end + context 'when user is an organizer' do + let!(:conference1) { create(:conference) } + let!(:conference2) { create(:conference) } + let(:role) { create(:organizer_role, resource: conference1) } + let(:user) { create(:user, role_ids: [role.id]) } + let(:someuser) { create(:user) } + let(:registration1) { create(:registration, user: someuser, conference_id: conference1.id) } + + it{ should be_able_to(:manage, conference1) } + it{ should_not be_able_to(:manage, conference2) } + it{ should be_able_to(:manage, registration1) } + it{ should be_able_to(:create, Registration) } + end + + context 'when user is part of cfp' do + let!(:conference1) { create(:conference) } + let!(:conference2) { create(:conference) } + let(:role) { create(:role, name: 'cfp', resource: conference1) } + let(:user) { create(:user, role_ids: role.id) } + let(:event) { create(:event, conference_id: conference1.id) } + let(:someevent) { create(:event, conference_id: conference2.id) } + let(:cfp) { create(:call_for_papers, conference: conference1) } + + it{ should_not be_able_to(:manage, conference1) } + it{ should_not be_able_to(:manage, conference2) } + it{ should be_able_to(:index, conference1) } + it{ should be_able_to(:show, conference1) } + + it{ should be_able_to(:manage, event) } + it{ should_not be_able_to(:manage, someevent) } + + it{ should be_able_to(:manage, cfp) } + it{ should be_able_to(:manage, create(:event_type, conference: conference1)) } + end + + context 'when user has multiple roles' do + let!(:conference1) { create(:conference) } # user is organizer + let!(:conference2) { create(:conference) } # user is cfp + let!(:conference3) { create(:conference) } # user is info_desk + let!(:conference4) { create(:conference) } # user is volunteer coordinator + let!(:conference5) { create(:conference, make_conference_public: true) } # user has no role + let!(:conference6) { create(:conference, make_conference_public: false) } # user has no role + let(:role_organizer) { create(:role, name: 'organizer', resource: conference1) } + let(:role_cfp) { create(:role, name: 'cfp', resource: conference2) } + let(:role_info_desk) { create(:role, name: 'info_desk', resource: conference3) } + let(:role_volunteer_coordinator) { create(:role, name: 'volunteer_coordinator', resource: conference4) } + let(:user) { create(:user, role_ids: [role_cfp.id, role_organizer.id, role_cfp.id, role_info_desk.id, role_volunteer_coordinator.id]) } + let(:admin) { create(:admin) } + + it{ should be_able_to(:manage, conference1) } + it{ should_not be_able_to(:update, conference2) } + it{ should_not be_able_to(:update, conference3) } + it{ should_not be_able_to(:update, conference4) } + it{ should_not be_able_to(:update, conference5) } + + it{ should be_able_to(:show, conference1) } + it{ should be_able_to(:show, conference2) } + it{ should be_able_to(:show, conference3) } + it{ should be_able_to(:show, conference4) } + it{ should be_able_to(:show, conference5) } + it{ should be_able_to(:show, conference6) } + + it{ should be_able_to(:manage, conference1.venue) } + it{ should_not be_able_to(:manage, conference2.venue) } + it{ should_not be_able_to(:manage, conference3.venue) } + it{ should_not be_able_to(:manage, conference4.venue) } + it{ should_not be_able_to(:manage, conference5.venue) } + + it{ should be_able_to(:manage, conference1.registrations.new) } + it{ should_not be_able_to(:manage, conference2.registrations.new) } + it{ should be_able_to(:manage, conference3.registrations.new) } + it{ should_not be_able_to(:manage, conference4.registrations.new) } + it{ should_not be_able_to(:manage, conference5.registrations.new) } + + it{ should be_able_to(:manage, conference1.events.new) } + it{ should be_able_to(:manage, conference2.events.new) } + it{ should_not be_able_to(:manage, conference3.events.new) } + it{ should_not be_able_to(:manage, conference4.events.new) } + it{ should_not be_able_to(:manage, conference5.events.new) } + + it{ should be_able_to(:manage, Question.new(conference_id: conference1.id)) } + it{ should_not be_able_to(:manage, Question.new(conference_id: conference2.id)) } + it{ should be_able_to(:manage, Question.new(conference_id: conference3.id)) } + it{ should_not be_able_to(:manage, Question.new(conference_id: conference4.id)) } + it{ should_not be_able_to(:manage, Question.new(conference_id: conference5.id)) } + end end end diff --git a/spec/models/conference_spec.rb b/spec/models/conference_spec.rb index e3897702..2ad64f83 100644 --- a/spec/models/conference_spec.rb +++ b/spec/models/conference_spec.rb @@ -274,9 +274,8 @@ describe Conference do describe '#get_top_submitter' do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } it 'calculates correct hash with top submitters' do event = create(:event, conference: subject) @@ -307,7 +306,7 @@ describe Conference do target = build(:target, target_count: 10, unit: Target.units[:registrations]) subject.targets = [target] result = { - "10 Registrations by #{target.due_date}" => '0' + "10 Registrations by #{target.due_date}" => '0' } expect(subject.get_targets(Target.units[:registrations])).to eq(result) end @@ -317,7 +316,7 @@ describe Conference do subject.targets = [target] subject.registrations = [create(:registration)] result = { - "10 Registrations by #{target.due_date}" => '10' + "10 Registrations by #{target.due_date}" => '10' } expect(subject.get_targets(Target.units[:registrations])).to eq(result) end @@ -330,7 +329,7 @@ describe Conference do target = build(:target, target_count: 10, unit: Target.units[:submissions]) subject.targets = [target] result = { - "10 Submissions by #{target.due_date}" => '0' + "10 Submissions by #{target.due_date}" => '0' } expect(subject.get_targets(Target.units[:submissions])).to eq(result) end @@ -340,7 +339,7 @@ describe Conference do subject.targets = [target] subject.events = [create(:event)] result = { - "10 Submissions by #{target.due_date}" => '10' + "10 Submissions by #{target.due_date}" => '10' } expect(subject.get_targets(Target.units[:submissions])).to eq(result) end @@ -349,7 +348,7 @@ describe Conference do target = build(:target, target_count: 300, unit: Target.units[:program_minutes]) subject.targets = [target] result = { - "300 Program minutes by #{target.due_date}" => '0' + "300 Program minutes by #{target.due_date}" => '0' } expect(subject.get_targets(Target.units[:program_minutes])).to eq(result) end @@ -359,7 +358,7 @@ describe Conference do subject.targets = [target] subject.events = [create(:event)] result = { - "300 Program minutes by #{target.due_date}" => '10' + "300 Program minutes by #{target.due_date}" => '10' } expect(subject.get_targets(Target.units[:program_minutes])).to eq(result) end @@ -897,9 +896,8 @@ describe Conference do describe 'self#event_distribution' do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } it 'self#event_distribution calculates correct values with user' do create(:user, last_sign_in_at: Date.today - 3.months) # active @@ -1426,9 +1424,8 @@ describe Conference do describe '#user_registered?' do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } + let!(:organizer_conference_1_role) { create(:organizer_conference_1_role) } let(:user) { create(:user) } diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index ffbcb1c4..5d599c35 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -3,66 +3,55 @@ require 'spec_helper' describe User do # It is necessary to use bang version of let to build roles before user - let!(:organizer_role) { create(:organizer_role) } - let!(:participant_role) { create(:participant_role) } - let!(:admin_role) { create(:admin_role) } - let!(:admin) { create(:user) } + let!(:admin) { create(:admin) } + let!(:participant) { create(:participant) } + let!(:organizer_conference_1) { create(:organizer_conference_1 ) } + let!(:organizer_conference_1_role) { Role.where(resource_type: 'Conference', resource_id: 1).first } it 'returns the correct role' do - participant = create(:user, email: 'participant@example.de') - expect(admin.roles.first).to eq(admin_role) - expect(participant.roles.first).to eq(participant_role) + expect(organizer_conference_1.roles.first).to eq(organizer_conference_1_role) end it 'returns the correct roles' do - roles = [organizer_role.id, participant_role.id, admin_role.id] + participant_role = create(:participant_role) + roles = [participant_role.id, organizer_conference_1_role.id] user_with_all_roles = create(:user, email: 'participant@example.de') user_with_all_roles.role_ids = roles user_with_all_roles.save - expect(user_with_all_roles.roles.length).to eq(3) + expect(user_with_all_roles.roles.length).to eq(2) expect(user_with_all_roles.roles[0]).to eq(participant_role) - expect(user_with_all_roles.roles[1]).to eq(organizer_role) - expect(user_with_all_roles.roles[2]).to eq(admin_role) + expect(user_with_all_roles.roles[1]).to eq(organizer_conference_1_role ) end - describe '#role?' do + describe '#has_role?' do shared_examples '#role?' do |user, role, expected| it "returns #{expected} for #{role}" do user_obj = create(user, email: 'e@example.com') - expect(user_obj.role?(role)).to be expected - expect(user_obj.role?(role.downcase)).to be expected - expect(user_obj.role?(role.upcase)).to be expected - expect(user_obj.role?(role.downcase.capitalize)).to be expected - end - end - - context 'admin' do - it_behaves_like '#role?', :admin, 'orgAnizer', false - it_behaves_like '#role?', :admin, 'adMin', true - it_behaves_like '#role?', :admin, 'partiCipant', false - - it 'assigns first user admin role' do - expect(admin.role?('Admin')).to be true - expect(admin.role_ids).to match_array([admin_role.id]) - end - end - - context 'participant' do - it_behaves_like '#role?', :participant, 'orgAnizer', false - it_behaves_like '#role?', :participant, 'adMin', false - it_behaves_like '#role?', :participant, 'partiCipant', true - - it 'assigns second user participant role' do - participant = create(:user, email: 'participant@example.de') - expect(participant.role_ids).to match_array([participant_role.id]) + expect(user_obj.has_role?(role.downcase, :any)).to be expected end end context 'organizer' do - it_behaves_like '#role?', :organizer, 'orgAnizer', true - it_behaves_like '#role?', :organizer, 'adMin', false - it_behaves_like '#role?', :organizer, 'partiCipant', false + it_behaves_like '#role?', :organizer_conference_1, 'organizer', true + it_behaves_like '#role?', :organizer_conference_1, 'participant', false + end + + context 'admin' do + it 'assigns first user admin role' do + expect(User.first.is_admin).to be true + expect(admin.is_admin).to eq(true) + end + end + + context 'participant' do + it_behaves_like '#role?', :participant, 'adMin', false + it_behaves_like '#role?', :participant, 'participant', true + +# it 'assigns second user participant role' do +# participant = create(:user, email: 'participant@example.de') +# expect(participant.role_ids).to match_array([participant_role.id]) +# end end end end diff --git a/spec/support/sidebar.rb b/spec/support/sidebar.rb index 4c730a97..cfa0285e 100644 --- a/spec/support/sidebar.rb +++ b/spec/support/sidebar.rb @@ -2,7 +2,7 @@ module Sidebar def sidebar @conference = create(:conference) assign :conference, @conference - render + render expect(view).to render_template('admin/conference/_sidebar') end end diff --git a/spec/views/admin/conference/edit.html.haml_spec.rb b/spec/views/admin/conference/edit.html.haml_spec.rb index 713956d2..44d2cc1a 100644 --- a/spec/views/admin/conference/edit.html.haml_spec.rb +++ b/spec/views/admin/conference/edit.html.haml_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe 'admin/conference/edit' do it 'renders conference details which are editable' do - @conference = create(:conference, title: 'OpenSUSE') + @conference = create(:conference, title: 'openSUSE') assign :conference, @conference render template: 'admin/conference/edit.html.haml' expect(rendered).to include('OpenSUSE') diff --git a/spec/views/admin/conference/index.html.haml_spec.rb b/spec/views/admin/conference/index.html.haml_spec.rb index 0d237a7c..99280fd0 100644 --- a/spec/views/admin/conference/index.html.haml_spec.rb +++ b/spec/views/admin/conference/index.html.haml_spec.rb @@ -2,9 +2,9 @@ require 'spec_helper' describe 'admin/conference/index' do it 'renders all conference names with links' do - assign(:conferences, [create(:conference, title: 'OpenSUSE'), create(:conference)]) + assign(:conferences, [create(:conference, title: 'openSUSE'), create(:conference)]) render - expect(rendered).to include('OpenSUSE') - expect(rendered).to include("The dog and pony show") + expect(rendered).to include('openSUSE') + expect(rendered).to include('The dog and pony show') end end diff --git a/spec/views/admin/conference/show.html.haml_spec.rb b/spec/views/admin/conference/show.html.haml_spec.rb index fa747370..383af195 100644 --- a/spec/views/admin/conference/show.html.haml_spec.rb +++ b/spec/views/admin/conference/show.html.haml_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe 'admin/conference/show' do it 'renders conference dashboard' do - conference = create(:conference, title: 'OpenSUSE') + conference = create(:conference, title: 'openSUSE') assign :conference, conference assign :conference_progress, conference.get_status render diff --git a/spec/views/admin/eventtypes/index.html.haml_spec.rb b/spec/views/admin/event_types/index.html.haml_spec.rb similarity index 89% rename from spec/views/admin/eventtypes/index.html.haml_spec.rb rename to spec/views/admin/event_types/index.html.haml_spec.rb index 095ebf93..661f7156 100644 --- a/spec/views/admin/eventtypes/index.html.haml_spec.rb +++ b/spec/views/admin/event_types/index.html.haml_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'admin/eventtypes/index' do +describe 'admin/event_types/index' do it 'renders event types' do @event_type = create(:event_type) diff --git a/spec/views/admin/social_events/index.html.haml_spec.rb b/spec/views/admin/social_events/index.html.haml_spec.rb index 650828a2..a95ec30e 100644 --- a/spec/views/admin/social_events/index.html.haml_spec.rb +++ b/spec/views/admin/social_events/index.html.haml_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe 'admin/social_events/index' do - it 'renders social events' do + it 'renders social events' do @social_event = create(:social_event) assign :conference, @social_event.conference render diff --git a/spec/views/admin/volunteers/show.html.haml_spec.rb b/spec/views/admin/volunteers/show.html.haml_spec.rb index 25646308..b322f996 100644 --- a/spec/views/admin/volunteers/show.html.haml_spec.rb +++ b/spec/views/admin/volunteers/show.html.haml_spec.rb @@ -1,5 +1,5 @@ require 'spec_helper' -describe "admin/volunteers/show" do +describe 'admin/volunteers/show' do pending "add some examples to (or delete) #{__FILE__}" end diff --git a/spec/views/conference/show.html.haml_spec.rb b/spec/views/conference/show.html.haml_spec.rb index e1d11cb7..cdc1db3a 100644 --- a/spec/views/conference/show.html.haml_spec.rb +++ b/spec/views/conference/show.html.haml_spec.rb @@ -68,8 +68,8 @@ describe 'conference/show.html.haml' do expect(view).to render_template('conference/_social_media') expect(view.content_for(:splash)).to include('http://www.fbexample.com') expect(view.content_for(:splash)).to include('http://www.google-example.com') - expect(view.content_for(:splash)).to include("http://instagram.com") - expect(view.content_for(:splash)).to include("http://twitter.com") + expect(view.content_for(:splash)).to include('http://instagram.com') + expect(view.content_for(:splash)).to include('http://twitter.com') end it 'renders location partial' do