RodAuthによるRails 6での認証の追加


このチュートリアルでは、我々はどのように完全に機能認証とアカウント管理機能をレール6アプリに追加する方法を示しますRodauth 認証フレームワークRodauthは工夫、呪術、クリアランス、および弁論などの主流の選択肢に多くの利点を持っていますprevious article イントロダクション.
我々は、基本的なポストCRUDを持っている新鮮なRailsアプリで働いていますBootstrap インストール
$ git clone https://gitlab.com/janko-m/rails_bootstrap_starter.git rodauth_blog
$ cd rodauth_blog
$ bin/setup

インストール


を始めましょうrodauth-rails ジェムファイルへの宝石
$ bundle add rodauth-rails
次に、私たちはrodauth:install Rodauth Railsによって提供されるジェネレータ
$ rails generate rodauth:install

# create  db/migrate/20200820215819_create_rodauth.rb
# create  config/initializers/rodauth.rb
# create  config/initializers/sequel.rb
# create  app/lib/rodauth_app.rb
# create  app/controllers/rodauth_controller.rb
# create  app/models/account.rb
これはデフォルトの認証機能を使用してRodAuthアプリケーションを作成しますSequel データベース相互作用のためにreuse Active Record's database connection , そして、ロードされたRodauth機能のためにテーブルを作成するマイグレーションを生成します.移動を実行しましょう
$ rails db:migrate

# == CreateRodauth: migrating ====================================
# -- create_table(:accounts)
# -- create_table(:account_password_hashes)
# -- create_table(:account_password_reset_keys)
# -- create_table(:account_verification_keys)
# -- create_table(:account_login_change_keys)
# -- create_table(:account_remember_keys)
# == CreateRodauth: migrated ===========================
すべてが正常にインストールされている場合、我々は/create-account ページとRodAuthのデフォルト登録フォームを見てください.

認証リンクの追加


RodAuth Railsによって生成されたRodAuthの設定は、認証とアカウント管理のためのいくつかのルートを提供します.
$ rails rodauth:routes

# /login                   rodauth.login_path
# /create-account          rodauth.create_account_path
# /verify-account-resend   rodauth.verify_account_resend_path
# /verify-account          rodauth.verify_account_path
# /logout                  rodauth.logout_path
# /remember                rodauth.remember_path
# /reset-password-request  rodauth.reset_password_request_path
# /reset-password          rodauth.reset_password_path
# /change-password         rodauth.change_password_path
# /change-login            rodauth.change_login_path
# /verify-login-change     rodauth.verify_login_change_path
# /close-account           rodauth.close_account_path
この情報を使用して、ナビゲーションヘッダーにいくつかの主な認証リンクを追加します.
<!-- app/views/application/_navbar.html.erb -->
<!-- ... --->
<% if rodauth.logged_in? %>
  <div class="dropdown">
    <%= link_to current_account.email, "#", class: "btn btn-info dropdown-toggle", data: { toggle: "dropdown" } %>
    <div class="dropdown-menu dropdown-menu-right">
      <%= link_to "Change password", rodauth.change_password_path, class: "dropdown-item" %>
      <%= link_to "Change email", rodauth.change_login_path, class: "dropdown-item" %>
      <div class="dropdown-divider"></div>
      <%= link_to "Close account", rodauth.close_account_path, class: "dropdown-item text-danger" %>
      <%= link_to "Sign out", rodauth.logout_path, method: :post, class: "dropdown-item" %>
    </div>
  </div>
<% else %>
  <div>
    <%= link_to "Sign in", rodauth.login_path, class: "btn btn-outline-primary" %>
    <%= link_to "Sign up", rodauth.create_account_path, class: "btn btn-success" %>
  </div>
<% end %>
<!-- ... --->
ロイトは定義していない#current_account 方法は、ペーストをコピーしましょう.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :current_account, if: -> { rodauth.logged_in? }

  private

  def current_account
    @current_account ||= Account.find(rodauth.session_value)
  rescue ActiveRecord::RecordNotFound
    rodauth.logout
    rodauth.login_required
  end
  helper_method :current_account
end
現在、我々のアプリケーションはログインと登録のリンクをユーザーがログインしていないときに表示します.

ログインしている間に、いくつかの基本的なアカウント管理のリンクが表示されます.

