From e4a33b7fc15922d69db03eff86c62fb3f8d9bac9 Mon Sep 17 00:00:00 2001
From: Ethan Huang <96758695+EthanKH@users.noreply.github.com>
Date: Thu, 26 Oct 2023 21:17:17 +0000
Subject: [PATCH 1/3] photogram industrial authorization
---
app/controllers/comments_controller.rb | 8 ++++++++
app/controllers/photos_controller.rb | 22 +++++++++++++++++-----
app/models/comment.rb | 1 +
app/views/photos/_photo.html.erb | 12 +++++++-----
app/views/users/show.html.erb | 19 ++++++++++---------
config/routes.rb | 8 ++++----
6 files changed, 47 insertions(+), 23 deletions(-)
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index 046a8e5d..738f2e97 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -1,5 +1,6 @@
class CommentsController < ApplicationController
before_action :set_comment, only: %i[ show edit update destroy ]
+ before_action :is_an_authorized_user, only: [:destroy, :create]
# GET /comments or /comments.json
def index
@@ -63,6 +64,13 @@ def set_comment
@comment = Comment.find(params[:id])
end
+ def is_an_authorized_user
+ @photo = Photo.find(params.fetch(:comment).fetch(:photo_id))
+ if current_user != @photo.owner && @photo.owner.private? && !current_user.leaders.include?(@photo.owner)
+ redirect_back fallback_location: root_url: "Not authorized"
+ end
+ end
+
# Only allow a list of trusted parameters through.
def comment_params
params.require(:comment).permit(:author_id, :photo_id, :body)
diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb
index 78e53163..9da2fc8d 100644
--- a/app/controllers/photos_controller.rb
+++ b/app/controllers/photos_controller.rb
@@ -1,5 +1,6 @@
class PhotosController < ApplicationController
before_action :set_photo, only: %i[ show edit update destroy ]
+ before_action :ensure_current_user_is_owner, only: [:destroy, :update, :edit]
# GET /photos or /photos.json
def index
@@ -50,19 +51,30 @@ def update
# DELETE /photos/1 or /photos/1.json
def destroy
- @photo.destroy
- respond_to do |format|
- format.html { redirect_back fallback_location: root_url, notice: "Photo was successfully destroyed." }
- format.json { head :no_content }
+ if current_user == @photo.owner
+ @photo.destroy
+ respond_to do |format|
+ format.html { redirect_back fallback_location: root_url, notice: "Photo was successfully destroyed." }
+ format.json { head :no_content }
+ end
+ else
+ redirect_back(fallback_location: root_url, notice: "Nice try, but that is not your photo.")
end
end
private
- # Use callbacks to share common setup or constraints between actions.
+
+ # Use callbacks to share common setup or constraints between actions.
def set_photo
@photo = Photo.find(params[:id])
end
+ def ensure_current_user_is_owner
+ if current_user != @photo.owner
+ redirect_back fallback_location: root_url, alert: "You're not authorized for that."
+ end
+ end
+
# Only allow a list of trusted parameters through.
def photo_params
params.require(:photo).permit(:image, :comments_count, :likes_count, :caption, :owner_id)
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 14a8eb00..0761b0e8 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -22,6 +22,7 @@
class Comment < ApplicationRecord
belongs_to :author, class_name: "User", counter_cache: true
belongs_to :photo, counter_cache: true
+ has_one :owner, through: :photo
validates :body, presence: true
end
diff --git a/app/views/photos/_photo.html.erb b/app/views/photos/_photo.html.erb
index f0de50b8..1d2f8454 100644
--- a/app/views/photos/_photo.html.erb
+++ b/app/views/photos/_photo.html.erb
@@ -7,12 +7,14 @@
- <%= link_to edit_photo_path(photo), class: "btn btn-link btn-sm text-muted" do %>
-
- <% end %>
+ <% if current_user == photo.owner %>
+ <%= link_to edit_photo_path(photo), class: "btn btn-link btn-sm text-muted" do %>
+
+ <% end %>
- <%= link_to photo, data: { turbo_method: :delete }, class: "btn btn-link btn-sm text-muted" do %>
-
+ <%= link_to photo, data: { turbo_method: :delete }, class: "btn btn-link btn-sm text-muted" do %>
+
+ <% end %>
<% end %>
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb
index 5656d7d5..c68a9af8 100644
--- a/app/views/users/show.html.erb
+++ b/app/views/users/show.html.erb
@@ -4,16 +4,17 @@
-
-
- <%= render "users/profile_nav", user: @user %>
-
-
-
-<% @user.own_photos.each do |photo| %>
-
+<% if current_user == @user || !@user.private? || current_user.leaders.include?(@user) %>
- <%= render "photos/photo", photo: photo %>
+ <%= render "users/profile_nav", user: @user %>
+
+ <% @user.own_photos.each do |photo| %>
+
+
+ <%= render "photos/photo", photo: photo %>
+
+
+ <% end %>
<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index 47050a54..53545094 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -4,9 +4,9 @@
devise_for :users
resources :comments
- resources :follow_requests
- resources :likes
- resources :photos
+ resources :follow_requests, except: [:index, :show, :new, :edit]
+ resources :likes, only: [:create, :destroy]
+ resources :photos, except: [:index]
get ":username" => "users#show", as: :user
get ":username/liked" => "users#liked", as: :liked
@@ -14,4 +14,4 @@
get ":username/discover" => "users#discover", as: :discover
get ":username/followers" => "users#followers", as: :followers
get ":username/following" => "users#following", as: :following
-end
\ No newline at end of file
+end
From d9e0b4f0bb26fdab6ae8416bb9ad858f6a8f7a4f Mon Sep 17 00:00:00 2001
From: Ethan Huang <96758695+EthanKH@users.noreply.github.com>
Date: Thu, 26 Oct 2023 21:37:48 +0000
Subject: [PATCH 2/3] finished authorization
---
app/controllers/photos_controller.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb
index 9da2fc8d..9176c340 100644
--- a/app/controllers/photos_controller.rb
+++ b/app/controllers/photos_controller.rb
@@ -64,7 +64,7 @@ def destroy
private
- # Use callbacks to share common setup or constraints between actions.
+ # Use callbacks to share common setup or constraints between actions
def set_photo
@photo = Photo.find(params[:id])
end
From f6e4e97ddc18ec059bdb3f7991889d3f2b43f6bd Mon Sep 17 00:00:00 2001
From: Ethan Huang <96758695+EthanKH@users.noreply.github.com>
Date: Fri, 27 Oct 2023 21:41:40 +0000
Subject: [PATCH 3/3] working for the most part, except after_action in
application_controller.rb
---
Gemfile | 2 +
Gemfile.lock | 3 ++
app/controllers/application_controller.rb | 20 +++++++++
app/controllers/photos_controller.rb | 9 ++++
app/policies/application_policy.rb | 53 +++++++++++++++++++++++
app/policies/photo_policy.rb | 17 ++++++++
app/policies/user_policy.rb | 17 ++++++++
app/views/users/show.html.erb | 4 +-
8 files changed, 124 insertions(+), 1 deletion(-)
create mode 100644 app/policies/application_policy.rb
create mode 100644 app/policies/photo_policy.rb
create mode 100644 app/policies/user_policy.rb
diff --git a/Gemfile b/Gemfile
index 9eebefb9..0a393dce 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,6 +3,8 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "3.2.1"
+gem "pundit"
+
gem "simple_form"
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
diff --git a/Gemfile.lock b/Gemfile.lock
index 42668dd8..e73e59d4 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -233,6 +233,8 @@ GEM
public_suffix (5.0.1)
puma (5.6.5)
nio4r (~> 2.0)
+ pundit (2.3.1)
+ activesupport (>= 3.0.0)
racc (1.6.2)
rack (2.2.7)
rack-protection (3.0.6)
@@ -425,6 +427,7 @@ DEPENDENCIES
pg (~> 1.1)
pry-rails
puma (~> 5.0)
+ pundit
rails (~> 7.0.4, >= 7.0.4.3)
rails-erd
rails_db
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index bd664b1d..6619aeb1 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,12 +1,32 @@
class ApplicationController < ActionController::Base
+ include Pundit
+
+ # after_action :verify_authorized
+
before_action :authenticate_user!
before_action :configure_permitted_parameters, if: :devise_controller?
+ rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
+
+ # blocker here trying to include the after_action, would appreciate guidance here!
+ # 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, unless: :devise_controller?
+
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:username, :private, :name, :bio, :website, :avatar_image])
devise_parameter_sanitizer.permit(:account_update, keys: [:username, :private, :name, :bio, :website, :avatar_image])
end
+
+ private
+
+ def user_not_authorized
+ flash[:alert] = "You are not authorized to perform this action."
+
+ redirect_back fallback_location: root_url
+ end
end
diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb
index 9176c340..33181b65 100644
--- a/app/controllers/photos_controller.rb
+++ b/app/controllers/photos_controller.rb
@@ -1,6 +1,7 @@
class PhotosController < ApplicationController
before_action :set_photo, only: %i[ show edit update destroy ]
before_action :ensure_current_user_is_owner, only: [:destroy, :update, :edit]
+ before_action :ensure_user_is_authorized, only: [:show]
# GET /photos or /photos.json
def index
@@ -9,6 +10,7 @@ def index
# GET /photos/1 or /photos/1.json
def show
+ authorize @photo
end
# GET /photos/new
@@ -75,6 +77,13 @@ def ensure_current_user_is_owner
end
end
+ # def ensure_user_is_authorized
+ # if !PhotoPolicy.new(current_user, @photo).show?
+ # raise Pundit::NotAuthorizedError, "not allowed"
+ # # redirect_back fallback_location: root_url
+ # end
+ # end
+
# Only allow a list of trusted parameters through.
def photo_params
params.require(:photo).permit(:image, :comments_count, :likes_count, :caption, :owner_id)
diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb
new file mode 100644
index 00000000..e000cba5
--- /dev/null
+++ b/app/policies/application_policy.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+class ApplicationPolicy
+ attr_reader :user, :record
+
+ def initialize(user, record)
+ @user = user
+ @record = record
+ end
+
+ def index?
+ false
+ end
+
+ def show?
+ false
+ end
+
+ def create?
+ false
+ end
+
+ def new?
+ create?
+ end
+
+ def update?
+ false
+ end
+
+ def edit?
+ update?
+ end
+
+ def destroy?
+ false
+ end
+
+ class Scope
+ def initialize(user, scope)
+ @user = user
+ @scope = scope
+ end
+
+ def resolve
+ raise NotImplementedError, "You must define #resolve in #{self.class}"
+ end
+
+ private
+
+ attr_reader :user, :scope
+ end
+end
diff --git a/app/policies/photo_policy.rb b/app/policies/photo_policy.rb
new file mode 100644
index 00000000..addcf7af
--- /dev/null
+++ b/app/policies/photo_policy.rb
@@ -0,0 +1,17 @@
+class PhotoPolicy < ApplicationPolicy
+ attr_reader :user, :photo
+
+ def initialize(user, photo)
+ @user = user
+ @photo = photo
+ end
+
+# Our policy is that a photo should only be seen by the owner or followers
+# of the owner, unless the owner is not private in which case anyone can
+# see it
+ def show?
+ user == photo.owner ||
+ !photo.owner.private? ||
+ photo.owner.followers.include?(user)
+ end
+end
diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb
new file mode 100644
index 00000000..6730e45d
--- /dev/null
+++ b/app/policies/user_policy.rb
@@ -0,0 +1,17 @@
+class UserPolicy
+ attr_reader :current_user, :user
+
+ def initialize(current_user, user)
+ @current_user = current_user
+ @user = user
+ end
+
+ def show?
+ user == current_user ||
+ !user.private? ||
+ user.followers.include?(current_user)
+ end
+ def feed?
+ true
+ end
+end
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb
index c68a9af8..2ee686d1 100644
--- a/app/views/users/show.html.erb
+++ b/app/views/users/show.html.erb
@@ -4,7 +4,9 @@
-<% if current_user == @user || !@user.private? || current_user.leaders.include?(@user) %>
+<%# if current_user == @user || !@user.private? || current_user.leaders.include?(@user) %>
+<% if policy(@user).show? %>
+
<%= render "users/profile_nav", user: @user %>