やりたいことはログインページでemail
とpassword
を入力して、ログインするとユーザー一覧ページに遷移します。
まずユーザー一覧ページを用意するためにPhoenixのEctoに関するドキュメントを読むといいです。
ログインページはネット上で探したものを使っています。その中にBootstrap3が含まれているので、Bootstrap3も使いたいです。自分のこの前の投稿を参照にするといいです。
- プロジェクトを作成します。
--no-brunch
についての説明はここにあります。
13:29:11 [N1210A001 => ~/Playground/elixir]
$ mix phoenix.new hello_phoenix --no-brunch
- ユーザー一覧のページを用意します。下のコマンドを実行すると
hello_phoenix/priv/repo/migrations/
ディレクトリの下にmigrationファイルが生成されて、後で使う$ mix ecto.migrate
コマンドの為です。
13:34:30 [N1210A001 => ~/Playground/elixir/hello_phoenix]
$ mix phoenix.gen.html User users name:string email:string password:string
resources "/users", UserController
をhello_phoenix/web/router.ex
に追加します。hello_phoenix_dev
データベースを作成します。なぜhello_phoenix_dev
を作成するかはhello_phoenix/config/dev.exs
ファイルの中に定義されています。
postgres
のroleがないなどのエラー出ている場合はこのページで答えは探せます。
13:37:18 [N1210A001 => ~/Playground/elixir/hello_phoenix]
$ mix ecto.create
- 作成されたデーターベスにテーブルを作成します。
13:47:53 [N1210A001 => ~/Playground/elixir/hello_phoenix]
$ mix ecto.migrate
- これでアプリを立ち上げてみます。下の図のようになっているはずです。
13:48:01 [N1210A001 => ~/Playground/elixir/hello_phoenix]
$ mix phoenix.server
* 画面上でユーザを複数を作成します。
http://localhost:4000/
にアクセスする際にログイン画面にします。
1) hello_phoenix/web/templates/layout/application.html.eex
を下のように修正します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Hello Phoenix!</title>
<link rel="stylesheet" href="<%= static_path(@conn, "/css/bootstrap.css") %>">
<link rel="stylesheet" href="<%= static_path(@conn, "/css/login.css") %>">
<link rel="stylesheet" href="<%= static_path(@conn, "/js/bootstrap.js") %>">
</head>
<body>
<%= @inner %>
</body>
</html>
2) hello_phoenix/web/templates/page/index.html.eex
を下のように修正します。
<div class="container">
<div class="row">
<div class="col-sm-6 col-md-4 col-md-offset-4">
<div class="account-wall">
<form class="form-signin" action="<%= page_path(@conn, :login) %>" method="post">
<input type="text" class="form-control" name="user[email]" placeholder="Email" required autofocus>
<input type="password" class="form-control" name="user[password]" placeholder="Password" required>
<input type="hidden" name="_csrf_token" value="<%= get_csrf_token() %>">
<button class="btn btn-lg btn-primary btn-block" type="submit">
Sign in</button>
<label class="checkbox pull-left">
<input type="checkbox" value="remember-me">
Remember me
</label>
<a href="#" class="pull-right need-help">Need help? </a><span class="clearfix"></span>
</form>
</div>
<a href="#" class="text-center new-account">Create an account </a>
</div>
</div>
</div>
なぜ<input type="hidden" name="_csrf_token" value="<%= get_csrf_token() %>">
を入れているかはstackoverflowの質問を参照するといいです。この1行を入れないと、下のようなエラーが出ます。
invalid CSRF (Cross Site Forgery Protection) token, make sure all requests include a '_csrf_token' param or an 'x-csrf-token' header
3) login.css
ファイルを下の中身で作成して、hello_phoenix/priv/static/css/
ディレクトリ下に移動します。
.form-signin
{
max-width: 330px;
padding: 15px;
margin: 0 auto;
}
.form-signin .form-signin-heading, .form-signin .checkbox
{
margin-bottom: 10px;
}
.form-signin .checkbox
{
font-weight: normal;
}
.form-signin .form-control
{
position: relative;
font-size: 16px;
height: auto;
padding: 10px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.form-signin .form-control:focus
{
z-index: 2;
}
.form-signin input[type="text"]
{
margin-bottom: -1px;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.form-signin input[type="password"]
{
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.account-wall
{
margin-top: 20px;
padding: 40px 0px 20px 0px;
background-color: #f7f7f7;
-moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
}
.login-title
{
color: #555;
font-size: 18px;
font-weight: 400;
display: block;
}
.profile-img
{
width: 96px;
height: 96px;
margin: 0 auto 10px;
display: block;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
}
.need-help
{
margin-top: 10px;
}
.new-account
{
display: block;
margin-top: 10px;
}
4) hello_phoenix/web/router.ex
ファイルに/login
を部分を追加して、下のようになります。注意して欲しいのはpost
を使っています。
defmodule HelloPhoenix.Router do
use HelloPhoenix.Web, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
end
pipeline :api do
plug :accepts, ["json"]
end
scope "/", HelloPhoenix do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
post "/login", PageController, :login
resources "/users", UserController
end
end
5) これでアプリを起動して、ログインページが表示されるようになっているはずです。
14:28:36 [N1210A001 => ~/Playground/elixir/hello_phoenix]
$ mix phoenix.server
- これからログイン処理に入ります。
hello_phoenix/web/controllers/page_controller.ex
ファイルを以下のように修正します。
defmodule HelloPhoenix.PageController do
use HelloPhoenix.Web, :controller
# `query = from u in User,`部分
# の`User`が使える為にaliasしている
alias HelloPhoenix.User
# `redirect conn, to: Helpers.user_path(conn, :index)`部分
# の`Helpers.user_path`が使えるためにaliasをしている
alias HelloPhoenix.Router.Helpers
plug :action
def index(conn, _params) do
render conn, "index.html"
end
def login(conn, %{"user" => %{"email" => email, "password" => password}}) do
query = from u in User,
where: u.email == ^email,
where: u.password == ^password,
select: u.id
result = HelloPhoenix.Repo.all(query)
# ユーザーが存在すればユーザー一覧ページにリダイレクトされます
case length(result) > 0 do
true ->
redirect conn, to: Helpers.user_path(conn, :index)
false ->
text conn, "ログイン失敗"
end
end
end
これで一番簡単なログインページができました。また実装していない部分は
1) パスワードの暗号化
2) ログインしていないユーザーはユーザー一覧を見られないように
どなたか上のような機能実装したら、教えてください。特に2)番目です。