Skip to content

Commit

Permalink
add User and Token with Ash Authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
tyalt1 committed Jun 4, 2024
1 parent f58f674 commit da74838
Show file tree
Hide file tree
Showing 17 changed files with 348 additions and 10 deletions.
11 changes: 10 additions & 1 deletion .formatter.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
[
import_deps: [:ecto, :ecto_sql, :phoenix, :ash, :ash_phoenix, :ash_postgres],
import_deps: [
:ecto,
:ecto_sql,
:phoenix,
:ash,
:ash_phoenix,
:ash_postgres,
:ash_authentication,
:ash_authentication_phoenix
],
subdirectories: ["priv/*/migrations"],
plugins: [Phoenix.LiveView.HTMLFormatter],
inputs: ["*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}", "priv/*/seeds.exs"]
Expand Down
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -523,9 +523,15 @@ Blog.destroy_post!(updated_post)
The implementation of these actions are only defined once in the `actions` block of the Post resource. This lays the foundation for deriving more functionality from these actions. We could also create other resources and domains.

In further sections I'll discuss
- User and Login with `AshAuthentication`
- Integrating Ash models with LiveView forms
- REST API with `AshJsonApi`
- GraphQL API with `AshGraphql`
- User and Login with [`AshAuthentication`](https://hexdocs.pm/ash_authentication_phoenix/get-started.html)
- REST API with [`AshJsonApi`](https://ash-hq.org/docs/guides/ash_json_api/latest/tutorials/getting-started-with-ash-json-api)
- GraphQL API with [`AshGraphql`](https://ash-hq.org/docs/guides/ash_graphql/latest/tutorials/getting-started-with-graphql)

### Section 4: TBD
### Section 4: Users with Ash Authentication

I follower [this tutorial](https://hexdocs.pm/ash_authentication_phoenix/get-started.html) for adding users to a Phoenix app with Ash Authentication and Ash Phoenix Authentication. I did not write addtional code.

### Section 5: REST API with with Ash JSON API

### Section 6: GraphQL API with Ash GraphQL
3 changes: 2 additions & 1 deletion assets/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ module.exports = {
content: [
"./js/**/*.js",
"../lib/petal_stack_tutorial_web.ex",
"../lib/petal_stack_tutorial_web/**/*.*ex"
"../lib/petal_stack_tutorial_web/**/*.*ex",
"../deps/ash_authentication_phoenix/**/*.*ex",
],
theme: {
extend: {
Expand Down
3 changes: 2 additions & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import Config

config :petal_stack_tutorial,
ash_domains: [PetalStackTutorial.Blog]
ash_domains: [PetalStackTutorial.Accounts, PetalStackTutorial.Blog],
ash_apis: [PetalStackTutorial.Accounts]

# Configures the endpoint
config :petal_stack_tutorial, PetalStackTutorialWeb.Endpoint,
Expand Down
8 changes: 8 additions & 0 deletions lib/petal_stack_tutorial/accounts/accounts.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
defmodule PetalStackTutorial.Accounts do
use Ash.Domain

resources do
resource PetalStackTutorial.Accounts.Token
resource PetalStackTutorial.Accounts.User
end
end
13 changes: 13 additions & 0 deletions lib/petal_stack_tutorial/accounts/secrets.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
defmodule PetalStackTutorial.Accounts.Secrets do
use AshAuthentication.Secret

def secret_for([:authentication, :tokens, :signing_secret], PetalStackTutorial.Accounts.User, _) do
case Application.fetch_env(:petal_stack_tutorial, PetalStackTutorialWeb.Endpoint) do
{:ok, endpoint_config} ->
Keyword.fetch(endpoint_config, :secret_key_base)

:error ->
:error
end
end
end
11 changes: 11 additions & 0 deletions lib/petal_stack_tutorial/accounts/token.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule PetalStackTutorial.Accounts.Token do
use Ash.Resource,
domain: PetalStackTutorial.Accounts,
data_layer: AshPostgres.DataLayer,
extensions: [AshAuthentication.TokenResource]

postgres do
table "tokens"
repo PetalStackTutorial.Repo
end
end
43 changes: 43 additions & 0 deletions lib/petal_stack_tutorial/accounts/user.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
defmodule PetalStackTutorial.Accounts.User do
use Ash.Resource,
domain: PetalStackTutorial.Accounts,
data_layer: AshPostgres.DataLayer,
extensions: [AshAuthentication]

postgres do
table "users"
repo PetalStackTutorial.Repo
end

attributes do
uuid_primary_key :id

attribute :email, :ci_string do
allow_nil? false
public? true
end

attribute :hashed_password, :string do
allow_nil? false
sensitive? true
end
end

authentication do
strategies do
password :password do
identity_field :email
end
end

tokens do
enabled? true
token_resource PetalStackTutorial.Accounts.Token
signing_secret PetalStackTutorial.Accounts.Secrets
end
end

identities do
identity :unique_email, [:email]
end
end
3 changes: 2 additions & 1 deletion lib/petal_stack_tutorial/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ defmodule PetalStackTutorial.Application do
# Start a worker by calling: PetalStackTutorial.Worker.start_link(arg)
# {PetalStackTutorial.Worker, arg},
# Start to serve requests, typically the last entry
PetalStackTutorialWeb.Endpoint
PetalStackTutorialWeb.Endpoint,
{AshAuthentication.Supervisor, otp_app: :petal_stack_tutorial}
]

# See https://hexdocs.pm/elixir/Supervisor.html
Expand Down
2 changes: 1 addition & 1 deletion lib/petal_stack_tutorial_web.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ defmodule PetalStackTutorialWeb do

def router do
quote do
use Phoenix.Router, helpers: false
use Phoenix.Router, helpers: true

# Import common connection and controller functions to use in pipelines
import Plug.Conn
Expand Down
28 changes: 28 additions & 0 deletions lib/petal_stack_tutorial_web/controllers/auth_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
defmodule PetalStackTutorialWeb.AuthController do
use PetalStackTutorialWeb, :controller
use AshAuthentication.Phoenix.Controller

def success(conn, _activity, user, _token) do
return_to = get_session(conn, :return_to, ~p"/")

conn
|> delete_session(:return_to)
|> store_in_session(user)
|> assign(:current_user, user)
|> redirect(to: return_to)
end

def failure(conn, _activity, _reason) do
conn
|> put_flash(:error, "Incorrect email or password")
|> redirect(to: ~p"/sign-in")
end

def sign_out(conn, _params) do
return_to = get_session(conn, :return_to, ~p"/")

conn
|> clear_session()
|> redirect(to: return_to)
end
end
11 changes: 11 additions & 0 deletions lib/petal_stack_tutorial_web/router.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule PetalStackTutorialWeb.Router do
use PetalStackTutorialWeb, :router
use AshAuthentication.Phoenix.Router

pipeline :browser do
plug :accepts, ["html"]
Expand All @@ -8,17 +9,27 @@ defmodule PetalStackTutorialWeb.Router do
plug :put_root_layout, html: {PetalStackTutorialWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :load_from_session
end

pipeline :api do
plug :accepts, ["json"]
plug :load_from_bearer
end

scope "/", PetalStackTutorialWeb do
pipe_through :browser

get "/", PageController, :home

# LiveView Example
live "/counter", Counter

# User Login
sign_in_route(register_path: "/register", reset_path: "/reset")
sign_out_route AuthController
auth_routes_for PetalStackTutorial.Accounts.User, to: AuthController
reset_route []
end

# Other scopes may use custom stacks.
Expand Down
4 changes: 3 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ defmodule PetalStackTutorial.MixProject do
{:ash, "~> 3.0"},
{:ash_phoenix, "~> 2.0"},
{:ash_postgres, "~> 2.0"},
{:ash_authentication, "~> 4.0"},
{:ash_authentication_phoenix, "~> 2.0"},

# phoenix
{:phoenix, "~> 1.7.12"},
Expand Down Expand Up @@ -76,7 +78,7 @@ defmodule PetalStackTutorial.MixProject do
defp aliases do
[
setup: ["deps.get", "ash.setup", "assets.setup", "assets.build"],
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
test: ["ash.setup --quiet", "test"],
"assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"],
"assets.build": ["tailwind petal_stack_tutorial", "esbuild petal_stack_tutorial"],
"assets.deploy": [
Expand Down
Loading

0 comments on commit da74838

Please sign in to comment.