認証を必要とする


認証を行っているので、アプリケーションの特定の部分を認証する必要があります.この場合、ポストコントローラを認証します.
我々は、Aを加えることができましたbefore_action コントローラへのコールバック、しかし、Rodauthは我々がRudAuthアプリのルート・ブロックの中でこれをするのを許します.この方法では、認証ロジックを1つの場所に含めることができます.
# app/lib/rodauth_app.rb
class RodauthApp < Rodauth::Rails::App
  # ...
  route do |r|
    # ...
    if r.path.start_with?("/posts")
      rodauth.require_authentication
    end
  end
end
現在/posts ページはユーザを/login ページがログオンしていない場合.

また、投稿を投稿するにはaccounts
$ rails generate migration add_account_id_to_posts account:references
$ rails db:migrate
# app/models/account.rb
class Account < ApplicationRecord
  has_many :posts
  # ...
end
そしてPOSTコントローラの現在のアカウントにスコープを設定します.
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
  # ...
  def index
    @posts = current_account.posts.all
  end
  # ...
  def create
    @post = current_account.posts.build(post_params)
    # ...
  end
  # ...
  private
    def set_post
      @post = current_account.posts.find(params[:id])
    end
    # ...
end

新しいフィールドの追加


メールアドレス以外の何かを我々のユーザーに表示するために、登録の間、彼らの名前を入力するのをユーザーに要求しましょう.これはまた、どのようにRodAuthを設定することができる機会を私たちに与えるでしょう.
登録フォームを編集する必要があるので、最初にRodauthのHTMLテンプレートをRailsアプリケーションにコピーしましょう.
$ rails generate rodauth:views

# create  app/views/rodauth/_field.html.erb
# create  app/views/rodauth/_field_error.html.erb
# create  app/views/rodauth/_login_field.html.erb
# create  app/views/rodauth/_login_display.html.erb
# create  app/views/rodauth/_password_field.html.erb
# create  app/views/rodauth/_submit.html.erb
# create  app/views/rodauth/_login_form.html.erb
# create  app/views/rodauth/_login_form_footer.html.erb
# create  app/views/rodauth/_login_form_header.html.erb
# create  app/views/rodauth/login.html.erb
# create  app/views/rodauth/multi_phase_login.html.erb
# create  app/views/rodauth/logout.html.erb
# create  app/views/rodauth/_login_confirm_field.html.erb
# create  app/views/rodauth/_password_confirm_field.html.erb
# create  app/views/rodauth/create_account.html.erb
# create  app/views/rodauth/_login_hidden_field.html.erb
# create  app/views/rodauth/verify_account_resend.html.erb
# create  app/views/rodauth/verify_account.html.erb
# create  app/views/rodauth/reset_password_request.html.erb
# create  app/views/rodauth/reset_password.html.erb
# create  app/views/rodauth/_new_password_field.html.erb
# create  app/views/rodauth/change_password.html.erb
# create  app/views/rodauth/change_login.html.erb
# create  app/views/rodauth/close_account.html.erb
我々は今、オープンすることができますcreate_account.erb 新しいテンプレートを追加するname フィールド
<!-- app/views/rodauth/create_account.erb -->
<%= form_tag rodauth.create_account_path, method: :post do %>
  <!-- new "name" field -->
  <div class="form-group">
    <%= label_tag "name", "Name" %>
    <%= render "field", name: "name", id: "name" %>
  </div>

  <%= render "login_field" %>
  <%= render "login_confirm_field" if rodauth.require_login_confirmation? %>
  <%= render "password_field" if rodauth.create_account_set_password? %>
  <%= render "password_confirm_field" if rodauth.create_account_set_password? && rodauth.require_password_confirmation? %>
  <%= render "submit", value: "Create Account" %>
<% end %>
ユーザの名前が認証に使用されないので、新しいものにそれを保存しましょうprofiles テーブル、および関連付けprofiles テーブルをaccounts 表.
$ rails generate model Profile account:references name:string
$ rails db:migrate
# app/models/account.rb
class Account < ApplicationRecord
  has_one :profile
  # ...
