diff --git a/Gemfile b/Gemfile index 9c3eda3f..9c571657 100644 --- a/Gemfile +++ b/Gemfile @@ -23,6 +23,8 @@ gem 'omniauth-github' # 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 bf7fb167..7420a87d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -299,6 +299,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) @@ -445,6 +446,7 @@ DEPENDENCIES rails-observers rdoc-generator-fivefish redcarpet + rolify rspec-activemodel-mocks rspec-rails rubocop diff --git a/app/assets/stylesheets/osem.css.scss b/app/assets/stylesheets/osem.css.scss index 4c4353c0..46e5d747 100644 --- a/app/assets/stylesheets/osem.css.scss +++ b/app/assets/stylesheets/osem.css.scss @@ -168,3 +168,7 @@ body { -webkit-flex: 2; flex: 2; } + +.table20 { + width: 20%; +} diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb new file mode 100644 index 00000000..036aec62 --- /dev/null +++ b/app/controllers/admin/base_controller.rb @@ -0,0 +1,17 @@ +module Admin + class BaseController < ApplicationController + before_filter :verify_user_admin + + def verify_user_admin + if (current_user.nil?) + redirect_to new_user_session_path + return false + end + 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 +end diff --git a/app/controllers/admin/callforpapers_controller.rb b/app/controllers/admin/callforpapers_controller.rb index 7d4ac3d2..b18d80de 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 + class CallforpapersController < Admin::BaseController + 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..8a0e3e23 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 + class CampaignsController < Admin::BaseController + 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! :index, 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), @@ -22,20 +21,11 @@ module Admin end end - def new - @conference = Conference.find_by(short_title: params[:conference_id]) - @campaign = @conference.campaigns.new - end + def new; end - def edit - @conference = Conference.find_by(short_title: params[:conference_id]) - @campaign = Campaign.find(params[:id]) - end + def edit; 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 +40,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..2a41b2dc 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] + class CommercialsController < Admin::BaseController + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource through: :conference, except: [:new, :create] def index @commercials = @conference.commercials @@ -9,13 +9,14 @@ module Admin def new @commercial = @conference.commercials.build + authorize! :create, @conference.commercials.new end - def edit - end + def edit; end def create @commercial = @conference.commercials.build(commercial_params) + authorize! :create, @commercial if @commercial.save redirect_to admin_conference_commercials_path, @@ -43,14 +44,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..8d7489c6 100644 --- a/app/controllers/admin/conference_controller.rb +++ b/app/controllers/admin/conference_controller.rb @@ -1,6 +1,7 @@ module Admin - class ConferenceController < ApplicationController - before_filter :verify_organizer + class ConferenceController < Admin::BaseController + load_and_authorize_resource :conference, find_by: :short_title + load_resource :user, only: [:remove_user] def index # Redirect to new form if there is no conference @@ -63,8 +64,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 +112,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 @@ -186,12 +191,47 @@ module Admin def edit @conferences = Conference.all - @conference = Conference.find_by(short_title: params[:id]) @date_string = date_string(@conference.start_date, @conference.end_date) respond_to do |format| format.html format.json { render json: @conference.to_json } end end + + def roles + @user = User.new + @roles = Role::ACTIONABLES + Role::LABELS + + params[:user] ? (@selection = params[:user][:roles].parameterize.underscore) : (@selection = 'organizer') + @role_users = get_users(@selection) + end + + def add_user + @user = User.find_by(email: params[:user][:email]) + @selection = params[:role].parameterize.underscore + @user.add_role @selection.to_sym, @conference + + @role_users = get_users(@selection) + render 'roles', formats: [:js] + end + + def remove_user + @selection = params[:role] + @user.revoke @selection.to_sym, @conference + + @role_users = get_users(@selection) + render 'roles', formats: [:js] + end + + protected + + def get_users(role_name) + @role_users = {} + # Initialize @role variable, so that view can show the role description + @role = Role.where(name: role_name, resource: @conference) + @role.blank? ? @role_users[role_name] = @role : @role_users[role_name] = @role.first.users + + @role_users + end end end diff --git a/app/controllers/admin/contacts_controller.rb b/app/controllers/admin/contacts_controller.rb index 6d97db98..a8cda01a 100644 --- a/app/controllers/admin/contacts_controller.rb +++ b/app/controllers/admin/contacts_controller.rb @@ -1,12 +1,13 @@ module Admin - class ContactsController < ApplicationController - before_action :set_conference - before_action :set_conference - before_action :set_contact, only: [:edit, :update] + class ContactsController < Admin::BaseController + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource through: :conference, singleton: true + + # GET /:conference/contact + def show; end # GET /:conference/contact/edit - def edit - end + def edit; end # PATCH/PUT /:conference/contact def update @@ -19,15 +20,6 @@ module Admin 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 - # 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..2720577c 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 + class DietchoicesController < Admin::BaseController + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource :dietary_choice, through: :conference def show render :diets_list diff --git a/app/controllers/admin/difficulty_levels_controller.rb b/app/controllers/admin/difficulty_levels_controller.rb index f32dc8d9..cfab7528 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 + class DifficultyLevelsController < Admin::BaseController + 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 diff --git a/app/controllers/admin/emails_controller.rb b/app/controllers/admin/emails_controller.rb index e4489180..b0f0a26c 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 + class EmailsController < Admin::BaseController + 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/eventtypes_controller.rb b/app/controllers/admin/event_types_controller.rb similarity index 52% rename from app/controllers/admin/eventtypes_controller.rb rename to app/controllers/admin/event_types_controller.rb index 616b4318..f6cfaab2 100644 --- a/app/controllers/admin/eventtypes_controller.rb +++ b/app/controllers/admin/event_types_controller.rb @@ -1,6 +1,11 @@ module Admin - class EventtypesController < ApplicationController - before_filter :verify_organizer + class EventTypesController < Admin::BaseController + 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 @@ -8,11 +13,11 @@ module Admin def update @conference.update_attributes!(params[:conference]) - redirect_to(admin_conference_eventtypes_path( + redirect_to(admin_conference_event_types_path( conference_id: @conference.short_title), notice: 'Event types were successfully updated.') rescue => e - redirect_to(admin_conference_eventtypes_path( + redirect_to(admin_conference_event_types_path( conference_id: @conference.short_title), alert: "Event types update failed: #{e.message}") end diff --git a/app/controllers/admin/events_controller.rb b/app/controllers/admin/events_controller.rb index 99dbfbc2..1b534f33 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 + class EventsController < Admin::BaseController + 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 @@ -121,8 +124,7 @@ module Admin redirect_back_or_to(admin_conference_event_path(@conference.short_title, @event)) end - def create - end + def create; end def accept send_mail = @event.conference.email_settings.send_on_accepted diff --git a/app/controllers/admin/lodgings_controller.rb b/app/controllers/admin/lodgings_controller.rb index 34dfa628..ce299ed7 100644 --- a/app/controllers/admin/lodgings_controller.rb +++ b/app/controllers/admin/lodgings_controller.rb @@ -1,16 +1,16 @@ module Admin - class LodgingsController < ApplicationController - before_filter :verify_organizer + class LodgingsController < Admin::BaseController + 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 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/photos_controller.rb b/app/controllers/admin/photos_controller.rb index fc598d09..14c5dc17 100644 --- a/app/controllers/admin/photos_controller.rb +++ b/app/controllers/admin/photos_controller.rb @@ -1,7 +1,7 @@ module Admin - class PhotosController < ApplicationController - before_action :set_conference - before_action :set_photo, only: [:edit, :update, :destroy] + class PhotosController < Admin::BaseController + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource through: :conference # GET /admin/photos def index @@ -14,8 +14,7 @@ module Admin end # GET /admin/photos/1/edit - def edit - end + def edit; end # POST /admin/photos def create @@ -46,16 +45,6 @@ module Admin private -# Use callbacks to share common setup or constraints between actions. - def set_conference - @conference = Conference.find_by(short_title: params[:conference_id]) - end - -# Use callbacks to share common setup or constraints between actions. - def set_photo - @photo = Photo.find_by(id: params[:id]) - end - # Only allow a trusted parameter "white list" through. def photo_params params[:photo] diff --git a/app/controllers/admin/questions_controller.rb b/app/controllers/admin/questions_controller.rb index 240909cd..a9da703b 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 + class QuestionsController < Admin::BaseController + 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]) + authorize! :index, 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,19 +32,13 @@ 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") + if @question.global 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.") else @@ -53,8 +48,7 @@ module Admin # Update questions used for the conference def update_conference - @conference = Conference.find_by(short_title: params[:conference_id]) - + authorize! :update, Question.new(conference_id: @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.") else @@ -64,19 +58,17 @@ module Admin # 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 + if !@question.global # Delete question and its answers begin Question.transaction do - @question.delete + @question.destroy @question.answers.each do |a| - a.delete + a.destroy end flash[:notice] = "Deleted question: #{@question.title} and its answers: #{@question.answers.map {|a| a.title}.join ','}" end diff --git a/app/controllers/admin/registrations_controller.rb b/app/controllers/admin/registrations_controller.rb index 6ebe3db0..bc17b1ff 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 + class RegistrationsController < Admin::BaseController + 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..0acb9586 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 + class RoomsController < Admin::BaseController + 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..0a939db8 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 + class SchedulesController < Admin::BaseController + # 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..bc8dae88 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 + class SocialEventsController < Admin::BaseController + load_and_authorize_resource :conference, find_by: :short_title + authorize_resource :social_event, through: :conference def show render :social_events_list diff --git a/app/controllers/admin/speakers_controller.rb b/app/controllers/admin/speakers_controller.rb index 76fd40ce..d3dfe700 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 + class SpeakersController < Admin::BaseController + 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..26d1df6e 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 + class SponsorsController < Admin::BaseController + 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..134295e3 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 + class SponsorshipLevelsController < Admin::BaseController + 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..a6ba21b8 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 + class StatsController < Admin::BaseController + 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..f0721c94 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 + class SupporterLevelsController < Admin::BaseController + 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..f1610631 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 + class SupportersController < Admin::BaseController + 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..21246185 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 + class TargetsController < Admin::BaseController + 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..089afacc 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 + class TracksController < Admin::BaseController + 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..d5a52787 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 + class UsersController < Admin::BaseController + load_and_authorize_resource + def new @user = User.new end @@ -10,32 +11,25 @@ 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}" + if @user.update_attributes(params[:user]) + redirect_to admin_users_path, notice: "Updated #{@user.name} (#{@user.email})!" + else + redirect_to admin_users_path, alert: "Could not update #{@user.name} (#{@user.email}). #{@user.errors.full_messages.join('. ')}." + end end - def edit - @user = User.find(params[:id]) - end - - def delete - @user = User.find(params[:id]) - end + def edit; end def destroy - @user = User.find(params[:id]) @user.destroy redirect_to admin_users_path, notice: 'User got deleted' end diff --git a/app/controllers/admin/venue_controller.rb b/app/controllers/admin/venue_controller.rb index 59379a09..f2d77495 100644 --- a/app/controllers/admin/venue_controller.rb +++ b/app/controllers/admin/venue_controller.rb @@ -1,9 +1,9 @@ module Admin - class VenueController < ApplicationController - before_filter :verify_organizer + class VenueController < Admin::BaseController + load_and_authorize_resource :conference, find_by: :short_title + load_and_authorize_resource :venue, through: :conference, singleton: true - def index - end + def index; end def update @venue = @conference.venue diff --git a/app/controllers/admin/volunteers_controller.rb b/app/controllers/admin/volunteers_controller.rb index 5713845f..e6c53e6e 100644 --- a/app/controllers/admin/volunteers_controller.rb +++ b/app/controllers/admin/volunteers_controller.rb @@ -1,26 +1,36 @@ module Admin - class VolunteersController < ApplicationController + class VolunteersController < Admin::BaseController + load_and_authorize_resource :conference, find_by: :short_title + def index - @conference = Conference.find_by(short_title: params[:conference_id]) - render :index + if can_manage_volunteers(@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 can_manage_volunteers(@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 can_manage_volunteers(@conference) + if @conference.update_attributes(params[:conference]) + redirect_to(admin_conference_volunteers_info_path(conference_id: params[:conference_id]), notice: "Volunteering options were successfully updated.") + else + redirect_to(admin_conference_volunteers_info_path(conference_id: params[:conference_id]), alert: "Volunteering options update failed: #{@conference.errors.full_messages.join '. '}") + end + else + authorize! :index, :volunteer end end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0219a4ca..1e8d6cd1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -4,13 +4,15 @@ class ApplicationController < ActionController::Base before_filter :get_conferences before_filter :store_location 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) @@ -39,36 +41,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..79a87f30 100644 --- a/app/controllers/commercials_controller.rb +++ b/app/controllers/commercials_controller.rb @@ -1,17 +1,18 @@ 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 - end + def edit; end 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 +41,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..488ec052 100644 --- a/app/controllers/conference_controller.rb +++ b/app/controllers/conference_controller.rb @@ -1,8 +1,7 @@ class ConferenceController < ApplicationController - 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 + load_and_authorize_resource find_by: :short_title + + def show; end def subscribe conference = Conference.find_by_short_title(params[:id]) @@ -41,7 +40,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..bfcc2e83 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,15 +57,15 @@ 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) + if user.subscriptions.where(conference: @conference).blank? + subscription = Subscription.new(conference_id: @conference.id, user_id: user.id) redirect_message = subscription.save ? 'You are now Registered and will be receiving Email Notifications.' : 'You are now Registered.' end else @@ -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..f58e4989 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,8 @@ 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 +27,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 @@ -41,16 +42,14 @@ class EventAttachmentsController < ApplicationController end end - def edit - @upload = EventAttachment.find(params[:id]) - end + def edit; end def create params[:event_attachment][:title] = params[:title][0] 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 @@ -83,9 +82,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]) format.html { redirect_to @upload, notice: 'Upload was successfully updated.' } @@ -98,14 +94,12 @@ 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..e9d60d1a 100644 --- a/app/controllers/schedule_controller.rb +++ b/app/controllers/schedule_controller.rb @@ -1,6 +1,7 @@ class ScheduleController < ApplicationController + authorize_resource class: false 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..caa1e560 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"] @@ -204,4 +196,19 @@ module ApplicationHelper end return providers end + + # Receives a hash, generated from User model, function get_roles + # Outputs the roles of a user, including the conferences for which the user has the roles + # Eg. organizer(oSC13, oSC14), cfp(oSC12, oSC13) + def show_roles(roles) + roles.map { |x| x[0].titleize + ' ' + x[1] }.join ', ' + end + + def can_manage_volunteers(conference) + if (current_user.has_role? :organizer, conference) || (current_user.has_role? :volunteer_coordinator, conference) + true + else + false + end + end end diff --git a/app/models/ability.rb b/app/models/ability.rb index 8c09734e..a7fb93e6 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -2,16 +2,147 @@ 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 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 + cannot [:edit, :update, :destroy], Question, global: true + 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 :index, Commercial, commercialable_type: 'Conference' + can :manage, Commercial, commercialable_type: 'Conference', commercialable_id: conf_ids_for_organizer + # 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 + can :manage, Photo, conference_id: conf_ids_for_organizer + end + + def guest + ## Abilities for everyone, even guests (not logged in users) + can [:show, :gallery_photos], Conference do |conference| + conference.make_conference_public == true + end + + # see commercials too + + can :show, Event do |event| + event.state == 'confirmed' + end + + can :index, :schedule # show? + end + + def signed_in(user) + guest # 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..77ff94f2 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 + :utm_content, :utm_campaign, :target_ids, :conference_id 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_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 498cb68c..77a38301 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,20 @@ 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 get_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..54235af3 --- /dev/null +++ b/app/views/admin/conference/_roles.html.haml @@ -0,0 +1,29 @@ +#myroles.roles + - 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: @selection), remote: true) do |f| + %h4 + = f.input :email, label: "Add role '#{@selection.humanize.titleize}' to user: ", placeholder: "User's email", input_html: { required: 'required' } + = f.action :submit, as: :button, label: 'Add User', button_html: {value: 'Add', class: 'btn btn-primary'} + .row + .col-md-12 + %h3 Users with role #{@selection.humanize.titleize} + %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_id: user.id, role: @selection), 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..145261e3 100644 --- a/app/views/admin/questions/_questions.html.haml +++ b/app/views/admin/questions/_questions.html.haml @@ -19,10 +19,8 @@ = 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') + class: 'btn btn-primary', disabled: !(can? :update, 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 && !has_role?(current_user, "Admin") + confirm: "Delete question '#{q.title}'?", disabled: !(can? :destroy, q) diff --git a/app/views/admin/questions/index.html.haml b/app/views/admin/questions/index.html.haml index e34e997a..7810ddb7 100644 --- a/app/views/admin/questions/index.html.haml +++ b/app/views/admin/questions/index.html.haml @@ -1,16 +1,18 @@ .row .col-md-8 .pull-right - %b= link_to 'Create New Question','#', 'data-toggle' => 'modal', - 'data-target' => '#new-question', class: 'btn btn-success' + - if can? :create, Question.new(conference_id: @conference.id) + %b= link_to 'Create New Question','#', 'data-toggle' => 'modal', + 'data-target' => '#new-question', class: 'btn btn-success' %br %br - if @questions.count > 0 = semantic_form_for(@conference, url: admin_conference_questions_update_conference_path(@conference.short_title)) do |f| .questions{id: 'myquestions'} = render partial: 'questions' - = f.submit "Update Questions for #{@conference.short_title}", class: 'btn btn-primary', - confirm: 'Are you sure you want to make these changes?' + - if can? :update, @conference + = f.submit "Update Questions for #{@conference.short_title}", class: 'btn btn-primary', + confirm: 'Are you sure you want to make these changes?' .modal.fade{id: 'new-question', 'role' => 'dialog', 'aria-hidden' => 'true'} .modal-dialog 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..e945bad7 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -1,5 +1,6 @@ = 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 diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index d66a475d..6c654b85 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.get_roles.blank? + = show_roles(user.get_roles.first(2)) + - if user.get_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..161d8708 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -1,7 +1,14 @@ +- if can? :edit, @user + .pull-right + = link_to "Edit", edit_admin_user_path(@user), class: 'btn btn-primary' %table.table - @show_attributes.each do |attr| %tr - %td + %td{class: 'table20'} %b = attr.capitalize.gsub('_', ' ') - %td= @user.send(attr) + - if attr == 'roles' + %td + = show_roles(@user.get_roles) + - 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..00db00b4 100644 --- a/app/views/layouts/_admin_sidebar.html.haml +++ b/app/views/layouts/_admin_sidebar.html.haml @@ -10,97 +10,124 @@ %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? :show, @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 + %ul + - if can? :update, Contact.new(conference_id: @conference.id) + %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.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..0b78cbdb 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| 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/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..89fc6e9e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,6 +8,12 @@ Osem::Application.routes.draw do resources :users resources :people resources :conference do + member do + get :roles + post :roles + post :add_user + delete :remove_user + end resource :contact, except: [:index, :new, :create, :show, :destroy] resources :photos, except: [:show] resource :schedule, only: [:show, :update] @@ -40,7 +46,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 +98,11 @@ 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..1511d822 --- /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, default: false + end +end diff --git a/db/migrate/20140730104658_migrate_roles_for_cancancan.rb b/db/migrate/20140730104658_migrate_roles_for_cancancan.rb new file mode 100644 index 00000000..89efebcd --- /dev/null +++ b/db/migrate/20140730104658_migrate_roles_for_cancancan.rb @@ -0,0 +1,27 @@ +class MigrateRolesForCancancan < ActiveRecord::Migration + def up + # Store the number of existing roles + old_roles = Role.count + + Role.all.each do |role| + role.users.each do |user| + Conference.all.each do |conference| + if role.name == 'Admin' || role.name == 'Organizer' + user.add_role :organizer, conference + else + user.add_role role.name.parameterize.underscore.to_sym, conference + end + end + end + end + + # Delete old roles + Role.first(old_roles).each do |role| + role.destroy + end + end + + def down + raise ActiveRecord::IrreversibleMigration.new('Cannot reverse migration. Deleted events cannot be re-created') + end +end diff --git a/db/schema.rb b/db/schema.rb index b21c54c0..99e48eb8 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", default: false 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..91f036d6 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') +QuestionType.create(title: 'Single Choice') +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..f3e179ab 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(:participant) { create(:participant) } + let!(:first_user) { create(:user) } + let!(:organizer_role) { create(:role, name: 'organizer', resource: conference) } - shared_examples 'access as administration or organizer' do + let(:organizer) { create(:user, role_ids: organizer_role.id) } + let(:organizer2) { create(:user, email: 'organizer2@email.osem', role_ids: organizer_role.id) } + let(:participant) { create(:user) } + + shared_examples 'access as organizer' 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 @@ -210,64 +212,193 @@ describe Admin::ConferenceController do expect(response).to render_template :new end end - end - describe 'administrator access' do + describe 'GET #roles' do + before(:each) do + get :roles, id: conference.short_title + end - before do - sign_in(admin) + it 'assigns default value to selection' do + expect(assigns(:selection)).to eq('organizer') + end + + it 'finds the correct role' do + expect(assigns(:role)).to eq([organizer_role]) + end + + it 'properly assigns role_users hash' do + expect(assigns(:role_users)).to eq('organizer' => [organizer, organizer2]) + end + + it 'properly assigns roles variable' do + expect(assigns(:roles)).to eq(['Organizer', 'CfP', 'Info Desk', 'Volunteers Coordinator', 'Attendee', 'Volunteer', 'Speaker', 'Sponsor', 'Press', 'Keynote Speaker', ]) + end end - it_behaves_like 'access as administration or organizer' + describe 'POST #roles' do + before(:each) do + post :roles, id: conference.short_title, user: { roles: 'CfP' } + end + it 'assigns selected value to selection' do + expect(assigns(:selection)).to eq('cfp') + end + + it 'sets role variable' do + post :roles, id: conference.short_title, user: { roles: 'Organizer' } + role = Role.where(name: 'organizer', resource: conference) + expect(assigns(:role)).to eq(role) + end + + it 'sets role variable (returns blank for nil role)' do + expect(assigns(:role)).to eq([]) + end + + it 'sets role_users hash with blank' do + expect(assigns(:role_users)).to eq('cfp' => []) + end + + it 'sets role_users has with data' do + organizer.add_role :cfp, conference + post :roles, id: conference.short_title, user: { roles: 'CfP' } + expect(assigns(:role_users)).to eq('cfp' => [organizer]) + end + + it 'sets roles variable' do + expect(assigns(:roles)).to eq(['Organizer', 'CfP', 'Info Desk', 'Volunteers Coordinator', 'Attendee', 'Volunteer', 'Speaker', 'Sponsor', 'Press', 'Keynote Speaker', ]) + end + end + + describe 'POST #add_user' do + before(:each) do + @new_user = create(:user, email: 'new_user@email.osem') + post :add_user, id: conference.short_title, user: { email: 'new_user@email.osem' }, role: 'organizer' + end + + it 'finds correct user' do + expect(assigns(:user)).to eq(@new_user) + end + + it 'sets role_users variable' do + expect(assigns(:role_users)).to eq('organizer' => organizer_role.users) + + post :add_user, id: conference.short_title, user: { email: 'new_user@email.osem' }, role: 'cfp' + expect(assigns(:role_users)).to eq('cfp' => [@new_user]) + end + + it 'assigns role to user' do + expect(@new_user.roles).to eq([organizer_role]) + end + + it 'assigns second role to user' do + post :add_user, id: conference.short_title, user: { email: @new_user.email }, role: 'cfp' + cfp_role = Role.find_by(name: 'cfp', resource: conference) + expect(@new_user.roles).to eq([organizer_role, cfp_role]) + end + end + + describe 'DELETE #remove_user' do + before(:each) do + + end + + it 'sets selection variable' do + delete :remove_user, id: conference.short_title, user_id: organizer2.id, role: 'organizer' + expect(assigns(:selection)).to eq('organizer') + end + + it 'sets role_users hash' do + delete :remove_user, id: conference.short_title, user_id: organizer2.id, role: 'organizer' + expect(assigns(:role_users)).to eq('organizer' => [organizer]) + end + + it 'removes role from user' do + delete :remove_user, id: conference.short_title, user_id: organizer2.id, role: 'organizer' + organizer2.reload + expect(organizer2.roles).to eq([]) + end + + it 'removes second role from user' do + # Add cfp role + organizer2.add_role :cfp, conference + cfp_role = Role.find_by(name: 'cfp', resource: conference) + # Remove role organizer + delete :remove_user, id: conference.short_title, user_id: organizer2.id, role: 'organizer' + + organizer2.reload + expect(organizer2.roles).to include(cfp_role) + expect(organizer2.roles[0]).to eq(cfp_role) + expect(organizer2.roles.count).to eq(1) + expect(assigns(:role_users)).to eq('organizer' => [organizer]) + + delete :remove_user, id: conference.short_title, user_id: organizer2.id, role: 'cfp' + organizer2.reload + expect(organizer2.roles).to eq([]) + end + end end describe 'organizer access' do - before(:each) do + before do sign_in(organizer) end - it_behaves_like 'access as administration or organizer' + it_behaves_like 'access as organizer' 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 +408,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..15f6d23e 100644 --- a/spec/factories/roles.rb +++ b/spec/factories/roles.rb @@ -1,16 +1,12 @@ FactoryGirl.define do factory :role do - factory :admin_role do - name 'Admin' - end - factory :organizer_role do - name 'Organizer' + name 'organizer' end - factory :participant_role do - name 'Participant' + factory :cfp_role do + name 'cfp' end end end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index 7ab2b62c..d404aefb 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -15,12 +15,8 @@ FactoryGirl.define do gravida. EOS - factory :participant 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 } + is_admin true end factory :organizer do diff --git a/spec/features/ability_spec.rb b/spec/features/ability_spec.rb new file mode 100644 index 00000000..616fdf0e --- /dev/null +++ b/spec/features/ability_spec.rb @@ -0,0 +1,302 @@ +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).to have_selector('li.nav-header.nav-header-bigger a', text: 'Dashboard') + expect(page).to have_link('Basics', href: "/admin/conference/#{conference1.short_title}/edit") + expect(page).to have_link('Contact', href: "/admin/conference/#{conference1.short_title}/contact/edit") + expect(page).to have_link('Commercials', href: "/admin/conference/#{conference1.short_title}/commercials") + expect(page).to have_link('Photos', href: "/admin/conference/#{conference1.short_title}/photos") + expect(page).to have_link('Events', href: "/admin/conference/#{conference1.short_title}/events") + expect(page).to have_link('Registrations', href: "/admin/conference/#{conference1.short_title}/registrations") + expect(page).to have_link('Schedule', href: "/admin/conference/#{conference1.short_title}/schedule") + expect(page).to have_link('Campaigns', href: "/admin/conference/#{conference1.short_title}/campaigns") + expect(page).to have_link('Targets', href: "/admin/conference/#{conference1.short_title}/targets") + expect(page).to have_link('Venue', href: "/admin/conference/#{conference1.short_title}/venue") + expect(page).to have_link('Rooms', href: "/admin/conference/#{conference1.short_title}/rooms") + expect(page).to have_link('Lodgings', href: "/admin/conference/#{conference1.short_title}/lodgings") + expect(page).to have_link('Sponsorship', href: "/admin/conference/#{conference1.short_title}/sponsorship_levels") + expect(page).to have_link('Sponsors', href: "/admin/conference/#{conference1.short_title}/sponsors") + expect(page).to have_link('Supporter Levels', href: "/admin/conference/#{conference1.short_title}/supporter_levels") + expect(page).to have_link('E-Mails', href: "/admin/conference/#{conference1.short_title}/emails") + expect(page).to have_link('Call for papers', href: "/admin/conference/#{conference1.short_title}/callforpapers") + expect(page).to have_link('Tracks', href: "/admin/conference/#{conference1.short_title}/tracks") + expect(page).to have_link('Event types', href: "/admin/conference/#{conference1.short_title}/event_types") + expect(page).to have_link('Difficulty levels', href: "/admin/conference/#{conference1.short_title}/difficulty_levels") + expect(page).to have_link('Questions', href: "/admin/conference/#{conference1.short_title}/questions") + expect(page).to have_link('Roles', href: "/admin/conference/#{conference1.short_title}/roles") + + 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).to have_selector('li.nav-header.nav-header-bigger a', text: 'Dashboard') + expect(page).to have_link('Basics', href: "/admin/conference/#{conference2.short_title}/edit") + expect(page).to_not have_link('Contact', href: "/admin/conference/#{conference2.short_title}/contact/edit") + expect(page).to have_link('Commercials', href: "/admin/conference/#{conference2.short_title}/commercials") + expect(page).to_not have_link('Photos', href: "/admin/conference/#{conference2.short_title}/photos") + expect(page).to have_link('Events', href: "/admin/conference/#{conference2.short_title}/events") + expect(page).to_not have_link('Registrations', href: "/admin/conference/#{conference2.short_title}/registrations") + expect(page).to have_link('Schedule', href: "/admin/conference/#{conference2.short_title}/schedule") + expect(page).to_not have_link('Campaigns', href: "/admin/conference/#{conference2.short_title}/campaigns") + expect(page).to_not have_link('Targets', href: "/admin/conference/#{conference2.short_title}/targets") + expect(page).to have_link('Venue', href: "/admin/conference/#{conference2.short_title}/venue") + expect(page).to have_link('Rooms', href: "/admin/conference/#{conference2.short_title}/rooms") + expect(page).to_not have_link('Lodgings', href: "/admin/conference/#{conference2.short_title}/lodgings") + expect(page).to_not have_link('Sponsorship', href: "/admin/conference/#{conference2.short_title}/sponsorship_levels") + expect(page).to_not have_link('Sponsors', href: "/admin/conference/#{conference2.short_title}/sponsors") + expect(page).to_not have_link('Supporter Levels', href: "/admin/conference/#{conference2.short_title}/supporter_levels") + expect(page).to have_link('E-Mails', href: "/admin/conference/#{conference2.short_title}/emails") + expect(page).to have_link('Call for papers', href: "/admin/conference/#{conference2.short_title}/callforpapers") + expect(page).to have_link('Tracks', href: "/admin/conference/#{conference2.short_title}/tracks") + expect(page).to have_link('Event types', href: "/admin/conference/#{conference2.short_title}/event_types") + expect(page).to have_link('Difficulty levels', href: "/admin/conference/#{conference2.short_title}/difficulty_levels") + expect(page).to_not have_link('Questions', href: "/admin/conference/#{conference2.short_title}/questions") + expect(page).to_not have_link('Roles', href: "/admin/conference/#{conference2.short_title}/roles") + + 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(conference2.short_title) + expect(current_path).to eq(admin_conference_commercials_path(conference2.short_title)) + end + + scenario 'when user is info desk' do + sign_in user + visit admin_conference_path(conference3.short_title) + + expect(page).to have_selector('li.nav-header.nav-header-bigger a', text: 'Dashboard') + expect(page).to have_link('Basics', href: "/admin/conference/#{conference3.short_title}/edit") + expect(page).to_not have_link('Contact', href: "/admin/conference/#{conference3.short_title}/contact/edit") + expect(page).to have_link('Commercials', href: "/admin/conference/#{conference3.short_title}/commercials") + expect(page).to_not have_link('Photos', href: "/admin/conference/#{conference3.short_title}/photos") + expect(page).to_not have_link('Events', href: "/admin/conference/#{conference3.short_title}/events") + expect(page).to have_link('Registrations', href: "/admin/conference/#{conference3.short_title}/registrations") + expect(page).to_not have_link('Schedule', href: "/admin/conference/#{conference3.short_title}/schedule") + expect(page).to_not have_link('Campaigns', href: "/admin/conference/#{conference3.short_title}/campaigns") + expect(page).to_not have_link('Targets', href: "/admin/conference/#{conference3.short_title}/targets") + expect(page).to_not have_link('Venue', href: "/admin/conference/#{conference3.short_title}/venue") + expect(page).to_not have_link('Rooms', href: "/admin/conference/#{conference3.short_title}/rooms") + expect(page).to_not have_link('Lodgings', href: "/admin/conference/#{conference3.short_title}/lodgings") + expect(page).to_not have_link('Sponsorship', href: "/admin/conference/#{conference3.short_title}/sponsorship_levels") + expect(page).to_not have_link('Sponsors', href: "/admin/conference/#{conference3.short_title}/sponsors") + expect(page).to_not have_link('Supporter Levels', href: "/admin/conference/#{conference3.short_title}/supporter_levels") + expect(page).to_not have_link('E-Mails', href: "/admin/conference/#{conference3.short_title}/emails") + expect(page).to_not have_link('Call for papers', href: "/admin/conference/#{conference3.short_title}/callforpapers") + expect(page).to_not have_link('Tracks', href: "/admin/conference/#{conference3.short_title}/tracks") + expect(page).to_not have_link('Event types', href: "/admin/conference/#{conference3.short_title}/event_types") + expect(page).to_not have_link('Difficulty levels', href: "/admin/conference/#{conference3.short_title}/difficulty_levels") + expect(page).to have_link('Questions', href: "/admin/conference/#{conference3.short_title}/questions") + expect(page).to_not have_link('Roles', href: "/admin/conference/#{conference3.short_title}/roles") + + 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).to have_selector('li.nav-header.nav-header-bigger a', text: 'Dashboard') + expect(page).to have_link('Basics', href: "/admin/conference/#{conference4.short_title}/edit") + expect(page).to_not have_link('Contact', href: "/admin/conference/#{conference4.short_title}/contact/edit") + expect(page).to have_link('Commercials', href: "/admin/conference/#{conference4.short_title}/commercials") + expect(page).to_not have_link('Photos', href: "/admin/conference/#{conference4.short_title}/photos") + expect(page).to_not have_link('Events', href: "/admin/conference/#{conference4.short_title}/events") + expect(page).to_not have_link('Registrations', href: "/admin/conference/#{conference4.short_title}/registrations") + expect(page).to_not have_link('Schedule', href: "/admin/conference/#{conference4.short_title}/schedule") + expect(page).to_not have_link('Campaigns', href: "/admin/conference/#{conference4.short_title}/campaigns") + expect(page).to_not have_link('Targets', href: "/admin/conference/#{conference4.short_title}/targets") + expect(page).to_not have_link('Venue', href: "/admin/conference/#{conference4.short_title}/venue") + expect(page).to_not have_link('Rooms', href: "/admin/conference/#{conference4.short_title}/rooms") + expect(page).to_not have_link('Lodgings', href: "/admin/conference/#{conference4.short_title}/lodgings") + expect(page).to_not have_link('Sponsorship', href: "/admin/conference/#{conference4.short_title}/sponsorship_levels") + expect(page).to_not have_link('Sponsors', href: "/admin/conference/#{conference4.short_title}/sponsors") + expect(page).to_not have_link('Supporter Levels', href: "/admin/conference/#{conference4.short_title}/supporter_levels") + expect(page).to_not have_link('E-Mails', href: "/admin/conference/#{conference4.short_title}/emails") + expect(page).to_not have_link('Call for papers', href: "/admin/conference/#{conference4.short_title}/callforpapers") + expect(page).to_not have_link('Tracks', href: "/admin/conference/#{conference4.short_title}/tracks") + expect(page).to_not have_link('Event types', href: "/admin/conference/#{conference4.short_title}/event_types") + expect(page).to_not have_link('Difficulty levels', href: "/admin/conference/#{conference4.short_title}/difficulty_levels") + expect(page).to_not have_link('Questions', href: "/admin/conference/#{conference4.short_title}/questions") + expect(page).to_not have_link('Roles', href: "/admin/conference/#{conference4.short_title}/roles") + + 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(conference4.short_title) + expect(current_path).to eq(admin_conference_commercials_path(conference4.short_title)) + end +end diff --git a/spec/features/campaign_spec.rb b/spec/features/campaign_spec.rb index 9c71a759..21382655 100644 --- a/spec/features/campaign_spec.rb +++ b/spec/features/campaign_spec.rb @@ -2,16 +2,14 @@ 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!(:conference) { create(:conference, short_title: 'osc14') } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } - shared_examples 'add and update campaign' do |user| + shared_examples 'add and update campaign' do scenario 'adds and update a campaign', feature: true, js: true do expected_count = Campaign.count + 1 - conference = create(:conference, short_title: 'osc14') - sign_in create(user) + sign_in organizer visit admin_conference_campaigns_path(conference.short_title) @@ -42,7 +40,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 +50,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' end end diff --git a/spec/features/cfp_spec.rb b/spec/features/cfp_spec.rb index 4c185872..23f2458a 100644 --- a/spec/features/cfp_spec.rb +++ b/spec/features/cfp_spec.rb @@ -2,16 +2,15 @@ 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!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } - shared_examples 'add and update cfp' do |user| + shared_examples 'add and update cfp' do scenario 'adds a new cfp', feature: true, js: true do expected_count = CallForPapers.count + 1 - conference = create(:conference) - sign_in create(user) + + sign_in organizer visit admin_conference_callforpapers_path(conference.short_title) @@ -47,11 +46,10 @@ feature Conference do end scenario 'update cfp', feature: true, js: true do - conference = create(:conference) conference.call_for_papers = create(:call_for_papers) expected_count = CallForPapers.count - sign_in create(user) + sign_in organizer visit admin_conference_callforpapers_path(conference.short_title) # Validate update with empty start date will not saved @@ -87,8 +85,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' end end diff --git a/spec/features/commercials_spec.rb b/spec/features/commercials_spec.rb index e180443d..e53524b7 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(:organizer_role, 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..45977092 100644 --- a/spec/features/conference_spec.rb +++ b/spec/features/conference_spec.rb @@ -1,16 +1,12 @@ require 'spec_helper' feature Conference do + let!(:user) { create(:admin) } - # 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) } - - shared_examples 'add and update conference' do |user| + shared_examples 'add and update conference' do scenario 'adds a new conference', feature: true, js: true do expected_count = Conference.count + 1 - sign_in create(user) + sign_in user visit new_admin_conference_path fill_in 'conference_title', with: 'Example Con' @@ -31,12 +27,18 @@ feature Conference do expect(flash). to eq('Conference was successfully created.') expect(Conference.count).to eq(expected_count) + + expect(user.has_role? :organizer, Conference.last).to eq(true) end scenario 'update conference', feature: true, js: true do conference = create(:conference) + organizer_role = create(:organizer_role, resource: conference) + organizer = create(:user, role_ids: [organizer_role.id]) + expected_count = Conference.count - sign_in create(user) + + sign_in organizer visit edit_admin_conference_path(conference.short_title) click_link 'Edit' @@ -63,11 +65,6 @@ feature Conference do end describe 'admin' do - it_behaves_like 'add and update conference', :admin + it_behaves_like 'add and update conference' end - - describe 'organizer' do - it_behaves_like 'add and update conference', :organizer - end - end diff --git a/spec/features/contact_spec.rb b/spec/features/contact_spec.rb index 2a7bff79..1876ae0d 100644 --- a/spec/features/contact_spec.rb +++ b/spec/features/contact_spec.rb @@ -2,18 +2,16 @@ require 'spec_helper' feature Contact 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!(:organizer) { create(:user, email: 'admin@example.com', role_ids: [organizer_role.id]) } - shared_examples 'update a contact' do |user| + shared_examples 'update a contact' do scenario 'sucessfully', feature: true, js: true do - conference = create(:conference) contact = conference.contact expected_count = Contact.count - sign_in create(user) + sign_in organizer visit edit_admin_conference_contact_path(conference.short_title) click_link 'Edit' @@ -39,10 +37,6 @@ feature Contact do end end - describe 'admin' do - it_behaves_like 'update a contact', :admin - end - describe 'organizer' do it_behaves_like 'update a contact', :organizer end diff --git a/spec/features/difficulty_levels_spec.rb b/spec/features/difficulty_levels_spec.rb index 6dcfb990..b81f9d00 100644 --- a/spec/features/difficulty_levels_spec.rb +++ b/spec/features/difficulty_levels_spec.rb @@ -1,15 +1,14 @@ 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!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } - shared_examples 'difficulty levels' do |user| + shared_examples 'difficulty levels' do scenario 'adds and updates difficulty level', feature: true, js: true do - conference = create(:conference) - sign_in create(user) + + sign_in organizer visit admin_conference_difficulty_levels_path( conference_id: conference.short_title) @@ -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' end end diff --git a/spec/features/email_spec.rb b/spec/features/email_spec.rb index c5838f31..7ba66e17 100644 --- a/spec/features/email_spec.rb +++ b/spec/features/email_spec.rb @@ -1,19 +1,17 @@ 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!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } - shared_examples 'email settings' do |user| + shared_examples 'email settings' do scenario 'updates email settings', feature: true, js: true do - conference = create(:conference) expected_count = EmailSettings.count - sign_in create(user) + sign_in organizer visit admin_conference_emails_path(conference.short_title) @@ -91,11 +89,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' end end diff --git a/spec/features/event_types_spec.rb b/spec/features/event_types_spec.rb index c900c65d..a71aacfa 100644 --- a/spec/features/event_types_spec.rb +++ b/spec/features/event_types_spec.rb @@ -1,19 +1,18 @@ 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!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } - shared_examples 'event types' do |user| + shared_examples 'event types' do scenario 'adds and updates event type', feature: true, js: true do - conference = create(:conference) - sign_in create(user) - visit admin_conference_eventtypes_path( + + sign_in organizer + 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' end end diff --git a/spec/features/lodgings_spec.rb b/spec/features/lodgings_spec.rb index 10576cc9..89a73ea8 100644 --- a/spec/features/lodgings_spec.rb +++ b/spec/features/lodgings_spec.rb @@ -1,17 +1,16 @@ 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!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } - shared_examples 'lodgings' do |user| + shared_examples 'lodgings' do scenario 'adds and updates lodgings', feature: true, js: true do path = "#{Rails.root}/app/assets/images/rails.png" - conference = create(:conference) + conference.venue = create(:venue) - sign_in create(user) + sign_in organizer visit admin_conference_lodgings_path( conference_id: conference.short_title) # Add lodging @@ -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' end end diff --git a/spec/features/omniauth_spec.rb b/spec/features/omniauth_spec.rb index 41cbb76e..3d343a8f 100644 --- a/spec/features/omniauth_spec.rb +++ b/spec/features/omniauth_spec.rb @@ -1,9 +1,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 scenario 'has option to log in with Google account' do @@ -27,7 +24,7 @@ feature Openid do end scenario 'signs in an existing user' do - create(:participant, email: 'test-participant-1@google.com') + create(:user, email: 'test-participant-1@google.com') expected_count_openid = Openid.count + 1 expected_count_user = User.count visit '/accounts/sign_in' @@ -54,7 +51,7 @@ feature Openid do scenario 'adds openid to existing user' do # Sign in user - user = create(:participant, email: 'test-participant-1@google.com') + user = create(:user, email: 'test-participant-1@google.com') sign_in user # Add openID to current user @@ -74,7 +71,7 @@ feature Openid do scenario 'signs in with openID using the same email as another associated openid' do # Sign in user - create(:participant, email: 'test-participant-1@google.com') + create(:user, email: 'test-participant-1@google.com') expected_count_openid = Openid.count + 1 expected_count_user = User.count visit '/accounts/sign_in' diff --git a/spec/features/photo_spec.rb b/spec/features/photo_spec.rb index c9150b30..9f9a94c0 100644 --- a/spec/features/photo_spec.rb +++ b/spec/features/photo_spec.rb @@ -2,16 +2,15 @@ require 'spec_helper' feature Photo 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!(:organizer) { create(:user, email: 'admin@example.com', role_ids: [organizer_role.id]) } - shared_examples 'add and update photo' do |user| + shared_examples 'add and update photo' do scenario 'adds a new photo', feature: true, js: true do expected_count = Photo.count + 1 - conference = create(:conference) - sign_in create(user) + + sign_in organizer visit new_admin_conference_photo_path(conference.short_title) @@ -28,9 +27,8 @@ feature Photo do scenario 'updates a photo', feature: true, js: true do expected_count = Photo.count + 1 - conference = create(:conference) - photo = create(:photo) - sign_in create(user) + photo = create(:photo, conference_id: conference.id) + sign_in organizer visit edit_admin_conference_photo_path(conference.short_title, photo.id) @@ -47,8 +45,7 @@ feature Photo do scenario 'adds a text file', feature: true, js: true do expected_count = Photo.count - conference = create(:conference) - sign_in create(user) + sign_in organizer visit new_admin_conference_photo_path(conference.short_title) @@ -64,12 +61,8 @@ feature Photo do end end - describe 'admin' do - it_behaves_like 'add and update photo', :admin - end - describe 'organizer' do - it_behaves_like 'add and update photo', :organizer + it_behaves_like 'add and update photo' end end diff --git a/spec/features/proposal_spec.rb b/spec/features/proposal_spec.rb index 68c5f9e0..1f4aa796 100644 --- a/spec/features/proposal_spec.rb +++ b/spec/features/proposal_spec.rb @@ -1,20 +1,17 @@ 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!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, email: 'admin@example.com', role_ids: [organizer_role.id]) } + let!(:participant) { create(:user, biography: '') } 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: "") - expected_count = Event.count + 1 - conference = create(:conference) + conference.call_for_papers = create(:call_for_papers) conference.email_settings = create(:email_settings) conference.event_types = [create(:event_type)] @@ -38,7 +35,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 +96,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..23911004 100644 --- a/spec/features/rooms_spec.rb +++ b/spec/features/rooms_spec.rb @@ -1,15 +1,14 @@ 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!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } - shared_examples 'rooms' do |user| + shared_examples 'rooms' do scenario 'adds and updates rooms', feature: true, js: true do - conference = create(:conference) - sign_in create(user) + + sign_in organizer visit admin_conference_rooms_path( conference_id: conference.short_title) @@ -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' end end diff --git a/spec/features/sponsor_spec.rb b/spec/features/sponsor_spec.rb index 24998340..79d3fcf0 100644 --- a/spec/features/sponsor_spec.rb +++ b/spec/features/sponsor_spec.rb @@ -1,17 +1,16 @@ 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!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } - shared_examples 'sponsors' do |user| + shared_examples 'sponsors' do scenario 'adds and updates sponsors', feature: true, js: true do path = "#{Rails.root}/app/assets/images/rails.png" - conference = create(:conference) + conference.sponsorship_levels << create(:sponsorship_level, conference: conference) - sign_in create(user) + sign_in organizer visit admin_conference_sponsors_path( conference_id: conference.short_title) @@ -63,17 +62,15 @@ feature Sponsor do # Remove sponsor click_link 'Remove sponsor' expect(page.all('div.nested-fields').count == 0).to be true - click_button 'Update Conference' + + find('button', text: 'Update Conference').trigger('click') + expect(flash).to eq('Sponsorships were successfully updated.') expect(page.all('div.nested-fields').count == 0).to be true end end - describe 'admin' do - it_behaves_like 'sponsors', :admin - end - describe 'organizer' do - it_behaves_like 'sponsors', :organizer + it_behaves_like 'sponsors' end end diff --git a/spec/features/sponsorship_level_spec.rb b/spec/features/sponsorship_level_spec.rb index c6f75ce4..229cb926 100644 --- a/spec/features/sponsorship_level_spec.rb +++ b/spec/features/sponsorship_level_spec.rb @@ -1,15 +1,14 @@ 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) } - 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!(:organizer) { create(:user, role_ids: [organizer_role.id]) } - shared_examples 'sponsorship levels' do |user| + shared_examples 'sponsorship levels' do scenario 'adds and updates sponsorship level', feature: true, js: true do - conference = create(:conference) - sign_in create(user) + + sign_in organizer visit admin_conference_sponsorship_levels_path( conference_id: conference.short_title) # Add sponsorship level @@ -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' 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..3d2949e2 100644 --- a/spec/features/tracks_spec.rb +++ b/spec/features/tracks_spec.rb @@ -1,15 +1,15 @@ 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!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } - shared_examples 'tracks' do |user| + shared_examples 'tracks' do scenario 'adds and updates tracks', feature: true, js: true do - conference = create(:conference) - sign_in create(user) + + sign_in organizer + visit admin_conference_tracks_path( conference_id: conference.short_title) @@ -50,11 +50,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' 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..ac28a55a 100644 --- a/spec/features/venue_spec.rb +++ b/spec/features/venue_spec.rb @@ -1,17 +1,15 @@ require 'spec_helper' feature Conference do + let!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } - # 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) } - - shared_examples 'venue' do |user| + shared_examples 'venue' do scenario 'adds and updates venue' do - conference = create(:conference) - sign_in create(user) + sign_in organizer + visit admin_conference_venue_info_path( conference_id: conference.short_title) @@ -59,12 +57,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' end end diff --git a/spec/features/volunteers_spec.rb b/spec/features/volunteers_spec.rb index bb82c468..20242781 100644 --- a/spec/features/volunteers_spec.rb +++ b/spec/features/volunteers_spec.rb @@ -1,16 +1,13 @@ 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(:conference) { create(:conference) } + let!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } 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 +51,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 +116,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..a95613ba 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(:user) } + 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 - let(:user) { create(:participant) } - let(:user2) { create(:participant) } + 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(:user) } + let(:user2) { create(:user) } 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..4336ef80 100644 --- a/spec/models/conference_spec.rb +++ b/spec/models/conference_spec.rb @@ -273,10 +273,9 @@ describe Conference do end 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!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } 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 @@ -896,10 +895,9 @@ describe Conference do end 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!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } it 'self#event_distribution calculates correct values with user' do create(:user, last_sign_in_at: Date.today - 3.months) # active @@ -1426,9 +1424,9 @@ 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!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } let(:user) { create(:user) } diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index ffbcb1c4..be110312 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -3,66 +3,51 @@ 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!(:user_admin) { create(:user) } + let!(:admin) { create(:admin) } + let!(:participant) { create(:user) } + let!(:conference) { create(:conference) } + let!(:organizer_role) { create(:organizer_role, resource: conference) } + let!(:cfp_role) { create(:cfp_role, resource: conference) } + let!(:organizer) { create(:user, role_ids: [organizer_role.id]) } 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(user_admin.is_admin).to eq(true) + expect(organizer.roles.first).to eq(organizer_role) end it 'returns the correct roles' do - roles = [organizer_role.id, participant_role.id, admin_role.id] - user_with_all_roles = create(:user, email: 'participant@example.de') - user_with_all_roles.role_ids = roles - user_with_all_roles.save + roles = [organizer_role.id, cfp_role.id] + another_user = create(:user, email: 'participant@example.de') + another_user.role_ids = roles + another_user.save - expect(user_with_all_roles.roles.length).to eq(3) - 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(another_user.roles.length).to eq(2) + expect(another_user.roles[0]).to eq(organizer_role) + expect(another_user.roles[1]).to eq(cfp_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]) + user_obj = create(user) + expect(user_obj.has_role?(role.downcase, conference)).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, 'organizer', true + it_behaves_like '#role?', :organizer, 'participant', false + end + + context 'admin' do + it 'assigns first user admin role' do + expect(User.first.is_admin).to be true + end + end + + context 'participant' do + it_behaves_like '#role?', :user, 'adMin', false 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/roles.html.haml_spec.rb b/spec/views/admin/conference/roles.html.haml_spec.rb new file mode 100644 index 00000000..0223cf4c --- /dev/null +++ b/spec/views/admin/conference/roles.html.haml_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe 'admin/conference/roles' do + let(:conference) { create(:conference) } + let(:organizer_role) { create(:organizer_role, description: 'My description for organizer role', resource: conference) } + let(:organizer) { create(:user, name: 'test name', email: 'test@email.com', role_ids: [organizer_role.id]) } + + it 'renders the roles template for the conference' do + assign :conference, conference + assign :selection, 'organizer' + assign :role, [organizer_role] + assign :role_users, 'organizer' => [organizer] + render + expect(rendered).to include('Show users for role:') + expect(rendered).to include(organizer_role.description) + expect(rendered).to include("Add role 'Organizer' to user:") + expect(rendered).to include('Add role') + expect(rendered).to include('Users with role Organizer') + expect(rendered).to have_selector("table thead th:nth-of-type(1)", text: 'ID') + expect(rendered).to have_selector("table thead th:nth-of-type(2)", text: 'Name') + expect(rendered).to have_selector("table thead th:nth-of-type(3)", text: 'Email') + expect(rendered).to have_selector("table tbody tr:nth-of-type(1) td:nth-of-type(1)", text: organizer.id) + expect(rendered).to have_selector("table tbody tr:nth-of-type(1) td:nth-of-type(2)", text: 'test name') + expect(rendered).to have_selector("table tbody tr:nth-of-type(1) td:nth-of-type(3)", text: 'test@email.com') + 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