readme update
This commit is contained in:
parent
5d4d4e8495
commit
6afdcdfa3e
174
README.md
174
README.md
@ -1,7 +1,5 @@
|
|||||||
# Auth tutorial for setting up basic user auth with `put_session()`
|
# Auth tutorial for setting up basic user auth with `put_session()`
|
||||||
|
|
||||||
**NOTE: PHOENIX_APP and PHOENIX_APP_WEB are just macros here, in your app user your apps name!**
|
|
||||||
|
|
||||||
## Deps used
|
## Deps used
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -22,9 +20,11 @@ Make sure that you have some context that is like `Accounts.User` with `email:un
|
|||||||
You can do this with
|
You can do this with
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
terminal:~/PHOENIX_PROJECT/$ mix phx.gen.html Accounts User users email:string:unique password_hash:string
|
terminal:~/tutorial/$ mix phx.gen.html Accounts User users email:string:unique password_hash:string
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Add `resources "/users", UserController, singleton: true` to the `router.ex`
|
||||||
|
|
||||||
### Password hashing
|
### Password hashing
|
||||||
|
|
||||||
After that open up `accounts/user.ex` and add line bellow to `changeset()`
|
After that open up `accounts/user.ex` and add line bellow to `changeset()`
|
||||||
@ -38,12 +38,12 @@ end
|
|||||||
|
|
||||||
### Auth helper
|
### Auth helper
|
||||||
|
|
||||||
In `PHOENIX_APP_WEB/` create folder `/helpers` and create file `auth.ex`
|
In `/tutorial_web/` create folder `/helpers` and create file `auth.ex`
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
defmodule PHOENIX_APP_WEB.Helpers.Auth do
|
defmodule TutorialWeb.Helpers.Auth do
|
||||||
import Plug.Conn, only: [get_session: 2]
|
import Plug.Conn, only: [get_session: 2]
|
||||||
alias PHOENIX_APP.{Repo, Accounts.User}
|
alias Tutorial.{Repo, Accounts.User}
|
||||||
|
|
||||||
def signed_in?(conn) do
|
def signed_in?(conn) do
|
||||||
user_id = get_session(conn, :current_user_id)
|
user_id = get_session(conn, :current_user_id)
|
||||||
@ -52,13 +52,13 @@ defmodule PHOENIX_APP_WEB.Helpers.Auth do
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Then open your `PHOENIX_APP_WEB.ex` and inside add this `import`, we are doing this because we want to have this function in every `view`
|
Then open your `tutorial_web.ex` and inside add this `import`, we are doing this because we want to have this function in every `view`
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
def view do
|
def view do
|
||||||
quote do
|
quote do
|
||||||
...
|
...
|
||||||
import PHOENIX_APP_WEB.Helpers.Auth, only: [signed_in?: 1]
|
import TutorialWeb.Helpers.Auth, only: [signed_in?: 1]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
@ -120,8 +120,8 @@ One will be used for Signing in and the other for Signing out
|
|||||||
Create `session_view.ex` in `/views` folder
|
Create `session_view.ex` in `/views` folder
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
defmodule PHOENIX_APP_WEB.SessionView do
|
defmodule TutorialWeb.SessionView do
|
||||||
use PHOENIX_APP_WEB, :view
|
use TutorialWeb, :view
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ end
|
|||||||
under you `scope "/"` add following
|
under you `scope "/"` add following
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
scope "/", PHOENIX_APP_WEB do
|
scope "/", TutorialWeb do
|
||||||
pipe_through :browser
|
pipe_through :browser
|
||||||
...
|
...
|
||||||
# Sign in
|
# Sign in
|
||||||
@ -148,11 +148,13 @@ end
|
|||||||
|
|
||||||
#### Controller
|
#### Controller
|
||||||
|
|
||||||
```elixir
|
Create `session_controller.ex` in `/controllers`
|
||||||
defmodule PHOENIX_APP_WEB.SessionController do
|
|
||||||
use PHOENIX_APP_WEB, :controller
|
|
||||||
|
|
||||||
alias PHOENIX_APP.Accounts
|
```elixir
|
||||||
|
defmodule TutorialWeb.SessionController do
|
||||||
|
use TutorialWeb, :controller
|
||||||
|
|
||||||
|
alias Tutorial.Accounts
|
||||||
alias Accounts.User
|
alias Accounts.User
|
||||||
|
|
||||||
def sign_in(conn, _params) do
|
def sign_in(conn, _params) do
|
||||||
@ -214,4 +216,144 @@ defmodule PHOENIX_APP_WEB.SessionController do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Update `accounts.ex`
|
||||||
|
|
||||||
|
Remember when we wrote `user = Accounts.get_by_email(auth_params["email"])` we need to define that fn
|
||||||
|
Open `accounts.ex` and add this fn after `get_user!(id)`
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
def get_by_email(nil), do: nil
|
||||||
|
|
||||||
|
def get_by_email(email), do: User |> Repo.get_by(email: email)
|
||||||
|
```
|
||||||
|
|
||||||
|
**NOTE** We will use advantage of pattern matching and create two fn-s just in case we get `nil`
|
||||||
|
|
||||||
|
#### Update `user_controller.ex`
|
||||||
|
|
||||||
|
##### Part 1 (update params)
|
||||||
|
|
||||||
|
In `UserController` `show`, `edit`, `update` and `delete` second param is trying to pattern match for `%{"id" => id}` but since we are going to get user data from `conn.asssigns.current_user` go ahead and replace `%{"id" => id}` with `_params`
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
def FN(conn, %{"id" => id}) do
|
||||||
|
...
|
||||||
|
end
|
||||||
|
# CHANGE TO
|
||||||
|
def FN(conn, _params) do
|
||||||
|
...
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
*Do that for all 4 of them*
|
||||||
|
|
||||||
|
##### Part 2 (update user data)
|
||||||
|
|
||||||
|
We are still in `UserController` and fn's `show`, `edit`, `update` and `delete` are using that `id` that we just removed, to obtain user data. We are going to change that now
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# Change
|
||||||
|
user = Accounts.get_user!(id)
|
||||||
|
# Into
|
||||||
|
user = conn.assigns.current_user
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set `conn.assigns.current_user`
|
||||||
|
|
||||||
|
Now we need to assign `current_user` to `@conn`. But how?
|
||||||
|
Read more to find out. :)
|
||||||
|
|
||||||
|
#### Setting up Auth Plug
|
||||||
|
|
||||||
|
You remember that `/helpers` folder that we created earlier? Open it and create new file inside, called `plug_auth.ex` and put this code inside.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
defmodule TutorialWeb.Helpers.AuthGuest do
|
||||||
|
import Plug.Conn
|
||||||
|
import Phoenix.Controller
|
||||||
|
alias Tutorial.Accounts
|
||||||
|
|
||||||
|
def init(default), do: default
|
||||||
|
|
||||||
|
def call(conn, _opts) do
|
||||||
|
user_id = get_session(conn, :current_user_id)
|
||||||
|
auth_reply(conn, user_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp auth_reply(conn, nil) do
|
||||||
|
conn
|
||||||
|
|> put_flash(:error, "You have to sign in first!")
|
||||||
|
|> redirect(to: "/sign-in")
|
||||||
|
|> halt()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp auth_reply(conn, user_id) do
|
||||||
|
user = Accounts.get_user!(user_id)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:current_user, user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
After that add this code into your `router.ex`
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
pipeline :auth do
|
||||||
|
plug TutorialWeb.Helpers.AuthGuest
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
And add that pipeline in `pipe_through` for scope you want to require logged user
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
scope "/", TutorialWeb do
|
||||||
|
pipe_through [:browser, :auth]
|
||||||
|
resources "/users", UserController, singleton: true
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## Templates update /users/ && add Sign-in and Sign-out links
|
||||||
|
|
||||||
|
### User template
|
||||||
|
|
||||||
|
After adding all of this, few things need to be considered.
|
||||||
|
|
||||||
|
* `singleton: true`
|
||||||
|
* We don't want our user to have acces to the list of **ALL USERS** so we need to remove links that point `to: Routes.user_path(@conn, :index)`.
|
||||||
|
Lets give that power only to admin.
|
||||||
|
|
||||||
|
* UserController fn-s `new` and `create`
|
||||||
|
* Again we don't want our user to be able to use these functions that are pre-generated by
|
||||||
|
`mix phx.gen.html` so we should delete those **files**, **controller functions** and **limit**
|
||||||
|
them in `router.ex`. Update existing resources tag with following.
|
||||||
|
`resources "/users", UserController, only: [:show, :edit, :update], singleton: true`
|
||||||
|
|
||||||
|
* Update UserController fn's with redirect
|
||||||
|
* Some fn's where you redirect to path that doesn't take user as params
|
||||||
|
but you still pass it because of `mix phx.gen.html`. You just need to
|
||||||
|
remove that user.
|
||||||
|
|
||||||
|
And finally lets open `/layout/app.html.eex` and add following
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
<%= if signed_in?(@conn) do %>
|
||||||
|
<%= link "Sign out", to: Routes.session_path(@conn, :sign_out), method: :post %>
|
||||||
|
<% else %>
|
||||||
|
<%= link "Sign in", to: Routes.session_path(@conn, :sign_in), method: :get %>
|
||||||
|
|
|
||||||
|
<%= link "Sign up", to: Routes.session_path(@conn, :sign_up), method: :get %>
|
||||||
|
<% end %>
|
||||||
|
```
|
||||||
|
|
||||||
|
****
|
||||||
|
|
||||||
|
## mix phx.server
|
||||||
|
|
||||||
|
Yep you read it, just run your app now and it should most of it gucci. :)
|
||||||
|
*except the `html.eex` files that you didn't change* :P
|
||||||
|
|
||||||
|
****
|
||||||
|
Loading…
Reference in New Issue
Block a user