[RUBY] Erstellen Sie mit Rails 6 # 18 eine Bulletin-Board-API mit Zertifizierung und Autorisierung. ・ Implementierung des Endbenutzer-Controllers

Erstellen einer Bulletin Board-API mit Zertifizierung und Autorisierung in Rails 6 # 17 Hinzufügen von Administratorrechten

Dies ist das Ende der 18-teiligen Serialisierung.

Dieses Mal erstellen wir einen Benutzer-Controller. Es ist eine Zusammenstellung der Vergangenheit, daher empfehlen wir, dass Sie es versuchen, ohne den Beispielcode zu betrachten.

Spezifikation

Es ist hauptsächlich für Administratoren zur Verwaltung von Benutzern und als Gruppe von Funktionen vorgesehen, mit denen Benutzer sich selbst aktualisieren und löschen können.

Verfahren

  1. Erstellen Sie users_controller
  2. Erstellen Sie user_policy
  3. Implementierung des user_policy-Tests
  4. Implementierung von user_policy
  5. Implementierung des Users_controller-Tests
  6. Implementierung von users_controller

Ich werde mit dem Verfahren fortfahren.

1. Erstellen Sie users_controller

Implementierungsbeispiel
Es ist einfach, weil Sie nur den Befehl drücken.
$ rails g controller v1/users

Hier ist eine Gruppe von Dateien, die leicht modifiziert wurden, damit Rubocop nicht wütend wird.

app/controllers/v1/users_controller.rb


# frozen_string_literal: true

module V1
  #
  #  users controller
  #
  class UsersController < ApplicationController
  end
end

spec/requests/v1/users_request_spec.rb


# frozen_string_literal: true

require "rails_helper"

RSpec.describe "V1::Users", type: :request do
end

2. Erstellen Sie user_policy

Implementierungsbeispiel

Drücken Sie den Befehl, um eine Datei zu erstellen.

$ rails g pundit:policy user

Nach geringfügigen Änderungen, damit Rubocop nicht wütend wird, ist es vorerst abgeschlossen.

app/policies/user_policy.rb


# frozen_string_literal: true

#
#Benutzerrichtlinienklasse
#
class UserPolicy < ApplicationPolicy
  #
  # scope
  #
  class Scope < Scope
    def resolve
      scope.all
    end
  end
end

spec/policies/user_policy_spec.rb


# frozen_string_literal: true

require "rails_helper"

RSpec.describe UserPolicy, type: :policy do
  let(:user) { User.new }

  subject { described_class }

  permissions ".scope" do
    pending "add some examples to (or delete) #{__FILE__}"
  end

  permissions :show? do
    pending "add some examples to (or delete) #{__FILE__}"
  end

  permissions :create? do
    pending "add some examples to (or delete) #{__FILE__}"
  end

  permissions :update? do
    pending "add some examples to (or delete) #{__FILE__}"
  end

  permissions :destroy? do
    pending "add some examples to (or delete) #{__FILE__}"
  end
end

3. Implementierung des user_policy-Tests

Implementierungsbeispiel

Überprüfung der Spezifikationen.

  • #index Nur Administratoren können anzeigen
  • #show Nur für Sie selbst oder den Administrator verfügbar
  • #create Nur Administratoren können erstellen
  • #update Nur Sie oder Ihr Administrator können aktualisieren
  • #destroy Nur der Administrator kann löschen

Es scheint, dass der Index #create, #destroy und #show, #update gemeinsam genutzt werden können.

Hier ist die Implementierung in diesem Sinne.

spec/policies/user_policy_spec.rb


# frozen_string_literal: true

require "rails_helper"

RSpec.describe UserPolicy, type: :policy do
  let(:user) { create(:user) }
  let(:another_user) { create(:user) }
  let(:admin_user) { create(:user, :admin) }

  subject { described_class }

  permissions :index?, :create?, :destroy? do
    it "Nicht erlaubt, wenn nicht angemeldet" do
      expect(subject).not_to permit(nil, user)
    end
    it "Nicht zulässig, wenn Sie als Benutzer ohne Administratorrechte angemeldet sind" do
      expect(subject).not_to permit(user, user)
    end
    it "Erlaubt, wenn Sie als Administrator angemeldet sind" do
      expect(subject).to permit(admin_user, user)
    end
  end

  permissions :show?, :update? do
    it "Nicht erlaubt, wenn nicht angemeldet" do
      expect(subject).not_to permit(nil, user)
    end
    it "Nicht erlaubt, wenn angemeldet, aber ein anderer Benutzer" do
      expect(subject).not_to permit(user, another_user)
    end
    it "Erlaubt, wenn Sie als Administrator angemeldet sind" do
      expect(subject).to permit(admin_user, user)
    end
    it "Erlaubt, wenn angemeldet und derselbe Benutzer" do
      expect(subject).to permit(user, user)
    end
  end
end

