Skip to content

Commit

Permalink
Pundit authorization (#117)
Browse files Browse the repository at this point in the history
* chore: update yarn lock

* chore add pundit & refactor authentication for user model

* chore: add circle policies

* chore: add policies to memberships

* fix: check accepted status on circle membership

* chore: add policies to albums

* chore: add policy for album images

* chore: refactor some stuff

* Fix code style issues with RuboCop

* chore: update stuff

---------

Co-authored-by: Lint Action <[email protected]>
  • Loading branch information
bbucsy and lint-action authored Feb 28, 2024
1 parent d7fcc18 commit efa08c9
Show file tree
Hide file tree
Showing 30 changed files with 2,714 additions and 2,053 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
# Ignore bundler config.
/.bundle

.yarn

# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
Expand Down
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,6 @@ gem 'omniauth-oauth2'
gem 'dotenv-rails', groups: %i[development test]

gem 'i18n_generators', '~> 2.2', '>= 2.2.2'

# Authorization
gem 'pundit', '~> 2.3'
36 changes: 22 additions & 14 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ GEM
ruby-vips (>= 2.0.17, < 3)
jbuilder (2.11.2)
activesupport (>= 5.0.0)
json (2.7.1)
jwt (2.2.2)
language_server-protocol (3.17.0.3)
listen (3.6.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
Expand Down Expand Up @@ -137,13 +139,16 @@ GEM
omniauth-oauth2 (1.7.0)
oauth2 (~> 1.4)
omniauth (~> 1.9)
parallel (1.20.1)
parser (3.0.2.0)
parallel (1.24.0)
parser (3.3.0.5)
ast (~> 2.4.1)
racc
pg (1.2.3)
public_suffix (4.0.6)
puma (5.6.4)
nio4r (~> 2.0)
pundit (2.3.1)
activesupport (>= 3.0.0)
racc (1.6.0)
rack (2.2.3)
rack-proxy (0.7.0)
Expand Down Expand Up @@ -176,29 +181,31 @@ GEM
method_source
rake (>= 0.13)
thor (~> 1.0)
rainbow (3.0.0)
rainbow (3.1.1)
rake (13.0.6)
rb-fsevent (0.11.0)
rb-inotify (0.10.1)
ffi (~> 1.0)
regexp_parser (2.1.1)
rexml (3.2.5)
rubocop (1.19.1)
regexp_parser (2.9.0)
rexml (3.2.6)
rubocop (1.60.2)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.0.0.0)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml
rubocop-ast (>= 1.9.1, < 2.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.30.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.10.0)
parser (>= 3.0.1.1)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0)
parser (>= 3.2.1.0)
rubocop-rails (2.11.3)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.7.0, < 2.0)
ruby-progressbar (1.11.0)
ruby-progressbar (1.13.0)
ruby-vips (2.1.4)
ffi (~> 1.12)
rubyzip (2.3.2)
Expand Down Expand Up @@ -234,7 +241,7 @@ GEM
turbolinks-source (5.2.0)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
unicode-display_width (2.0.0)
unicode-display_width (2.5.0)
web-console (4.1.0)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
Expand Down Expand Up @@ -273,6 +280,7 @@ DEPENDENCIES
omniauth-oauth2
pg (>= 0.18, < 2.0)
puma (~> 5.6)
pundit (~> 2.3)
rails (~> 6.1.0, >= 6.1.4)
rubocop
rubocop-rails
Expand Down
10 changes: 1 addition & 9 deletions app/controllers/album_image_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,7 @@ def show

def set_image
@image = AlbumImage.friendly.find(params[:id])
authorize_image
end

def authorize_image
return if @image.album.public?

unless current_user.present? && (current_user.site_admin? || logged_in_as_admin_of?(album.circle) || album.shared?)
redirect_to '/', notice: I18n.t('unauthorized', scope: 'album_images.errors')
end
authorize @image
end

def content_headers_from(blob)
Expand Down
37 changes: 15 additions & 22 deletions app/controllers/albums_controller.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
class AlbumsController < ApplicationController
before_action :set_album, only: %i[edit update destroy delete_image add_image image]
before_action :login_required
before_action :admin_or_owner_required, only: %i[edit update destroy]
before_action :admin_or_owner_or_shared_required, only: %i[delete_image add_image]

attr_accessor :render_target

after_action :analyze_album, only: %i[create add_image]
after_action :verify_authorized, if: -> { Rails.env.development? }

# GET /albums
def index
authorize Album
@albums = Album.all.order(created_at: :desc)
@title = 'Minden album'
end

# GET /albums/myalbums
def myalbums
authorize Album
@albums = Album.where(user: current_user).order(created_at: :desc)
@title = 'Albumaim'
render :index
Expand All @@ -23,21 +24,26 @@ def myalbums
# GET /albums/1
def show
@album = Album.includes(:album_images).find(params[:id])
authorize @album
end

# GET /albums/new
def new
authorize Album
@album = Album.new
@circles = current_user.memberships.where(accepted: true).map(&:circle)

redirect_to circles_path, notice: 'Nincs körtagsága, nem hozhat létre kört!' if @circles.empty?
end

# GET /albums/1/edit
def edit; end
def edit
authorize @album
end

