From 6f0cedff4077c1609d32567bfb889fc8fa908db7 Mon Sep 17 00:00:00 2001 From: Brent Date: Fri, 26 Jan 2018 06:30:15 +0700 Subject: [PATCH] Allow guests to update an event (fat_model_auth). - Using my fat_model_auth gem to allow both the organiser and any guests of an event to update the event information. --- Gemfile | 3 +-- Gemfile.lock | 2 ++ app/controllers/events_controller.rb | 7 ++++--- app/models/event.rb | 7 +++++++ app/models/group.rb | 2 ++ spec/factories/user_factory.rb | 5 +++++ spec/requests/events_request_spec.rb | 29 +++++++++++++++++++++++++--- 7 files changed, 47 insertions(+), 8 deletions(-) diff --git a/Gemfile b/Gemfile index e6e15e0..b5619b3 100644 --- a/Gemfile +++ b/Gemfile @@ -11,6 +11,7 @@ gem 'puma', '~> 3.7' gem 'paranoia' gem 'acts_as_human' +gem 'fat_model_auth'#, path: '/Users/hit/projects/fat_model_auth' gem 'active_model_serializers' gem 'bcrypt' gem 'jwt' @@ -19,8 +20,6 @@ gem 'jwt' # gem 'jbuilder', '~> 2.5' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 3.0' -# Use ActiveModel has_secure_password -# gem 'bcrypt', '~> 3.1.7' # Use Capistrano for deployment # gem 'capistrano-rails', group: :development diff --git a/Gemfile.lock b/Gemfile.lock index 787cc47..5160d16 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -61,6 +61,7 @@ GEM factory_girl_rails (4.8.0) factory_girl (~> 4.8.0) railties (>= 3.0.0) + fat_model_auth (4.0.0) ffi (1.9.18) formatador (0.2.5) globalid (0.4.0) @@ -198,6 +199,7 @@ DEPENDENCIES bcrypt byebug factory_girl_rails + fat_model_auth guard-rspec jwt listen (>= 3.0.5, < 3.2) diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index a598cd2..75d21a6 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -1,6 +1,7 @@ class EventsController < ApplicationController before_action :load_current_user - before_action :load_event, only: [:update, :destroy] + before_action :load_event, only: :update + before_action :auth_required, only: :update def index render json: current_user.events @@ -16,7 +17,7 @@ def update end def destroy - @event.destroy + current_user.events.find( params[:id] ).destroy end private @@ -32,6 +33,6 @@ def event_params end def load_event - @event = current_user.events.find params[:id] + @event = Event.find params[:id] end end diff --git a/app/models/event.rb b/app/models/event.rb index 13f1e53..29c9889 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -7,6 +7,13 @@ class Event < ApplicationRecord belongs_to :group accepts_nested_attributes_for :group + delegate :guests, to: :group + + allows :update, + if: -> (event, user) do + event.organiser == user || event.guests.include?( user ) + end + before_validation :calc_duration, if: :has_dates? validates :name, :location, :starting, :ending, :description, diff --git a/app/models/group.rb b/app/models/group.rb index f88156f..db3808f 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -4,4 +4,6 @@ class Group < ApplicationRecord has_many :group_users accepts_nested_attributes_for :group_users + + has_many :guests, through: 'group_users', source: 'user' end diff --git a/spec/factories/user_factory.rb b/spec/factories/user_factory.rb index 76b0580..061de2c 100644 --- a/spec/factories/user_factory.rb +++ b/spec/factories/user_factory.rb @@ -16,5 +16,10 @@ email 'someone@example.com' password 'strange' end + + factory :guest do + full_name 'Invited Person' + email { "invited#{User.count}@example.com" } + end end end diff --git a/spec/requests/events_request_spec.rb b/spec/requests/events_request_spec.rb index 2eb7b9e..7076bab 100644 --- a/spec/requests/events_request_spec.rb +++ b/spec/requests/events_request_spec.rb @@ -76,8 +76,8 @@ def auth(user) }.to change(GroupUser, :count).by(2) end - let(:guest1) { create(:user) } - let(:guest2) { create(:user) } + let(:guest1) { create(:guest) } + let(:guest2) { create(:guest) } def event attributes_for(:event).merge({ @@ -222,13 +222,24 @@ def invalid end context 'by a different user' do - before { patch "/events/#{event.to_param}", params: {event: ev}, headers: auth(create(:someone_else)) } + before { patch "/events/#{event.to_param}", params: {event: ev}, headers: auth(someone_else) } it 'is not found' do expect( response ).to have_http_status(404) end end + context 'by a guest' do + before { event.guests << guest1 } + + before { patch "/events/#{event.to_param}", params: {event: ev}, headers: auth(guest1) } + + it 'is allowed' do + expect( response ).to have_http_status(204) + expect( event.reload.name ).to eq 'New Name' + end + end + context 'with a new group name' do before { patch "/events/#{event.to_param}", params: {event: new_group_name}, headers: auth(organiser) } @@ -247,6 +258,8 @@ def new_group_name end end + let(:someone_else) { create(:someone_else) } + # DELETE describe '#Destroying an Event' do let(:event) { create(:event, organiser: organiser) } @@ -277,6 +290,16 @@ def new_group_name end end + context 'by a guest' do + before { event.guests << guest1 } + + before { delete "/events/#{event.to_param}", headers: auth(guest1) } + + it 'is not found' do + expect( response ).to have_http_status(404) + end + end + it_behaves_like 'an action that requires authorization' do let(:action) { "delete#events/#{event.to_param}" } let(:params) { {} }