Add pundit authorization policies

This commit is contained in:
Jesse C. Fisher 2023-04-28 17:59:23 +00:00 committed by Bort
parent 986664ca82
commit ac4285ac15
16 changed files with 123 additions and 30 deletions

View File

@ -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

View File

@ -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

View File

@ -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_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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,2 +1,3 @@
class VisitorsController < ApplicationController
before_action :skip_authorization
end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,9 +1,11 @@
<nav>
<ul>
<li><%= link_to 'Main Menu', root_path %></li>
<%# <li><%= link_to 'Main Menu', root_path %1></li> %>
<% if policy(:table).index? %>
<li><%= link_to 'Tables', tables_path %></li>
<% end %>
<% if current_user.signed_in? %>
<li><%= link_to 'Edit account', edit_user_registration_path %></li>
<li><%= link_to 'My account', edit_user_registration_path %></li>
<li><%= link_to 'Sign out', destroy_user_session_path, :method=>'delete' %></li>
<% else %>
<li><%= link_to 'Sign in', new_user_session_path %></li>

View File

@ -12,7 +12,7 @@
- else
-# = button_to empty_seat_path(seat), :data => { :confirm => 'Are you sure you want to empty this seat?' } do
= button_to empty_seat_path(seat) do
- "Empty"
- "Clear Seat"
- else
= button_to sit_seat_path(seat) do
- "Sit"

View File

@ -19,8 +19,8 @@
#table-controls
#newgame= button_to 'New Game', new_game_table_path(@table)
#qrcode
:javascript
-# #qrcode
-# :javascript
function gen_qrcode(){
var qrcode = new QRCode(document.getElementById("qrcode"), {
text: "#{request.original_url}",

View File

@ -2,7 +2,10 @@
%h1 Thirteen <br/>Tien Len
#main-menu
= link_to 'Play Now', play_now_path
= link_to 'Browse Tables', tables_path
= link_to 'Tutorial', tutorial_path
= link_to 'About', page_path('about')
- if policy(:table).play_now?
= link_to 'Play', play_now_path
- else
Soon
-# = link_to 'Browse Tables', tables_path
-# = link_to 'Tutorial', tutorial_path
-# = link_to 'About', page_path('about')

View File

@ -10,7 +10,7 @@ feature 'Home page' do
scenario 'visit the home page' do
visit root_path
expect(page).to have_link 'Play Now'
expect(page).to have_link 'Browse Tables'
expect(page).to have_link 'Tutorial'
# expect(page).to have_link 'Browse Tables'
# expect(page).to have_link 'Tutorial'
end
end