Skip to content

Commit

Permalink
Add a LocationPolicy to handle edit/archive permissions
Browse files Browse the repository at this point in the history
Create a separate "archive" action rather than handling update
and archive in the "update" action.

This requires adding some JS magic to swap out the `action`
of the Location form right when the user clicks it.
It looks like <input type='submit' data-custom-action='beep/boop'>
  • Loading branch information
tjgrathwell committed Feb 19, 2016
1 parent de2e2e4 commit 9a99904
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 25 deletions.
4 changes: 4 additions & 0 deletions app/assets/javascripts/forms.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
jQuery ->
$('input[type=submit][data-custom-action]').click (e) ->
$input = $(e.target)
$input.closest('form').attr('action', $input.data('custom-action'))
33 changes: 16 additions & 17 deletions app/controllers/locations_controller.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
class LocationsController < ApplicationController
before_action :authenticate_user!, except: [:show, :index]
before_action :assign_location, only: [:show, :edit, :update, :destroy]
before_action :skip_authorization
before_action :assign_location, only: [:show, :edit, :update, :destroy, :archive]

def index
skip_authorization
@locations = Location.all.includes(:events, :event_sessions)
end

def show
skip_authorization
end

def new
skip_authorization
@location = Location.new
end

def edit
skip_authorization
end

def create
skip_authorization
@location = Location.new(location_params)

respond_to do |format|
Expand All @@ -31,19 +35,16 @@ def create
end
end

def update
if params[:commit] == 'Archive Location'
if @location.archivable_by?(current_user)
@location.archive!
return redirect_to locations_path, notice: 'Location was successfully archived.'
else
return redirect_to @location, alert: 'This location is only editable by admins and organizers of events that have taken place there.'
end
end
def archive
authorize @location

unless @location.editable_by?(current_user)
return redirect_to @location, alert: 'This location is only editable by admins and organizers of events that have taken place there.'
end
@location.archive!

redirect_to locations_path, notice: 'Location was successfully archived.'
end

def update
authorize @location, :edit?

@location.gmaps = false

Expand All @@ -55,9 +56,7 @@ def update
end

def destroy
if @location.events.count > 0
return redirect_to root_url, alert: "Can't delete a location that's still assigned to an event."
end
authorize @location

@location.destroy

Expand Down
13 changes: 13 additions & 0 deletions app/policies/location_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class LocationPolicy < ApplicationPolicy
def destroy?
record.events.count == 0
end

def archive?
record.archivable_by?(user)
end

def edit?
record.editable_by?(user)
end
end
11 changes: 5 additions & 6 deletions app/views/locations/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@
<% remote = modal ? true : false %>

<div class="row">
<% if remote %>
<div class="col-md-12">
<% else %>
<div class="col-md-6">
<% end %>
<div class="<%= remote ? 'col-md-12' : 'col-md-6' %>">

<%= simple_form_for(@location, remote: remote, html: {role: :form, 'data-model' => 'location'}) do |f| %>
<%= render 'shared/model_error_messages', model: @location %>
Expand All @@ -33,7 +29,10 @@
<div class="actions">
<%= f.submit class: 'btn btn-submit', data: {disable_with: 'Please wait...'} %>
<% if @location.archivable_by?(current_user) %>
<%= f.submit 'Archive Location', class: 'btn btn-warning', data: {disable_with: 'Please wait...'} %>
<%= f.submit 'Archive Location', class: 'btn btn-warning', data: {
disable_with: 'Please wait...',
custom_action: archive_location_path(@location)
} %>
<% end %>
</div>
<% end %>
Expand Down
4 changes: 3 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
end
resources :meetup_users, only: [:show]

resources :locations
resources :locations do
patch :archive, on: :member
end
resources :chapters do
resources :leaders, only: [:index, :create, :destroy], controller: 'chapters/leaders' do
get :potential, on: :collection
Expand Down
2 changes: 1 addition & 1 deletion spec/features/locations_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
expect(location.notes).to eq('cool notes')
end

it "can archive a location that is no longer available" do
it "can archive a location that is no longer available", js: true do
visit edit_location_path(location)
click_button "Archive Location"

Expand Down

0 comments on commit 9a99904

Please sign in to comment.