Der Punkt ist, dass ein anderer Benutzer namens "another_user" definiert ist. Zu diesem Zeitpunkt haben wir noch keine Richtlinie festgelegt. Stellen Sie daher sicher, dass einige Tests Moos sind.

4. Implementierung von user_policy

Implementierungsbeispiel

app/policies/user_policy.rb


# frozen_string_literal: true

#
#Benutzerrichtlinienklasse
#
class UserPolicy < ApplicationPolicy
  def index?
    admin?
  end

  def show?
    me? || admin?
  end

  def create?
    admin?
  end

  def update?
    me? || admin?
  end

  def destroy?
    admin?
  end

  private

  def me?
    @record == @user
  end

  #
  # scope
  #
  class Scope < Scope
    def resolve
      scope.all
    end
  end
end

Der Punkt ist, eine private Methode namens "me?" In user_policy.rb zu definieren.

Mine? In application_policy.rb wurden @ record.user == @ user und @ records user mit dem eigenen verglichen. Dieses Mal werden wir jedoch prüfen, ob "@ record" und "@ user" übereinstimmen, sodass die englische Grammatik "ich" anstelle von "meine" lautet. Außerdem scheint es, dass im Moment nur users_controller mit user selbst verglichen werden kann, also habe ich es user_policy anstelle von application_policy vorgeschlagen.

Der Test sollte ohne besondere Erwähnung bestanden haben. </ div> </ details>

5. Implementierung des Users_controller-Tests

Implementierungsbeispiel

spec/requests/v1/users_request_spec.rb


# frozen_string_literal: true

require "rails_helper"

RSpec.describe "V1::Users", type: :request do
  before do
    @user = create(:user, name: "Benutzertest")
    @authorized_headers = authorized_user_headers @user
    admin = create(:user, :admin)
    @authorized_admin_headers = authorized_user_headers admin
  end
  describe "GET /v1/users#index" do
    before do
      create_list(:user, 3)
    end
    it "Der normale Antwortcode wird zurückgegeben" do
      get v1_users_url, headers: @authorized_admin_headers
      expect(response.status).to eq 200
    end
    it "Die Nummer wird korrekt zurückgegeben" do
      get v1_users_url, headers: @authorized_admin_headers
      json = JSON.parse(response.body)
      expect(json["users"].length).to eq(3 + 2) #Enthält 2 für Header
    end
    it "Die Antworten werden in absteigender Reihenfolge der ID zurückgegeben" do
      get v1_users_url, headers: @authorized_admin_headers
      json = JSON.parse(response.body)
      first_id = json["users"][0]["id"]
      expect(json["users"][1]["id"]).to eq(first_id - 1)
      expect(json["users"][2]["id"]).to eq(first_id - 2)
      expect(json["users"][3]["id"]).to eq(first_id - 3)
      expect(json["users"][4]["id"]).to eq(first_id - 4)
    end
  end

  describe "GET /v1/users#show" do
    it "Der normale Antwortcode wird zurückgegeben" do
      get v1_user_url({ id: @user.id }), headers: @authorized_headers
      expect(response.status).to eq 200
    end
    it "Name wird korrekt zurückgegeben" do
      get v1_user_url({ id: @user.id }), headers: @authorized_headers
      json = JSON.parse(response.body)
      expect(json["user"]["name"]).to eq("Benutzertest")
    end
    it "Die Antwort 404 wird zurückgegeben, wenn die ID nicht vorhanden ist" do
      last_user = User.last
      get v1_user_url({ id: last_user.id + 1 }), headers: @authorized_headers
      expect(response.status).to eq 404
    end
  end

  describe "POST /v1/users#create" do
    let(:new_user) do
      attributes_for(:user, name: "create_Namenstest", email: "[email protected]", admin: true)
    end
    it "Der normale Antwortcode wird zurückgegeben" do
      post v1_users_url, params: new_user, headers: @authorized_admin_headers
      expect(response.status).to eq 200
    end
    it "Ein weiterer Fall wird zurückgesandt" do
      expect do
        post v1_users_url, params: new_user, headers: @authorized_admin_headers
      end.to change { User.count }.by(1)
    end
    it "name, email,admin kehrt korrekt zurück" do
      post v1_users_url, params: new_user, headers: @authorized_admin_headers
      json = JSON.parse(response.body)
      expect(json["user"]["name"]).to eq("create_Namenstest")
      expect(json["user"]["email"]).to eq("[email protected]")
      expect(json["user"]["admin"]).to be true
    end
    it "Fehler werden zurückgegeben, wenn der Parameter ungültig ist" do
      post v1_users_url, params: {}, headers: @authorized_admin_headers
      json = JSON.parse(response.body)
      expect(json.key?("errors")).to be true
    end
  end

  describe "PUT /v1/users#update" do
    let(:update_param) do
      update_param = attributes_for(:user, name: "update_Namenstest", email: "[email protected]", admin: true)
      update_param[:id] = @user.id
      update_param
    end
    it "Der normale Antwortcode wird zurückgegeben" do
      put v1_user_url({ id: update_param[:id] }), params: update_param, headers: @authorized_headers
      expect(response.status).to eq 200
    end
    it "name, email,admin kehrt korrekt zurück" do
      put v1_user_url({ id: update_param[:id] }), params: update_param, headers: @authorized_headers
      json = JSON.parse(response.body)
      expect(json["user"]["name"]).to eq("update_Namenstest")
      expect(json["user"]["email"]).to eq("[email protected]")
      expect(json["user"]["admin"]).to be false #Es ist ein Problem, wenn die Administratorberechtigung neu geschrieben werden kann. Lassen Sie sie daher als falsch
    end
    it "Fehler werden zurückgegeben, wenn der Parameter ungültig ist" do
      put v1_user_url({ id: update_param[:id] }), params: { name: "" }, headers: @authorized_headers
      json = JSON.parse(response.body)
      expect(json.key?("errors")).to be true
    end
    it "Die Antwort 404 wird zurückgegeben, wenn die ID nicht vorhanden ist" do
      last_user = User.last
      put v1_user_url({ id: last_user.id + 1 }), params: update_param, headers: @authorized_admin_headers
      expect(response.status).to eq 404
    end
  end

  describe "DELETE /v1/users#destroy" do
    it "Der normale Antwortcode wird zurückgegeben" do
      delete v1_user_url({ id: @user.id }), headers: @authorized_admin_headers
      expect(response.status).to eq 200
    end
    it "Eins weniger und kehrt zurück" do
      expect do
        delete v1_user_url({ id: @user.id }), headers: @authorized_admin_headers
      end.to change { User.count }.by(-1)
    end
    it "Die Antwort 404 wird zurückgegeben, wenn die ID nicht vorhanden ist" do
      last_user = User.last
      delete v1_user_url({ id: last_user.id + 1 }), headers: @authorized_admin_headers
      expect(response.status).to eq 404
    end
  end
