👖
アクセス制限を設定しURL入力による遷移を阻止する
この記事で分かること
- アクセス制限の設定方法
完成コード
app/product_controllers
class Public::ProductsController < ApplicationController
before_action :authenticate_user!
+ before_action :ensure_current_user, {only: [:edit, :update, :show]}
def new
@user = User.find(params[:user_id])
@product = Product.new
end
def index
@user = User.find(params[:user_id])
@release_products = @user.products.where(is_secret: true).page(params[:page])
@secret_products = @user.products.where(is_secret: false)
@products = @user.products
@reviews = Review.all
end
def create
@product = Product.new(product_params)
@user = User.find(params[:user_id])
@product.user_id = @user.id
if @product.save
flash[:notice] = "商品を登録しました"
redirect_to user_products_path(@user)
else
flash[:alert] = "正しい内容を入力してください"
render :new
end
end
def show
@user = User.find(params[:user_id])
@product = Product.find(params[:id])
@review = Review.new
@reviews = @product.reviews.includes(:user)
@all_rating = '総合評価'
end
def edit
@user = User.find(params[:user_id])
@product = Product.find(params[:id])
end
def update
@user = User.find(params[:user_id])
@product = Product.find(params[:id])
if current_user == @user
if params[:is_secret] == "公開中"
flash[:notice] = "商品を公開しました"
@product.is_secret = true
elsif params[:is_secret] == "非公開"
flash[:notice] = "商品を非公開にしました"
@product.is_secret = false
else
flash[:notice] = "商品の設定を更新しました"
@product.update!(product_params)
end
if @product.save!
redirect_to user_product_path(@user)
else
render "edit"
flash[:alert] = "更新に失敗しました"
end
else
render "edit"
flash[:alert] = "更新に失敗しました"
end
end
private
def product_params
params.require(:product).permit(:name, :introduction, :price, :image, :active_status, :genre_id ,:user_id, :item_id, :is_secret,)
end
+ def ensure_current_user
+ @user = User.find(params[:user_id])
+ @product = Product.find(params[:id])
+ if @product.is_secret == false && current_user.id != params[:user_id].to_i
+ flash[:alert]="閲覧権限がありません"
+ redirect_to user_products_path(@user)
+ end
+ end
end
前提条件
- deviseが実装済み
- アクセス制限したい部分の機能やページが実装済み
- Routingでは、親 : 子 = User : Productの関係を持つ
現状の問題点
投稿ユーザーの画面
閲覧ユーザーの画面
テーブル
- 本記事ではProductsカラムの「is_secret」を使用します。
is_secret
データ型はbool型で、公開商品ならば(true),非公開ならば(false)を持ちます。
今回の目的は、非公開商品かつ投稿したユーザーでないならば、URL遷移できない設定にするため、if文で「is_secret == false」を使います。
実装手順
- before_actionで制限を設ける
before_actionとは?
アクションを実行する前に特定の処理を実行するためのもの
ex) createアクションで商品登録するアクションを行うならば、createアクションを実行する前に before_actionでログインユーザーの情報を確認するアクションを実行できる
- 基盤となるコード
before_action :メソッド名
実装方法
before_actionの内容を定義します。
app/product_controllers
before_action :ensure_current_user, {only: [:edit, :update, :show]}
def ensure_current_user
@user = User.find(params[:user_id])
@product = Product.find(params[:id])
if @product.is_secret == false && current_user.id != params[:user_id].to_i
flash[:alert]="閲覧権限がありません"
redirect_to user_products_path(@user)
end
end
解説
-
{only: [:edit, :update, :show]}
→ edit,update,showアクションの時に実行する -
@product.is_secret == false
→ 非公開商品に限定する -
current_user.id != params[:user_id].to_i
→「ログインユーザーIDがURLのユーザーIDと一致しなければ」という意味
→ params[:user_id]で取得できる値は「文字列」であるため、整数型に変換する(.to_i)
以上で完成です。(全体のコードは「完成コード」を参照)
- 閲覧ユーザーの画面でURL遷移を実行し権限を確認
感想
この問題はメンターさんからのフィードバックで気づくことができました。1人だと気づきにくい部分かもしれませんが大事な要素なので見落とさないように注意していきたいです。
この記事をかいた人
23/6/1にDWCに入学し、主にRailsの学習に取り組みました。卒業が近づきこれから何で学習をするか悩んだときに、技術ブログをしようと考えました。初心者ですがよろしくお願いします。
Discussion