Skip to content

Commit

Permalink
Implement track requests and add the track organizer role
Browse files Browse the repository at this point in the history
About track requests:
Create migration that adds the fields submitter_id, state, and
cfp_active to Tracks
Add validations and the self_organized? method to the Track model
Create a new TracksController outide of the admin namespace
Create the relevant views for index, show, new and edit
Modify the admin views for tracks to include extra info for
self-organized tracks

About track organizers:
Create the role when a self-organized track is created
Define track organizer abilities
Modify the roles views and controller to handle the new role

The route for Roles#edit needs to have higher priority than the nested
routes for track roles, otherwise, the word edit in the url is matched
as a track with short_name edit
  • Loading branch information
AEtherC0r3 authored and differentreality committed Jul 14, 2017
1 parent 98fc113 commit 68fc750
Show file tree
Hide file tree
Showing 26 changed files with 766 additions and 27 deletions.
6 changes: 6 additions & 0 deletions .haml-lint_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ linters:
- "app/views/users/edit.html.haml"
- "app/views/users/show.html.haml"
- "app/views/admin/cfps/index.html.haml"
- "app/views/tracks/_form.html.haml"
- "app/views/tracks/index.html.haml"
- "app/views/tracks/show.html.haml"

# Offense count: 223
InstanceVariables:
Expand Down Expand Up @@ -231,6 +234,7 @@ linters:
- "app/views/schedules/_schedule_item.html.haml"
- "app/views/schedules/_schedule_tabs.html.haml"
- "app/views/admin/cfps/_events_cfp.html.haml"
- "app/views/tracks/_form.html.haml"

# Offense count: 32
IdNames:
Expand Down Expand Up @@ -330,6 +334,8 @@ linters:
- "app/views/shared/_object_changes.html.haml"
- "app/views/tickets/_ticket.html.haml"
- "app/views/tickets/index.html.haml"
- "app/views/tracks/index.html.haml"
- "app/views/tracks/show.html.haml"

# Offense count: 23
ClassesBeforeIds:
Expand Down
1 change: 1 addition & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ Metrics/BlockLength:
Exclude:
- 'spec/models/conference_spec.rb'
- 'spec/features/ability_spec.rb'
- 'spec/models/ability_spec.rb'
3 changes: 3 additions & 0 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ Metrics/ModuleLength:
# Offense count: 14
Metrics/PerceivedComplexity:
Max: 15
Exclude:
- 'app/controllers/admin/roles_controller.rb'

# Offense count: 11
# Cop supports --auto-correct.
Expand Down Expand Up @@ -850,6 +852,7 @@ Style/SymbolProc:
- 'app/controllers/admin/questions_controller.rb'
- 'app/helpers/application_helper.rb'
- 'app/models/ability.rb'
- 'app/models/admin_ability.rb'
- 'db/migrate/20140730104658_migrate_roles_for_cancancan.rb'
- 'spec/controllers/admin/conferences_controller_spec.rb'
- 'spec/support/flash.rb'
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/admin/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ def verify_user_admin
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? :organization_admin, :any) ||
(current_user.has_role? :volunteers_coordinator, :any) || current_user.is_admin
(current_user.has_role? :volunteers_coordinator, :any) ||
(current_user.has_role? :track_organizer, :any) || current_user.is_admin
raise CanCan::AccessDenied.new('You are not authorized to access this page.')
end
end
Expand Down
49 changes: 42 additions & 7 deletions app/controllers/admin/roles_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,40 @@ class RolesController < Admin::BaseController

def index
@roles = Role.where(resource: @conference)
tracks = @conference.program.tracks.where.not(submitter: nil)
@roles += Role.where(resource: tracks)
authorize! :index, @role
end

def show
@url = if @track
toggle_user_track_admin_conference_role_path(@conference.short_title, @role.name, @track.name.tr(' ', '_'))
else
toggle_user_admin_conference_role_path(@conference.short_title, @role.name)
end
@users = @role.users
end

def edit
@url = if @track
track_admin_conference_role_path(@conference.short_title, @role.name, @track.name.tr(' ', '_'))
else
admin_conference_role_path(@conference.short_title, @role.name)
end
@users = @role.users
end

def update
role_name = @role.name

if @role.update_attributes(role_params)
redirect_to admin_conference_role_path(@conference.short_title, @role.name),
url = if @track
track_admin_conference_role_path(@conference.short_title, @role.name, @track.name.tr(' ', '_'))
else
admin_conference_role_path(@conference.short_title, @role.name)
end

redirect_to url,
notice: 'Successfully updated role ' + @role.name
else
@role.name = role_name
Expand All @@ -36,8 +54,14 @@ def toggle_user
user = User.find_by(email: user_params[:email])
state = user_params[:state]

url = if @track
track_admin_conference_role_path(@conference.short_title, @role.name, @track.name.tr(' ', '_'))
else
admin_conference_role_path(@conference.short_title, @role.name)
end