end

Es gibt einige Überlegungen, die sich von denen der Post unterscheiden.

  • Da beim Erstellen des Headers "create (: user)" ausgeführt wird, schreiben Sie den Test unter Berücksichtigung dieser beiden Fälle.
  • Wenn Sie die nicht vorhandene ID überprüfen, erhalten Sie last_user und +1
  • Da es ein Problem ist, wenn das Admin-Flag frei umgeschrieben wird, wird das Admin-Flag durch Erstellen, aber nicht durch Aktualisieren wiedergegeben.

Ich baue ein.

Da die Antwort ein Administratorurteil enthält, muss der Serializer geändert werden.

app/serializers/user_serializer.rb


 # user serializer
 #
 class UserSerializer < ActiveModel::Serializer
-  attributes :id, :name, :email
+  attributes :id, :name, :email, :admin
 end

Jetzt bist du bereit. Als nächstes werden wir die Controller-Implementierung eingeben. </ div> </ details>

6. Implementierung von users_controller

Implementierungsbeispiel

Ändern Sie die Routen so, dass Sie auf den Controller zugreifen können.

config/routes.rb


 Rails.application.routes.draw do
   namespace "v1" do
     resources :posts
+    resources :users
     mount_devise_token_auth_for "User", at: "auth"
   end

Als nächstes kommt der Controller. Dies kann fast von der Post abgelenkt werden.

app/controllers/v1/users_controller.rb


# frozen_string_literal: true

module V1
  #
  #  users controller
  #
  class UsersController < ApplicationController
    before_action :set_user, only: %i[show update destroy]

    def index
      users = User.order(created_at: :desc).limit(20)
      authorize users
      render json: users
    end

    def show
      authorize @user
      render json: @user
    end

    def create
      user = User.new(user_create_params)
      user[:provider] = :email
      authorize user
      if user.save
        render json: user
      else
        render json: { errors: user.errors }
      end
    end

    def update
      authorize @user
      if @user.update(user_params)
        render json: @user
      else
        render json: { errors: @user.errors }
      end
    end

    def destroy
      authorize @user
      @user.destroy
      render json: @user
    end

    private

    def set_user
      @user = User.find(params[:id])
    end

    def user_create_params
      #Zulassen, dass Administratorrechte nur beim Erstellen festgelegt werden
      params.permit(:name, :email, :admin, :password)
    end

    def user_params
      params.permit(:name, :email, :password)
    end
  end
end

Wie ich im Testabschnitt geschrieben habe, lässt der Administrator dies nur beim Erstellen zu. </ div> </ details>

das ist alles. Vielen Dank, dass Sie unsere Website 18 Mal besucht haben.

Erweitern Sie auf dieser Grundlage die Funktionen wie Kommentarfunktion und Social Login.

Inhaltsverzeichnis

[Zur Serialisierungstabelle]

Recommended Posts