[RUBY] # 16 paramètre de stratégie pour créer une API de tableau d'affichage avec autorisation de certification dans Rails 6

Création d'une API de tableau d'affichage avec autorisation de certification avec Rails 6 # 15 pundit introduction

Modifier post_policy

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.

Modifier les spécifications de la demande

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éecreate (: 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`.

Création d'une méthode de jugement de correspondance utilisateur correspondante

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.

A continué

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

# 16 paramètre de stratégie pour créer une API de tableau d'affichage avec autorisation de certification dans Rails 6
Implémentation n ° 8 pour créer une API de tableau d'affichage avec autorisation de certification dans Rails 6
Présentation du sérialiseur n ° 9 pour créer une API de tableau d'affichage avec certification et autorisation dans Rails 6
Créez une API de tableau d'affichage avec certification et autorisation dans Rails 6 # 6 show, créez une implémentation
Introduction de # 10 devise_token_auth pour créer une API de tableau d'affichage avec autorisation d'authentification dans Rails 6
Introduction de l'expert n ° 15 pour créer une API de tableau d'affichage avec certification et autorisation dans Rails 6
Créer une API de tableau d'affichage avec autorisation de certification dans la mise à jour Rails 6 # 7, détruire l'implémentation
Créer une API de tableau d'affichage avec autorisation de certification dans Rails 6 # 13 Accorder l'en-tête d'authentification
Construire une API de tableau d'affichage avec certification et autorisation dans le contrôleur Rails 6 # 5, implémentation des routes
Créez une API de tableau d'affichage avec certification et autorisation dans Rails 6 # 17 Ajoutez des privilèges d'administrateur
Construire une API de tableau d'affichage avec certification et autorisation dans Rails 6 # 14 Seed Affichage du temps d'exécution
Créez une API de tableau d'affichage avec certification et autorisation avec Rails 6 # 1 Construction de l'environnement
Créer une API de tableau d'affichage avec autorisation dans Rails 6 # 12 Association d'utilisateur et de publication
Créer une API de tableau d'affichage avec autorisation de certification dans Rails 6 # 11 Test et validation du modèle utilisateur ajoutés
Présentation de # 2 git et rubocop pour créer une API de tableau d'affichage avec autorisation d'authentification dans Rails
Construire une API de tableau d'affichage avec certification et autorisation avec Rails 6 # 18 ・ Implémentation du contrôleur de l'utilisateur final
Créez une API de tableau d'affichage avec certification et autorisation avec Rails 6 # 3 RSpec, FactoryBot introduit et post-modèle
# 4 post-validation et mise en œuvre de test pour créer une API de tableau d'affichage avec certification et autorisation dans Rails 6
Comment créer une API avec GraphQL et Rails
J'ai essayé de créer une fonction de groupe (babillard) avec Rails
Comment créer un environnement Rails 6 avec Docker
Essayez de créer un babillard en Java
[Rails] Comment créer un environnement avec Docker
[Comment insérer une vidéo dans un hameau avec Rails]
Comment interroger Array dans jsonb avec Rails + postgres
Environnement Build Rails (API) x MySQL x Nuxt.js avec Docker
Politique de mise en œuvre pour enregistrer et afficher dynamiquement le fuseau horaire dans les rails
J'étais accro à la configuration de default_url_options avec l'introduction de la conception de Rails
Comment configurer un proxy avec authentification dans Feign
Authentification 802.1X au réseau du paramètre de liaison dans CentOS7
Japaneseize en utilisant i18n avec Rails
Implémenter l'authentification LTI dans Rails
J'ai essayé d'implémenter l'API Rails avec TDD par RSpec. part2 -authentification de l'utilisateur-
Ce à quoi j'étais accro lors de la mise en œuvre de l'authentification Google avec des rails
Comment obtenir la valeur de boolean avec jQuery sous forme simple de rails
Comment renommer un modèle avec des contraintes de clé externes dans Rails
Comment créer un environnement Rails + Vue + MySQL avec Docker [dernière version 2020/09]
J'ai essayé d'implémenter l'API Rails avec TDD par RSpec. part3-Implémentation d'action avec authentification-
Étapes pour créer un environnement de développement Ruby on Rails avec Vagrant