# POST /albums
def create
authorize Album
@render_target = :new

@album = Album.new(album_params)
Expand All @@ -53,6 +59,7 @@ def create

# PATCH/PUT /albums/1
def update
authorize @album
@render_target = :edit

if @album.update(album_params)
Expand All @@ -64,6 +71,7 @@ def update

# DELETE /albums/1
def destroy
authorize @album
@album.album_images.each do |image|
image.file.purge
end
Expand All @@ -74,6 +82,7 @@ def destroy

# GET /albums/1/image?image_id=1
def image
authorize @album
image = @album.album_images.find_by(id: params[:image_id])
return render json: { status: 404 }, status: :not_found if image.blank?

Expand All @@ -85,6 +94,7 @@ def image

# DELETE one image of the album
def delete_image
authorize @album
image = AlbumImage.find(params[:image_id])
image.file.purge
image.destroy!
Expand All @@ -93,6 +103,7 @@ def delete_image

# POST add image(s) to the album
def add_image
authorize @album
images = params[:images]
@album.build_images(images) if images.present?
@album.save
Expand All @@ -111,24 +122,6 @@ def analyze_album
@album.images.map(&:file).each { |i| i.analyze unless i.analyzed? }
end

# Allow only owner or admin
def admin_or_owner_required
unless current_user == @album.user || logged_in_as_site_admin? || logged_in_as_admin_of?(@album.circle)
redirect_to @album,
notice: 'Nincs jogosultságod az funkcióhoz!'
end
end

# Allow for shared
def admin_or_owner_or_shared_required
unless current_user == @album.user ||
logged_in_as_site_admin? ||
logged_in_as_admin_of?(@album.circle) ||
@album.shared?
redirect_to @album, notice: 'Nincs jogosultságod az funkcióhoz!'
end
end

# Only allow a list of trusted parameters through.
def album_params
params.require(:album).permit(:title, :desc, :shared, :public, :tag, :circle_id)
Expand Down
24 changes: 5 additions & 19 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
class ApplicationController < ActionController::Base
include Pundit::Authorization

rescue_from ActiveRecord::RecordNotFound, with: :record_not_found
rescue_from Pundit::NotAuthorizedError, with: :not_authorized

protected

Expand All @@ -21,32 +24,15 @@ def accepted_in_circle?(circle)

helper_method :accepted_in_circle?

def logged_in_as_site_admin?
current_user&.site_admin?
end

helper_method :logged_in_as_site_admin?

def logged_in_as_admin_of?(circle)
Membership.exists?(user: current_user, circle: circle, admin: true)
end

helper_method :logged_in_as_admin_of?

def current_user
@current_user ||= User.find(session[:user_id]) if logged_in?
end

helper_method :current_user

# Function used in derived classes as before actions
def login_required
redirect_to root_path, notice: 'Be kell jelentkezned!' unless logged_in?
end

# Function used in derived classes as before actions
def site_admin_required
redirect_to root_path, notice: 'Nincs jogosultságod az oldalhoz!' unless logged_in_as_site_admin?
def not_authorized
redirect_to root_path, notice: 'Nincs jogosultságod az oldalhoz!'
end

def record_not_found
Expand Down
31 changes: 13 additions & 18 deletions app/controllers/circles_controller.rb
Original file line number Diff line number Diff line change
@@ -1,33 +1,39 @@
class CirclesController < ApplicationController
before_action :set_circle, only: %i[details show edit update destroy]
before_action :site_admin_required, only: %i[edit update destroy]
before_action :admin_required, only: %i[details]
before_action :admin_or_member_required, only: %i[show]
after_action :verify_authorized, if: -> { Rails.env.development? }

# GET /circles
def index
authorize Circle
@circles = Circle.all
end

# GET /circles/1
def show
authorize @circle
@albums = Album.where(circle: @circle).order(created_at: :desc)
render 'albums/index'
end

# GET /circles/1/details
def details; end
def details
authorize @circle
end

# GET /circles/new
def new
authorize Circle
@circle = Circle.new
end

# GET /circles/1/edit
def edit; end
def edit
authorize @circle
end

# POST /circles
def create
authorize Circle
@render_target = :new

@circle = Circle.new(circle_params)
Expand All @@ -42,6 +48,7 @@ def create

# PUT /circles/1
def update
authorize @circle
@render_target = :edit

if @circle.update(circle_params)
Expand All @@ -53,6 +60,7 @@ def update

# DELETE /circles/1
def destroy
authorize @circle
@circle.destroy
redirect_to circles_url, notice: 'Kör sikeresen törölve.'
end
Expand All @@ -68,17 +76,4 @@ def set_circle
def circle_params
params.require(:circle).permit(:name)
end

# Allow for admin of circle
def admin_required
unless logged_in_as_site_admin? || logged_in_as_admin_of?(@circle)
redirect_to circles_path, notice: 'Nincs jogosultságod az funkcióhoz!'
end
end

def admin_or_member_required
unless logged_in_as_site_admin? || logged_in_as_admin_of?(@circle) || accepted_in_circle?(@circle)
redirect_to circles_path, notice: 'Nincs jogosultságod az funkcióhoz!'
end
end
end
Loading

0 comments on commit efa08c9

Please sign in to comment.