diff --git a/Gemfile b/Gemfile index 5f544ca..d955d37 100644 --- a/Gemfile +++ b/Gemfile @@ -46,6 +46,8 @@ gem 'thruster', require: false gem 'tailwindcss-rails' gem 'view_component', '~> 3.20' +gem 'cancancan' + group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem gem 'debug', platforms: %i[mri windows], require: 'debug/prelude' diff --git a/Gemfile.lock b/Gemfile.lock index c3b3812..06851f1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -88,6 +88,7 @@ GEM brakeman (6.2.2) racc builder (3.3.0) + cancancan (3.6.1) capybara (3.40.0) addressable matrix @@ -452,6 +453,7 @@ DEPENDENCIES bcrypt (~> 3.1.7) bootsnap brakeman + cancancan capybara (~> 3.40) debug guard-rspec (~> 4.7) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index bd7cdcc..74d521c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,6 +5,9 @@ class ApplicationController < ActionController::Base before_action :ensure_authentication + rescue_from StandardError, with: :standard_error unless Rails.env.development? + rescue_from CanCan::AccessDenied, with: :access_denied unless Rails.env.development? + protected def ensure_authentication @@ -14,4 +17,16 @@ class ApplicationController < ActionController::Base def current_user @current_user ||= User.find_by(id: session[:current_user_id]) end + + def current_ability + @current_ability ||= Ability.new(current_user) + end + + def access_denied + render 'application/access_denied', status: :unauthorized + end + + def standard_error + render 'application/standard_error', status: :internal_server_error + end end diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index e9740d6..d0d9ba8 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -1,12 +1,13 @@ # frozen_string_literal: true class ConversationsController < ApplicationController + load_and_authorize_resource except: %i[create] + def index - @conversations = @current_user.conversations + @conversations = Conversation.accessible_by(current_ability) end def show - @conversation = @current_user.conversations.find(params[:id]) @messages = @conversation.messages @prompt = Message.new(conversation: @conversation) end diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 4dd7f73..7b025f1 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -1,14 +1,14 @@ # frozen_string_literal: true class MessagesController < ApplicationController + load_and_authorize_resource + def create - # TODO: Revisit auth once cancancan is installed - @message = Message.new(message_params) if @message.save GenerateReplyJob.perform_later(@message.conversation) redirect_to @message.conversation else - redirect_to conversations_path + redirect_to @message.conversation || conversations_path end end diff --git a/app/models/ability.rb b/app/models/ability.rb new file mode 100644 index 0000000..b5c7243 --- /dev/null +++ b/app/models/ability.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class Ability + include CanCan::Ability + + def initialize(user) + can :create, Conversation + can :read, Conversation, user: user + can :create, Message, conversation: { user: user } + can %i[index read], Message, conversation: { user: user } + end +end diff --git a/app/views/application/access_denied.html.erb b/app/views/application/access_denied.html.erb new file mode 100644 index 0000000..284e2b1 --- /dev/null +++ b/app/views/application/access_denied.html.erb @@ -0,0 +1 @@ +