unless user
redirect_to admin_conference_role_path(@conference.short_title, @role.name),
redirect_to url,
error: 'Could not find user. Please provide a valid email!'
return
end
Expand All @@ -49,25 +73,31 @@ def toggle_user
return
end

if @role.resource_type == 'Conference'
role_resource = @conference
elsif @role.resource_type == 'Track'
role_resource = @track
end

# Remove user
if state == 'false'
if user.remove_role @role.name, @conference
if user.remove_role @role.name, role_resource
flash[:notice] = "Successfully removed role #{@role.name} from user #{user.email}"
else
flash[:error] = "Could not remove role #{@role.name} from user #{user.email}"
end
elsif user.has_role? @role.name, @conference
elsif user.has_role? @role.name, role_resource
flash[:error] = "User #{user.email} already has the role #{@role.name}"
# Add user
elsif user.add_role @role.name, @conference
elsif user.add_role @role.name, role_resource
flash[:notice] = "Successfully added role #{@role.name} to user #{user.email}"
else
flash[:error] = "Coud not add role #{@role.name} to #{user.email}"
end

respond_to do |format|
format.js
format.html { redirect_to admin_conference_role_path(@conference.short_title, @role.name) }
format.html { redirect_to url }
end
end

Expand All @@ -77,7 +107,12 @@ def set_selection
# Set 'organizer' as default role, when there is no other selection
@selection = params[:id] ? params[:id].parameterize.underscore : 'organizer'

@role = Role.find_by(name: @selection, resource: @conference)
if @selection == 'track_organizer'
@track = @conference.program.tracks.find_by(short_name: params[:track_name])
@role = Role.find_by(name: @selection, resource: @track)
else
@role = Role.find_by(name: @selection, resource: @conference)
end
end

def role_params
Expand Down
11 changes: 10 additions & 1 deletion app/controllers/admin/tracks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,19 @@ def destroy
end
end

def toggle_cfp_inclusion
@track.cfp_active = !@track.cfp_active
if @track.save
head :ok
else
head :unprocessable_entity
end
end

private

def track_params
params.require(:track).permit(:name, :description, :color, :short_name)
params.require(:track).permit(:name, :description, :color, :short_name, :cfp_active)
end
end
end
47 changes: 47 additions & 0 deletions app/controllers/tracks_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
class TracksController < ApplicationController
load_resource :conference, find_by: :short_title
load_resource :program, through: :conference, singleton: true
load_and_authorize_resource through: :program, find_by: :short_name

def index
@tracks = current_user.tracks.where(program: @program)
end

def show; end

def new
@track = @program.tracks.new(color: @conference.next_color_for_collection(:tracks))
end

def edit; end

def create
@track = @program.tracks.new(track_params)
@track.submitter = current_user
@track.state = 'new'
@track.cfp_active = false
if @track.save
redirect_to conference_program_tracks_path(conference_id: @conference.short_title),
notice: 'Track request successfully created.'
else
flash.now[:error] = "Creating Track request failed: #{@track.errors.full_messages.join('. ')}."
render :new
end
end

def update
if @track.update_attributes(track_params)
redirect_to admin_conference_program_tracks_path(conference_id: @conference.short_title),
notice: 'Track request successfully updated.'
else
flash.now[:error] = "Track request update failed: #{@track.errors.full_messages.join('. ')}."
render :edit
end
end

private

def track_params
params.require(:track).permit(:name, :description, :color, :short_name)
end
end
50 changes: 45 additions & 5 deletions app/models/admin_ability.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ def common_abilities_for_roles(user)
cannot :destroy, Venue do |venue|
venue.conference.program.events.where.not(room_id: nil).any?
end

# Prevent requests for tracks from being destroyed
cannot :destroy, Track do |track|
track.self_organized?
end
end

# Abilities for signed in users with roles
Expand All @@ -79,6 +84,7 @@ def signed_in_with_roles(user)
signed_in_with_cfp_role(user) if user.has_role? :cfp, :any
signed_in_with_info_desk_role(user) if user.has_role? :info_desk, :any
signed_in_with_volunteers_coordinator_role(user) if user.has_role? :volunteers_coordinator, :any
signed_in_with_track_organizer_role(user) if user.has_role? :track_organizer, :any
common_abilities_for_roles(user)
end

Expand All @@ -100,6 +106,9 @@ def signed_in_with_organizer_role(user, conf_ids_for_organization_admin = [])
# ids of all the conferences for which the user has the 'organizer' role and
# conferences that belong to organizations for which user is 'organization_admin'
conf_ids = conf_ids_for_organization_admin.concat(Conference.with_role(:organizer, user).pluck(:id)).uniq
# ids of all the tracks that belong to the programs of the above conferences
track_ids = Track.joins(:program).where('programs.conference_id IN (?)', conf_ids).pluck(:id)

