diff --git a/Gemfile b/Gemfile index e3efa72..a6099ae 100644 --- a/Gemfile +++ b/Gemfile @@ -10,6 +10,7 @@ gem 'bootsnap', require: false gem 'draper' gem 'pg', '>= 0.18', '< 2.0' gem 'puma' +gem 'pundit' gem 'rails', '= 5.2.2' gem 'slim-rails' gem 'webpacker', '~> 3' # 3.x does not support npm package webpack 4.x. Will be fixed in 4.x. diff --git a/Gemfile.lock b/Gemfile.lock index 8c961ee..814850c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -124,6 +124,8 @@ GEM pry-rails (0.3.9) pry (>= 0.10.4) puma (3.12.0) + pundit (2.0.1) + activesupport (>= 3.0.0) rack (2.0.6) rack-proxy (0.6.5) rack @@ -215,6 +217,7 @@ DEPENDENCIES pry-byebug pry-rails puma + pundit rails (= 5.2.2) slim-rails spring diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 7944f9f..ee5fd0e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,4 +1,15 @@ # frozen_string_literal: true class ApplicationController < ActionController::Base + include Pundit + + delegate :current_user, to: :helpers, allow_nil: true + + rescue_from Pundit::NotAuthorizedError, with: :redirect_user_back + + private + + def redirect_user_back + redirect_back(fallback_location: root_path, alert: 'You are not authorized to perform this action.') + end end diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index cd75764..76e1ea4 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -2,11 +2,12 @@ class NotesController < ApplicationController def index - @notes = Note.not_ended.not_completed.decorate + @notes = policy_scope(Note).decorate end def show @note = Note.find(params[:id]).decorate + authorize(@note) end def new @@ -25,10 +26,14 @@ def create def edit @note = Note.find(params[:id]) + authorize(@note) + end def update @note = Note.find(params[:id]) + authorize(@note) + if @note.update(note_params) redirect_to @note, notice: 'Note successfully updated.' else @@ -38,18 +43,21 @@ def update def complete @note = Note.find(params[:id]) + authorize(@note) + service = Notes::Complete.new(note: @note) if service.save flash[:notice] = 'Note successfully marked as completed.' + redirect_to notes_path else flash[:alert] = "Note not marked as completed: #{service.errors.full_messages.join(', ')}" + redirect_to @note end - redirect_to @note end private def note_params - params.require(:note).permit(:title, :description, :started_at, :ended_at).merge(user: helpers.current_user) + params.require(:note).permit(:title, :description, :started_at, :ended_at).merge(user: current_user) end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index f376ce9..1af115b 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -2,10 +2,14 @@ class SessionsController < ApplicationController def new + authorize(:session) + @login = Login.new end def create + authorize(:session) + @login = Login.new(user_params) if @login.save helpers.log_in(@login.user) @@ -16,6 +20,8 @@ def create end def destroy + authorize(:session) + helpers.log_out redirect_to notes_path, notice: 'Successfully logged out.' end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 6d90b0f..a5a64cc 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -2,10 +2,14 @@ class UsersController < ApplicationController def new + authorize(:register) + @register = Register.new end def create + authorize(:register) + @register = Register.new(user_params) if @register.save helpers.log_in(@register.user) diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb new file mode 100644 index 0000000..965fa3b --- /dev/null +++ b/app/policies/application_policy.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +class ApplicationPolicy + attr_reader :user, :record + + class Scope + attr_reader :user, :scope + + def initialize(user, scope) + @user = user + @scope = scope + end + + def resolve + scope.all + end + end + + def initialize(user, record) + @user = user + @record = record + end + + def index? + false + end + + def show? + false + end + + def new? + create? + end + + def create? + false + end + + def edit? + update? + end + + def update? + false + end + + def destroy? + false + end + + private + + def logged_in? + user.present? + end +end diff --git a/app/policies/note_policy.rb b/app/policies/note_policy.rb new file mode 100644 index 0000000..8b07f8c --- /dev/null +++ b/app/policies/note_policy.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class NotePolicy < ApplicationPolicy + class Scope < Scope + def resolve + scope.not_completed.where(user: user.presence) + end + end + + def show? + record.user == user.presence + end + + def update? + return false if record.completed? + + show? + end + + def complete? + update? + end +end diff --git a/app/policies/register_policy.rb b/app/policies/register_policy.rb new file mode 100644 index 0000000..48631d7 --- /dev/null +++ b/app/policies/register_policy.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class RegisterPolicy < ApplicationPolicy + def create? + !logged_in? + end +end diff --git a/app/policies/session_policy.rb b/app/policies/session_policy.rb new file mode 100644 index 0000000..78d67d2 --- /dev/null +++ b/app/policies/session_policy.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class SessionPolicy < ApplicationPolicy + def create? + !logged_in? + end + + def destroy? + logged_in? + end +end