end
我々は今、実際に新しいアプリケーションを処理する当社のRodAuthアプリが必要ですname パラメータアカウントが作成された後に、それが埋められて、関連プロフィール記録を作成するのを検証します.
# app/lib/rodauth_app.rb
class RodauthApp < Rodauth::Rails::App
  configure do
    # ...
    before_create_account do
      # Validate presence of the name field
      throw_error_status(422, "name", "must be present") unless param_or_nil("name")
    end
    after_create_account do
      # Create the associated profile record with name
      Profile.create!(account_id: account_id, name: param("name"))
    end
    after_close_account do
      # Delete the associated profile record
      Profile.find_by!(account_id: account_id).destroy
    end
    # ...
  end
end
今、我々は彼らの電子メールアドレスの代わりにユーザーの名前を使用するために我々のナビゲーションヘッダーをアップデートすることができます:
-     <%= link_to current_account.email, "#", class: "btn btn-info dropdown-toggle", data: { toggle: "dropdown" } %>
+     <%= link_to current_account.profile.name, "#", class: "btn btn-info dropdown-toggle", data: { toggle: "dropdown" } %>

メールを非同期に送信する


RodAuthアカウントの検証、メールの変更、パスワードの変更、パスワードのリセットの一部として電子メールを送信します.デフォルトでは、これらのメールは内部のメーラーを介して同期的に送信されますが、パフォーマンス上の理由から、バックグラウンドジョブ内で非同期的にこれらのメールを送信する必要があります.
最終的にはRodAuthのデフォルトのメールテンプレートを修正したいので、デフォルトのテンプレートで独自のメーラーを作成しましょう.
$ rails generate rodauth:mailer

# create  app/mailers/rodauth_mailer.rb
# create  app/views/rodauth_mailer/email_auth.text.erb
# create  app/views/rodauth_mailer/password_changed.text.erb
# create  app/views/rodauth_mailer/reset_password.text.erb
# create  app/views/rodauth_mailer/unlock_account.text.erb
# create  app/views/rodauth_mailer/verify_account.text.erb
# create  app/views/rodauth_mailer/verify_login_change.text.erb
class RodauthMailer < ApplicationMailer
  def verify_account(recipient, email_link)
    # ...
  end
  def reset_password(recipient, email_link)
    # ...
  end
  def verify_login_change(recipient, old_login, new_login, email_link)
    # ...
  end
  def password_changed(recipient)
    # ...
  end
end
さて、私たちのメーラーが自動的にrodauthによって呼び出され、バックグラウンドでメールを配信するために、次の行をrodauthアプリケーションでコメントしてみましょう.
# app/lib/rodauth_app.rb
class RodauthApp < Rodauth::Rails::App
  configure do
    # ...
    send_reset_password_email do
      mailer_send(:reset_password, email_to, reset_password_email_link)
    end
    send_verify_account_email do
      mailer_send(:verify_account, email_to, verify_account_email_link)
    end
    send_verify_login_change_email do |login|
      mailer_send(:verify_login_change, login, verify_login_change_old_login, verify_login_change_new_login, verify_login_change_email_link)
    end
    send_password_changed_email do
      mailer_send(:password_changed, email_to)
    end
    auth_class_eval do
      def mailer_send(type, *args)
        db.after_commit do
          RodauthMailer.public_send(type, *args).deliver_later
        end
      end
    end
    # ...
  end
end
私たちは、データベーストランザクションがコミットされた後に電子メール配送をenqueueします.そして、バックグラウンド仕事が拾われるとき、rodauthが我々のメーラーに呼ばれる前になされるどんなデータベース変化も確実にしました.

閉鎖語


このチュートリアルでは、RodAuth認証フレームワークを使用して完全認証とアカウント管理フローを徐々に構築しました.これは、ログイン&ログアウト、電子メールの検証と猶予期間、パスワード変更&パスワードのリセット、電子メールの検証とメールの変更、およびアカウントの機能を持つアカウントの作成をサポートします.特定のルートに対する認証を要求し、登録フォームに新しいフィールドを追加し、認証メールを非同期で送信する方法を見ました.
私は個人的にロドウスについて非常に興奮しています.そして、それは印象的なfeaturesetときれいにきれいなデザインを持っています、そして、それもレールに縛られません.一生懸命働いてきたrodauth-rails 可能な限り簡単にレールで始めるので、うまくいけばそれはRodauthがRailsコミュニティでより多くのトラクションを得るのを助けるでしょう.