From 329b4904895760de78ad8649484c5b03e8994b7c Mon Sep 17 00:00:00 2001 From: "Jesse C. Fisher" Date: Fri, 28 Apr 2023 17:59:23 +0000 Subject: [PATCH] Add pundit authorization policies --- app/assets/stylesheets/application.css.sass | 18 +++++++- app/assets/stylesheets/tables.css.sass | 10 +++-- app/controllers/application_controller.rb | 12 +++--- app/controllers/games_controller.rb | 2 + app/controllers/seats_controller.rb | 7 ++++ app/controllers/tables_controller.rb | 7 +++- app/controllers/visitors_controller.rb | 1 + app/models/user.rb | 4 +- app/policies/game_policy.rb | 11 ++++- app/policies/seat_policy.rb | 44 ++++++++++++++++++++ app/policies/table_policy.rb | 8 ++++ app/views/layouts/_navigation_links.html.erb | 8 ++-- app/views/tables/_seat.html.haml | 2 +- app/views/tables/show.html.haml | 4 +- app/views/visitors/index.html.haml | 11 +++-- spec/features/visitors/home_page_spec.rb | 4 +- 16 files changed, 123 insertions(+), 30 deletions(-) create mode 100644 app/policies/seat_policy.rb diff --git a/app/assets/stylesheets/application.css.sass b/app/assets/stylesheets/application.css.sass index 87d18870..1acb7fec 100644 --- a/app/assets/stylesheets/application.css.sass +++ b/app/assets/stylesheets/application.css.sass @@ -33,6 +33,8 @@ a text-decoration: none color: white outline: none + &:hover + color: yellow h1 font-size: 7vmin @@ -67,6 +69,7 @@ header #home-headline + margin-top: 6em flex: 1 1 auto text-align: center h1 @@ -89,13 +92,24 @@ header border: 2px solid black text-align: center &:hover - background: #bada55 - color: black + background: #ffffff44 + color: yellow &:active background: (#bada55 + 100) *, *:before, *:after box-sizing: inherit + font-family: fantasy + font-weight: lighter li list-style: none + +.alert + padding: 1em + background: #ffffff77 + font-size: 1.2rem + color: #ffffff + text-shadow: 0 0 3px black + font-family: fantasy + letter-spacing: 0.3 diff --git a/app/assets/stylesheets/tables.css.sass b/app/assets/stylesheets/tables.css.sass index 86c6f114..37631116 100644 --- a/app/assets/stylesheets/tables.css.sass +++ b/app/assets/stylesheets/tables.css.sass @@ -10,14 +10,16 @@ #qrcode float: right - margin-top: -.5em - margin-right: 1em + margin-top: -7em + margin-right: 1.25em transform: scale(10%) - transition: all 0.5s ease-in-out + transition: all 0.25s ease-out width: 38px height: 38px &.full - margin-right: 2em + margin-top: -6em + margin-right: 0 + margin-bottom: 1em transform: scale(100%) width: 384px height: 384px diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 98e8ab66..78d31b3c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,18 +5,16 @@ class ApplicationController < ActionController::Base after_action :flash_to_http_header if (Rails.env.development? || Rails.env.test?) - # https://github.com/RailsApps/rails-devise-pundit/issues/10 include Pundit - # https://github.com/elabs/pundit#ensuring-policies-are-used - #after_action :verify_authorized, except: :index - #after_action :verify_policy_scoped, only: :index - + after_action :verify_authorized, unless: -> { devise_controller? } + # after_action :verify_policy_scoped, only: :index rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized private - def user_not_authorized - flash[:alert] = 'Access denied.' + def user_not_authorized(exception) + policy_name = exception.policy.class.to_s.underscore + flash[:alert] = "#{policy_name}.#{exception.query}" redirect_to (request.referrer || root_path) end end diff --git a/app/controllers/games_controller.rb b/app/controllers/games_controller.rb index 91b6232a..efce67c1 100644 --- a/app/controllers/games_controller.rb +++ b/app/controllers/games_controller.rb @@ -28,6 +28,7 @@ class GamesController < ApplicationController end def play_hand + authorize @game # TODO: move this logic out of controller maybe to model(s) ? # validate player's turn @@ -124,6 +125,7 @@ class GamesController < ApplicationController end def start + authorize @game begin @game.start rescue StandardError => e diff --git a/app/controllers/seats_controller.rb b/app/controllers/seats_controller.rb index 4c546e02..3272926a 100644 --- a/app/controllers/seats_controller.rb +++ b/app/controllers/seats_controller.rb @@ -44,6 +44,7 @@ class SeatsController < ApplicationController # PATCH/PUT /seats/1 # PATCH/PUT /seats/1.json def update + authorize @seat respond_to do |format| if @seat.update(seat_params) format.html { redirect_to @seat, notice: 'Seat was successfully updated.' } @@ -58,6 +59,7 @@ class SeatsController < ApplicationController # DELETE /seats/1 # DELETE /seats/1.json def destroy + authorize @seat @seat.destroy respond_to do |format| format.html { redirect_to seats_url, notice: 'Seat was successfully destroyed.' } @@ -67,6 +69,7 @@ class SeatsController < ApplicationController # POST /seats/1 def sit + authorize @seat @message = @seat.sit current_user respond_to do |format| if @seat.save @@ -78,11 +81,13 @@ class SeatsController < ApplicationController end def stand + authorize @seat @message = @seat.stand current_user redirect_to @seat.table, notice: @message end def add_bot + authorize @seat @message = @seat.add_bot redirect_to @seat.table, notice: @message end @@ -93,11 +98,13 @@ class SeatsController < ApplicationController end def empty + authorize @seat @message = @seat.empty redirect_to @seat.table, notice: @message end def remove_player + authorize @seat @message = @seat.remove_player redirect_to @seat.table, notice: @message end diff --git a/app/controllers/tables_controller.rb b/app/controllers/tables_controller.rb index 39e48bce..15391309 100644 --- a/app/controllers/tables_controller.rb +++ b/app/controllers/tables_controller.rb @@ -7,9 +7,10 @@ class TablesController < ApplicationController # First empty seat @seat = Seat.where(user_soft_token: nil).select{|s| !s.player.try("is_bot?")}.first if @seat + authorize @seat @seat.sit current_user else - @table = Table.create(title: "Table " + current_user.soft_token[0..4]) + authorize @table = Table.create(title: "Table " + current_user.soft_token[0..4]) @seat = @table.seats.first @seat.sit current_user end @@ -24,12 +25,13 @@ class TablesController < ApplicationController # GET /tables # GET /tables.json def index - @tables = Table.all + @tables = authorize Table.all end # GET /tables/1 # GET /tables/1.json def show + authorize @game # TODO refactor to ensure play for 2nd and 3rd place if @game.controlling_player.try("is_bot?") @@ -41,6 +43,7 @@ class TablesController < ApplicationController end def new_game + authorize @table @game = @table.add_game begin @game.start diff --git a/app/controllers/visitors_controller.rb b/app/controllers/visitors_controller.rb index ebe5fb60..5c8d7136 100644 --- a/app/controllers/visitors_controller.rb +++ b/app/controllers/visitors_controller.rb @@ -1,2 +1,3 @@ class VisitorsController < ApplicationController + before_action :skip_authorization end diff --git a/app/models/user.rb b/app/models/user.rb index 377f9ca9..8ae9a6d1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -17,7 +17,7 @@ class User < ActiveRecord::Base end def display_name - self.email || "Guest#{self.soft_token[0..5]}" + self.email.split("@")[0] || "Guest#{self.soft_token[0..5]}" end def sit_in(seat) @@ -40,6 +40,6 @@ class User < ActiveRecord::Base # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable - devise :invitable, :database_authenticatable, :registerable, :confirmable, + devise :invitable, :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable end diff --git a/app/policies/game_policy.rb b/app/policies/game_policy.rb index fce4873b..77c3d621 100644 --- a/app/policies/game_policy.rb +++ b/app/policies/game_policy.rb @@ -11,7 +11,8 @@ class GamePolicy end def show? - @current_user.admin? || @current_user == @user + true + # @current_user.admin? || @game.players.find_by_soft_token(soft_token: @current_user.soft_token) end def update? @@ -22,4 +23,12 @@ class GamePolicy return false if @current_user == @user @current_user.admin? end + + def start? + true + end + + def play_hand? + true + end end diff --git a/app/policies/seat_policy.rb b/app/policies/seat_policy.rb new file mode 100644 index 00000000..fc472aae --- /dev/null +++ b/app/policies/seat_policy.rb @@ -0,0 +1,44 @@ +class SeatPolicy + attr_reader :current_user, :model + + def initialize(current_user, model) + @current_user = current_user || User.new + @seat = model + end + + def index? + @current_user.admin? + end + + def show? + @current_user.admin? + end + + def update? + @current_user.admin? + end + + def destroy? + @current_user.admin? + end + + def play_now? + true + end + + def sit? + true + end + + def add_bot? + true + end + + def remove_player? + true + end + + def empty? + true + end +end diff --git a/app/policies/table_policy.rb b/app/policies/table_policy.rb index c7d591fd..d8a368b3 100644 --- a/app/policies/table_policy.rb +++ b/app/policies/table_policy.rb @@ -22,4 +22,12 @@ class TablePolicy return false if @current_user == @user @current_user.admin? end + + def play_now? + false + end + + def new_game? + true + end end diff --git a/app/views/layouts/_navigation_links.html.erb b/app/views/layouts/_navigation_links.html.erb index 825d30fb..59f01b65 100644 --- a/app/views/layouts/_navigation_links.html.erb +++ b/app/views/layouts/_navigation_links.html.erb @@ -1,9 +1,11 @@