チュートリアル11章

アカウントの有効化

アカウントを有効化するステップを新規登録の途中に差し込むことで、本当にそのメールアドレスの持ち主なのかどうかを確認できるようにしてみます

流れは、
(1) 有効化トークンやダイジェストを関連付けておいた状態で、
(2) 有効化トークンを含めたリンクをユーザーにメールで送信し、
(3) ユーザーがそのリンクをクリックすると有効化できるようにする

アカウントを有効化する段取りは
１ユーザーの初期状態は「有効化されていない」(unactivated) にしておく。

２ユーザー登録が行われたときに、有効化トークンと、それに対応する有効化ダイジェストを生成する。

３有効化ダイジェストはデータベースに保存しておき、有効化トークンはメールアドレスと一緒に、ユーザーに送信する有効化用メールのリンクに仕込んでおく

４ユーザーがメールのリンクをクリックしたら、アプリケーションはメールアドレスをキーにしてユーザーを探し、データベース内に保存しておいた有効化ダイジェストと比較することでトークンを認証する。

５ユーザーを認証できたら、ユーザーのステータスを「有効化されていない」から「有効化済み」(activated) に変更する。

```ruby:
$ rails generate controller AccountActivations
```

```ruby:config/routes.rb
 Rails.application.routes.draw do
  root   'static_pages#home'
  get    '/help',    to: 'static_pages#help'
  get    '/about',   to: 'static_pages#about'
  get    '/contact', to: 'static_pages#contact'
  get    '/signup',  to: 'users#new'
  get    '/login',   to: 'sessions#new'
  post   '/login',   to: 'sessions#create'
  delete '/logout',  to: 'sessions#destroy'
  resources :users
  resources :account_activations, only: [:edit]　←ここ追加
end
```

攻撃者がデータベースへのアクセスに成功した場合、新しく登録されたユーザーアカウントの有効化トークンを盗み取り、本来のユーザーが使う前にそのトークンを使ってしまう恐れがある

パスワードでやったように仮想的な属性を使ってハッシュ化した文字列をデータベースに保存する

```ruby:
$ rails generate migration add_activation_to_users \
> activation_digest:string activated:boolean activated_at:datetime
```

```ruby:db/migrate/[timestamp]_add_activation_to_users.rb
 class AddActivationToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :activation_digest, :string
    add_column :users, :activated, :boolean, default: false　←ここ追加
    add_column :users, :activated_at, :datetime
  end
end
```

```ruby:
$ rails db:migrate
```



```ruby:app/models/user.rb
 class User < ApplicationRecord
  attr_accessor :remember_token, :activation_token
  before_save   :downcase_email
  before_create :create_activation_digest

.
.
.
 private

    # メールアドレスをすべて小文字にする
    def downcase_email
      self.email = email.downcase
    end

    # 有効化トークンとダイジェストを作成および代入する
    def create_activation_digest
      self.activation_token  = User.new_token
      self.activation_digest = User.digest(activation_token)
    end
end
```

サンプルユーザーの生成とテスト

```ruby:db/seeds.rb
 User.create!(name:  "Example User",
             email: "example@railstutorial.org",
             password:              "foobar",
             password_confirmation: "foobar",
             admin:     true,
             activated: true,
             activated_at: Time.zone.now)

99.times do |n|
  name  = Faker::Name.name
  email = "example-#{n+1}@railstutorial.org"
  password = "password"
  User.create!(name:  name,
              email: email,
              password:              password,
              password_confirmation: password,
              activated: true,
              activated_at: Time.zone.now)
end

上と下の下二行を追加
```

```ruby:test/fixtures/users.yml
 michael:
  name: Michael Example
  email: michael@example.com
  password_digest: <%= User.digest('password') %>
  admin: true
  activated: true
  activated_at: <%= Time.zone.now %>

archer:
  name: Sterling Archer
  email: duchess@example.gov
  password_digest: <%= User.digest('password') %>
  activated: true
  activated_at: <%= Time.zone.now %>

lana:
  name: Lana Kane
  email: hands@example.gov
  password_digest: <%= User.digest('password') %>
  activated: true
  activated_at: <%= Time.zone.now %>

malory:
  name: Malory Archer
  email: boss@example.gov
  password_digest: <%= User.digest('password') %>
  activated: true
  activated_at: <%= Time.zone.now %>

<% 30.times do |n| %>
user_<%= n %>:
  name:  <%= "User #{n}" %>
  email: <%= "user-#{n}@example.com" %>
  password_digest: <%= User.digest('password') %>
  activated: true
  activated_at: <%= Time.zone.now %>
<% end %>

全てに下二行を追加
```

```ruby:
$ rails db:migrate:reset
$ rails db:seed
```

11.2 アカウント有効化のメール送信

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

ｖ
```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```

```ruby:
```