③Elixirユーザ認証ライブラリ「phx_gen_auth」の本番向け改造ポイント：ページヘッダーの変更

[Elixir Digitalization Implementors／fukuoka.ex／kokura.ex](https://fukuokaex.connpass.com/)のpiacereです
ご覧いただいて、ありがとうございます :bow:

[前回](https://qiita.com/piacerex/items/5f11e33db748830c7636)に引き続き、Phoenixユーザ認証ライブラリ「phx_gen_auth」のプロダクション向け改造ポイントとして、今回は、ページヘッダーの変更について解説します

phx_gen_auth用の各リンクをプルダウンメニュー化したり、ナビゲーションバーに配置するといったページデザインを行うとき、今回の内容が役に立つと思います

<h3>:ocean::ocean: Elixir ranked second on the Qiita Advent calendar :ocean::ocean:</h3>

In the programming language category ranking, Rust was 1st, Elixir was 2nd, Golang was 3rd, and all were modern programming languages.:laughing:
https://qiita.com/advent-calendar/2020/elixir
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/ea185203-c525-c778-dc10-6d2ecc391616.png)](https://qiita.com/advent-calendar/2020/elixir)

In addition, our Elixir community "fukuoka.ex" has won the top spot in the Web Technology category.
https://qiita.com/advent-calendar/2020/fukuokaex
[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/8a22a81f-2917-6072-10bd-525e0fc24b75.png)](https://qiita.com/advent-calendar/2020/neosvr_reso)

# 本コラムの検証環境

本コラムは、以下環境で検証しています（Windowsで実施していますが、Linuxやmacでも動作する想定です）

- Windows 11
- Elixir 1.12.0 on WSL2 Ubuntu　※<b>[最新版のインストール手順はコチラ](https://qiita.com/piacerex/items/6b64dfe70f48c89d8385)</b>
- Phoenix 1.6.0　　　　　　　　※<b>[最新版のインストール手順はコチラ](https://qiita.com/piacere_ex/items/b7787580fce5f148242f#phoenix%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)</b>
- PostgreSQL 10.17　　　　　　※<b>[最新版のインストール手順はコチラ](https://qiita.com/piacere_ex/items/a7558adc6856e3577dc6#postgresql%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)</b>

なお、本コラム内で扱うPhoenix PJ名は「basic」、phx_gen_authのコンテキスト名は「Accounts」を前提にしています

# ③ページヘッダーの変更

## ③－１：ヘッダーの構成

未ログイン時のヘッダーは、下記の赤囲みのような出力を行います
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/08eda73e-8333-2a6d-2888-9e464a21df52.png)

ログイン済みの場合は、下記の緑囲みのような出力に切り替わります（ログアウトすると未ログイン時に戻ります）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/26f36307-3b41-395a-a4e6-34af183fd334.png)

この制御をしている対象ファイルは、以下の通りです

ファイルパス | 役割
-+-
lib/basic_web/templates/layout/_account_menu.html.heex | ログイン前／後のメニューリンクがある
lib/basic_web/templates/layout/root.html.heex | _account_menu.html.heexをrenderで読み込んでいる

各ファイルは、下記のような内容です

```erb:lib/basic_web/templates/layout/_account_menu.html.heex
<ul>
<%= if @current_account do %>
  <li><%= @current_account.email %></li>
  <li><%= link "Settings", to: Routes.account_settings_path(@conn, :edit) %></li>
  <li><%= link "Log out", to: Routes.account_session_path(@conn, :delete), method: :delete %></li>
<% else %>
  <li><%= link "Register", to: Routes.account_registration_path(@conn, :new) %></li>
  <li><%= link "Log in", to: Routes.account_session_path(@conn, :new) %></li>
<% end %>
</ul>
```

root.html.heex は、_account_menu.html.heex をrenderで読み込んでいます

```erb:lib/basic_web/templates/layout/root.html.heex
<!DOCTYPE html>
…
  <body>
    <header>
      <section class="container">
        <nav>
          <ul>
            <li><a href="https://hexdocs.pm/phoenix/overview.html">Get Started</a></li>
            <%= if function_exported?(Routes, :live_dashboard_path, 2) do %>
              <li><%= link "LiveDashboard", to: Routes.live_dashboard_path(@conn, :home) %></li>
            <% end %>
          </ul>
          <%= render "_account_menu.html", assigns %>
…
```

## ③－２．調整例１：ヘッダーそのものを削除する

RegisterやLogin、メールアドレス表示などを、根本的にデザイン変更し、表示位置を変えたりしたい場合は、元々あるリンクを削除した方が都合が良いです

この対応は簡単で、root.html.heex の _account_menu.html をrenderしているところをコメントアウト or 削除するだけです

```erb:lib/basic_web/templates/layout/root.html.heex
<!DOCTYPE html>
…
  <body>
    <header>
      <section class="container">
        <nav>
          <ul>
            <li><a href="https://hexdocs.pm/phoenix/overview.html">Get Started</a></li>
            <%= if function_exported?(Routes, :live_dashboard_path, 2) do %>
              <li><%= link "LiveDashboard", to: Routes.live_dashboard_path(@conn, :home) %></li>
            <% end %>
          </ul>
          <%= # render "_account_menu.html", assigns  # <-- comment-out here %>
…
```

もしくは、_account_menu.html の内容を空にするでもOKです

この通り、phx_gen_auth関連のリンクが、全て削除され、ここからのログインやユーザ登録等は一切できなくなります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/6fca16a2-de09-95b1-8817-70a4f598df9c.png)

なお、URL直打ちすれば、該当ページは利用できるので、ページの別場所からリンクを設定し、phx_gen_authの機能を各種ページ箇所にバラすことも可能です

一方、使用しないURLを機能させないようにしたい場合（後述のRegister削除など）は、下記のように、router.exからエントリーを削除します

```elixir:lib/basic_web/router.ex
defmodule BasicWeb.Router do
…
  ## Authentication routes

  scope "/", BasicWeb do
    pipe_through [:browser, :redirect_if_account_is_authenticated]

# v-- comment-out start
    # get "/accounts/register", AccountRegistrationController, :new
    # post "/accounts/register", AccountRegistrationController, :create
    # get "/accounts/log_in", AccountSessionController, :new
    # post "/accounts/log_in", AccountSessionController, :create
    # get "/accounts/reset_password", AccountResetPasswordController, :new
    # post "/accounts/reset_password", AccountResetPasswordController, :create
    # get "/accounts/reset_password/:token", AccountResetPasswordController, :edit
    # put "/accounts/reset_password/:token", AccountResetPasswordController, :update
# ^-- comment-out end
  end
…
```

## ③－３．調整例２：ヘッダーからRegisterを削除する（招待制サイト向き対応）

たとえば、会員制サイトの中でも、招待制のサイトであれば、ユーザ自身によるユーザ登録を禁止している場合があります

一方、デフォルトのphx_gen_authは、ユーザ自身によるユーザ登録を許可しているため、都合が悪いです

しかも初期状態では、仮登録等を挟まないので、いきなりユーザ登録／ログインができてしまいます（なお、仮登録を有効にするカスタマイズは、次回以降のコラムで紹介予定です）

こういうケースでは、_account_menu.html.heex の方を直接いじって、Register リンクを削除します

```erb:lib/basic_web/templates/layout/_account_menu.html.heex
<ul>
<%= if @current_account do %>
  <li><%= @current_account.email %></li>
  <li><%= link "Settings", to: Routes.account_settings_path(@conn, :edit) %></li>
  <li><%= link "Log out", to: Routes.account_session_path(@conn, :delete), method: :delete %></li>
<% else %>
  <!--<li>--><%= # link "Register", to: Routes.account_registration_path(@conn, :new) %><!--</li>-->
  <li><%= link "Log in", to: Routes.account_session_path(@conn, :new) %></li>
<% end %>
</ul>
```

なお、HTML部分を削除するだけで無く、Registerのlink生成しているElixirコードもコメントアウト or 削除することをお忘れなく

これで、Registerリンクのみが消え、画面からのユーザ登録ができなくなります（URL直打ちも出来なくするには、router.ex 側も修正してください）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/3f847bb8-6005-0c32-06ef-8a9457044eb3.png)

招待制のユーザ登録導線側の実装は、機会があれば、別途コラムで紹介します

# 最後に

今回は、「phx_gen_auth」のプロダクション向け改造ポイントの中でも、ナビゲーションとデザインに関係してくるページヘッダーの変更を行いました

ヘッダーの変更は、定義ファイルの位置さえ把握してしまえば、難しく無いかと思いますが、ページデザイン内にphx_gen_authの機能をバラす際には必須のテクニックとなります

Elixir／Phoenixで、会員制サイトのような、ユーザ認証付きWebサイトを開発する際は、phx_gen_authを活用するとハッピーになれますよ:kissing_heart:

なお、気が向いたら、上記を全てセッティングした会員制WebサイトのテンプレートをOSS化したいなぁって思っています … つまり、Elixir／Phoenixであれば、会員制Webサイトの構築をイチからやらなくて良くなります

[次回は、phx_gen_authの各種ページデザインのカスタマイズ](https://qiita.com/piacerex/items/5be752bdb9b18b1e6e6c)をします