can :manage, Resource, conference_id: conf_ids
can [:read, :update, :destroy], Conference, id: conf_ids
can :manage, Splashpage, conference_id: conf_ids
Expand Down Expand Up @@ -140,11 +149,12 @@ def signed_in_with_organizer_role(user, conf_ids_for_organization_admin = [])

# Abilities for Role (Conference resource)
can [:index, :show], Role do |role|
role.resource_type == 'Conference'
role.resource_type == 'Conference' || role.resource_type == 'Track'
end

can [:edit, :update, :toggle_user], Role do |role|
role.resource_type == 'Conference' && (conf_ids.include? role.resource_id)
role.resource_type == 'Conference' && (conf_ids.include? role.resource_id) ||
role.resource_type == 'Track' && (track_ids.include? role.resource_id)
end

can [:index, :revert_object, :revert_attribute], PaperTrail::Version do |version|
Expand Down Expand Up @@ -178,7 +188,7 @@ def signed_in_with_cfp_role(user)

# Abilities for Role (Conference resource)
can [:index, :show], Role do |role|
role.resource_type == 'Conference'
role.resource_type == 'Conference' || role.resource_type == 'Track'
end
# Can add or remove users from role, when user has that same role for the conference
# Eg. If you are member of the CfP team, you can add more CfP team members (add users to the role 'CfP')
Expand Down Expand Up @@ -211,7 +221,7 @@ def signed_in_with_info_desk_role(user)

# Abilities for Role (Conference resource)
can [:index, :show], Role do |role|
role.resource_type == 'Conference'
role.resource_type == 'Conference' || role.resource_type == 'Track'
end
# Can add or remove users from role, when user has that same role for the conference
# Eg. If you are member of the CfP team, you can add more CfP team members (add users to the role 'CfP')
Expand All @@ -234,7 +244,7 @@ def signed_in_with_volunteers_coordinator_role(user)

# Abilities for Role (Conference resource)
can [:index, :show], Role do |role|
role.resource_type == 'Conference'
role.resource_type == 'Conference' || role.resource_type == 'Track'
end
# Can add or remove users from role, when user has that same role for the conference
# Eg. If you are member of the CfP team, you can add more CfP team members (add users to the role 'CfP')
Expand All @@ -243,4 +253,34 @@ def signed_in_with_volunteers_coordinator_role(user)
(Conference.with_role(:volunteers_coordinator, user).pluck(:id).include? role.resource_id)
end
end

def signed_in_with_track_organizer_role(user)
# ids of all the conferences for which the user has the 'track organizer' role
conf_ids_for_track_organizer = Track.with_role(:track_organizer, user).joins(:program).pluck(:conference_id)
# ids of all the tracks for which the user has the 'track_organizer' role
track_ids_for_track_organizer = Track.with_role(:track_organizer, user).pluck(:id)

can :show, Conference do |conf|
conf_ids_for_track_organizer.include?(conf.id)
end

# Show Program in the admin sidebar
can :show, Program, conference_id: conf_ids_for_track_organizer

# Show Tracks in the admin sidebar
can :update, Track do |track|
track.new_record? && conf_ids_for_track_organizer.include?(track.program.conference_id)
end

can :manage, Track, id: track_ids_for_track_organizer

# Show Roles in the admin sidebar and allow authorization of the index action
can [:index, :show], Role do |role|
role.resource_type == 'Conference' || role.resource_type == 'Track'
end

can :toggle_user, Role do |role|
role.resource_type == 'Track' && track_ids_for_track_organizer.include?(role.resource_id)
end
end
end
24 changes: 24 additions & 0 deletions app/models/track.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
class Track < ActiveRecord::Base
include RevisionCount

resourcify :roles, dependent: :delete_all

belongs_to :program
belongs_to :submitter, class_name: 'User'
has_many :events, dependent: :nullify

has_paper_trail only: [:name, :description, :color], meta: { conference_id: :conference_id }
Expand All @@ -14,13 +18,27 @@ class Track < ActiveRecord::Base
uniqueness: {
scope: :program
}
validates :state, presence: true, if: :self_organized?
validates :cfp_active, inclusion: { in: [true, false] }, if: :self_organized?

before_validation :capitalize_color

after_create :create_organizer_role, if: :self_organized?

def conference
program.conference
end

##
# Checks if the track is self-organized
# ====Returns
# * +true+ -> If the track has a submitter
# * +false+ -> if the track doesn't have a submitter
def self_organized?
return true if submitter
false
end

private

def generate_guid
Expand All @@ -38,4 +56,10 @@ def capitalize_color
def conference_id
program.conference_id
end

##
# Creates the role of the track organizer
def create_organizer_role
Role.where(name: 'track_organizer', resource: self).first_or_create(description: 'For the organizers of the Track')
end
end
Loading

0 comments on commit 68fc750

Please sign in to comment.