Compare commits
8 commits
b1f5e09eaf
...
08b3735c1b
| Author | SHA1 | Date | |
|---|---|---|---|
| 08b3735c1b | |||
| b69ef02169 | |||
| 7e32979f39 | |||
| 033d7aa675 | |||
| e0f26c6164 | |||
| 2c4af8c2a4 | |||
| 944ab37b22 | |||
| 7e1c1a4379 |
30 changed files with 906 additions and 238 deletions
|
|
@ -1,7 +1,9 @@
|
||||||
[
|
[
|
||||||
import_deps: [
|
import_deps: [
|
||||||
|
:ash_authentication_phoenix,
|
||||||
:ash_admin,
|
:ash_admin,
|
||||||
:ash_postgres,
|
:ash_postgres,
|
||||||
|
:ash_authentication,
|
||||||
:ash_phoenix,
|
:ash_phoenix,
|
||||||
:ash,
|
:ash,
|
||||||
:reactor,
|
:reactor,
|
||||||
|
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -36,3 +36,6 @@ npm-debug.log
|
||||||
/assets/node_modules/
|
/assets/node_modules/
|
||||||
|
|
||||||
.cursor
|
.cursor
|
||||||
|
|
||||||
|
# Ignore the .env file with env variables
|
||||||
|
.env
|
||||||
|
|
|
||||||
10
.igniter.exs
Normal file
10
.igniter.exs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
# This is a configuration file for igniter.
|
||||||
|
# For option documentation, see https://hexdocs.pm/igniter/Igniter.Project.IgniterConfig.html
|
||||||
|
# To keep it up to date, use `mix igniter.setup`
|
||||||
|
[
|
||||||
|
module_location: :outside_matching_folder,
|
||||||
|
extensions: [{Igniter.Extensions.Phoenix, []}],
|
||||||
|
deps_location: :last_list_literal,
|
||||||
|
source_folders: ["lib", "test/support"],
|
||||||
|
dont_move_files: [~r"lib/mix"]
|
||||||
|
]
|
||||||
2
Justfile
2
Justfile
|
|
@ -1,3 +1,5 @@
|
||||||
|
set dotenv-load := true
|
||||||
|
|
||||||
run: install-dependencies start-database migrate-database seed-database
|
run: install-dependencies start-database migrate-database seed-database
|
||||||
mix phx.server
|
mix phx.server
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ const path = require("path")
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: [
|
||||||
|
"../deps/ash_authentication_phoenix/**/*.*ex",
|
||||||
"./js/**/*.js",
|
"./js/**/*.js",
|
||||||
"../lib/mv_web.ex",
|
"../lib/mv_web.ex",
|
||||||
"../lib/mv_web/**/*.*ex"
|
"../lib/mv_web/**/*.*ex"
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ config :spark,
|
||||||
config :mv,
|
config :mv,
|
||||||
ecto_repos: [Mv.Repo],
|
ecto_repos: [Mv.Repo],
|
||||||
generators: [timestamp_type: :utc_datetime],
|
generators: [timestamp_type: :utc_datetime],
|
||||||
ash_domains: [Mv.Membership]
|
ash_domains: [Mv.Membership, Mv.Accounts]
|
||||||
|
|
||||||
# Configures the endpoint
|
# Configures the endpoint
|
||||||
config :mv, MvWeb.Endpoint,
|
config :mv, MvWeb.Endpoint,
|
||||||
|
|
|
||||||
|
|
@ -84,3 +84,14 @@ config :phoenix_live_view,
|
||||||
|
|
||||||
# Disable swoosh api client as it is only required for production adapters.
|
# Disable swoosh api client as it is only required for production adapters.
|
||||||
config :swoosh, :api_client, false
|
config :swoosh, :api_client, false
|
||||||
|
|
||||||
|
config :mv, :secret_key_base, "ryn7D6ssmIHQFWIks2sFiTGATgwwAR1+3bN8p7fy6qVtB8qnxOuk1uyAwHz1Q8WB"
|
||||||
|
|
||||||
|
# Signing Secret for Authentication
|
||||||
|
config :mv, :token_signing_secret, "IwUwi65TrEeExwBXXFPGm2I7889NsL"
|
||||||
|
|
||||||
|
config :mv, :rauthy,
|
||||||
|
client_id: "mv",
|
||||||
|
base_url: "http://localhost:8080/auth/v1",
|
||||||
|
client_secret: System.get_env("OIDC_CLIENT_SECRET"),
|
||||||
|
redirect_uri: "http://localhost:4000/auth/user/rauthy/callback"
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ if config_env() == :prod do
|
||||||
|
|
||||||
config :mv, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY")
|
config :mv, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY")
|
||||||
|
|
||||||
|
config :mv, :rauthy, redirect_uri: "http://localhost:4000/auth/user/rauthy/callback"
|
||||||
|
|
||||||
config :mv, MvWeb.Endpoint,
|
config :mv, MvWeb.Endpoint,
|
||||||
url: [host: host, port: 443, scheme: "https"],
|
url: [host: host, port: 443, scheme: "https"],
|
||||||
http: [
|
http: [
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
|
version: "3.5"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
local:
|
||||||
|
rauthy-test:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
image: postgres:17.5-alpine
|
image: postgres:17.5-alpine
|
||||||
|
|
@ -16,9 +23,46 @@ services:
|
||||||
networks:
|
networks:
|
||||||
- local
|
- local
|
||||||
|
|
||||||
networks:
|
mailcrab:
|
||||||
local:
|
image: marlonb/mailcrab:latest
|
||||||
|
ports:
|
||||||
|
- "1080:1080"
|
||||||
|
networks:
|
||||||
|
- rauthy-test
|
||||||
|
|
||||||
|
|
||||||
|
rauthy:
|
||||||
|
container_name: rauthy-test
|
||||||
|
image: ghcr.io/sebadob/rauthy:0.30.2
|
||||||
|
environment:
|
||||||
|
- LOCAL_TEST=true
|
||||||
|
- SMTP_URL=mailcrab
|
||||||
|
- SMTP_PORT=1025
|
||||||
|
- SMTP_DANGER_INSECURE=true
|
||||||
|
- LISTEN_SCHEME=http
|
||||||
|
- PUB_URL=localhost:8080
|
||||||
|
- BOOTSTRAP_ADMIN_PASSWORD_PLAIN=RauthyTest12345
|
||||||
|
#- HIQLITE=false
|
||||||
|
#- PG_HOST=db
|
||||||
|
#- PG_PORT=5432
|
||||||
|
#- PG_USER=postgres
|
||||||
|
#- PG_PASSWORD=postgres
|
||||||
|
#- PG_DB_NAME=mv_dev
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
depends_on:
|
||||||
|
- mailcrab
|
||||||
|
- db
|
||||||
|
networks:
|
||||||
|
- rauthy-test
|
||||||
|
- local
|
||||||
|
volumes:
|
||||||
|
- type: volume
|
||||||
|
source: rauthy-data
|
||||||
|
target: /app/data
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres-data:
|
postgres-data:
|
||||||
|
rauthy-data:
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
18
lib/accounts/accounts.ex
Normal file
18
lib/accounts/accounts.ex
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
defmodule Mv.Accounts do
|
||||||
|
@moduledoc """
|
||||||
|
AshAuthentication specific domain to handle Authentication for users.
|
||||||
|
"""
|
||||||
|
use Ash.Domain,
|
||||||
|
extensions: [AshPhoenix]
|
||||||
|
|
||||||
|
resources do
|
||||||
|
resource Mv.Accounts.User do
|
||||||
|
define :create_user, action: :create
|
||||||
|
define :list_users, action: :read
|
||||||
|
define :update_user, action: :update
|
||||||
|
define :destroy_user, action: :destroy
|
||||||
|
end
|
||||||
|
|
||||||
|
resource Mv.Accounts.Token
|
||||||
|
end
|
||||||
|
end
|
||||||
14
lib/accounts/token.ex
Normal file
14
lib/accounts/token.ex
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
defmodule Mv.Accounts.Token do
|
||||||
|
@moduledoc """
|
||||||
|
AshAuthentication specific ressource
|
||||||
|
"""
|
||||||
|
use Ash.Resource,
|
||||||
|
data_layer: AshPostgres.DataLayer,
|
||||||
|
extensions: [AshAuthentication.TokenResource],
|
||||||
|
domain: Mv.Accounts
|
||||||
|
|
||||||
|
postgres do
|
||||||
|
table "tokens"
|
||||||
|
repo Mv.Repo
|
||||||
|
end
|
||||||
|
end
|
||||||
117
lib/accounts/user.ex
Normal file
117
lib/accounts/user.ex
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
defmodule Mv.Accounts.User do
|
||||||
|
@moduledoc """
|
||||||
|
The ressource for keeping user-specific data related to the login process. It is used by AshAuthentication to handle the Authentication strategies like SSO.
|
||||||
|
"""
|
||||||
|
use Ash.Resource,
|
||||||
|
domain: Mv.Accounts,
|
||||||
|
data_layer: AshPostgres.DataLayer,
|
||||||
|
extensions: [AshAuthentication]
|
||||||
|
|
||||||
|
# authorizers: [Ash.Policy.Authorizer]
|
||||||
|
|
||||||
|
postgres do
|
||||||
|
table "users"
|
||||||
|
repo Mv.Repo
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
AshAuthentication specific: Defines the strategies we want to use for authentication.
|
||||||
|
Currently password and SSO with Rauthy as OIDC provider
|
||||||
|
"""
|
||||||
|
authentication do
|
||||||
|
tokens do
|
||||||
|
enabled? true
|
||||||
|
token_resource Mv.Accounts.Token
|
||||||
|
require_token_presence_for_authentication? true
|
||||||
|
store_all_tokens? true
|
||||||
|
#signing_algorithm "EdDSA" -> https://git.local-it.org/local-it/mitgliederverwaltung/issues/87
|
||||||
|
|
||||||
|
signing_secret fn _, _ ->
|
||||||
|
{:ok, Application.get_env(:mv, :token_signing_secret)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
strategies do
|
||||||
|
oidc :rauthy do
|
||||||
|
client_id Mv.Secrets
|
||||||
|
base_url Mv.Secrets
|
||||||
|
redirect_uri Mv.Secrets
|
||||||
|
client_secret Mv.Secrets
|
||||||
|
auth_method :client_secret_jwt
|
||||||
|
code_verifier true
|
||||||
|
#id_token_signed_response_alg "EdDSA" #-> https://git.local-it.org/local-it/mitgliederverwaltung/issues/87
|
||||||
|
end
|
||||||
|
|
||||||
|
password :password do
|
||||||
|
identity_field :email
|
||||||
|
hash_provider AshAuthentication.BcryptProvider
|
||||||
|
confirmation_required? false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
actions do
|
||||||
|
defaults [:read, :create, :destroy, :update]
|
||||||
|
|
||||||
|
read :get_by_subject do
|
||||||
|
description "Get a user by the subject claim in a JWT"
|
||||||
|
argument :subject, :string, allow_nil?: false
|
||||||
|
get? true
|
||||||
|
prepare AshAuthentication.Preparations.FilterBySubject
|
||||||
|
end
|
||||||
|
|
||||||
|
read :sign_in_with_rauthy do
|
||||||
|
argument :user_info, :map, allow_nil?: false
|
||||||
|
argument :oauth_tokens, :map, allow_nil?: false
|
||||||
|
prepare AshAuthentication.Strategy.OAuth2.SignInPreparation
|
||||||
|
|
||||||
|
filter expr(email == get_path(^arg(:user_info), [:email]))
|
||||||
|
end
|
||||||
|
|
||||||
|
create :register_with_rauthy do
|
||||||
|
argument :user_info, :map, allow_nil?: false
|
||||||
|
argument :oauth_tokens, :map, allow_nil?: false
|
||||||
|
upsert? true
|
||||||
|
upsert_identity :unique_email
|
||||||
|
|
||||||
|
change AshAuthentication.GenerateTokenChange
|
||||||
|
|
||||||
|
change fn changeset, _ctx ->
|
||||||
|
user_info = Ash.Changeset.get_argument(changeset, :user_info)
|
||||||
|
|
||||||
|
changeset
|
||||||
|
|> Ash.Changeset.change_attribute(:email, user_info["preferred_username"])
|
||||||
|
|> Ash.Changeset.change_attribute(:oidc_id, user_info["id"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
attributes do
|
||||||
|
uuid_primary_key :id
|
||||||
|
|
||||||
|
attribute :email, :ci_string, allow_nil?: false, public?: true
|
||||||
|
attribute :hashed_password, :string, sensitive?: true, allow_nil?: true
|
||||||
|
attribute :oidc_id, :string, allow_nil?: true
|
||||||
|
end
|
||||||
|
|
||||||
|
relationships do
|
||||||
|
belongs_to :member, Mv.Membership.Member
|
||||||
|
end
|
||||||
|
|
||||||
|
identities do
|
||||||
|
identity :unique_email, [:email]
|
||||||
|
identity :unique_oidc_id, [:oidc_id]
|
||||||
|
end
|
||||||
|
|
||||||
|
# You can customize this if you wish, but this is a safe default that
|
||||||
|
# only allows user data to be interacted with via AshAuthentication.
|
||||||
|
# policies do
|
||||||
|
# bypass AshAuthentication.Checks.AshAuthenticationInteraction do
|
||||||
|
# authorize_if(always())
|
||||||
|
# end
|
||||||
|
|
||||||
|
# policy always() do
|
||||||
|
# forbid_if(always())
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
end
|
||||||
18
lib/accounts/user_identity.exs
Normal file
18
lib/accounts/user_identity.exs
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
defmodule Mv.Accounts.UserIdentity do
|
||||||
|
@moduledoc """
|
||||||
|
AshAuthentication specific ressource
|
||||||
|
"""
|
||||||
|
use Ash.Resource,
|
||||||
|
data_layer: AshPostgres.DataLayer,
|
||||||
|
extensions: [AshAuthentication.UserIdentity],
|
||||||
|
domain: Mv.Accounts
|
||||||
|
|
||||||
|
postgres do
|
||||||
|
table "user_identities"
|
||||||
|
repo Mv.Repo
|
||||||
|
end
|
||||||
|
|
||||||
|
user_identity do
|
||||||
|
user_resource Mv.Accounts.User
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
defmodule Mv.Accounts.User.Senders.SendNewUserConfirmationEmail do
|
||||||
|
@moduledoc """
|
||||||
|
Sends an email for a new user to confirm their email address.
|
||||||
|
"""
|
||||||
|
|
||||||
|
use AshAuthentication.Sender
|
||||||
|
use MvWeb, :verified_routes
|
||||||
|
|
||||||
|
import Swoosh.Email
|
||||||
|
|
||||||
|
alias Mv.Mailer
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def send(user, token, _) do
|
||||||
|
new()
|
||||||
|
# TODO: Replace with your email
|
||||||
|
|> from({"noreply", "noreply@example.com"})
|
||||||
|
|> to(to_string(user.email))
|
||||||
|
|> subject("Confirm your email address")
|
||||||
|
|> html_body(body(token: token))
|
||||||
|
|> Mailer.deliver!()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp body(params) do
|
||||||
|
url = url(~p"/confirm_new_user/#{params[:token]}")
|
||||||
|
|
||||||
|
"""
|
||||||
|
<p>Click this link to confirm your email:</p>
|
||||||
|
<p><a href="#{url}">#{url}</a></p>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
end
|
||||||
32
lib/mv/accounts/user/senders/send_password_reset_email.ex
Normal file
32
lib/mv/accounts/user/senders/send_password_reset_email.ex
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
defmodule Mv.Accounts.User.Senders.SendPasswordResetEmail do
|
||||||
|
@moduledoc """
|
||||||
|
Sends a password reset email
|
||||||
|
"""
|
||||||
|
|
||||||
|
use AshAuthentication.Sender
|
||||||
|
use MvWeb, :verified_routes
|
||||||
|
|
||||||
|
import Swoosh.Email
|
||||||
|
|
||||||
|
alias Mv.Mailer
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def send(user, token, _) do
|
||||||
|
new()
|
||||||
|
# TODO: Replace with your email
|
||||||
|
|> from({"noreply", "noreply@example.com"})
|
||||||
|
|> to(to_string(user.email))
|
||||||
|
|> subject("Reset your password")
|
||||||
|
|> html_body(body(token: token))
|
||||||
|
|> Mailer.deliver!()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp body(params) do
|
||||||
|
url = url(~p"/password-reset/#{params[:token]}")
|
||||||
|
|
||||||
|
"""
|
||||||
|
<p>Click this link to reset your password:</p>
|
||||||
|
<p><a href="#{url}">#{url}</a></p>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -14,6 +14,7 @@ defmodule Mv.Application do
|
||||||
{Phoenix.PubSub, name: Mv.PubSub},
|
{Phoenix.PubSub, name: Mv.PubSub},
|
||||||
# Start the Finch HTTP client for sending emails
|
# Start the Finch HTTP client for sending emails
|
||||||
{Finch, name: Mv.Finch},
|
{Finch, name: Mv.Finch},
|
||||||
|
{AshAuthentication.Supervisor, otp_app: :my},
|
||||||
# Start a worker by calling: Mv.Worker.start_link(arg)
|
# Start a worker by calling: Mv.Worker.start_link(arg)
|
||||||
# {Mv.Worker, arg},
|
# {Mv.Worker, arg},
|
||||||
# Start to serve requests, typically the last entry
|
# Start to serve requests, typically the last entry
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ defmodule Mv.Repo do
|
||||||
@impl true
|
@impl true
|
||||||
def installed_extensions do
|
def installed_extensions do
|
||||||
# Add extensions here, and the migration generator will install them.
|
# Add extensions here, and the migration generator will install them.
|
||||||
["ash-functions"]
|
["ash-functions", "citext"]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Don't open unnecessary transactions
|
# Don't open unnecessary transactions
|
||||||
|
|
|
||||||
26
lib/mv/secrets.ex
Normal file
26
lib/mv/secrets.ex
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
defmodule Mv.Secrets do
|
||||||
|
use AshAuthentication.Secret
|
||||||
|
|
||||||
|
def secret_for([:authentication, :strategies, :rauthy, :client_id], Mv.Accounts.User, _opts, _meth) do
|
||||||
|
get_config(:client_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def secret_for([:authentication, :strategies, :rauthy, :redirect_uri], Mv.Accounts.User, _opts, _meth) do
|
||||||
|
get_config(:redirect_uri)
|
||||||
|
end
|
||||||
|
|
||||||
|
def secret_for([:authentication, :strategies, :rauthy, :client_secret], Mv.Accounts.User, _opts, _meth) do
|
||||||
|
get_config(:client_secret)
|
||||||
|
end
|
||||||
|
|
||||||
|
def secret_for([:authentication, :strategies, :rauthy, :base_url], Mv.Accounts.User, _opts, _meth) do
|
||||||
|
get_config(:base_url)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_config(key) do
|
||||||
|
:mv
|
||||||
|
|> Application.fetch_env!(:rauthy)
|
||||||
|
|> Keyword.fetch!(key)
|
||||||
|
|> then(&{:ok, &1})
|
||||||
|
end
|
||||||
|
end
|
||||||
20
lib/mv_web/auth_overrides.ex
Normal file
20
lib/mv_web/auth_overrides.ex
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
defmodule MvWeb.AuthOverrides do
|
||||||
|
use AshAuthentication.Phoenix.Overrides
|
||||||
|
|
||||||
|
# configure your UI overrides here
|
||||||
|
|
||||||
|
# First argument to `override` is the component name you are overriding.
|
||||||
|
# The body contains any number of configurations you wish to override
|
||||||
|
# Below are some examples
|
||||||
|
|
||||||
|
# For a complete reference, see https://hexdocs.pm/ash_authentication_phoenix/ui-overrides.html
|
||||||
|
|
||||||
|
# override AshAuthentication.Phoenix.Components.Banner do
|
||||||
|
# set :image_url, "https://media.giphy.com/media/g7GKcSzwQfugw/giphy.gif"
|
||||||
|
# set :text_class, "bg-red-500"
|
||||||
|
# end
|
||||||
|
|
||||||
|
# override AshAuthentication.Phoenix.Components.SignIn do
|
||||||
|
# set :show_banner, false
|
||||||
|
# end
|
||||||
|
end
|
||||||
57
lib/mv_web/controllers/auth_controller.ex
Normal file
57
lib/mv_web/controllers/auth_controller.ex
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
require Logger
|
||||||
|
defmodule MvWeb.AuthController do
|
||||||
|
use MvWeb, :controller
|
||||||
|
use AshAuthentication.Phoenix.Controller
|
||||||
|
|
||||||
|
def success(conn, activity, user, _token) do
|
||||||
|
return_to = get_session(conn, :return_to) || ~p"/"
|
||||||
|
|
||||||
|
message =
|
||||||
|
case activity do
|
||||||
|
{:confirm_new_user, :confirm} -> "Your email address has now been confirmed"
|
||||||
|
{:password, :reset} -> "Your password has successfully been reset"
|
||||||
|
_ -> "You are now signed in"
|
||||||
|
end
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> delete_session(:return_to)
|
||||||
|
|> store_in_session(user)
|
||||||
|
# If your resource has a different name, update the assign name here (i.e :current_admin)
|
||||||
|
|> assign(:current_user, user)
|
||||||
|
|> put_flash(:info, message)
|
||||||
|
|> redirect(to: return_to)
|
||||||
|
end
|
||||||
|
|
||||||
|
def failure(conn, activity, reason) do
|
||||||
|
Logger.error(%{conn: conn, reason: reason})
|
||||||
|
message =
|
||||||
|
case {activity, reason} do
|
||||||
|
{_,
|
||||||
|
%AshAuthentication.Errors.AuthenticationFailed{
|
||||||
|
caused_by: %Ash.Error.Forbidden{
|
||||||
|
errors: [%AshAuthentication.Errors.CannotConfirmUnconfirmedUser{}]
|
||||||
|
}
|
||||||
|
}} ->
|
||||||
|
"""
|
||||||
|
You have already signed in another way, but have not confirmed your account.
|
||||||
|
You can confirm your account using the link we sent to you, or by resetting your password.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
"Incorrect email or password"
|
||||||
|
end
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_flash(:error, message)
|
||||||
|
|> redirect(to: ~p"/sign-in")
|
||||||
|
end
|
||||||
|
|
||||||
|
def sign_out(conn, _params) do
|
||||||
|
return_to = get_session(conn, :return_to) || ~p"/"
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> clear_session(:mv)
|
||||||
|
|> put_flash(:info, "You are now signed out")
|
||||||
|
|> redirect(to: return_to)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,222 +1,55 @@
|
||||||
<.flash_group flash={@flash} />
|
<!--
|
||||||
<div class="left-[40rem] fixed inset-y-0 right-0 z-0 hidden lg:block xl:left-[50rem]">
|
THIS IS JUST THE ASHAUTHENTICATION EXAMPLE - WE NEED TO CHANGE IT LATER
|
||||||
<svg
|
-->
|
||||||
viewBox="0 0 1480 957"
|
<nav class="bg-gray-800">
|
||||||
fill="none"
|
<div class="px-2 mx-auto max-w-7xl sm:px-6 lg:px-8">
|
||||||
aria-hidden="true"
|
<div class="relative flex items-center justify-between h-16">
|
||||||
class="absolute inset-0 h-full w-full"
|
<div class="flex items-center justify-center flex-1 sm:items-stretch sm:justify-start">
|
||||||
preserveAspectRatio="xMinYMid slice"
|
<div class="block ml-6">
|
||||||
>
|
<div class="flex space-x-4">
|
||||||
<path fill="#EE7868" d="M0 0h1480v957H0z" />
|
<div class="px-3 py-2 text-xl font-medium text-white ">
|
||||||
<path
|
Mitgliederverwaltung
|
||||||
d="M137.542 466.27c-582.851-48.41-988.806-82.127-1608.412 658.2l67.39 810 3083.15-256.51L1535.94-49.622l-98.36 8.183C1269.29 281.468 734.115 515.799 146.47 467.012l-8.928-.742Z"
|
</div>
|
||||||
fill="#FF9F92"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M371.028 528.664C-169.369 304.988-545.754 149.198-1361.45 665.565l-182.58 792.025 3014.73 694.98 389.42-1689.25-96.18-22.171C1505.28 697.438 924.153 757.586 379.305 532.09l-8.277-3.426Z"
|
|
||||||
fill="#FA8372"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M359.326 571.714C-104.765 215.795-428.003-32.102-1349.55 255.554l-282.3 1224.596 3047.04 722.01 312.24-1354.467C1411.25 1028.3 834.355 935.995 366.435 577.166l-7.109-5.452Z"
|
|
||||||
fill="#E96856"
|
|
||||||
fill-opacity=".6"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M1593.87 1236.88c-352.15 92.63-885.498-145.85-1244.602-613.557l-5.455-7.105C-12.347 152.31-260.41-170.8-1225-131.458l-368.63 1599.048 3057.19 704.76 130.31-935.47Z"
|
|
||||||
fill="#C42652"
|
|
||||||
fill-opacity=".2"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M1411.91 1526.93c-363.79 15.71-834.312-330.6-1085.883-863.909l-3.822-8.102C72.704 125.95-101.074-242.476-1052.01-408.907l-699.85 1484.267 2837.75 1338.01 326.02-886.44Z"
|
|
||||||
fill="#A41C42"
|
|
||||||
fill-opacity=".2"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M1116.26 1863.69c-355.457-78.98-720.318-535.27-825.287-1115.521l-1.594-8.816C185.286 163.833 112.786-237.016-762.678-643.898L-1822.83 608.665 571.922 2635.55l544.338-771.86Z"
|
|
||||||
fill="#A41C42"
|
|
||||||
fill-opacity=".2"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="px-4 py-10 sm:px-6 sm:py-28 lg:px-8 xl:px-28 xl:py-32">
|
|
||||||
<div class="mx-auto max-w-xl lg:mx-0">
|
|
||||||
<svg viewBox="0 0 71 48" class="h-12" aria-hidden="true">
|
|
||||||
<path
|
|
||||||
d="m26.371 33.477-.552-.1c-3.92-.729-6.397-3.1-7.57-6.829-.733-2.324.597-4.035 3.035-4.148 1.995-.092 3.362 1.055 4.57 2.39 1.557 1.72 2.984 3.558 4.514 5.305 2.202 2.515 4.797 4.134 8.347 3.634 3.183-.448 5.958-1.725 8.371-3.828.363-.316.761-.592 1.144-.886l-.241-.284c-2.027.63-4.093.841-6.205.735-3.195-.16-6.24-.828-8.964-2.582-2.486-1.601-4.319-3.746-5.19-6.611-.704-2.315.736-3.934 3.135-3.6.948.133 1.746.56 2.463 1.165.583.493 1.143 1.015 1.738 1.493 2.8 2.25 6.712 2.375 10.265-.068-5.842-.026-9.817-3.24-13.308-7.313-1.366-1.594-2.7-3.216-4.095-4.785-2.698-3.036-5.692-5.71-9.79-6.623C12.8-.623 7.745.14 2.893 2.361 1.926 2.804.997 3.319 0 4.149c.494 0 .763.006 1.032 0 2.446-.064 4.28 1.023 5.602 3.024.962 1.457 1.415 3.104 1.761 4.798.513 2.515.247 5.078.544 7.605.761 6.494 4.08 11.026 10.26 13.346 2.267.852 4.591 1.135 7.172.555ZM10.751 3.852c-.976.246-1.756-.148-2.56-.962 1.377-.343 2.592-.476 3.897-.528-.107.848-.607 1.306-1.336 1.49Zm32.002 37.924c-.085-.626-.62-.901-1.04-1.228-1.857-1.446-4.03-1.958-6.333-2-1.375-.026-2.735-.128-4.031-.61-.595-.22-1.26-.505-1.244-1.272.015-.78.693-1 1.31-1.184.505-.15 1.026-.247 1.6-.382-1.46-.936-2.886-1.065-4.787-.3-2.993 1.202-5.943 1.06-8.926-.017-1.684-.608-3.179-1.563-4.735-2.408l-.043.03a2.96 2.96 0 0 0 .04-.029c-.038-.117-.107-.12-.197-.054l.122.107c1.29 2.115 3.034 3.817 5.004 5.271 3.793 2.8 7.936 4.471 12.784 3.73A66.714 66.714 0 0 1 37 40.877c1.98-.16 3.866.398 5.753.899Zm-9.14-30.345c-.105-.076-.206-.266-.42-.069 1.745 2.36 3.985 4.098 6.683 5.193 4.354 1.767 8.773 2.07 13.293.51 3.51-1.21 6.033-.028 7.343 3.38.19-3.955-2.137-6.837-5.843-7.401-2.084-.318-4.01.373-5.962.94-5.434 1.575-10.485.798-15.094-2.553Zm27.085 15.425c.708.059 1.416.123 2.124.185-1.6-1.405-3.55-1.517-5.523-1.404-3.003.17-5.167 1.903-7.14 3.972-1.739 1.824-3.31 3.87-5.903 4.604.043.078.054.117.066.117.35.005.699.021 1.047.005 3.768-.17 7.317-.965 10.14-3.7.89-.86 1.685-1.817 2.544-2.71.716-.746 1.584-1.159 2.645-1.07Zm-8.753-4.67c-2.812.246-5.254 1.409-7.548 2.943-1.766 1.18-3.654 1.738-5.776 1.37-.374-.066-.75-.114-1.124-.17l-.013.156c.135.07.265.151.405.207.354.14.702.308 1.07.395 4.083.971 7.992.474 11.516-1.803 2.221-1.435 4.521-1.707 7.013-1.336.252.038.503.083.756.107.234.022.479.255.795.003-2.179-1.574-4.526-2.096-7.094-1.872Zm-10.049-9.544c1.475.051 2.943-.142 4.486-1.059-.452.04-.643.04-.827.076-2.126.424-4.033-.04-5.733-1.383-.623-.493-1.257-.974-1.889-1.457-2.503-1.914-5.374-2.555-8.514-2.5.05.154.054.26.108.315 3.417 3.455 7.371 5.836 12.369 6.008Zm24.727 17.731c-2.114-2.097-4.952-2.367-7.578-.537 1.738.078 3.043.632 4.101 1.728.374.388.763.768 1.182 1.106 1.6 1.29 4.311 1.352 5.896.155-1.861-.726-1.861-.726-3.601-2.452Zm-21.058 16.06c-1.858-3.46-4.981-4.24-8.59-4.008a9.667 9.667 0 0 1 2.977 1.39c.84.586 1.547 1.311 2.243 2.055 1.38 1.473 3.534 2.376 4.962 2.07-.656-.412-1.238-.848-1.592-1.507Zm17.29-19.32c0-.023.001-.045.003-.068l-.006.006.006-.006-.036-.004.021.018.012.053Zm-20 14.744a7.61 7.61 0 0 0-.072-.041.127.127 0 0 0 .015.043c.005.008.038 0 .058-.002Zm-.072-.041-.008-.034-.008.01.008-.01-.022-.006.005.026.024.014Z"
|
|
||||||
fill="#FD4F00"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<h1 class="text-brand mt-10 flex items-center text-sm font-semibold leading-6">
|
|
||||||
Phoenix Framework
|
|
||||||
<small class="bg-brand/5 text-[0.8125rem] ml-3 rounded-full px-2 font-medium leading-6">
|
|
||||||
v{Application.spec(:phoenix, :vsn)}
|
|
||||||
</small>
|
|
||||||
</h1>
|
|
||||||
<p class="text-[2rem] mt-4 font-semibold leading-10 tracking-tighter text-zinc-900 text-balance">
|
|
||||||
Peace of mind from prototype to production.
|
|
||||||
</p>
|
|
||||||
<p class="mt-4 text-base leading-7 text-zinc-600">
|
|
||||||
Build rich, interactive web applications quickly, with less code and fewer moving parts. Join our growing community of developers using Phoenix to craft APIs, HTML5 apps and more, for fun or at scale.
|
|
||||||
</p>
|
|
||||||
<div class="flex">
|
|
||||||
<div class="w-full sm:w-auto">
|
|
||||||
<div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-3">
|
|
||||||
<a
|
|
||||||
href="https://hexdocs.pm/phoenix/overview.html"
|
|
||||||
class="group relative rounded-2xl px-6 py-4 text-sm font-semibold leading-6 text-zinc-900 sm:py-6"
|
|
||||||
>
|
|
||||||
<span class="absolute inset-0 rounded-2xl bg-zinc-50 transition group-hover:bg-zinc-100 sm:group-hover:scale-105">
|
|
||||||
</span>
|
|
||||||
<span class="relative flex items-center gap-4 sm:flex-col">
|
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" class="h-6 w-6">
|
|
||||||
<path d="m12 4 10-2v18l-10 2V4Z" fill="#18181B" fill-opacity=".15" />
|
|
||||||
<path
|
|
||||||
d="M12 4 2 2v18l10 2m0-18v18m0-18 10-2v18l-10 2"
|
|
||||||
stroke="#18181B"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
Guides & Docs
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://github.com/phoenixframework/phoenix"
|
|
||||||
class="group relative rounded-2xl px-6 py-4 text-sm font-semibold leading-6 text-zinc-900 sm:py-6"
|
|
||||||
>
|
|
||||||
<span class="absolute inset-0 rounded-2xl bg-zinc-50 transition group-hover:bg-zinc-100 sm:group-hover:scale-105">
|
|
||||||
</span>
|
|
||||||
<span class="relative flex items-center gap-4 sm:flex-col">
|
|
||||||
<svg viewBox="0 0 24 24" aria-hidden="true" class="h-6 w-6">
|
|
||||||
<path
|
|
||||||
fill-rule="evenodd"
|
|
||||||
clip-rule="evenodd"
|
|
||||||
d="M12 0C5.37 0 0 5.506 0 12.303c0 5.445 3.435 10.043 8.205 11.674.6.107.825-.262.825-.585 0-.292-.015-1.261-.015-2.291C6 21.67 5.22 20.346 4.98 19.654c-.135-.354-.72-1.446-1.23-1.738-.42-.23-1.02-.8-.015-.815.945-.015 1.62.892 1.845 1.261 1.08 1.86 2.805 1.338 3.495 1.015.105-.8.42-1.338.765-1.645-2.67-.308-5.46-1.37-5.46-6.075 0-1.338.465-2.446 1.23-3.307-.12-.308-.54-1.569.12-3.26 0 0 1.005-.323 3.3 1.26.96-.276 1.98-.415 3-.415s2.04.139 3 .416c2.295-1.6 3.3-1.261 3.3-1.261.66 1.691.24 2.952.12 3.26.765.861 1.23 1.953 1.23 3.307 0 4.721-2.805 5.767-5.475 6.075.435.384.81 1.122.81 2.276 0 1.645-.015 2.968-.015 3.383 0 .323.225.707.825.585a12.047 12.047 0 0 0 5.919-4.489A12.536 12.536 0 0 0 24 12.304C24 5.505 18.63 0 12 0Z"
|
|
||||||
fill="#18181B"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
Source Code
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href={"https://github.com/phoenixframework/phoenix/blob/v#{Application.spec(:phoenix, :vsn)}/CHANGELOG.md"}
|
|
||||||
class="group relative rounded-2xl px-6 py-4 text-sm font-semibold leading-6 text-zinc-900 sm:py-6"
|
|
||||||
>
|
|
||||||
<span class="absolute inset-0 rounded-2xl bg-zinc-50 transition group-hover:bg-zinc-100 sm:group-hover:scale-105">
|
|
||||||
</span>
|
|
||||||
<span class="relative flex items-center gap-4 sm:flex-col">
|
|
||||||
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" class="h-6 w-6">
|
|
||||||
<path
|
|
||||||
d="M12 1v6M12 17v6"
|
|
||||||
stroke="#18181B"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
/>
|
|
||||||
<circle
|
|
||||||
cx="12"
|
|
||||||
cy="12"
|
|
||||||
r="4"
|
|
||||||
fill="#18181B"
|
|
||||||
fill-opacity=".15"
|
|
||||||
stroke="#18181B"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
Changelog
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="mt-10 grid grid-cols-1 gap-y-4 text-sm leading-6 text-zinc-700 sm:grid-cols-2">
|
|
||||||
<div>
|
|
||||||
<a
|
|
||||||
href="https://twitter.com/elixirphoenix"
|
|
||||||
class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 16 16"
|
|
||||||
aria-hidden="true"
|
|
||||||
class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600"
|
|
||||||
>
|
|
||||||
<path d="M5.403 14c5.283 0 8.172-4.617 8.172-8.62 0-.131 0-.262-.008-.391A6.033 6.033 0 0 0 15 3.419a5.503 5.503 0 0 1-1.65.477 3.018 3.018 0 0 0 1.263-1.676 5.579 5.579 0 0 1-1.824.736 2.832 2.832 0 0 0-1.63-.916 2.746 2.746 0 0 0-1.821.319A2.973 2.973 0 0 0 8.076 3.78a3.185 3.185 0 0 0-.182 1.938 7.826 7.826 0 0 1-3.279-.918 8.253 8.253 0 0 1-2.64-2.247 3.176 3.176 0 0 0-.315 2.208 3.037 3.037 0 0 0 1.203 1.836A2.739 2.739 0 0 1 1.56 6.22v.038c0 .7.23 1.377.65 1.919.42.54 1.004.912 1.654 1.05-.423.122-.866.14-1.297.052.184.602.541 1.129 1.022 1.506a2.78 2.78 0 0 0 1.662.598 5.656 5.656 0 0 1-2.007 1.074A5.475 5.475 0 0 1 1 12.64a7.827 7.827 0 0 0 4.403 1.358" />
|
|
||||||
</svg>
|
|
||||||
Follow on Twitter
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<a
|
|
||||||
href="https://elixirforum.com"
|
|
||||||
class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 16 16"
|
|
||||||
aria-hidden="true"
|
|
||||||
class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600"
|
|
||||||
>
|
|
||||||
<path d="M8 13.833c3.866 0 7-2.873 7-6.416C15 3.873 11.866 1 8 1S1 3.873 1 7.417c0 1.081.292 2.1.808 2.995.606 1.05.806 2.399.086 3.375l-.208.283c-.285.386-.01.905.465.85.852-.098 2.048-.318 3.137-.81a3.717 3.717 0 0 1 1.91-.318c.263.027.53.041.802.041Z" />
|
|
||||||
</svg>
|
|
||||||
Discuss on the Elixir Forum
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<a
|
|
||||||
href="https://web.libera.chat/#elixir"
|
|
||||||
class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 16 16"
|
|
||||||
aria-hidden="true"
|
|
||||||
class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fill-rule="evenodd"
|
|
||||||
clip-rule="evenodd"
|
|
||||||
d="M6.356 2.007a.75.75 0 0 1 .637.849l-1.5 10.5a.75.75 0 1 1-1.485-.212l1.5-10.5a.75.75 0 0 1 .848-.637ZM11.356 2.008a.75.75 0 0 1 .637.848l-1.5 10.5a.75.75 0 0 1-1.485-.212l1.5-10.5a.75.75 0 0 1 .848-.636Z"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
fill-rule="evenodd"
|
|
||||||
clip-rule="evenodd"
|
|
||||||
d="M14 5.25a.75.75 0 0 1-.75.75h-9.5a.75.75 0 0 1 0-1.5h9.5a.75.75 0 0 1 .75.75ZM13 10.75a.75.75 0 0 1-.75.75h-9.5a.75.75 0 0 1 0-1.5h9.5a.75.75 0 0 1 .75.75Z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
Chat on Libera IRC
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<a
|
|
||||||
href="https://discord.gg/elixir"
|
|
||||||
class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 16 16"
|
|
||||||
aria-hidden="true"
|
|
||||||
class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600"
|
|
||||||
>
|
|
||||||
<path d="M13.545 2.995c-1.02-.46-2.114-.8-3.257-.994a.05.05 0 0 0-.052.024c-.141.246-.297.567-.406.82a12.377 12.377 0 0 0-3.658 0 8.238 8.238 0 0 0-.412-.82.052.052 0 0 0-.052-.024 13.315 13.315 0 0 0-3.257.994.046.046 0 0 0-.021.018C.356 6.063-.213 9.036.066 11.973c.001.015.01.029.02.038a13.353 13.353 0 0 0 3.996 1.987.052.052 0 0 0 .056-.018c.308-.414.582-.85.818-1.309a.05.05 0 0 0-.028-.069 8.808 8.808 0 0 1-1.248-.585.05.05 0 0 1-.005-.084c.084-.062.168-.126.248-.191a.05.05 0 0 1 .051-.007c2.619 1.176 5.454 1.176 8.041 0a.05.05 0 0 1 .053.006c.08.065.164.13.248.192a.05.05 0 0 1-.004.084c-.399.23-.813.423-1.249.585a.05.05 0 0 0-.027.07c.24.457.514.893.817 1.307a.051.051 0 0 0 .056.019 13.31 13.31 0 0 0 4.001-1.987.05.05 0 0 0 .021-.037c.334-3.396-.559-6.345-2.365-8.96a.04.04 0 0 0-.021-.02Zm-8.198 7.19c-.789 0-1.438-.712-1.438-1.587 0-.874.637-1.586 1.438-1.586.807 0 1.45.718 1.438 1.586 0 .875-.637 1.587-1.438 1.587Zm5.316 0c-.788 0-1.438-.712-1.438-1.587 0-.874.637-1.586 1.438-1.586.807 0 1.45.718 1.438 1.586 0 .875-.63 1.587-1.438 1.587Z" />
|
|
||||||
</svg>
|
|
||||||
Join our Discord server
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<a
|
|
||||||
href="https://fly.io/docs/elixir/getting-started/"
|
|
||||||
class="group -mx-2 -my-0.5 inline-flex items-center gap-3 rounded-lg px-2 py-0.5 hover:bg-zinc-50 hover:text-zinc-900"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
aria-hidden="true"
|
|
||||||
class="h-4 w-4 fill-zinc-400 group-hover:fill-zinc-600"
|
|
||||||
>
|
|
||||||
<path d="M1 12.5A4.5 4.5 0 005.5 17H15a4 4 0 001.866-7.539 3.504 3.504 0 00-4.504-4.272A4.5 4.5 0 004.06 8.235 4.502 4.502 0 001 12.5z" />
|
|
||||||
</svg>
|
|
||||||
Deploy your application
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
|
||||||
|
<%= if @current_user do %>
|
||||||
|
<span class="px-3 py-2 text-sm font-medium text-white rounded-md">
|
||||||
|
{@current_user.email}
|
||||||
|
</span>
|
||||||
|
<a
|
||||||
|
href="/sign-out"
|
||||||
|
class="rounded-lg bg-zinc-100 px-2 py-1 text-[0.8125rem] font-semibold leading-6 text-zinc-900 hover:bg-zinc-200/80 active:text-zinc-900/70"
|
||||||
|
>
|
||||||
|
Sign out
|
||||||
|
</a>
|
||||||
|
<% else %>
|
||||||
|
<a
|
||||||
|
href="/sign-in"
|
||||||
|
class="rounded-lg bg-zinc-100 px-2 py-1 text-[0.8125rem] font-semibold leading-6 text-zinc-900 hover:bg-zinc-200/80 active:text-zinc-900/70"
|
||||||
|
>
|
||||||
|
Sign In
|
||||||
|
</a>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="py-10">
|
||||||
|
<header>
|
||||||
|
<div class="px-4 mx-auto max-w-7xl sm:px-6 lg:px-8">
|
||||||
|
<h1 class="text-3xl font-bold leading-tight tracking-tight text-gray-900">
|
||||||
|
Demo
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
|
||||||
|
<div class="px-4 py-8 sm:px-0">
|
||||||
|
<div class="border-4 border-gray-200 border-dashed rounded-lg h-96"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
46
lib/mv_web/live_user_auth.ex
Normal file
46
lib/mv_web/live_user_auth.ex
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
defmodule MvWeb.LiveUserAuth do
|
||||||
|
@moduledoc """
|
||||||
|
Helpers for authenticating users in LiveViews.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import Phoenix.Component
|
||||||
|
use MvWeb, :verified_routes
|
||||||
|
|
||||||
|
# This is used for nested liveviews to fetch the current user.
|
||||||
|
# To use, place the following at the top of that liveview:
|
||||||
|
# on_mount {MvWeb.LiveUserAuth, :current_user}
|
||||||
|
def on_mount(:current_user, _params, session, socket) do
|
||||||
|
return_to = session[:return_to]
|
||||||
|
|
||||||
|
socket =
|
||||||
|
socket
|
||||||
|
|> assign(:return_to, return_to)
|
||||||
|
|> AshAuthentication.Phoenix.LiveSession.assign_new_resources(session)
|
||||||
|
|
||||||
|
{:cont, session, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_mount(:live_user_optional, _params, _session, socket) do
|
||||||
|
if socket.assigns[:current_user] do
|
||||||
|
{:cont, socket}
|
||||||
|
else
|
||||||
|
{:cont, assign(socket, :current_user, nil)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_mount(:live_user_required, _params, _session, socket) do
|
||||||
|
if socket.assigns[:current_user] do
|
||||||
|
{:cont, socket}
|
||||||
|
else
|
||||||
|
{:halt, Phoenix.LiveView.redirect(socket, to: ~p"/sign-in")}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_mount(:live_no_user, _params, _session, socket) do
|
||||||
|
if socket.assigns[:current_user] do
|
||||||
|
{:halt, Phoenix.LiveView.redirect(socket, to: ~p"/")}
|
||||||
|
else
|
||||||
|
{:cont, assign(socket, :current_user, nil)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
defmodule MvWeb.Router do
|
defmodule MvWeb.Router do
|
||||||
use MvWeb, :router
|
use MvWeb, :router
|
||||||
|
|
||||||
|
use AshAuthentication.Phoenix.Router
|
||||||
|
|
||||||
|
import AshAuthentication.Plug.Helpers
|
||||||
|
|
||||||
pipeline :browser do
|
pipeline :browser do
|
||||||
plug :accepts, ["html"]
|
plug :accepts, ["html"]
|
||||||
plug :fetch_session
|
plug :fetch_session
|
||||||
|
|
@ -8,33 +12,86 @@ defmodule MvWeb.Router do
|
||||||
plug :put_root_layout, html: {MvWeb.Layouts, :root}
|
plug :put_root_layout, html: {MvWeb.Layouts, :root}
|
||||||
plug :protect_from_forgery
|
plug :protect_from_forgery
|
||||||
plug :put_secure_browser_headers
|
plug :put_secure_browser_headers
|
||||||
|
plug :load_from_session
|
||||||
end
|
end
|
||||||
|
|
||||||
pipeline :api do
|
pipeline :api do
|
||||||
plug :accepts, ["json"]
|
plug :accepts, ["json"]
|
||||||
|
plug :load_from_bearer
|
||||||
|
plug :set_actor, :user
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/", MvWeb do
|
scope "/", MvWeb do
|
||||||
pipe_through :browser
|
pipe_through :browser
|
||||||
|
|
||||||
get "/", PageController, :home
|
ash_authentication_live_session :authenticated_routes do
|
||||||
live "/members", MemberLive.Index, :index
|
# in each liveview, add one of the following at the top of the module:
|
||||||
live "/members/new", MemberLive.Index, :new
|
#
|
||||||
live "/members/:id/edit", MemberLive.Index, :edit
|
# If an authenticated user must be present:
|
||||||
live "/members/:id", MemberLive.Show, :show
|
# on_mount {MvWeb.LiveUserAuth, :live_user_required}
|
||||||
live "/members/:id/show/edit", MemberLive.Show, :edit
|
#
|
||||||
|
# If an authenticated user *may* be present:
|
||||||
|
# on_mount {MvWeb.LiveUserAuth, :live_user_optional}
|
||||||
|
#
|
||||||
|
# If an authenticated user must *not* be present:
|
||||||
|
# on_mount {MvWeb.LiveUserAuth, :live_no_user}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
live "/property_types", PropertyTypeLive.Index, :index
|
scope "/", MvWeb do
|
||||||
live "/property_types/new", PropertyTypeLive.Index, :new
|
pipe_through :browser
|
||||||
live "/property_types/:id/edit", PropertyTypeLive.Index, :edit
|
|
||||||
live "/property_types/:id", PropertyTypeLive.Show, :show
|
|
||||||
live "/property_types/:id/show/edit", PropertyTypeLive.Show, :edit
|
|
||||||
|
|
||||||
live "/properties", PropertyLive.Index, :index
|
@doc """
|
||||||
live "/properties/new", PropertyLive.Index, :new
|
AshAuthentication-specific: We define that all routes can only be accessed when the user is signed in.
|
||||||
live "/properties/:id/edit", PropertyLive.Index, :edit
|
"""
|
||||||
live "/properties/:id", PropertyLive.Show, :show
|
ash_authentication_live_session :authentication_required,
|
||||||
live "/properties/:id/show/edit", PropertyLive.Show, :edit
|
on_mount: {MvWeb.LiveUserAuth, :live_user_required} do
|
||||||
|
get "/", PageController, :home
|
||||||
|
|
||||||
|
live "/members", MemberLive.Index, :index
|
||||||
|
live "/members/new", MemberLive.Index, :new
|
||||||
|
live "/members/:id/edit", MemberLive.Index, :edit
|
||||||
|
live "/members/:id", MemberLive.Show, :show
|
||||||
|
live "/members/:id/show/edit", MemberLive.Show, :edit
|
||||||
|
|
||||||
|
live "/property_types", PropertyTypeLive.Index, :index
|
||||||
|
live "/property_types/new", PropertyTypeLive.Index, :new
|
||||||
|
live "/property_types/:id/edit", PropertyTypeLive.Index, :edit
|
||||||
|
live "/property_types/:id", PropertyTypeLive.Show, :show
|
||||||
|
live "/property_types/:id/show/edit", PropertyTypeLive.Show, :edit
|
||||||
|
|
||||||
|
live "/properties", PropertyLive.Index, :index
|
||||||
|
live "/properties/new", PropertyLive.Index, :new
|
||||||
|
live "/properties/:id/edit", PropertyLive.Index, :edit
|
||||||
|
live "/properties/:id", PropertyLive.Show, :show
|
||||||
|
live "/properties/:id/show/edit", PropertyLive.Show, :edit
|
||||||
|
end
|
||||||
|
|
||||||
|
# ASHAUTHENTICATION GENERATED AUTH ROUTES
|
||||||
|
auth_routes AuthController, Mv.Accounts.User, path: "/auth"
|
||||||
|
sign_out_route AuthController
|
||||||
|
|
||||||
|
# Remove these if you'd like to use your own authentication views
|
||||||
|
sign_in_route register_path: "/register",
|
||||||
|
reset_path: "/reset",
|
||||||
|
auth_routes_prefix: "/auth",
|
||||||
|
on_mount: [{MvWeb.LiveUserAuth, :live_no_user}],
|
||||||
|
overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default]
|
||||||
|
|
||||||
|
# Remove this if you do not want to use the reset password feature
|
||||||
|
reset_route auth_routes_prefix: "/auth",
|
||||||
|
overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default]
|
||||||
|
|
||||||
|
# Remove this if you do not use the confirmation strategy
|
||||||
|
confirm_route Mv.Accounts.User, :confirm_new_user,
|
||||||
|
auth_routes_prefix: "/auth",
|
||||||
|
overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default]
|
||||||
|
|
||||||
|
# Remove this if you do not use the magic link strategy.
|
||||||
|
# magic_sign_in_route(Mv.Accounts.User, :magic_link,
|
||||||
|
# auth_routes_prefix: "/auth",
|
||||||
|
# overrides: [MvWeb.AuthOverrides, AshAuthentication.Phoenix.Overrides.Default]
|
||||||
|
# )
|
||||||
end
|
end
|
||||||
|
|
||||||
# Other scopes may use custom stacks.
|
# Other scopes may use custom stacks.
|
||||||
|
|
|
||||||
6
mix.exs
6
mix.exs
|
|
@ -40,6 +40,9 @@ defmodule Mv.MixProject do
|
||||||
{:ash_postgres, "~> 2.0"},
|
{:ash_postgres, "~> 2.0"},
|
||||||
{:ash_phoenix, "~> 2.0"},
|
{:ash_phoenix, "~> 2.0"},
|
||||||
{:ash, "~> 3.0"},
|
{:ash, "~> 3.0"},
|
||||||
|
{:bcrypt_elixir, "~> 3.0"},
|
||||||
|
{:ash_authentication, "~> 4.9"},
|
||||||
|
{:ash_authentication_phoenix, "~> 2.10"},
|
||||||
{:igniter, "~> 0.6", only: [:dev, :test]},
|
{:igniter, "~> 0.6", only: [:dev, :test]},
|
||||||
{:phoenix, "~> 1.7.20"},
|
{:phoenix, "~> 1.7.20"},
|
||||||
{:phoenix_ecto, "~> 4.5"},
|
{:phoenix_ecto, "~> 4.5"},
|
||||||
|
|
@ -91,7 +94,8 @@ defmodule Mv.MixProject do
|
||||||
"tailwind mv --minify",
|
"tailwind mv --minify",
|
||||||
"esbuild mv --minify",
|
"esbuild mv --minify",
|
||||||
"phx.digest"
|
"phx.digest"
|
||||||
]
|
],
|
||||||
|
"phx.routes": ["phx.routes", "ash_authentication.phoenix.routes"]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
10
mix.lock
10
mix.lock
|
|
@ -1,19 +1,25 @@
|
||||||
%{
|
%{
|
||||||
"ash": {:hex, :ash, "3.5.19", "defd1c6b94475352a7b69f430b792fb64e3a9f7ca030195737bb97dc0f1311b5", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:igniter, ">= 0.6.4 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, "~> 0.11", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.2.65 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, ">= 0.2.6 and < 1.0.0-0", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ded976230b1ef823aeb25008cc62de6545bf3ad6208cf1f3badb598fa6c01375"},
|
"ash": {:hex, :ash, "3.5.19", "defd1c6b94475352a7b69f430b792fb64e3a9f7ca030195737bb97dc0f1311b5", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:igniter, ">= 0.6.4 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, "~> 0.11", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.2.65 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, ">= 0.2.6 and < 1.0.0-0", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ded976230b1ef823aeb25008cc62de6545bf3ad6208cf1f3badb598fa6c01375"},
|
||||||
"ash_admin": {:hex, :ash_admin, "0.13.9", "8a7c0f52be4aa490e4a59137bc40e3abafba9e1977f800bb2edae3f331ef1ebb", [:mix], [{:ash, ">= 3.4.63 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:ash_phoenix, ">= 2.1.8 and < 3.0.0-0", [hex: :ash_phoenix, repo: "hexpm", optional: false]}, {:gettext, "~> 0.26", [hex: :gettext, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.7", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}], "hexpm", "1373e1749d6b5b21c7ff7d7fc79ac932f6f8d1bd0d154a80758eab168948ea37"},
|
"ash_admin": {:hex, :ash_admin, "0.13.9", "8a7c0f52be4aa490e4a59137bc40e3abafba9e1977f800bb2edae3f331ef1ebb", [:mix], [{:ash, ">= 3.4.63 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:ash_phoenix, ">= 2.1.8 and < 3.0.0-0", [hex: :ash_phoenix, repo: "hexpm", optional: false]}, {:gettext, "~> 0.26", [hex: :gettext, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.7", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}], "hexpm", "1373e1749d6b5b21c7ff7d7fc79ac932f6f8d1bd0d154a80758eab168948ea37"},
|
||||||
|
"ash_authentication": {:hex, :ash_authentication, "4.9.3", "2347b7982e3b00ae1165a4ef6875e05540204e933922e302bd3ac2be4c043e20", [:mix], [{:argon2_elixir, "~> 4.0", [hex: :argon2_elixir, repo: "hexpm", optional: true]}, {:ash, ">= 3.4.29 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:ash_postgres, "~> 2.0", [hex: :ash_postgres, repo: "hexpm", optional: true]}, {:assent, "~> 0.2.13", [hex: :assent, repo: "hexpm", optional: false]}, {:bcrypt_elixir, "~> 3.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: false]}, {:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:finch, "~> 0.19", [hex: :finch, repo: "hexpm", optional: false]}, {:igniter, "~> 0.4", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:joken, "~> 2.5", [hex: :joken, repo: "hexpm", optional: false]}, {:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: false]}, {:spark, "~> 2.0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}], "hexpm", "1641988f6c67b7d7517caed9e6cb0f6bd906bbb994e2831022b6ad7cecf45ad0"},
|
||||||
|
"ash_authentication_phoenix": {:hex, :ash_authentication_phoenix, "2.10.1", "6facb8e14d7e93c3268b8cb5300d42d3802bd754d241f4215f2c5fc1d34c4c94", [:mix], [{:ash, "~> 3.0", [hex: :ash, repo: "hexpm", optional: false]}, {:ash_authentication, ">= 4.9.1 and < 5.0.0-0", [hex: :ash_authentication, repo: "hexpm", optional: false]}, {:ash_phoenix, "~> 2.0", [hex: :ash_phoenix, repo: "hexpm", optional: false]}, {:bcrypt_elixir, "~> 3.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: false]}, {:gettext, "~> 0.26", [hex: :gettext, repo: "hexpm", optional: true]}, {:igniter, ">= 0.5.25 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_html_helpers, "~> 1.0", [hex: :phoenix_html_helpers, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:slugify, "~> 1.3", [hex: :slugify, repo: "hexpm", optional: false]}], "hexpm", "efc27905b29476cacb67562658d5b38ca0656b3c81c4bcb40a117a2d8d686433"},
|
||||||
"ash_phoenix": {:hex, :ash_phoenix, "2.3.6", "c2bea1673af52f305b2fe0c04999bd1f0dc8e127d4757a3d7f42d0b9dea16a7a", [:mix], [{:ash, ">= 3.5.13 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:igniter, "~> 0.6", [hex: :igniter, repo: "hexpm", optional: true]}, {:inertia, "~> 2.3", [hex: :inertia, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.6 or ~> 1.6", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.20.3 or ~> 1.0-rc.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:spark, ">= 2.2.29 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}], "hexpm", "6923dca70fe1d533864134999f4d9c5c59ef745a6b50982d42d60c18966474cd"},
|
"ash_phoenix": {:hex, :ash_phoenix, "2.3.6", "c2bea1673af52f305b2fe0c04999bd1f0dc8e127d4757a3d7f42d0b9dea16a7a", [:mix], [{:ash, ">= 3.5.13 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:igniter, "~> 0.6", [hex: :igniter, repo: "hexpm", optional: true]}, {:inertia, "~> 2.3", [hex: :inertia, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.6 or ~> 1.6", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.20.3 or ~> 1.0-rc.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:spark, ">= 2.2.29 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}], "hexpm", "6923dca70fe1d533864134999f4d9c5c59ef745a6b50982d42d60c18966474cd"},
|
||||||
"ash_postgres": {:hex, :ash_postgres, "2.6.6", "f60f806e3e969669329dfd33068bf602f3d7f214e0bbb36c241433f34cbff2e0", [:mix], [{:ash, ">= 3.5.13 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:ash_sql, ">= 0.2.72 and < 1.0.0-0", [hex: :ash_sql, repo: "hexpm", optional: false]}, {:ecto, ">= 3.12.1 and < 4.0.0-0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.12", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:igniter, "~> 0.6", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "3133800432273f9e6effb6f8464fe81da22c5b577aa73291f63fd229f4bb43fb"},
|
"ash_postgres": {:hex, :ash_postgres, "2.6.6", "f60f806e3e969669329dfd33068bf602f3d7f214e0bbb36c241433f34cbff2e0", [:mix], [{:ash, ">= 3.5.13 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:ash_sql, ">= 0.2.72 and < 1.0.0-0", [hex: :ash_sql, repo: "hexpm", optional: false]}, {:ecto, ">= 3.12.1 and < 4.0.0-0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.12", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:igniter, "~> 0.6", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "3133800432273f9e6effb6f8464fe81da22c5b577aa73291f63fd229f4bb43fb"},
|
||||||
"ash_sql": {:hex, :ash_sql, "0.2.80", "7717dca3794d7461b8302b107f039bce2c57773840177528cf94c7c264ed763b", [:mix], [{:ash, "~> 3.5", [hex: :ash, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.9", [hex: :ecto_sql, repo: "hexpm", optional: false]}], "hexpm", "036f96b78bf612a1d1fe798b8795ab1e6ecef81e41ca473b1533b139dd0202ab"},
|
"ash_sql": {:hex, :ash_sql, "0.2.80", "7717dca3794d7461b8302b107f039bce2c57773840177528cf94c7c264ed763b", [:mix], [{:ash, "~> 3.5", [hex: :ash, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.9", [hex: :ecto_sql, repo: "hexpm", optional: false]}], "hexpm", "036f96b78bf612a1d1fe798b8795ab1e6ecef81e41ca473b1533b139dd0202ab"},
|
||||||
|
"assent": {:hex, :assent, "0.2.13", "11226365d2d8661d23e9a2cf94d3255e81054ff9d88ac877f28bfdf38fa4ef31", [:mix], [{:certifi, ">= 0.0.0", [hex: :certifi, repo: "hexpm", optional: true]}, {:finch, "~> 0.15", [hex: :finch, repo: "hexpm", optional: true]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: true]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:req, "~> 0.4", [hex: :req, repo: "hexpm", optional: true]}, {:ssl_verify_fun, ">= 0.0.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: true]}], "hexpm", "bf9f351b01dd6bceea1d1f157f05438f6765ce606e6eb8d29296003d29bf6eab"},
|
||||||
"bandit": {:hex, :bandit, "1.7.0", "d1564f30553c97d3e25f9623144bb8df11f3787a26733f00b21699a128105c0c", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "3e2f7a98c7a11f48d9d8c037f7177cd39778e74d55c7af06fe6227c742a8168a"},
|
"bandit": {:hex, :bandit, "1.7.0", "d1564f30553c97d3e25f9623144bb8df11f3787a26733f00b21699a128105c0c", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "3e2f7a98c7a11f48d9d8c037f7177cd39778e74d55c7af06fe6227c742a8168a"},
|
||||||
|
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.3.2", "d50091e3c9492d73e17fc1e1619a9b09d6a5ef99160eb4d736926fd475a16ca3", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "471be5151874ae7931911057d1467d908955f93554f7a6cd1b7d804cac8cef53"},
|
||||||
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
|
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
|
||||||
"castore": {:hex, :castore, "1.0.14", "4582dd7d630b48cf5e1ca8d3d42494db51e406b7ba704e81fbd401866366896a", [:mix], [], "hexpm", "7bc1b65249d31701393edaaac18ec8398d8974d52c647b7904d01b964137b9f4"},
|
"castore": {:hex, :castore, "1.0.14", "4582dd7d630b48cf5e1ca8d3d42494db51e406b7ba704e81fbd401866366896a", [:mix], [], "hexpm", "7bc1b65249d31701393edaaac18ec8398d8974d52c647b7904d01b964137b9f4"},
|
||||||
"circular_buffer": {:hex, :circular_buffer, "0.4.1", "477f370fd8cfe1787b0a1bade6208bbd274b34f1610e41f1180ba756a7679839", [:mix], [], "hexpm", "633ef2e059dde0d7b89bbab13b1da9d04c6685e80e68fbdf41282d4fae746b72"},
|
"circular_buffer": {:hex, :circular_buffer, "0.4.1", "477f370fd8cfe1787b0a1bade6208bbd274b34f1610e41f1180ba756a7679839", [:mix], [], "hexpm", "633ef2e059dde0d7b89bbab13b1da9d04c6685e80e68fbdf41282d4fae746b72"},
|
||||||
|
"comeonin": {:hex, :comeonin, "5.5.1", "5113e5f3800799787de08a6e0db307133850e635d34e9fab23c70b6501669510", [:mix], [], "hexpm", "65aac8f19938145377cee73973f192c5645873dcf550a8a6b18187d17c13ccdb"},
|
||||||
"credo": {:hex, :credo, "1.7.12", "9e3c20463de4b5f3f23721527fcaf16722ec815e70ff6c60b86412c695d426c1", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8493d45c656c5427d9c729235b99d498bd133421f3e0a683e5c1b561471291e5"},
|
"credo": {:hex, :credo, "1.7.12", "9e3c20463de4b5f3f23721527fcaf16722ec815e70ff6c60b86412c695d426c1", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8493d45c656c5427d9c729235b99d498bd133421f3e0a683e5c1b561471291e5"},
|
||||||
"db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
|
"db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
|
||||||
"decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"},
|
"decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"},
|
||||||
"dns_cluster": {:hex, :dns_cluster, "0.2.0", "aa8eb46e3bd0326bd67b84790c561733b25c5ba2fe3c7e36f28e88f384ebcb33", [:mix], [], "hexpm", "ba6f1893411c69c01b9e8e8f772062535a4cf70f3f35bcc964a324078d8c8240"},
|
"dns_cluster": {:hex, :dns_cluster, "0.2.0", "aa8eb46e3bd0326bd67b84790c561733b25c5ba2fe3c7e36f28e88f384ebcb33", [:mix], [], "hexpm", "ba6f1893411c69c01b9e8e8f772062535a4cf70f3f35bcc964a324078d8c8240"},
|
||||||
"ecto": {:hex, :ecto, "3.12.6", "8bf762dc5b87d85b7aca7ad5fe31ef8142a84cea473a3381eb933bd925751300", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4c0cba01795463eebbcd9e4b5ef53c1ee8e68b9c482baef2a80de5a61e7a57fe"},
|
"ecto": {:hex, :ecto, "3.12.6", "8bf762dc5b87d85b7aca7ad5fe31ef8142a84cea473a3381eb933bd925751300", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4c0cba01795463eebbcd9e4b5ef53c1ee8e68b9c482baef2a80de5a61e7a57fe"},
|
||||||
"ecto_sql": {:hex, :ecto_sql, "3.12.1", "c0d0d60e85d9ff4631f12bafa454bc392ce8b9ec83531a412c12a0d415a3a4d0", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "aff5b958a899762c5f09028c847569f7dfb9cc9d63bdb8133bff8a5546de6bf5"},
|
"ecto_sql": {:hex, :ecto_sql, "3.12.1", "c0d0d60e85d9ff4631f12bafa454bc392ce8b9ec83531a412c12a0d415a3a4d0", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "aff5b958a899762c5f09028c847569f7dfb9cc9d63bdb8133bff8a5546de6bf5"},
|
||||||
|
"elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"},
|
||||||
"esbuild": {:hex, :esbuild, "0.10.0", "b0aa3388a1c23e727c5a3e7427c932d89ee791746b0081bbe56103e9ef3d291f", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "468489cda427b974a7cc9f03ace55368a83e1a7be12fba7e30969af78e5f8c70"},
|
"esbuild": {:hex, :esbuild, "0.10.0", "b0aa3388a1c23e727c5a3e7427c932d89ee791746b0081bbe56103e9ef3d291f", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "468489cda427b974a7cc9f03ace55368a83e1a7be12fba7e30969af78e5f8c70"},
|
||||||
"ets": {:hex, :ets, "0.9.0", "79c6a6c205436780486f72d84230c6cba2f8a9920456750ddd1e47389107d5fd", [:mix], [], "hexpm", "2861fdfb04bcaeff370f1a5904eec864f0a56dcfebe5921ea9aadf2a481c822b"},
|
"ets": {:hex, :ets, "0.9.0", "79c6a6c205436780486f72d84230c6cba2f8a9920456750ddd1e47389107d5fd", [:mix], [], "hexpm", "2861fdfb04bcaeff370f1a5904eec864f0a56dcfebe5921ea9aadf2a481c822b"},
|
||||||
"expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"},
|
"expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"},
|
||||||
|
|
@ -28,6 +34,8 @@
|
||||||
"inflex": {:hex, :inflex, "2.1.0", "a365cf0821a9dacb65067abd95008ca1b0bb7dcdd85ae59965deef2aa062924c", [:mix], [], "hexpm", "14c17d05db4ee9b6d319b0bff1bdf22aa389a25398d1952c7a0b5f3d93162dd8"},
|
"inflex": {:hex, :inflex, "2.1.0", "a365cf0821a9dacb65067abd95008ca1b0bb7dcdd85ae59965deef2aa062924c", [:mix], [], "hexpm", "14c17d05db4ee9b6d319b0bff1bdf22aa389a25398d1952c7a0b5f3d93162dd8"},
|
||||||
"iterex": {:hex, :iterex, "0.1.2", "58f9b9b9a22a55cbfc7b5234a9c9c63eaac26d276b3db80936c0e1c60355a5a6", [:mix], [], "hexpm", "2e103b8bcc81757a9af121f6dc0df312c9a17220f302b1193ef720460d03029d"},
|
"iterex": {:hex, :iterex, "0.1.2", "58f9b9b9a22a55cbfc7b5234a9c9c63eaac26d276b3db80936c0e1c60355a5a6", [:mix], [], "hexpm", "2e103b8bcc81757a9af121f6dc0df312c9a17220f302b1193ef720460d03029d"},
|
||||||
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
|
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
|
||||||
|
"joken": {:hex, :joken, "2.6.2", "5daaf82259ca603af4f0b065475099ada1b2b849ff140ccd37f4b6828ca6892a", [:mix], [{:jose, "~> 1.11.10", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "5134b5b0a6e37494e46dbf9e4dad53808e5e787904b7c73972651b51cce3d72b"},
|
||||||
|
"jose": {:hex, :jose, "1.11.10", "a903f5227417bd2a08c8a00a0cbcc458118be84480955e8d251297a425723f83", [:mix, :rebar3], [], "hexpm", "0d6cd36ff8ba174db29148fc112b5842186b68a90ce9fc2b3ec3afe76593e614"},
|
||||||
"libgraph": {:hex, :libgraph, "0.16.0", "3936f3eca6ef826e08880230f806bfea13193e49bf153f93edcf0239d4fd1d07", [:mix], [], "hexpm", "41ca92240e8a4138c30a7e06466acc709b0cbb795c643e9e17174a178982d6bf"},
|
"libgraph": {:hex, :libgraph, "0.16.0", "3936f3eca6ef826e08880230f806bfea13193e49bf153f93edcf0239d4fd1d07", [:mix], [], "hexpm", "41ca92240e8a4138c30a7e06466acc709b0cbb795c643e9e17174a178982d6bf"},
|
||||||
"live_debugger": {:hex, :live_debugger, "0.2.4", "2e0b02874ca562ba2d8cebb9e024c25c0ae9c1f4ee499135a70814e1dea6183e", [:mix], [{:igniter, ">= 0.5.40 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20.4 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "bfd0db143be54ccf2872f15bfd2209fbec1083d0b06b81b4cedeecb2fa9ac208"},
|
"live_debugger": {:hex, :live_debugger, "0.2.4", "2e0b02874ca562ba2d8cebb9e024c25c0ae9c1f4ee499135a70814e1dea6183e", [:mix], [{:igniter, ">= 0.5.40 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20.4 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "bfd0db143be54ccf2872f15bfd2209fbec1083d0b06b81b4cedeecb2fa9ac208"},
|
||||||
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
|
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
|
||||||
|
|
@ -39,6 +47,7 @@
|
||||||
"phoenix": {:hex, :phoenix, "1.7.21", "14ca4f1071a5f65121217d6b57ac5712d1857e40a0833aff7a691b7870fc9a3b", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "336dce4f86cba56fed312a7d280bf2282c720abb6074bdb1b61ec8095bdd0bc9"},
|
"phoenix": {:hex, :phoenix, "1.7.21", "14ca4f1071a5f65121217d6b57ac5712d1857e40a0833aff7a691b7870fc9a3b", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "336dce4f86cba56fed312a7d280bf2282c720abb6074bdb1b61ec8095bdd0bc9"},
|
||||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.6.4", "dcf3483ab45bab4c15e3a47c34451392f64e433846b08469f5d16c2a4cd70052", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "f5b8584c36ccc9b903948a696fc9b8b81102c79c7c0c751a9f00cdec55d5f2d7"},
|
"phoenix_ecto": {:hex, :phoenix_ecto, "4.6.4", "dcf3483ab45bab4c15e3a47c34451392f64e433846b08469f5d16c2a4cd70052", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "f5b8584c36ccc9b903948a696fc9b8b81102c79c7c0c751a9f00cdec55d5f2d7"},
|
||||||
"phoenix_html": {:hex, :phoenix_html, "4.2.1", "35279e2a39140068fc03f8874408d58eef734e488fc142153f055c5454fd1c08", [:mix], [], "hexpm", "cff108100ae2715dd959ae8f2a8cef8e20b593f8dfd031c9cba92702cf23e053"},
|
"phoenix_html": {:hex, :phoenix_html, "4.2.1", "35279e2a39140068fc03f8874408d58eef734e488fc142153f055c5454fd1c08", [:mix], [], "hexpm", "cff108100ae2715dd959ae8f2a8cef8e20b593f8dfd031c9cba92702cf23e053"},
|
||||||
|
"phoenix_html_helpers": {:hex, :phoenix_html_helpers, "1.0.1", "7eed85c52eff80a179391036931791ee5d2f713d76a81d0d2c6ebafe1e11e5ec", [:mix], [{:phoenix_html, "~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "cffd2385d1fa4f78b04432df69ab8da63dc5cf63e07b713a4dcf36a3740e3090"},
|
||||||
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.7", "405880012cb4b706f26dd1c6349125bfc903fb9e44d1ea668adaf4e04d4884b7", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "3a8625cab39ec261d48a13b7468dc619c0ede099601b084e343968309bd4d7d7"},
|
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.7", "405880012cb4b706f26dd1c6349125bfc903fb9e44d1ea668adaf4e04d4884b7", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "3a8625cab39ec261d48a13b7468dc619c0ede099601b084e343968309bd4d7d7"},
|
||||||
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.6.0", "2791fac0e2776b640192308cc90c0dbcf67843ad51387ed4ecae2038263d708d", [:mix], [{:file_system, "~> 0.2.10 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "b3a1fa036d7eb2f956774eda7a7638cf5123f8f2175aca6d6420a7f95e598e1c"},
|
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.6.0", "2791fac0e2776b640192308cc90c0dbcf67843ad51387ed4ecae2038263d708d", [:mix], [{:file_system, "~> 0.2.10 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "b3a1fa036d7eb2f956774eda7a7638cf5123f8f2175aca6d6420a7f95e598e1c"},
|
||||||
"phoenix_live_view": {:hex, :phoenix_live_view, "1.0.17", "beeb16d83a7d3760f7ad463df94e83b087577665d2acc0bf2987cd7d9778068f", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0-rc", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a4ca05c1eb6922c4d07a508a75bfa12c45e5f4d8f77ae83283465f02c53741e1"},
|
"phoenix_live_view": {:hex, :phoenix_live_view, "1.0.17", "beeb16d83a7d3760f7ad463df94e83b087577665d2acc0bf2987cd7d9778068f", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0-rc", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a4ca05c1eb6922c4d07a508a75bfa12c45e5f4d8f77ae83283465f02c53741e1"},
|
||||||
|
|
@ -51,6 +60,7 @@
|
||||||
"reactor": {:hex, :reactor, "0.15.4", "ef0c56a901c132529a14ab59fed0ccb4fcecb24308fb189a94c908255d4fdafc", [:mix], [{:igniter, "~> 0.4", [hex: :igniter, repo: "hexpm", optional: true]}, {:iterex, "~> 0.1", [hex: :iterex, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:libgraph, "~> 0.16", [hex: :libgraph, repo: "hexpm", optional: false]}, {:spark, "~> 2.0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.11", [hex: :yaml_elixir, repo: "hexpm", optional: false]}, {:ymlr, "~> 5.0", [hex: :ymlr, repo: "hexpm", optional: false]}], "hexpm", "783bf62fd0c72ded033afabdb8b6190b7048769771a2a97256e6f0bf4fb0a891"},
|
"reactor": {:hex, :reactor, "0.15.4", "ef0c56a901c132529a14ab59fed0ccb4fcecb24308fb189a94c908255d4fdafc", [:mix], [{:igniter, "~> 0.4", [hex: :igniter, repo: "hexpm", optional: true]}, {:iterex, "~> 0.1", [hex: :iterex, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:libgraph, "~> 0.16", [hex: :libgraph, repo: "hexpm", optional: false]}, {:spark, "~> 2.0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.11", [hex: :yaml_elixir, repo: "hexpm", optional: false]}, {:ymlr, "~> 5.0", [hex: :ymlr, repo: "hexpm", optional: false]}], "hexpm", "783bf62fd0c72ded033afabdb8b6190b7048769771a2a97256e6f0bf4fb0a891"},
|
||||||
"req": {:hex, :req, "0.5.10", "a3a063eab8b7510785a467f03d30a8d95f66f5c3d9495be3474b61459c54376c", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "8a604815743f8a2d3b5de0659fa3137fa4b1cffd636ecb69b30b2b9b2c2559be"},
|
"req": {:hex, :req, "0.5.10", "a3a063eab8b7510785a467f03d30a8d95f66f5c3d9495be3474b61459c54376c", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "8a604815743f8a2d3b5de0659fa3137fa4b1cffd636ecb69b30b2b9b2c2559be"},
|
||||||
"rewrite": {:hex, :rewrite, "1.1.2", "f5a5d10f5fed1491a6ff48e078d4585882695962ccc9e6c779bae025d1f92eda", [:mix], [{:glob_ex, "~> 0.1", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.0", [hex: :sourceror, repo: "hexpm", optional: false]}, {:text_diff, "~> 0.1", [hex: :text_diff, repo: "hexpm", optional: false]}], "hexpm", "7f8b94b1e3528d0a47b3e8b7bfeca559d2948a65fa7418a9ad7d7712703d39d4"},
|
"rewrite": {:hex, :rewrite, "1.1.2", "f5a5d10f5fed1491a6ff48e078d4585882695962ccc9e6c779bae025d1f92eda", [:mix], [{:glob_ex, "~> 0.1", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.0", [hex: :sourceror, repo: "hexpm", optional: false]}, {:text_diff, "~> 0.1", [hex: :text_diff, repo: "hexpm", optional: false]}], "hexpm", "7f8b94b1e3528d0a47b3e8b7bfeca559d2948a65fa7418a9ad7d7712703d39d4"},
|
||||||
|
"slugify": {:hex, :slugify, "1.3.1", "0d3b8b7e5c1eeaa960e44dce94382bee34a39b3ea239293e457a9c5b47cc6fd3", [:mix], [], "hexpm", "cb090bbeb056b312da3125e681d98933a360a70d327820e4b7f91645c4d8be76"},
|
||||||
"sobelow": {:hex, :sobelow, "0.14.0", "dd82aae8f72503f924fe9dd97ffe4ca694d2f17ec463dcfd365987c9752af6ee", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "7ecf91e298acfd9b24f5d761f19e8f6e6ac585b9387fb6301023f1f2cd5eed5f"},
|
"sobelow": {:hex, :sobelow, "0.14.0", "dd82aae8f72503f924fe9dd97ffe4ca694d2f17ec463dcfd365987c9752af6ee", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "7ecf91e298acfd9b24f5d761f19e8f6e6ac585b9387fb6301023f1f2cd5eed5f"},
|
||||||
"sourceror": {:hex, :sourceror, "1.10.0", "38397dedbbc286966ec48c7af13e228b171332be1ad731974438c77791945ce9", [:mix], [], "hexpm", "29dbdfc92e04569c9d8e6efdc422fc1d815f4bd0055dc7c51b8800fb75c4b3f1"},
|
"sourceror": {:hex, :sourceror, "1.10.0", "38397dedbbc286966ec48c7af13e228b171332be1ad731974438c77791945ce9", [:mix], [], "hexpm", "29dbdfc92e04569c9d8e6efdc422fc1d815f4bd0055dc7c51b8800fb75c4b3f1"},
|
||||||
"spark": {:hex, :spark, "2.2.65", "4c10d109c108417ce394158f330be09ef184878bde45de6462397fbda68cec29", [:mix], [{:igniter, ">= 0.3.64 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: true]}, {:sourceror, "~> 1.2", [hex: :sourceror, repo: "hexpm", optional: true]}], "hexpm", "d66d5070a77f4c69cb4f007e941ac17d5d751ce71190fcd6e6e5fb42ba86f101"},
|
"spark": {:hex, :spark, "2.2.65", "4c10d109c108417ce394158f330be09ef184878bde45de6462397fbda68cec29", [:mix], [{:igniter, ">= 0.3.64 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: true]}, {:sourceror, "~> 1.2", [hex: :sourceror, repo: "hexpm", optional: true]}], "hexpm", "d66d5070a77f4c69cb4f007e941ac17d5d751ce71190fcd6e6e5fb42ba86f101"},
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
defmodule Mv.Repo.Migrations.AddAccountsDomainExtensions do
|
||||||
|
@moduledoc """
|
||||||
|
Installs any extensions that are mentioned in the repo's `installed_extensions/0` callback
|
||||||
|
|
||||||
|
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||||
|
"""
|
||||||
|
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
execute("CREATE EXTENSION IF NOT EXISTS \"citext\"")
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
# Uncomment this if you actually want to uninstall the extensions
|
||||||
|
# when this migration is rolled back:
|
||||||
|
# execute("DROP EXTENSION IF EXISTS \"citext\"")
|
||||||
|
end
|
||||||
|
end
|
||||||
58
priv/repo/migrations/20250620110850_add_accounts_domain.exs
Normal file
58
priv/repo/migrations/20250620110850_add_accounts_domain.exs
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
defmodule Mv.Repo.Migrations.AddAccountsDomain do
|
||||||
|
@moduledoc """
|
||||||
|
Updates resources based on their most recent snapshots.
|
||||||
|
|
||||||
|
This file was autogenerated with `mix ash_postgres.generate_migrations`
|
||||||
|
"""
|
||||||
|
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
create table(:users, primary_key: false) do
|
||||||
|
add :id, :uuid, null: false, default: fragment("gen_random_uuid()"), primary_key: true
|
||||||
|
add :email, :citext, null: false
|
||||||
|
add :hashed_password, :text
|
||||||
|
add :oidc_id, :text
|
||||||
|
|
||||||
|
add :member_id,
|
||||||
|
references(:members,
|
||||||
|
column: :id,
|
||||||
|
name: "users_member_id_fkey",
|
||||||
|
type: :uuid,
|
||||||
|
prefix: "public"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
create unique_index(:users, [:email], name: "users_unique_email_index")
|
||||||
|
|
||||||
|
create unique_index(:users, [:oidc_id], name: "users_unique_oidc_id_index")
|
||||||
|
|
||||||
|
create table(:tokens, primary_key: false) do
|
||||||
|
add :updated_at, :utc_datetime_usec,
|
||||||
|
null: false,
|
||||||
|
default: fragment("(now() AT TIME ZONE 'utc')")
|
||||||
|
|
||||||
|
add :created_at, :utc_datetime_usec,
|
||||||
|
null: false,
|
||||||
|
default: fragment("(now() AT TIME ZONE 'utc')")
|
||||||
|
|
||||||
|
add :extra_data, :map
|
||||||
|
add :purpose, :text, null: false
|
||||||
|
add :expires_at, :utc_datetime, null: false
|
||||||
|
add :subject, :text, null: false
|
||||||
|
add :jti, :text, null: false, primary_key: true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
drop table(:tokens)
|
||||||
|
|
||||||
|
drop_if_exists unique_index(:users, [:oidc_id], name: "users_unique_oidc_id_index")
|
||||||
|
|
||||||
|
drop_if_exists unique_index(:users, [:email], name: "users_unique_email_index")
|
||||||
|
|
||||||
|
drop constraint(:users, "users_member_id_fkey")
|
||||||
|
|
||||||
|
drop table(:users)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"ash_functions_version": 5,
|
"ash_functions_version": 5,
|
||||||
"installed": [
|
"installed": [
|
||||||
"ash-functions"
|
"ash-functions",
|
||||||
|
"citext"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
103
priv/resource_snapshots/repo/tokens/20250620110850.json
Normal file
103
priv/resource_snapshots/repo/tokens/20250620110850.json
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
{
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "updated_at",
|
||||||
|
"type": "utc_datetime_usec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "fragment(\"(now() AT TIME ZONE 'utc')\")",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "created_at",
|
||||||
|
"type": "utc_datetime_usec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "extra_data",
|
||||||
|
"type": "map"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "purpose",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "expires_at",
|
||||||
|
"type": "utc_datetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "subject",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": true,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "jti",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"base_filter": null,
|
||||||
|
"check_constraints": [],
|
||||||
|
"custom_indexes": [],
|
||||||
|
"custom_statements": [],
|
||||||
|
"has_create_action": true,
|
||||||
|
"hash": "EA1475C339B5BE2728560EFB2AF911275B2F65C2CE66CD1C093FAB5D9183BB11",
|
||||||
|
"identities": [],
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"repo": "Elixir.Mv.Repo",
|
||||||
|
"schema": null,
|
||||||
|
"table": "tokens"
|
||||||
|
}
|
||||||
127
priv/resource_snapshots/repo/users/20250620110850.json
Normal file
127
priv/resource_snapshots/repo/users/20250620110850.json
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
{
|
||||||
|
"attributes": [
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "fragment(\"gen_random_uuid()\")",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": true,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "id",
|
||||||
|
"type": "uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": false,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "email",
|
||||||
|
"type": "citext"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "hashed_password",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": null,
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "oidc_id",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_nil?": true,
|
||||||
|
"default": "nil",
|
||||||
|
"generated?": false,
|
||||||
|
"precision": null,
|
||||||
|
"primary_key?": false,
|
||||||
|
"references": {
|
||||||
|
"deferrable": false,
|
||||||
|
"destination_attribute": "id",
|
||||||
|
"destination_attribute_default": null,
|
||||||
|
"destination_attribute_generated": null,
|
||||||
|
"index?": false,
|
||||||
|
"match_type": null,
|
||||||
|
"match_with": null,
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"name": "users_member_id_fkey",
|
||||||
|
"on_delete": null,
|
||||||
|
"on_update": null,
|
||||||
|
"primary_key?": true,
|
||||||
|
"schema": "public",
|
||||||
|
"table": "members"
|
||||||
|
},
|
||||||
|
"scale": null,
|
||||||
|
"size": null,
|
||||||
|
"source": "member_id",
|
||||||
|
"type": "uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"base_filter": null,
|
||||||
|
"check_constraints": [],
|
||||||
|
"custom_indexes": [],
|
||||||
|
"custom_statements": [],
|
||||||
|
"has_create_action": true,
|
||||||
|
"hash": "03EBA1A8BCE47C4706E2D718E00364465E08C9A3999988D49FC1B89DEC5D717C",
|
||||||
|
"identities": [
|
||||||
|
{
|
||||||
|
"all_tenants?": false,
|
||||||
|
"base_filter": null,
|
||||||
|
"index_name": "users_unique_email_index",
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"type": "atom",
|
||||||
|
"value": "email"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "unique_email",
|
||||||
|
"nils_distinct?": true,
|
||||||
|
"where": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"all_tenants?": false,
|
||||||
|
"base_filter": null,
|
||||||
|
"index_name": "users_unique_oidc_id_index",
|
||||||
|
"keys": [
|
||||||
|
{
|
||||||
|
"type": "atom",
|
||||||
|
"value": "oidc_id"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "unique_oidc_id",
|
||||||
|
"nils_distinct?": true,
|
||||||
|
"where": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"multitenancy": {
|
||||||
|
"attribute": null,
|
||||||
|
"global": null,
|
||||||
|
"strategy": null
|
||||||
|
},
|
||||||
|
"repo": "Elixir.Mv.Repo",
|
||||||
|
"schema": null,
|
||||||
|
"table": "users"
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue