Commencez par modifier spec / spec_helper.rb
comme suit.
Comme indiqué dans la formule pundit, vous pouvez utiliser la méthode rspec pour pundit en ajoutant ce qui suit.
spec/spec_helper.rb
RSpec.configure do |config|
...
+ require "pundit/rspec"
end
Ensuite, nous incorporerons le test dans spec / policies / post_policy_spec.rb
.
spec/policies/post_policy_spec.rb
# frozen_string_literal: true
require "rails_helper"
RSpec.describe PostPolicy, type: :policy do
let(:user) { create(:user) }
let(:post) { create(:post) }
subject { described_class }
permissions :index?, :show? do
it "Autorisé lorsqu'il n'est pas connecté" do
expect(subject).to permit(nil, post)
end
end
permissions :create? do
it "Non autorisé lorsqu'il n'est pas connecté" do
expect(subject).not_to permit(nil, post)
end
it "Autoriser une fois connecté" do
expect(subject).to permit(user, post)
end
end
permissions :update?, :destroy? do
it "Non autorisé lorsqu'il n'est pas connecté" do
expect(subject).not_to permit(nil, post)
end
it "Non autorisé lors de la connexion mais avec un autre utilisateur" do
expect(subject).not_to permit(user, post)
end
it "Autorisé une fois connecté et le même utilisateur" do
post.user = user
expect(subject).to permit(user, post)
end
end
end
Je pense que vous pouvez le lire d'une manière ou d'une autre, mais au cas où, veuillez l'expliquer.
permissions :index?, :show? do
it "Autorisé lorsqu'il n'est pas connecté" do
expect(subject).to permit(nil, post)
end
end
Puisque l'index et le spectacle ont les mêmes conditions, ils sont testés ensemble.
permit (nil, post)
spécifie le modèle d'utilisateur de connexion dans le premier argument et le modèle cible dans le deuxième argument.
Ensuite, il teste si l'utilisateur du premier argument a l'index? Ou affiche? Permission de l'objet du second argument.
permissions :update?, :destroy? do
...
it "Non autorisé lors de la connexion mais avec un autre utilisateur" do
expect(subject).not_to permit(user, post)
end
it "Autorisé une fois connecté et le même utilisateur" do
post.user = user
expect(subject).to permit(user, post)
end
end
Je regarde toujours not_to, mais c'est un test pour ne pas être autorisé. Et le test final réussit en faisant correspondre l'utilisateur propriétaire du message.
Déplaçons rspec une fois.
Alors spec / requests / v1 / posts_request_spec.rb
sera assez mousseux.
La cause est la même que ci-dessus, car si #update ou #destory n'est pas le login de l'utilisateur auquel il appartient, ce sera 403.
Cependant, le helper ʻauthorized_user_headers utilisé dans
posts_request_spec.rbcrée
create (: user)` en interne, donc l'utilisateur connecté et l'utilisateur du message ne peuvent pas être mis en correspondance.
Par conséquent, apportez les modifications suivantes.
spec/support/authorization_spec_helper.rb
module AuthorizationSpecHelper
- def authorized_user_headers
- user = create(:user)
+ def authorized_user_headers(user = nil)
+ user = create(:user) if user.nil?
post v1_user_session_url, params: { email: user.email, password: "password" }
Maintenant, si vous le passez à ʻauthorized_user_headers` sans argument, un utilisateur sera créé en interne, et si vous passez un utilisateur en argument, il sera utilisé.
Cependant, ʻauthorized_user_headers` devient un peu compliqué et reste bloqué dans AbcSize de rubocop, nous prendrons donc les mesures suivantes.
diff:.rubocop.yml
...
+
+#AbcSize Default 15 est difficile, alors augmentez-le à 20
+Metrics/AbcSize:
+ Max: 20
Maintenant, il est enfin temps de corriger la spécification de la requête.
spec/requests/v1/posts_request_spec.rb
...
it "Le code de réponse normal est renvoyé" do
- put v1_post_url({ id: update_param[:id] }), params: update_param
+ post = Post.find(update_param[:id])
+ put v1_post_url({ id: update_param[:id] }), params: update_param, headers: authorized_user_headers(post.user)
expect(response.status).to eq 200
end
it "subject,le corps revient correctement" do
- put v1_post_url({ id: update_param[:id] }), params: update_param
+ post = Post.find(update_param[:id])
+ put v1_post_url({ id: update_param[:id] }), params: update_param, headers: authorized_user_headers(post.user)
json = JSON.parse(response.body)
expect(json["post"]["subject"]).to eq("update_test du sujet")
expect(json["post"]["body"]).to eq("update_test corporel")
end
it "Des erreurs sont renvoyées lorsque le paramètre n'est pas valide" do
- put v1_post_url({ id: update_param[:id] }), params: { subject: "" }
+ post = Post.find(update_param[:id])
+ put v1_post_url({ id: update_param[:id] }), params: { subject: "" }, headers: authorized_user_headers(post.user)
json = JSON.parse(response.body)
expect(json.key?("errors")).to be true
end
@@ -106,13 +109,13 @@ RSpec.describe "V1::Posts", type: :request do
create(:post)
end
it "Le code de réponse normal est renvoyé" do
- delete v1_post_url({ id: delete_post.id })
+ delete v1_post_url({ id: delete_post.id }), headers: authorized_user_headers(delete_post.user)
expect(response.status).to eq 200
end
it "Un de moins et revient" do
delete_post
expect do
- delete v1_post_url({ id: delete_post.id })
+ delete v1_post_url({ id: delete_post.id }), headers: authorized_user_headers(delete_post.user)
end.to change { Post.count }.by(-1)
end
Il n'y a pas tellement de changement. Passez l'autorisation en passant l'utilisateur propriétaire du message à ʻauthorized_user_headers`.
Je vais changer cela un peu plus intuitivement. Le processus visant à déterminer s'il vous appartient ne se limite pas à la publication et il semble qu'il sera détourné vers divers modèles à l'avenir.
def update?
@record.user == @user
end
def destroy?
@record.user == @user
end
Par conséquent, créez une méthode privée dans application_policy.rb pour déterminer si elle vous appartient.
app/policies/application_policy.rb
class ApplicationPolicy
...
+ private
+
+ def mine?
+ @record.user == @user
+ end
#
# scope
#
class Scope
...
Je vais le refléter dans post_policy.
app/policies/post_policy.rb
def update?
- @record.user == @user
+ mine?
end
def destroy?
- @record.user == @user
+ mine?
end
C'était rafraîchissant.
Désormais, l'action à exécuter uniquement lorsque le modèle associé à l'utilisateur en est propriétaire consiste simplement à créer un fichier de politique et à placer la méthode mine?
. C'est super facile.
→ Création d'une API de tableau d'affichage avec authentification et autorisation dans Rails 6 # 17 Ajout de privilèges d'administrateur [Vers la table de sérialisation]
Recommended Posts