[*Rails*] deviseの使い方（rails6版）

# はじめに
Rails6での再再検証版です。
以下のRails5のときのものをRails6で実行し、一部変更になっている部分を反映したバージョンです。
[[*Rails*] deviseの使い方（rails5版）](https://qiita.com/cigalecigales/items/f4274088f20832252374)

```
【前回】
rails : 5.0.0.1
ruby  : 2.3.1
devise: 4.2.0

↓

【今回】
rails : 6.0.2.2
ruby  : 2.7.1
devise: 4.7.1
```

# deviseとは
ユーザー登録して、送られてきたメールのリンクをクリックして本登録して、ログインして、パスワード忘れたら再設定して、何回もログインミスったらアカウントロックして…などといった認証系アプリに必要な機能を簡単に追加できる便利なgemです。

## 1. gemのインストール

### 1. プロジェクトの作成
新しいプロジェクトを作ります。

```bash
$ rails new devise_rails6
$ cd devise_rails6/
```

### 2. Gemfileの編集とインストール
以下ファイルに`devise`と`omniauth-twitter`を追加します。

```ruby
source 'https://rubygems.org'

# (省略)...

# Devise
gem 'devise'
gem 'omniauth-twitter'
```

gemをインストール。

```bash
$ bundle install
```

## 2. deviseの設定

devise関連ファイルを追加。
すると以下のような英文が表示されます。1から4まで順番に見ていきます。

```bash
$ rails generate devise:install

Running via Spring preloader in process 30440
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
===============================================================================

Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views

===============================================================================

```

### 1. デフォルトURLの指定

英文の例に書いてあった `config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }` を以下のファイルに追加しました。
`config.action_mailer.default_url_options = { host: 'localhost:3000' }` でもOKです。

```ruby:config/environments/development.rb
Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.

  # (省略)...
  
  # mailer setting
  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
  # config.action_mailer.default_url_options = { host: 'localhost:3000' }
end
```

### 2. root_urlの指定
1番で指定した `http://localhost:3000/` にアクセスした際に表示されるページを指定します。
現状ページは1つも作っていないため、先に追加します。

Pagesコントローラーと、indexページとshowページを追加してみます。

```bash
$ rails g controller Pages index show
```

`routes.rb` に以下を指定します。

```ruby:config/routes.rb
Rails.application.routes.draw do
  root 'pages#index'
  get 'pages/show'
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
```

### 3. flashメッセージの設定
ログインした時などに上の方に「ログインしました」みたいなメッセージが出るようにします。
以下のファイルの `<body>` タグのすぐ下に指定されたタグを挿入します。

```erb:app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>DeviseRails6</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <!-- ここに追加 -->
    <p class="notice"><%= notice %></p>
    <p class="alert"><%= alert %></p>

    <%= yield %>
  </body>
</html>
```

### 4. deviseのViewを生成
deviseの導入で追加されるViewは、以下のコマンドを実行しなければデザインを変更できないので、デザインをカスタマイズするためにも実行します。

```bash
$ rails g devise:views
```

すると以下の様なファイルが生成されます。

```
app/views/devise/shared/_error_messages.html.erb (エラーメッセージ用パーシャル)
app/views/devise/shared/_links.html.erb (リンク用パーシャル)
app/views/devise/confirmations/new.html.erb (認証メールの再送信画面)
app/views/devise/passwords/edit.html.erb (パスワード変更画面)
app/views/devise/passwords/new.html.erb (パスワードを忘れた際、メールを送る画面)
app/views/devise/registrations/edit.html.erb (ユーザー情報変更画面)
app/views/devise/registrations/new.html.erb (ユーザー登録画面)
app/views/devise/sessions/new.html.erb (ログイン画面)
app/views/devise/unlocks/new.html.erb (ロック解除メール再送信画面)
app/views/devise/mailer/confirmation_instructions.html.erb (メール用アカウント認証文)
app/views/devise/mailer/email_changed.html.erb （メール用メールアドレス変更完了文）
app/views/devise/mailer/password_change.html.erb （メール用パスワード変更完了文）
app/views/devise/mailer/reset_password_instructions.html.erb (メール用パスワードリセット文)
app/views/devise/mailer/unlock_instructions.html.erb (メール用ロック解除文)
```

## 3. Userモデルの設定
### 1. Userモデルの作成
以下を実行。

```bash
$ rails g devise User
```

マイグレーションファイルができます。
デフォルトではこんな感じになってます。

```ruby:db/migrate/20200404040003_devise_create_users.rb
# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.string   :current_sign_in_ip
      # t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

```

Userモデルはこんな感じになっています。
デフォルトでは `database_authenticatable` 、 `registerable` 、 `recoverable` 、 `rememberable` 、 `validatable` が使えるようになっています。

```ruby:app/models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
end
```

### 2. deviseモジュール概要

各モジュールについて以下に紹介します。

|機能|概要|
|:--|:--|
|database_authenticatable|サインイン時にユーザーの正当性を検証するためにパスワードをハッシュ化してDBに登録します。認証方法としてはPOSTリクエストかHTTP Basic認証が使えます。|
|registerable|登録処理を通してユーザーをサインアップします。また、ユーザーに自身のアカウントを編集したり削除できるようにします。|
|recoverable|パスワードをリセットし、それを通知します。|
|rememberable|保存されたcookieから、ユーザーを記憶するためのトークンを生成・削除します。|
|trackable|サインイン回数や、サインイン時間、IPアドレスを記録します。|
|validatable|Emailやパスワードのバリデーションを提供します。独自に定義したバリデーションを追加することもできます。|
|confirmable|メールに記載されているURLをクリックして本登録を完了する、といったよくある登録方式を提供します。また、サインイン中にアカウントが認証済みかどうかを検証します。|
|lockable|一定回数サインインを失敗するとアカウントをロックします。ロック解除にはメールによる解除か、一定時間経つと解除するといった方法があります。|
|timeoutable|一定時間活動していないアカウントのセッションを破棄します。|
|omniauthable|[*intridea/omniauth*](https://github.com/intridea/omniauth)をサポートします。TwitterやFacebookなどの認証を追加したい場合はこれを使用します。|

### 3. Userモデルの編集
今回はデフォルトではないものも触ってみたいと思うので全部入れてみます。
Twitter認証を使うのでTwitterを指定しています。

```ruby:app/models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :confirmable, :lockable, :timeoutable, :trackable, :omniauthable, omniauth_providers:[:twitter]
end
```

### 4. マイグレーションファイルの編集

上に合わせて使用モジュールに対応する部分のコメントアウトを外します。今回は全部使うので全部外します。
全部を使用しない場合は 3. で使うことにしたものに関連する項目だけコメントアウトを外してください。

```ruby:db/migrate/20200404040003_devise_create_users.rb
# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Confirmable
      t.string   :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at
      t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      t.string   :unlock_token # Only if unlock strategy is :email or :both
      t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    add_index :users, :confirmation_token,   unique: true
    add_index :users, :unlock_token,         unique: true
  end
end
```

### 5. omniauth-twitter用カラムの追加
ついでに `omniauth-twitter` で使う `provider` と `uid` 、それとTwitter認証の場合はアカウント名を保存しておきたいので `username` もUserテーブルに追加します。
その他、保存したい項目があったら [arunagw / omniauth-twitter](https://github.com/arunagw/omniauth-twitter#authentication-hash) の認証時のハッシュ情報を参考に保存用カラムを追加してください。

```bash
$ rails g migration add_columns_to_users provider uid username
```

以下のようなマイグレーションファイルができます。

```ruby:db/migrate/20200404042756_add_columns_to_users.rb
class AddColumnsToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :provider, :string
    add_column :users, :uid, :string
    add_column :users, :username, :string
  end
end
```

ここまで出来たら以下を実行します。

```bash
$ rake db:migrate
```

## 4. viewの編集
以下のファイルを編集して、ページ上部にメニューが出るようにします。
`user_signed_in?` はdeviseのHelperメソッドです。
ログインしているかしてないかで上部のメニューの表示が変わるようになります。
`current_user` で現在サインインしているユーザーの情報を取得できます。

```erb:app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>DeviseRails6</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <header>
      <nav>
          <% if user_signed_in? %>
            <strong><%= link_to current_user.username, pages_show_path %></strong>
            <%= link_to 'プロフィール変更', edit_user_registration_path %>
            <%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>
          <% else %>
            <%= link_to 'サインアップ', new_user_registration_path %>
            <%= link_to 'ログイン', new_user_session_path %>
          <% end %>
      </nav>
    </header>
    <!-- ここに追加 -->
    <p class="notice"><%= notice %></p>
    <p class="alert"><%= alert %></p>

    <%= yield %>
  </body>
</html>
```

以下の2ページも修正。
indexの方がトップページ、showの方がログインしているユーザー用のページになる予定です。

```erb:app/views/pages/index.html.erb
<h1>ようこそ</h1>
<p>トップページです。</p>
```

```erb:app/views/pages/show.html.erb
<h1>こんにちは、<%= current_user.username %>さん</h1>
<p>ユーザー用ページです。</p>
```

サーバーを立ち上げて、「サインアップ」を押下すると、 `app/models/user.rb` で `omniauthable` を設定しているのに何の設定もしていないので現状ではエラーになります。

```bash
$ brew install yarn
$ rails webpacker:install
$ rails s
```
<img width="1089" alt="スクリーンショット 2020-04-04 13.39.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/1acd1cfa-0fd8-e5ca-229d-acf3e1cdf69d.png">

<img width="967" alt="スクリーンショット 2020-04-04 13.40.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/b32557bc-4fd5-7c23-598c-30356dc89550.png">


`omniauthable` を設定していない場合はサインアップページが表示されます。

# Twitterで認証する
## 1. 設定
### 1. Twitter Developerの登録
[Twitter Developer](https://developer.twitter.com/en/apps)にアクセスし、 `Create an app` をクリックし（ツイッターにログインしてないとボタンが出ません）、情報を入力にします。
審査がいるようになってしまったので、私がやったときは何週間かかかった気がします。
私は今回、rails5版のこの記事を書いたときのものを使用しています。

<img width="880" alt="スクリーンショット 2020-04-04 13.49.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/115e398e-4d3e-f681-614e-9f1d3b8737a0.png">

新規申請する場合は、申請時に `Enable Sign in with Twitter` にチェックを入れておいてください。

<img width="454" alt="スクリーンショット 2020-04-04 13.52.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/778b9a88-40fb-5503-2506-0c25347afe2e.png">

### 2. 設定ファイルの編集
`Keys and tokens` タブを開き、 `API key` と `API secret key` を以下の該当箇所にコピーして貼り付けます。

<img width="1274" alt="スクリーンショット 2020-04-04 13.55.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/d031bb3a-b330-ef4c-cb86-1da31c25fb91.png">

`callback_url` を `http://127.0.0.1:3000/users/auth/twitter/callback` にし、Twitter Developer側のコールバックの設定も変更する必要があるようです。
なので、以下の用に修正しました。

<img width="320" alt="スクリーンショット 2020-04-04 14.16.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/77a0e0fc-6923-9b79-f243-9d62d1f14124.png">


```ruby:config/initializers/devise.rb
Devise.setup do |config|
  # (省略)...

  config.omniauth :twitter, 'API Key', 'API Secret', callback_url: 'http://127.0.0.1:3000/users/auth/twitter/callback'
end
```

## 2. 動作確認
サーバーを立ち上げてサインアップページの下の方にあるSign in with Twitterというリンクをクリックします。

すると以下の様な画面が開くのでログインして `連携アプリを認証` をクリックします。

<img width="1033" alt="スクリーンショット 2020-04-04 14.16.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/153f7ca3-a0a1-69a1-6672-c9e3085b3350.png">

こんな画面が出るはずです。

<img width="799" alt="スクリーンショット 2020-04-04 14.20.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/64f76d78-c642-7aa9-5d43-0ffcda0f2070.png">

## 3. コールバック用コントローラーの作成
Twitter認証後適切に画面が遷移するように以下を実行してコントローラーを作ります。

```bash
$ rails g controller omniauth_callbacks
```

作成したコントローラーの中身を以下のように修正します。
継承するのが `Devise::OmniauthCallbacksController` になっていることに注意です。
`omniauth.auth` という環境変数に認証に関する情報が入っています。
その情報を使ってユーザーが登録されているかを検証し、登録してる場合はログイン、登録されてない場合は登録用ページに遷移します。

```ruby:app/controllers/omniauth_callbacks_controller.rb
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def twitter
    @user = User.from_omniauth(request.env["omniauth.auth"].except("extra"))

    if @user.persisted?
        sign_in_and_redirect @user
    else
        session["devise.user_attributes"] = @user.attributes
        redirect_to new_user_registration_url
    end
  end
end
```

ちなみに `omniauth.auth` の中にはこんなものが入ってます。（一部の値は適当に変えてあります。）

```bash
{
  "provider"=>"twitter",
  "uid"=>"0123456789",
  "info"=>{
    "nickname"=>"manycicadas",
    "name"=>"芭蕉",
    "location"=>"関東",
    "image"=>"http://pbs.twimg.com/profile_images/483964583371997185/2ZqzhzKV_normal.png",
    "description"=>"JavaEE/Ruby(Rails)/HTML/CSS/JavaScript/Raspberry Pi などなどが好き。",
    "urls"=>{
      "Website"=>nil,
      "Twitter"=>"https://twitter.com/manycicadas"
    }
  },
  "credentials"=>{
    "token"=>"xxx",
    "secret"=>"xxxxxx"
  }
  (省略)...
}
```

Userモデルに `self.from_omniauth` と `self.new_with_session` を作ります。
`self.from_omniauth` では `uid` と `provider` で検索してあったらそれを、無かったらレコードを作ります。
`self.new_with_session` については、もしこのメソッドを追加しておかなければ、Twitter認証後サインアップページで登録を行っても、認証情報として取ってきたuidやproviderなどが登録されません。それらが登録されないのでTwitterで認証しても登録されてないユーザーとして毎回サインアップページに飛ばされます。

```ruby:app/models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :confirmable, :lockable, :timeoutable, :trackable, :omniauthable, omniauth_providers:[:twitter]

  def self.from_omniauth(auth)
    find_or_create_by(provider: auth["provider"], uid: auth["uid"]) do |user|
      user.provider = auth["provider"]
      user.uid = auth["uid"]
      user.username = auth["info"]["nickname"]
    end
  end

  def self.new_with_session(params, session)
    if session["devise.user_attributes"]
      new(session["devise.user_attributes"]) do |user|
        user.attributes = params
      end
    else
      super
    end
  end
end
```

以下ファイルを編集して、コールバック用のコントローラーとしてさっき作ったコントローラーが呼ばれるようにします。これを書かないとdevise側のコントローラーが呼ばれます。

```ruby:config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: { :omniauth_callbacks => "omniauth_callbacks" }
  
  root 'pages#index'
  get 'pages/show'
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
```

これでTwitter認証ができるようになりました。
初回、Twitter認証を行うと、サインアップページに飛ばされ、そこでメールアドレスやパスワードを入力して登録するとユーザー情報が登録されます。
今回は `comfirmable` 機能を入れているので、登録したら確認メッセージを送ったとのメッセージが出て、そのままログインすることはできません。
この機能を入れてなかった場合、登録すると即ログインします。

# アカウント登録確認メールを送る
## 1. comfirmable概要
多くの登録系サイトで採用されている、登録すると仮登録状態になり、届いたメールのリンクをクリックするとログイン可能になるという仕組みを追加できるのがcomfirmableです。
今回はGmailのアカウントを使って実際にメールが届くように設定します。

## 2. ログを見る
```text:log/deployments.log
Devise::Mailer#confirmation_instructions: processed outbound mail in 8.8ms
Delivered mail 5e881d3772753_89a53b9c70510@SampleMacBook-Pro.local.mail (22.3ms)
Date: Sat, 04 Apr 2020 14:37:59 +0900
From: please-change-me-at-config-initializers-devise@example.com
Reply-To: please-change-me-at-config-initializers-devise@example.com
To: sample@example.com
Message-ID: <5e881d3772753_89a53b9c70510@SampleMacBook-Pro.local.mail>
Subject: Confirmation instructions
Mime-Version: 1.0
Content-Type: text/html;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

<p>Welcome sample@example.com!</p>

<p>You can confirm your account email through the link below:</p>

<p><a href="http://localhost:3000/users/confirmation?confirmation_token=1vus7S8UesPoay5yz2je">Confirm my account</a></p>
```

## 3. メールが実際に届くようにする

### 1. 設定ファイルの編集
今回はgmailを使うのでメールアドレスにはgmailを設定します。
デフォルトの設定があると思うので、それを変更してください。

```ruby:config/initializers/devise.rb
Devise.setup do |config|
  # (省略)...
  config.mailer_sender = "メールアドレス"
end
```

gmailの場合はGメールアドレスとGメールパスワードの部分を自分のアカウントのものに変更します。

```ruby:config/environments/development.rb
Rails.application.configure do
  # (省略)...

  # mailer setting
  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
  # config.action_mailer.default_url_options = { host: 'localhost:3000' }
  config.action_mailer.raise_delivery_errors = true
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :address => 'smtp.gmail.com',
    :port => 587,
    :user_name => 'Gメールアドレス',
    :password => 'Gメールパスワード',
    :authentication => :plain,
    :enable_starttls_auto => true
  }
end
```

### 2. Gmailの設定
#### 1. とりあえず試したい場合
デフォルトでは安全性の低いアプリケーションからGmailへのアクセスが制限されています。
よってその制限を解除することで動くようにできます。
ただ、安全性の低いアプリからのアクセスを許可するということはセキュリティ的にはいまいちなのであくまで動作確認ように利用することをおすすめします。
[安全性の低いアプリがアカウントにアクセスするのを許可する](https://support.google.com/accounts/answer/6010255) の安全性の低いアプリを許可というリンクをクリックして、以下のように設定します。

<img width="692" alt="スクリーンショット 2020-04-04 14.48.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/3ef409ba-ddc4-fa7a-de5b-a67a772fcac1.png">

#### 2. 2段階認証がオンの場合
2段階認証をオンにしている場合、1の設定はできないはずなのでこちらをやってください。
また、1のセキュリティ的にイマイチな方をやりたくない方もこの際2段階認証をオンにしてこの設定をやってください。

[アカウントへのアクセスとセキュリティ設定の管理](https://myaccount.google.com/u/1/security?pli=1)を開きます。
2段階認証がオフの場合は2段階認証プロセスから2段階認証の設定をしてください。（[2 段階認証プロセスを有効にする](https://support.google.com/accounts/answer/185839))
2段階認証設定を行っている場合はアプリパスワードを開きます。

<img width="856" alt="スクリーンショット 2020-04-04 15.00.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/b14ce31e-556b-6e1f-c392-98cd124e9630.png">

`アプリを選択` で `その他` を選択します。

<img width="702" alt="スクリーンショット 2020-04-04 15.00.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/954d2b94-ce25-e97b-8d09-ffd5003f10af.png">

適当に名前をつけます。

<img width="702" alt="スクリーンショット 2020-04-04 15.01.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/bca0968e-eb07-6d13-8405-b5d65cf9754b.png">

パスワードが生成されます。

<img width="677" alt="スクリーンショット 2020-04-04 15.04.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/bb5f6359-0e36-d382-6a31-24473b8758c3.png">

生成されたパスワードを、1の設定の `:password => "Gメールパスワード",` のGメールのパスワードの部分に設定します。

### 3. 届いたメールを確認

これでアプリ側からサインアップすると、以下の様なメールが届くようになります。 `Confirm my account` をクリックするログイン画面からログインが可能になります。

<img width="467" alt="スクリーンショット 2020-04-04 15.08.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/cd6b7dc3-f423-50ea-d3d6-54bc15653412.png">

メールで送られる文章は以下のファイルを編集することで可能です。
`app/views/devise/confirmation_instructions.html.erb`

# アカウントをロックする
## 1. lockable概要
アカウントの認証を一定回数間違うと、アカウントをロックするようにする機能です。

## 2. 設定
### 1. 設定ファイルの編集
以下ファイルを修正して、アカウントの認証を5回失敗します。

```ruby:config/initializers/devise.rb
Devise.setup do |config|
    # (省略)...

    # lock sessings
    config.unlock_strategy = :email
    config.maximum_attempts = 4
end
```

するとアカウントがロックされてこのようなメールが届きます。

<img width="600" alt="スクリーンショット 2020-04-04 15.14.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/bd990df2-ca30-2b08-a8ed-1cbcd6025402.png">

メールの中身は `app/views/devise/mailer/unlock_instructions.rb` ファイルを修正すれば変わります。

### 2. 設定値について

* **lock_strategy**（ロック方法）

|属性|説明|
|:--|:--|
|:failed_attempts|失敗回数によってロック。|
|:none|ロックしない。|

* **unlock_strategy**（ロック解除方法）

|属性|説明|
|:--|:--|
|:time|指定時間でロックを解除する。|
|:email|メールでロックを解除する。|
|:both|:timeと:emailの両方。|
|:none|解除させない。|

`:none` を指定した場合、ユーザーのレコードの`locked_at`カラムを`nil`にアップデートしたらロックが解除できます。

* **unlock_in**（ロック解除時間）

2時間で解除するなら`config.unlock_in = 2.hours`といった具合に指定。

* **unlock_keys**

アカウントをロックまたは解除するときに使用するキーを定義するらしいです。
`config.unlock_keys = [:username]`という感じで指定できます。

* **maximum_attempts**（失敗可能回数）

アカウントの認証を失敗して良い回数を指定します。
`config.maximum_attempts = 4`と指定した場合、4回目までは失敗しても大丈夫ですが、5回目を失敗した時点でアカウントがロックされます。

# セッションをタイムアウトする
## 1. timeoutable概要
一定時間活動がない場合にセッションをタイムアウトさせるのがtimeoutableです。

## 2. 設定
以下ファイルを修正するとタイムアウトまでの時間を指定できます。
以下の場合だと3分後にセッションがタイムアウトします。
デフォルトは30分だそうです。

```ruby:config/initializers/devise.rb
Devise.setup do |config|
    (省略)...
  # timeout setting
  config.timeout_in = 3.minutes
end
```

# その他の設定
## 1. ログイン後のページを変更する
ログインすると、デフォルトでは `root_url` に飛ばされます。
これを `app/views/pages/show.html.erb` になるように修正します。
`after_sign_in_path_for` メソッドを追加します。ここにログイン後に遷移したいページを指定します。
あと `sign_in_required` も追加します。showページはログインしているユーザーだけにアクセスさせ、ログインしてない場合はログインページに遷移させます。

```ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  def after_sign_in_path_for(resource)
    pages_show_path
  end

  private
      def sign_in_required
          redirect_to new_user_session_url unless user_signed_in?
      end
end
```

Pagesコントローラーに `before_action` を追加します。

```ruby:app/controllers/pages_controller.rb
class PagesController < ApplicationController
  before_action :sign_in_required, only: [:show]
  
  def index
  end

  def show
  end
end
```

これでログイン後showページに遷移するようになります。

## 2. サインアップする際に登録するパラメーターを増やす

ユーザーを登録するときにデフォルトではEmailとパスワードだけですが、
ユーザー名も登録させたい、などの場合があると思います。

まずはサインアップページにユーザー名を入力するエリアを追加します。
ユーザーのプロフィール変更ページ（`views/devise/registrations/edit.html.erb`）にも同様に追加しときます。

```erb:app/views/devise/registrations/new.html.erb
<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  # (省略)...

  <!-- ユーザー名を追加 -->
  <div class="field">
    <%= f.label :username %><br />
    <%= f.text_field :username %>
  </div>

  # (省略)...

<%= render "devise/shared/links" %>
```

次に `ApplicationController` に以下を追加します。
テンプレートを変えて、ユーザー名を入力するようにしただけでは実際に登録されないからです。
詳しくは `strong_parameters` について調べてください。
簡単に言えばよく分からんパラメーターは渡せないようになってるので渡せるようにします。

```ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :configure_permitted_parameters, if: :devise_controller?

  # (省略)...
  
  protected
    def configure_permitted_parameters
      devise_parameer_sanitizer.permit(:sign_up, keys: [:username])
      devise_parameter_sanitizer.permit(:account_update, keys: [:username])
    end
end
```

# 最後に
作ったプロジェクト全体は以下です。
[cigalecigales/devise_rails6](https://github.com/cigalecigales/devise_rails6)

<img width="869" alt="スクリーンショット 2020-04-04 15.42.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/555885b0-de24-388e-5fa0-92add8e1359b.png">