Compare commits
14 commits
536b8e6ead
...
9bbb142869
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bbb142869 | ||
| 25f8362d68 | |||
| d7ced0d9e5 | |||
| bdc250f2d6 | |||
| fba9abc2c1 | |||
| c7b13c0ecb | |||
| cc51763a6e | |||
| b796746a45 | |||
| 0ff41f7c93 | |||
| 565aaddd94 | |||
| 7bfde5e230 | |||
| a6fcaa1640 | |||
| 192ceaed45 | |||
| f154eea055 |
40 changed files with 1319 additions and 450 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,19 @@ 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"
|
||||||
|
|
||||||
|
# AshAuthentication development configuration
|
||||||
|
config :mv, :session_identifier, :jti
|
||||||
|
|
||||||
|
config :mv, :require_token_presence_for_authentication, true
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,13 @@ 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"
|
||||||
|
|
||||||
|
# AshAuthentication production configuration
|
||||||
|
config :mv, :session_identifier, :jti
|
||||||
|
|
||||||
|
config :mv, :require_token_presence_for_authentication, true
|
||||||
|
|
||||||
config :mv, MvWeb.Endpoint,
|
config :mv, MvWeb.Endpoint,
|
||||||
url: [host: host, port: 443, scheme: "https"],
|
url: [host: host, port: 443, scheme: "https"],
|
||||||
http: [
|
http: [
|
||||||
|
|
|
||||||
|
|
@ -36,3 +36,12 @@ config :phoenix, :plug_init_mode, :runtime
|
||||||
# Enable helpful, but potentially expensive runtime checks
|
# Enable helpful, but potentially expensive runtime checks
|
||||||
config :phoenix_live_view,
|
config :phoenix_live_view,
|
||||||
enable_expensive_runtime_checks: true
|
enable_expensive_runtime_checks: true
|
||||||
|
|
||||||
|
# Token signing secret for AshAuthentication tests
|
||||||
|
config :mv, :token_signing_secret, "test_secret_key_for_ash_authentication_tokens"
|
||||||
|
|
||||||
|
# AshAuthentication test-specific configuration
|
||||||
|
# In Tests we don't need token presence, but in other envs its recommended
|
||||||
|
config :mv, :session_identifier, :unsafe
|
||||||
|
|
||||||
|
config :mv, :require_token_presence_for_authentication, false
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
|
version: "3.5"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
local:
|
||||||
|
rauthy-dev:
|
||||||
|
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-dev
|
||||||
|
|
||||||
|
|
||||||
|
rauthy:
|
||||||
|
container_name: rauthy-dev
|
||||||
|
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-dev
|
||||||
|
- 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
|
||||||
126
lib/accounts/user.ex
Normal file
126
lib/accounts/user.ex
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
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
|
||||||
|
session_identifier Application.get_env(:mv, :session_identifier)
|
||||||
|
|
||||||
|
tokens do
|
||||||
|
enabled? true
|
||||||
|
token_resource Mv.Accounts.Token
|
||||||
|
|
||||||
|
require_token_presence_for_authentication? Application.get_env(
|
||||||
|
:mv,
|
||||||
|
:require_token_presence_for_authentication
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
||||||
46
lib/mv/secrets.ex
Normal file
46
lib/mv/secrets.ex
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
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
|
||||||
59
lib/mv_web/controllers/auth_controller.ex
Normal file
59
lib/mv_web/controllers/auth_controller.ex
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
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} -> gettext("Your email address has now been confirmed")
|
||||||
|
{:password, :reset} -> gettext("Your password has successfully been reset")
|
||||||
|
_ -> gettext("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{}]
|
||||||
|
}
|
||||||
|
}} -> gettext(
|
||||||
|
"""
|
||||||
|
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.
|
||||||
|
""")
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
gettext("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, gettext("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,36 +12,92 @@ 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
|
||||||
plug :set_locale
|
plug :set_locale
|
||||||
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
|
||||||
|
|
||||||
post "/set_locale", LocaleController, :set_locale
|
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
|
||||||
|
|
||||||
|
post "/set_locale", LocaleController, :set_locale
|
||||||
|
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],
|
||||||
|
gettext_backend: {MvWeb.Gettext, "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],
|
||||||
|
gettext_backend: {MvWeb.Gettext, "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],
|
||||||
|
gettext_backend: {MvWeb.Gettext, "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.
|
||||||
|
|
|
||||||
8
mix.exs
8
mix.exs
|
|
@ -35,11 +35,14 @@ defmodule Mv.MixProject do
|
||||||
[
|
[
|
||||||
{:tidewave, "~> 0.1", only: [:dev]},
|
{:tidewave, "~> 0.1", only: [:dev]},
|
||||||
{:sourceror, "~> 1.8", only: [:dev, :test]},
|
{:sourceror, "~> 1.8", only: [:dev, :test]},
|
||||||
{:live_debugger, "~> 0.2", only: [:dev]},
|
{:live_debugger, "~> 0.3", only: [:dev]},
|
||||||
{:ash_admin, "~> 0.13"},
|
{:ash_admin, "~> 0.13"},
|
||||||
{: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"},
|
||||||
|
|
@ -92,7 +95,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
|
||||||
|
|
|
||||||
48
mix.lock
48
mix.lock
|
|
@ -1,37 +1,45 @@
|
||||||
%{
|
%{
|
||||||
"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.25", "99f7139e98b745a64312ae80e2420589205b2fec1799f00fc58da771d2c63373", [: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", "d45844ea30062b796d4adcad75b8d91e21081ac0f1bb6627d1a2663ca5ecf258"},
|
||||||
"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.11", "00bf3228b09ed6137e49a68374262f1de2cd5e1ea43ac2a6e2666cce71b7032e", [: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", "ed9e8833affb80454ba04c51a70ad96da95bb9d24429cf4f9d7cd538306c6256"},
|
||||||
"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_authentication": {:hex, :ash_authentication, "4.9.5", "9a72fef7dc6912ef46bde34dc582eaa83c12e289c68b69456e8870857d122c85", [: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.6.8 and < 3.0.0-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", "80e83db132c9b97fac739805f634f650cf8a30a904d6bb055be82c42b0506d29"},
|
||||||
"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_authentication_phoenix": {:hex, :ash_authentication_phoenix, "2.10.2", "474b450ca85e4773d0eafd5c1c9dbcfdfc6e95f496aa049d3c20d4cb701829d9", [: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", "d122d97b5269d8f2acba749312ea9c6574c03b647cac9ff501cecaf7f0af7592"},
|
||||||
"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_phoenix": {:hex, :ash_phoenix, "2.3.9", "684645f02725ca71625fcade6a4cc7c3a881a150762cdc532d03a32bde5a366d", [: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", "462ed487e62aa7de14d587c3fed64c9a3971e4132a9d0121033754c444c1400e"},
|
||||||
|
"ash_postgres": {:hex, :ash_postgres, "2.6.9", "8312bbe1ec463036841f08861196595ea233eadc1cd4c8097a1701ff7b0e95ed", [: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.13", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.13", [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", "1eb0c258d7dbe594312b37697097745ebb396162f38cddde282e011c26eb834c"},
|
||||||
|
"ash_sql": {:hex, :ash_sql, "0.2.84", "1187555609f4773aacb5cccdca82a78c2b3f7390e78b400a8f03c91b2e7cd82f", [:mix], [{:ash, ">= 3.5.25 and < 4.0.0-0", [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", "5e6a4d3070e60a0653c572527276a8c034b9458e37b1aca8868b17fcf0a1d1c0"},
|
||||||
|
"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.2", "b088989532af3d1733d35a08933ec9a232a56d0f06a078739f05fe24965d91d2", [:mix], [], "hexpm", "bc5f4ba112bce88aa4692427a8b23aa5baddf7c810d5dc3e7696f398194f104e"},
|
||||||
|
"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.8.0", "64fd82cfa6d8e25ec6660cea73e92a4cbc6a18b31343910427b702838c4b33b2", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "008399dae5eee1bf5caa6e86d204dcb44242c82b1ed5e22c881f2c34da201b15"},
|
||||||
"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.13.2", "7d0c0863f3fc8d71d17fc3ad3b9424beae13f02712ad84191a826c7169484f01", [: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", "669d9291370513ff56e7b7e7081b7af3283d02e046cf3d403053c557894a0b3e"},
|
||||||
"ecto_commons": {:hex, :ecto_commons, "0.3.6", "7b1d9e59396cf8c8cbe5a26d50d03f9b6d0fe6c640210dd503622f276f1e59bb", [:mix], [{:burnex, "~> 3.0", [hex: :burnex, repo: "hexpm", optional: true]}, {:ecto, "~> 3.4", [hex: :ecto, repo: "hexpm", optional: false]}, {:ex_phone_number, "~> 0.2", [hex: :ex_phone_number, repo: "hexpm", optional: false]}, {:luhn, "~> 0.3.0", [hex: :luhn, repo: "hexpm", optional: false]}], "hexpm", "3f12981a1e398f206c5d2014e7b732b7ec91b110b9cb84875cb5b28fc75d7a0a"},
|
"ecto_commons": {:hex, :ecto_commons, "0.3.6", "7b1d9e59396cf8c8cbe5a26d50d03f9b6d0fe6c640210dd503622f276f1e59bb", [:mix], [{:burnex, "~> 3.0", [hex: :burnex, repo: "hexpm", optional: true]}, {:ecto, "~> 3.4", [hex: :ecto, repo: "hexpm", optional: false]}, {:ex_phone_number, "~> 0.2", [hex: :ex_phone_number, repo: "hexpm", optional: false]}, {:luhn, "~> 0.3.0", [hex: :luhn, repo: "hexpm", optional: false]}], "hexpm", "3f12981a1e398f206c5d2014e7b732b7ec91b110b9cb84875cb5b28fc75d7a0a"},
|
||||||
"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.13.2", "a07d2461d84107b3d037097c822ffdd36ed69d1cf7c0f70e12a3d1decf04e2e1", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.13.0", [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", "539274ab0ecf1a0078a6a72ef3465629e4d6018a3028095dc90f60a19c371717"},
|
||||||
|
"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"},
|
||||||
"ex_phone_number": {:hex, :ex_phone_number, "0.4.5", "2065cc48c3e9d1ed9821f50877c32f2f6898362cb990f44147ca217c5d1374ed", [:mix], [{:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: false]}], "hexpm", "67163f8706f8cbfef1b1f4b9230c461f19786d0d79fd0b22cbeeefc6f0b99d4a"},
|
"ex_phone_number": {:hex, :ex_phone_number, "0.4.5", "2065cc48c3e9d1ed9821f50877c32f2f6898362cb990f44147ca217c5d1374ed", [:mix], [{:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: false]}], "hexpm", "67163f8706f8cbfef1b1f4b9230c461f19786d0d79fd0b22cbeeefc6f0b99d4a"},
|
||||||
"expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"},
|
"expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"},
|
||||||
"file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"},
|
"file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"},
|
||||||
"finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"},
|
"finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"},
|
||||||
"floki": {:hex, :floki, "0.37.1", "d7aaee758c8a5b4a7495799a4260754fec5530d95b9c383c03b27359dea117cf", [:mix], [], "hexpm", "673d040cb594d31318d514590246b6dd587ed341d3b67e17c1c0eb8ce7ca6f04"},
|
"floki": {:hex, :floki, "0.38.0", "62b642386fa3f2f90713f6e231da0fa3256e41ef1089f83b6ceac7a3fd3abf33", [:mix], [], "hexpm", "a5943ee91e93fb2d635b612caf5508e36d37548e84928463ef9dd986f0d1abd9"},
|
||||||
"gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"},
|
"gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"},
|
||||||
"glob_ex": {:hex, :glob_ex, "0.1.11", "cb50d3f1ef53f6ca04d6252c7fde09fd7a1cf63387714fe96f340a1349e62c93", [:mix], [], "hexpm", "342729363056e3145e61766b416769984c329e4378f1d558b63e341020525de4"},
|
"glob_ex": {:hex, :glob_ex, "0.1.11", "cb50d3f1ef53f6ca04d6252c7fde09fd7a1cf63387714fe96f340a1349e62c93", [:mix], [], "hexpm", "342729363056e3145e61766b416769984c329e4378f1d558b63e341020525de4"},
|
||||||
"heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "0435d4ca364a608cc75e2f8683d374e55abbae26", [tag: "v2.2.0", sparse: "optimized", depth: 1]},
|
"heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "0435d4ca364a608cc75e2f8683d374e55abbae26", [tag: "v2.2.0", sparse: "optimized", depth: 1]},
|
||||||
"hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"},
|
"hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"},
|
||||||
"igniter": {:hex, :igniter, "0.6.7", "4e183afc59d89289e223c4282fd3e9bb39b82e28d0aa6d3369f70fbd3e21a243", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:owl, "~> 0.11", [hex: :owl, repo: "hexpm", optional: false]}, {:phx_new, "~> 1.7", [hex: :phx_new, repo: "hexpm", optional: true]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:rewrite, ">= 1.1.1 and < 2.0.0-0", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "43b0a584dc84fd1320772c87047355b604ed2bcdd25392b17f7da8bdd09b61ac"},
|
"igniter": {:hex, :igniter, "0.6.9", "99dd9ea7bcf2fe829617dac660069b3461183e4efbf303dd120fdef96923287d", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:owl, "~> 0.11", [hex: :owl, repo: "hexpm", optional: false]}, {:phx_new, "~> 1.7", [hex: :phx_new, repo: "hexpm", optional: true]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:rewrite, ">= 1.1.1 and < 2.0.0-0", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "5fe407e10bc9416f7cd6af90d0409c8226ff2acacb9a7e7b9a097a66c8b5caef"},
|
||||||
"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.3.0", "346837b808961d12eb4a6c12863dbb8d02b980720683d482f1ac8934821af404", [: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", "afd8c01346cb1dde8f9ff0185d3718182cd1a6c0262ce72f0f74ed0ad489b932"},
|
||||||
"luhn": {:hex, :luhn, "0.3.3", "5aa0c6a32c2db4b9db9f9b883ba8301c1ae169d57199b9e6cb1ba2707bc51d96", [:mix], [], "hexpm", "3e823a913a25aab51352c727f135278d22954874d5f0835be81ed4fec3daf78d"},
|
"luhn": {:hex, :luhn, "0.3.3", "5aa0c6a32c2db4b9db9f9b883ba8301c1ae169d57199b9e6cb1ba2707bc51d96", [:mix], [], "hexpm", "3e823a913a25aab51352c727f135278d22954874d5f0835be81ed4fec3daf78d"},
|
||||||
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
|
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
|
||||||
"mint": {:hex, :mint, "1.7.1", "113fdb2b2f3b59e47c7955971854641c61f378549d73e829e1768de90fc1abf1", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "fceba0a4d0f24301ddee3024ae116df1c3f4bb7a563a731f45fdfeb9d39a231b"},
|
"mint": {:hex, :mint, "1.7.1", "113fdb2b2f3b59e47c7955971854641c61f378549d73e829e1768de90fc1abf1", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "fceba0a4d0f24301ddee3024ae116df1c3f4bb7a563a731f45fdfeb9d39a231b"},
|
||||||
|
|
@ -40,35 +48,37 @@
|
||||||
"nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
|
"nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
|
||||||
"owl": {:hex, :owl, "0.12.2", "65906b525e5c3ef51bab6cba7687152be017aebe1da077bb719a5ee9f7e60762", [:mix], [{:ucwidth, "~> 0.2", [hex: :ucwidth, repo: "hexpm", optional: true]}], "hexpm", "6398efa9e1fea70a04d24231e10dcd66c1ac1aa2da418d20ef5357ec61de2880"},
|
"owl": {:hex, :owl, "0.12.2", "65906b525e5c3ef51bab6cba7687152be017aebe1da077bb719a5ee9f7e60762", [:mix], [{:ucwidth, "~> 0.2", [hex: :ucwidth, repo: "hexpm", optional: true]}], "hexpm", "6398efa9e1fea70a04d24231e10dcd66c1ac1aa2da418d20ef5357ec61de2880"},
|
||||||
"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.5", "c4ef322acd15a574a8b1a08eff0ee0a85e73096b53ce1403b6563709f15e1cea", [: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", "26ec3208eef407f31b748cadd044045c6fd485fbff168e35963d2f9dfff28d4b"},
|
||||||
"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"},
|
||||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
|
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
|
||||||
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
|
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
|
||||||
"phoenix_view": {:hex, :phoenix_view, "2.0.4", "b45c9d9cf15b3a1af5fb555c674b525391b6a1fe975f040fb4d913397b31abf4", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "4e992022ce14f31fe57335db27a28154afcc94e9983266835bb3040243eb620b"},
|
"phoenix_view": {:hex, :phoenix_view, "2.0.4", "b45c9d9cf15b3a1af5fb555c674b525391b6a1fe975f040fb4d913397b31abf4", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "4e992022ce14f31fe57335db27a28154afcc94e9983266835bb3040243eb620b"},
|
||||||
"plug": {:hex, :plug, "1.18.0", "d78df36c41f7e798f2edf1f33e1727eae438e9dd5d809a9997c463a108244042", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "819f9e176d51e44dc38132e132fe0accaf6767eab7f0303431e404da8476cfa2"},
|
"plug": {:hex, :plug, "1.18.1", "5067f26f7745b7e31bc3368bc1a2b818b9779faa959b49c934c17730efc911cf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "57a57db70df2b422b564437d2d33cf8d33cd16339c1edb190cd11b1a3a546cc2"},
|
||||||
"plug_crypto": {:hex, :plug_crypto, "2.1.1", "19bda8184399cb24afa10be734f84a16ea0a2bc65054e23a62bb10f06bc89491", [:mix], [], "hexpm", "6470bce6ffe41c8bd497612ffde1a7e4af67f36a15eea5f921af71cf3e11247c"},
|
"plug_crypto": {:hex, :plug_crypto, "2.1.1", "19bda8184399cb24afa10be734f84a16ea0a2bc65054e23a62bb10f06bc89491", [:mix], [], "hexpm", "6470bce6ffe41c8bd497612ffde1a7e4af67f36a15eea5f921af71cf3e11247c"},
|
||||||
"postgrex": {:hex, :postgrex, "0.20.0", "363ed03ab4757f6bc47942eff7720640795eb557e1935951c1626f0d303a3aed", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "d36ef8b36f323d29505314f704e21a1a038e2dc387c6409ee0cd24144e187c0f"},
|
"postgrex": {:hex, :postgrex, "0.20.0", "363ed03ab4757f6bc47942eff7720640795eb557e1935951c1626f0d303a3aed", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "d36ef8b36f323d29505314f704e21a1a038e2dc387c6409ee0cd24144e187c0f"},
|
||||||
"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.6", "d717f9add549b25a089a94c90197718d2d838e35d81dd776b1d81587d4cf2aaa", [: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", "74db98165e3644d86e0f723672d91ceca4339eaa935bcad7e78bf146a46d77b9"},
|
||||||
"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.14", "521b449fa0bf275e6d034c05f29bec21789a0d6cd6f7a1c326c7bee642bf6e07", [: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", "b7b15692071d556c73432c7797aa7e96b51d1a2db76f746b976edef95c930021"},
|
||||||
"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.67", "67626cb9f59ea4b1c5aa85d4afdd025e0740cbd49ed82665d0a40ff007d7fd4b", [: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", "c8575402e3afc66871362e821bece890536d16319cdb758c5fb2d1250182e46f"},
|
||||||
"spitfire": {:hex, :spitfire, "0.2.1", "29e154873f05444669c7453d3d931820822cbca5170e88f0f8faa1de74a79b47", [:mix], [], "hexpm", "6eeed75054a38341b2e1814d41bb0a250564092358de2669fdb57ff88141d91b"},
|
"spitfire": {:hex, :spitfire, "0.2.1", "29e154873f05444669c7453d3d931820822cbca5170e88f0f8faa1de74a79b47", [:mix], [], "hexpm", "6eeed75054a38341b2e1814d41bb0a250564092358de2669fdb57ff88141d91b"},
|
||||||
"splode": {:hex, :splode, "0.2.9", "3a2776e187c82f42f5226b33b1220ccbff74f4bcc523dd4039c804caaa3ffdc7", [:mix], [], "hexpm", "8002b00c6e24f8bd1bcced3fbaa5c33346048047bb7e13d2f3ad428babbd95c3"},
|
"splode": {:hex, :splode, "0.2.9", "3a2776e187c82f42f5226b33b1220ccbff74f4bcc523dd4039c804caaa3ffdc7", [:mix], [], "hexpm", "8002b00c6e24f8bd1bcced3fbaa5c33346048047bb7e13d2f3ad428babbd95c3"},
|
||||||
"stream_data": {:hex, :stream_data, "1.2.0", "58dd3f9e88afe27dc38bef26fce0c84a9e7a96772b2925c7b32cd2435697a52b", [:mix], [], "hexpm", "eb5c546ee3466920314643edf68943a5b14b32d1da9fe01698dc92b73f89a9ed"},
|
"stream_data": {:hex, :stream_data, "1.2.0", "58dd3f9e88afe27dc38bef26fce0c84a9e7a96772b2925c7b32cd2435697a52b", [:mix], [], "hexpm", "eb5c546ee3466920314643edf68943a5b14b32d1da9fe01698dc92b73f89a9ed"},
|
||||||
"swoosh": {:hex, :swoosh, "1.19.2", "b2325aa7cd2bcd63ba023fa07a73dfc4f80660a592d40912975a879966ed9b7b", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5.10 or ~> 0.6 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cab7ef7c2c94c68fe21d3da26f6b86db118fdf4e7024ccb5842a4972c1056837"},
|
|
||||||
"sweet_xml": {:hex, :sweet_xml, "0.7.5", "803a563113981aaac202a1dbd39771562d0ad31004ddbfc9b5090bdcd5605277", [:mix], [], "hexpm", "193b28a9b12891cae351d81a0cead165ffe67df1b73fe5866d10629f4faefb12"},
|
"sweet_xml": {:hex, :sweet_xml, "0.7.5", "803a563113981aaac202a1dbd39771562d0ad31004ddbfc9b5090bdcd5605277", [:mix], [], "hexpm", "193b28a9b12891cae351d81a0cead165ffe67df1b73fe5866d10629f4faefb12"},
|
||||||
|
"swoosh": {:hex, :swoosh, "1.19.3", "02ad4455939f502386e4e1443d4de94c514995fd0e51b3cafffd6bd270ffe81c", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5.10 or ~> 0.6 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "04a10f8496786b744b84130e3510eb53ca51e769c39511b65023bdf4136b732f"},
|
||||||
"tailwind": {:hex, :tailwind, "0.3.1", "a89d2835c580748c7a975ad7dd3f2ea5e63216dc16d44f9df492fbd12c094bed", [:mix], [], "hexpm", "98a45febdf4a87bc26682e1171acdedd6317d0919953c353fcd1b4f9f4b676a2"},
|
"tailwind": {:hex, :tailwind, "0.3.1", "a89d2835c580748c7a975ad7dd3f2ea5e63216dc16d44f9df492fbd12c094bed", [:mix], [], "hexpm", "98a45febdf4a87bc26682e1171acdedd6317d0919953c353fcd1b4f9f4b676a2"},
|
||||||
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
|
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
|
||||||
"telemetry_metrics": {:hex, :telemetry_metrics, "1.1.0", "5bd5f3b5637e0abea0426b947e3ce5dd304f8b3bc6617039e2b5a008adc02f8f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7b79e8ddfde70adb6db8a6623d1778ec66401f366e9a8f5dd0955c56bc8ce67"},
|
"telemetry_metrics": {:hex, :telemetry_metrics, "1.1.0", "5bd5f3b5637e0abea0426b947e3ce5dd304f8b3bc6617039e2b5a008adc02f8f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7b79e8ddfde70adb6db8a6623d1778ec66401f366e9a8f5dd0955c56bc8ce67"},
|
||||||
"telemetry_poller": {:hex, :telemetry_poller, "1.2.0", "ba82e333215aed9dd2096f93bd1d13ae89d249f82760fcada0850ba33bac154b", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7216e21a6c326eb9aa44328028c34e9fd348fb53667ca837be59d0aa2a0156e8"},
|
"telemetry_poller": {:hex, :telemetry_poller, "1.2.0", "ba82e333215aed9dd2096f93bd1d13ae89d249f82760fcada0850ba33bac154b", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7216e21a6c326eb9aa44328028c34e9fd348fb53667ca837be59d0aa2a0156e8"},
|
||||||
"text_diff": {:hex, :text_diff, "0.1.0", "1caf3175e11a53a9a139bc9339bd607c47b9e376b073d4571c031913317fecaa", [:mix], [], "hexpm", "d1ffaaecab338e49357b6daa82e435f877e0649041ace7755583a0ea3362dbd7"},
|
"text_diff": {:hex, :text_diff, "0.1.0", "1caf3175e11a53a9a139bc9339bd607c47b9e376b073d4571c031913317fecaa", [:mix], [], "hexpm", "d1ffaaecab338e49357b6daa82e435f877e0649041ace7755583a0ea3362dbd7"},
|
||||||
"thousand_island": {:hex, :thousand_island, "1.3.14", "ad45ebed2577b5437582bcc79c5eccd1e2a8c326abf6a3464ab6c06e2055a34a", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d0d24a929d31cdd1d7903a4fe7f2409afeedff092d277be604966cd6aa4307ef"},
|
"thousand_island": {:hex, :thousand_island, "1.3.14", "ad45ebed2577b5437582bcc79c5eccd1e2a8c326abf6a3464ab6c06e2055a34a", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d0d24a929d31cdd1d7903a4fe7f2409afeedff092d277be604966cd6aa4307ef"},
|
||||||
"tidewave": {:hex, :tidewave, "0.1.7", "a93c500a414cfd211c7058a2b4b22759fb8cde5d72c471a34f7046cd66a5a5e6", [:mix], [{:circular_buffer, "~> 0.4", [hex: :circular_buffer, repo: "hexpm", optional: false]}, {:igniter, ">= 0.5.47 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.17", [hex: :plug, repo: "hexpm", optional: false]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}], "hexpm", "2cfe9c0c3295132cc682b3cd1c859f801bf2e4d02816618d0659f4d765d26435"},
|
"tidewave": {:hex, :tidewave, "0.1.10", "8cb6d25d7788b67b72aa0918219bfce956d5d37f02c6ce27602d38f88054979f", [:mix], [{:circular_buffer, "~> 0.4", [hex: :circular_buffer, repo: "hexpm", optional: false]}, {:igniter, ">= 0.5.47 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.17", [hex: :plug, repo: "hexpm", optional: false]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}], "hexpm", "a2f589f56b06c66354930ba74f3411635526c60c352dd88f6123415aed000525"},
|
||||||
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
|
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
|
||||||
"websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"},
|
"websock_adapter": {:hex, :websock_adapter, "0.5.8", "3b97dc94e407e2d1fc666b2fb9acf6be81a1798a2602294aac000260a7c4a47d", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "315b9a1865552212b5f35140ad194e67ce31af45bcee443d4ecb96b5fd3f3782"},
|
||||||
"yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"},
|
"yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"},
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,9 @@ msgstr "Bist du sicher?"
|
||||||
msgid "Attempting to reconnect"
|
msgid "Attempting to reconnect"
|
||||||
msgstr "Verbindung wird wiederhergestellt"
|
msgstr "Verbindung wird wiederhergestellt"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:48
|
#: lib/mv_web/member_live/form_component.ex:50
|
||||||
#: lib/mv_web/member_live/index.ex:25
|
#: lib/mv_web/member_live/index.ex:25
|
||||||
#: lib/mv_web/member_live/show.ex:30
|
#: lib/mv_web/member_live/show.ex:32
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "City"
|
msgid "City"
|
||||||
msgstr "Stadt"
|
msgstr "Stadt"
|
||||||
|
|
@ -43,12 +43,12 @@ msgid "Edit"
|
||||||
msgstr "Bearbeiten"
|
msgstr "Bearbeiten"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/index.ex:76
|
#: lib/mv_web/member_live/index.ex:76
|
||||||
#: lib/mv_web/member_live/show.ex:91
|
#: lib/mv_web/member_live/show.ex:93
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Edit Member"
|
msgid "Edit Member"
|
||||||
msgstr "Mitglied bearbeiten"
|
msgstr "Mitglied bearbeiten"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:41
|
#: lib/mv_web/member_live/form_component.ex:43
|
||||||
#: lib/mv_web/member_live/index.ex:24
|
#: lib/mv_web/member_live/index.ex:24
|
||||||
#: lib/mv_web/member_live/show.ex:23
|
#: lib/mv_web/member_live/show.ex:23
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -60,7 +60,7 @@ msgstr "E-Mail"
|
||||||
msgid "Error!"
|
msgid "Error!"
|
||||||
msgstr "Fehler!"
|
msgstr "Fehler!"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:39
|
#: lib/mv_web/member_live/form_component.ex:41
|
||||||
#: lib/mv_web/member_live/index.ex:22
|
#: lib/mv_web/member_live/index.ex:22
|
||||||
#: lib/mv_web/member_live/show.ex:21
|
#: lib/mv_web/member_live/show.ex:21
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -72,14 +72,14 @@ msgstr "Vorname"
|
||||||
msgid "Hang in there while we get back on track"
|
msgid "Hang in there while we get back on track"
|
||||||
msgstr "Bitte warten, wir stellen die Verbindung wieder her."
|
msgstr "Bitte warten, wir stellen die Verbindung wieder her."
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:45
|
#: lib/mv_web/member_live/form_component.ex:47
|
||||||
#: lib/mv_web/member_live/index.ex:26
|
#: lib/mv_web/member_live/index.ex:26
|
||||||
#: lib/mv_web/member_live/show.ex:27
|
#: lib/mv_web/member_live/show.ex:29
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Join Date"
|
msgid "Join Date"
|
||||||
msgstr "Beitrittsdatum"
|
msgstr "Beitrittsdatum"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:40
|
#: lib/mv_web/member_live/form_component.ex:42
|
||||||
#: lib/mv_web/member_live/index.ex:23
|
#: lib/mv_web/member_live/index.ex:23
|
||||||
#: lib/mv_web/member_live/show.ex:22
|
#: lib/mv_web/member_live/show.ex:22
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -124,76 +124,76 @@ msgstr "Keine Internetverbindung gefunden"
|
||||||
msgid "close"
|
msgid "close"
|
||||||
msgstr "schließen"
|
msgstr "schließen"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:42
|
#: lib/mv_web/member_live/form_component.ex:44
|
||||||
#: lib/mv_web/member_live/show.ex:24
|
#: lib/mv_web/member_live/show.ex:24
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Birth Date"
|
msgid "Birth Date"
|
||||||
msgstr "Geburtsdatum"
|
msgstr "Geburtsdatum"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:53
|
#: lib/mv_web/member_live/form_component.ex:55
|
||||||
#: lib/mv_web/member_live/show.ex:36
|
#: lib/mv_web/member_live/show.ex:38
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Custom Properties"
|
msgid "Custom Properties"
|
||||||
msgstr "Eigene Eigenschaften"
|
msgstr "Eigene Eigenschaften"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:46
|
#: lib/mv_web/member_live/form_component.ex:48
|
||||||
#: lib/mv_web/member_live/show.ex:28
|
#: lib/mv_web/member_live/show.ex:30
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Exit Date"
|
msgid "Exit Date"
|
||||||
msgstr "Austrittsdatum"
|
msgstr "Austrittsdatum"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:50
|
#: lib/mv_web/member_live/form_component.ex:52
|
||||||
#: lib/mv_web/member_live/show.ex:32
|
#: lib/mv_web/member_live/show.ex:34
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "House Number"
|
msgid "House Number"
|
||||||
msgstr "Hausnummer"
|
msgstr "Hausnummer"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:47
|
#: lib/mv_web/member_live/form_component.ex:49
|
||||||
#: lib/mv_web/member_live/show.ex:29
|
#: lib/mv_web/member_live/show.ex:31
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Notes"
|
msgid "Notes"
|
||||||
msgstr "Notizen"
|
msgstr "Notizen"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:43
|
#: lib/mv_web/member_live/form_component.ex:45
|
||||||
#: lib/mv_web/member_live/show.ex:25
|
#: lib/mv_web/member_live/show.ex:25
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Paid"
|
msgid "Paid"
|
||||||
msgstr "Bezahlt"
|
msgstr "Bezahlt"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:44
|
#: lib/mv_web/member_live/form_component.ex:46
|
||||||
#: lib/mv_web/member_live/show.ex:26
|
#: lib/mv_web/member_live/show.ex:28
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Phone Number"
|
msgid "Phone Number"
|
||||||
msgstr "Telefonnummer"
|
msgstr "Telefonnummer"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:51
|
#: lib/mv_web/member_live/form_component.ex:53
|
||||||
#: lib/mv_web/member_live/show.ex:33
|
#: lib/mv_web/member_live/show.ex:35
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Postal Code"
|
msgid "Postal Code"
|
||||||
msgstr "Postleitzahl"
|
msgstr "Postleitzahl"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:73
|
#: lib/mv_web/member_live/form_component.ex:75
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Save Member"
|
msgid "Save Member"
|
||||||
msgstr "Mitglied speichern"
|
msgstr "Mitglied speichern"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:73
|
#: lib/mv_web/member_live/form_component.ex:75
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Saving..."
|
msgid "Saving..."
|
||||||
msgstr "Speichern..."
|
msgstr "Speichern..."
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:49
|
#: lib/mv_web/member_live/form_component.ex:51
|
||||||
#: lib/mv_web/member_live/show.ex:31
|
#: lib/mv_web/member_live/show.ex:33
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Street"
|
msgid "Street"
|
||||||
msgstr "Straße"
|
msgstr "Straße"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:29
|
#: lib/mv_web/member_live/form_component.ex:30
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Use this form to manage member records and their properties."
|
msgid "Use this form to manage member records and their properties."
|
||||||
msgstr "Dieses Formular dient zur Verwaltung von Mitgliedern und deren Eigenschaften."
|
msgstr "Dieses Formular dient zur Verwaltung von Mitgliedern und deren Eigenschaften."
|
||||||
|
|
||||||
#: lib/mv_web/member_live/show.ex:50
|
#: lib/mv_web/member_live/show.ex:52
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Back to members"
|
msgid "Back to members"
|
||||||
msgstr "Zurück zur Mitgliederliste"
|
msgstr "Zurück zur Mitgliederliste"
|
||||||
|
|
@ -208,12 +208,12 @@ msgstr "Mitglied bearbeiten"
|
||||||
msgid "Id"
|
msgid "Id"
|
||||||
msgstr "ID"
|
msgstr "ID"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/show.ex:25
|
#: lib/mv_web/member_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "Nein"
|
msgstr "Nein"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/show.ex:90
|
#: lib/mv_web/member_live/show.ex:92
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
msgid "Show Member"
|
msgid "Show Member"
|
||||||
msgstr "Mitglied anzeigen"
|
msgstr "Mitglied anzeigen"
|
||||||
|
|
@ -223,22 +223,52 @@ msgstr "Mitglied anzeigen"
|
||||||
msgid "This is a member record from your database."
|
msgid "This is a member record from your database."
|
||||||
msgstr "Dies ist ein Mitglied aus deiner Datenbank."
|
msgstr "Dies ist ein Mitglied aus deiner Datenbank."
|
||||||
|
|
||||||
#: lib/mv_web/member_live/show.ex:25
|
#: lib/mv_web/member_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr "Ja"
|
msgstr "Ja"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:107
|
#: lib/mv_web/member_live/form_component.ex:102
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Member %{action} successfully"
|
|
||||||
msgstr "Mitglied %{action} erfolgreich"
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:100
|
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "create"
|
msgid "create"
|
||||||
msgstr "erstellt"
|
msgstr "erstellt"
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:101
|
#: lib/mv_web/member_live/form_component.ex:103
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "update"
|
msgid "update"
|
||||||
msgstr "aktualisiert"
|
msgstr "aktualisiert"
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:43
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Incorrect email or password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:109
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Member %{action} successfully"
|
||||||
|
msgstr "Mitglied %{action} erfolgreich"
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:14
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "You are now signed in"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:56
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "You are now signed out"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:36
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "You have already signed in another way, but have not confirmed your account.\nYou can confirm your account using the link we sent to you, or by resetting your password.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:12
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Your email address has now been confirmed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:13
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Your password has successfully been reset"
|
||||||
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -110,24 +110,3 @@ msgstr ""
|
||||||
|
|
||||||
msgid "must be equal to %{number}"
|
msgid "must be equal to %{number}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "is not a valid email"
|
|
||||||
msgstr "ist keine gültige E-Mail-Adresse"
|
|
||||||
|
|
||||||
msgid "cannot be in the future"
|
|
||||||
msgstr "darf nicht in der Zukunft liegen"
|
|
||||||
|
|
||||||
msgid "must be present"
|
|
||||||
msgstr "muss ausgefüllt sein"
|
|
||||||
|
|
||||||
msgid "is not a valid phone number"
|
|
||||||
msgstr "ist keine gültige Telefonnummer"
|
|
||||||
|
|
||||||
msgid "length must be greater than or equal to 5"
|
|
||||||
msgstr "Die Länge muss mindestens 5 Zeichen betragen"
|
|
||||||
|
|
||||||
msgid "cannot be before join date"
|
|
||||||
msgstr "darf nicht vor dem Eintrittsdatum liegen"
|
|
||||||
|
|
||||||
msgid "must consist of 5 digits"
|
|
||||||
msgstr "muss aus 5 Ziffern bestehen"
|
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@ msgstr ""
|
||||||
msgid "Attempting to reconnect"
|
msgid "Attempting to reconnect"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:48
|
#: lib/mv_web/member_live/form_component.ex:50
|
||||||
#: lib/mv_web/member_live/index.ex:25
|
#: lib/mv_web/member_live/index.ex:25
|
||||||
#: lib/mv_web/member_live/show.ex:30
|
#: lib/mv_web/member_live/show.ex:32
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "City"
|
msgid "City"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -44,12 +44,12 @@ msgid "Edit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/index.ex:76
|
#: lib/mv_web/member_live/index.ex:76
|
||||||
#: lib/mv_web/member_live/show.ex:91
|
#: lib/mv_web/member_live/show.ex:93
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Edit Member"
|
msgid "Edit Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:41
|
#: lib/mv_web/member_live/form_component.ex:43
|
||||||
#: lib/mv_web/member_live/index.ex:24
|
#: lib/mv_web/member_live/index.ex:24
|
||||||
#: lib/mv_web/member_live/show.ex:23
|
#: lib/mv_web/member_live/show.ex:23
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -61,7 +61,7 @@ msgstr ""
|
||||||
msgid "Error!"
|
msgid "Error!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:39
|
#: lib/mv_web/member_live/form_component.ex:41
|
||||||
#: lib/mv_web/member_live/index.ex:22
|
#: lib/mv_web/member_live/index.ex:22
|
||||||
#: lib/mv_web/member_live/show.ex:21
|
#: lib/mv_web/member_live/show.ex:21
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -73,14 +73,14 @@ msgstr ""
|
||||||
msgid "Hang in there while we get back on track"
|
msgid "Hang in there while we get back on track"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:45
|
#: lib/mv_web/member_live/form_component.ex:47
|
||||||
#: lib/mv_web/member_live/index.ex:26
|
#: lib/mv_web/member_live/index.ex:26
|
||||||
#: lib/mv_web/member_live/show.ex:27
|
#: lib/mv_web/member_live/show.ex:29
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Join Date"
|
msgid "Join Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:40
|
#: lib/mv_web/member_live/form_component.ex:42
|
||||||
#: lib/mv_web/member_live/index.ex:23
|
#: lib/mv_web/member_live/index.ex:23
|
||||||
#: lib/mv_web/member_live/show.ex:22
|
#: lib/mv_web/member_live/show.ex:22
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -125,76 +125,76 @@ msgstr ""
|
||||||
msgid "close"
|
msgid "close"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:42
|
#: lib/mv_web/member_live/form_component.ex:44
|
||||||
#: lib/mv_web/member_live/show.ex:24
|
#: lib/mv_web/member_live/show.ex:24
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Birth Date"
|
msgid "Birth Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:53
|
#: lib/mv_web/member_live/form_component.ex:55
|
||||||
#: lib/mv_web/member_live/show.ex:36
|
#: lib/mv_web/member_live/show.ex:38
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Custom Properties"
|
msgid "Custom Properties"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:46
|
#: lib/mv_web/member_live/form_component.ex:48
|
||||||
#: lib/mv_web/member_live/show.ex:28
|
#: lib/mv_web/member_live/show.ex:30
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Exit Date"
|
msgid "Exit Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:50
|
#: lib/mv_web/member_live/form_component.ex:52
|
||||||
#: lib/mv_web/member_live/show.ex:32
|
#: lib/mv_web/member_live/show.ex:34
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "House Number"
|
msgid "House Number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:47
|
|
||||||
#: lib/mv_web/member_live/show.ex:29
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Notes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:43
|
|
||||||
#: lib/mv_web/member_live/show.ex:25
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Paid"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:44
|
|
||||||
#: lib/mv_web/member_live/show.ex:26
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Phone Number"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:51
|
|
||||||
#: lib/mv_web/member_live/show.ex:33
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Postal Code"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:73
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Save Member"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:73
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Saving..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:49
|
#: lib/mv_web/member_live/form_component.ex:49
|
||||||
#: lib/mv_web/member_live/show.ex:31
|
#: lib/mv_web/member_live/show.ex:31
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Notes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:45
|
||||||
|
#: lib/mv_web/member_live/show.ex:25
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Paid"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:46
|
||||||
|
#: lib/mv_web/member_live/show.ex:28
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Phone Number"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:53
|
||||||
|
#: lib/mv_web/member_live/show.ex:35
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Postal Code"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:75
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Save Member"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:75
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Saving..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:51
|
||||||
|
#: lib/mv_web/member_live/show.ex:33
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Street"
|
msgid "Street"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:29
|
#: lib/mv_web/member_live/form_component.ex:30
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Use this form to manage member records and their properties."
|
msgid "Use this form to manage member records and their properties."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/show.ex:50
|
#: lib/mv_web/member_live/show.ex:52
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Back to members"
|
msgid "Back to members"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -209,12 +209,12 @@ msgstr ""
|
||||||
msgid "Id"
|
msgid "Id"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/show.ex:25
|
#: lib/mv_web/member_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/show.ex:90
|
#: lib/mv_web/member_live/show.ex:92
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Show Member"
|
msgid "Show Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -224,22 +224,52 @@ msgstr ""
|
||||||
msgid "This is a member record from your database."
|
msgid "This is a member record from your database."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/show.ex:25
|
#: lib/mv_web/member_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:107
|
#: lib/mv_web/member_live/form_component.ex:102
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Mitglied %{action} erfolgreich"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:100
|
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "create"
|
msgid "create"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:101
|
#: lib/mv_web/member_live/form_component.ex:103
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "update"
|
msgid "update"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:43
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Incorrect email or password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:109
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Member %{action} successfully"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:14
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "You are now signed in"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:56
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "You are now signed out"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:36
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "You have already signed in another way, but have not confirmed your account.\nYou can confirm your account using the link we sent to you, or by resetting your password.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:12
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Your email address has now been confirmed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:13
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Your password has successfully been reset"
|
||||||
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@ msgstr ""
|
||||||
msgid "Attempting to reconnect"
|
msgid "Attempting to reconnect"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:48
|
#: lib/mv_web/member_live/form_component.ex:50
|
||||||
#: lib/mv_web/member_live/index.ex:25
|
#: lib/mv_web/member_live/index.ex:25
|
||||||
#: lib/mv_web/member_live/show.ex:30
|
#: lib/mv_web/member_live/show.ex:32
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "City"
|
msgid "City"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -44,12 +44,12 @@ msgid "Edit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/index.ex:76
|
#: lib/mv_web/member_live/index.ex:76
|
||||||
#: lib/mv_web/member_live/show.ex:91
|
#: lib/mv_web/member_live/show.ex:93
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Edit Member"
|
msgid "Edit Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:41
|
#: lib/mv_web/member_live/form_component.ex:43
|
||||||
#: lib/mv_web/member_live/index.ex:24
|
#: lib/mv_web/member_live/index.ex:24
|
||||||
#: lib/mv_web/member_live/show.ex:23
|
#: lib/mv_web/member_live/show.ex:23
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -61,7 +61,7 @@ msgstr ""
|
||||||
msgid "Error!"
|
msgid "Error!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:39
|
#: lib/mv_web/member_live/form_component.ex:41
|
||||||
#: lib/mv_web/member_live/index.ex:22
|
#: lib/mv_web/member_live/index.ex:22
|
||||||
#: lib/mv_web/member_live/show.ex:21
|
#: lib/mv_web/member_live/show.ex:21
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -73,14 +73,14 @@ msgstr ""
|
||||||
msgid "Hang in there while we get back on track"
|
msgid "Hang in there while we get back on track"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:45
|
#: lib/mv_web/member_live/form_component.ex:47
|
||||||
#: lib/mv_web/member_live/index.ex:26
|
#: lib/mv_web/member_live/index.ex:26
|
||||||
#: lib/mv_web/member_live/show.ex:27
|
#: lib/mv_web/member_live/show.ex:29
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Join Date"
|
msgid "Join Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:40
|
#: lib/mv_web/member_live/form_component.ex:42
|
||||||
#: lib/mv_web/member_live/index.ex:23
|
#: lib/mv_web/member_live/index.ex:23
|
||||||
#: lib/mv_web/member_live/show.ex:22
|
#: lib/mv_web/member_live/show.ex:22
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
@ -125,76 +125,76 @@ msgstr ""
|
||||||
msgid "close"
|
msgid "close"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:42
|
#: lib/mv_web/member_live/form_component.ex:44
|
||||||
#: lib/mv_web/member_live/show.ex:24
|
#: lib/mv_web/member_live/show.ex:24
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Birth Date"
|
msgid "Birth Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:53
|
#: lib/mv_web/member_live/form_component.ex:55
|
||||||
#: lib/mv_web/member_live/show.ex:36
|
#: lib/mv_web/member_live/show.ex:38
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Custom Properties"
|
msgid "Custom Properties"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:46
|
#: lib/mv_web/member_live/form_component.ex:48
|
||||||
#: lib/mv_web/member_live/show.ex:28
|
#: lib/mv_web/member_live/show.ex:30
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Exit Date"
|
msgid "Exit Date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:50
|
#: lib/mv_web/member_live/form_component.ex:52
|
||||||
#: lib/mv_web/member_live/show.ex:32
|
#: lib/mv_web/member_live/show.ex:34
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "House Number"
|
msgid "House Number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:47
|
|
||||||
#: lib/mv_web/member_live/show.ex:29
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Notes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:43
|
|
||||||
#: lib/mv_web/member_live/show.ex:25
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Paid"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:44
|
|
||||||
#: lib/mv_web/member_live/show.ex:26
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Phone Number"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:51
|
|
||||||
#: lib/mv_web/member_live/show.ex:33
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Postal Code"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:73
|
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
|
||||||
msgid "Save Member"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:73
|
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Saving..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:49
|
#: lib/mv_web/member_live/form_component.ex:49
|
||||||
#: lib/mv_web/member_live/show.ex:31
|
#: lib/mv_web/member_live/show.ex:31
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Notes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:45
|
||||||
|
#: lib/mv_web/member_live/show.ex:25
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Paid"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:46
|
||||||
|
#: lib/mv_web/member_live/show.ex:28
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Phone Number"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:53
|
||||||
|
#: lib/mv_web/member_live/show.ex:35
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Postal Code"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:75
|
||||||
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
|
msgid "Save Member"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:75
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Saving..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:51
|
||||||
|
#: lib/mv_web/member_live/show.ex:33
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Street"
|
msgid "Street"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:29
|
#: lib/mv_web/member_live/form_component.ex:30
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Use this form to manage member records and their properties."
|
msgid "Use this form to manage member records and their properties."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/show.ex:50
|
#: lib/mv_web/member_live/show.ex:52
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Back to members"
|
msgid "Back to members"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -209,12 +209,12 @@ msgstr ""
|
||||||
msgid "Id"
|
msgid "Id"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/show.ex:25
|
#: lib/mv_web/member_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/show.ex:90
|
#: lib/mv_web/member_live/show.ex:92
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
msgid "Show Member"
|
msgid "Show Member"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
@ -224,22 +224,52 @@ msgstr ""
|
||||||
msgid "This is a member record from your database."
|
msgid "This is a member record from your database."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/show.ex:25
|
#: lib/mv_web/member_live/show.ex:26
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:107
|
#: lib/mv_web/member_live/form_component.ex:102
|
||||||
#, elixir-autogen, elixir-format
|
|
||||||
msgid "Member %{action} successfully"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:100
|
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "create"
|
msgid "create"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/mv_web/member_live/form_component.ex:101
|
#: lib/mv_web/member_live/form_component.ex:103
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "update"
|
msgid "update"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:43
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Incorrect email or password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/member_live/form_component.ex:109
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Member %{action} successfully"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:14
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "You are now signed in"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:56
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "You are now signed out"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:36
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "You have already signed in another way, but have not confirmed your account.\nYou can confirm your account using the link we sent to you, or by resetting your password.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:12
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Your email address has now been confirmed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv_web/controllers/auth_controller.ex:13
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Your password has successfully been reset"
|
||||||
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -110,12 +110,3 @@ msgstr ""
|
||||||
|
|
||||||
msgid "must be equal to %{number}"
|
msgid "must be equal to %{number}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "length must be greater than or equal to 5"
|
|
||||||
msgstr "length must be greater than or equal to 5"
|
|
||||||
|
|
||||||
msgid "cannot be before join date"
|
|
||||||
msgstr "cannot be before join date"
|
|
||||||
|
|
||||||
msgid "must consist of 5 digits"
|
|
||||||
msgstr "must consist of 5 digits"
|
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
48
test/mv_web/controllers/auth_controller_test.exs
Normal file
48
test/mv_web/controllers/auth_controller_test.exs
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
defmodule MvWeb.AuthControllerTest do
|
||||||
|
use MvWeb.ConnCase, async: true
|
||||||
|
|
||||||
|
test "GET /sign-in shows sign in form", %{conn: conn} do
|
||||||
|
conn = get(conn, ~p"/sign-in")
|
||||||
|
assert html_response(conn, 200) =~ "Sign in"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "POST /sign-in with valid credentials redirects to home", %{conn: conn} do
|
||||||
|
# Create a test user first
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
|
conn = get(conn, ~p"/sign-in")
|
||||||
|
|
||||||
|
assert redirected_to(conn) == ~p"/"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "POST /sign-in with invalid credentials shows error", %{conn: conn} do
|
||||||
|
conn =
|
||||||
|
post(conn, ~p"/auth/sign_in", %{
|
||||||
|
"user" => %{
|
||||||
|
"email" => "wrong@example.com",
|
||||||
|
"password" => "wrongpassword"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
assert conn.status == 404
|
||||||
|
end
|
||||||
|
|
||||||
|
test "GET /sign-out redirects to home", %{conn: conn} do
|
||||||
|
# First sign in a user
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
|
|
||||||
|
# Then sign out
|
||||||
|
conn = get(conn, ~p"/sign-out")
|
||||||
|
assert redirected_to(conn) == ~p"/"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "unauthenticated user accessing protected route gets redirected to sign-in", %{conn: conn} do
|
||||||
|
conn = get(conn, ~p"/members")
|
||||||
|
assert redirected_to(conn) == ~p"/sign-in"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "authenticated user can access protected route", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
|
conn = get(conn, ~p"/members")
|
||||||
|
assert conn.status == 200
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -2,7 +2,9 @@ defmodule MvWeb.PageControllerTest do
|
||||||
use MvWeb.ConnCase
|
use MvWeb.ConnCase
|
||||||
|
|
||||||
test "GET /", %{conn: conn} do
|
test "GET /", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
|
|
||||||
conn = get(conn, ~p"/")
|
conn = get(conn, ~p"/")
|
||||||
assert html_response(conn, 200) =~ "Peace of mind from prototype to production"
|
assert html_response(conn, 200) =~ "Mitgliederverwaltung"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
import Phoenix.LiveViewTest
|
import Phoenix.LiveViewTest
|
||||||
|
|
||||||
test "shows translated title in German", %{conn: conn} do
|
test "shows translated title in German", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
conn = Plug.Test.init_test_session(conn, locale: "de")
|
conn = Plug.Test.init_test_session(conn, locale: "de")
|
||||||
{:ok, _view, html} = live(conn, "/members")
|
{:ok, _view, html} = live(conn, "/members")
|
||||||
# Expected German title
|
# Expected German title
|
||||||
|
|
@ -10,6 +11,7 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows translated title in English", %{conn: conn} do
|
test "shows translated title in English", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
Gettext.put_locale(MvWeb.Gettext, "en")
|
Gettext.put_locale(MvWeb.Gettext, "en")
|
||||||
{:ok, _view, html} = live(conn, "/members")
|
{:ok, _view, html} = live(conn, "/members")
|
||||||
# Expected English title
|
# Expected English title
|
||||||
|
|
@ -17,18 +19,21 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows translated button text in German", %{conn: conn} do
|
test "shows translated button text in German", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
conn = Plug.Test.init_test_session(conn, locale: "de")
|
conn = Plug.Test.init_test_session(conn, locale: "de")
|
||||||
{:ok, _view, html} = live(conn, "/members/new")
|
{:ok, _view, html} = live(conn, "/members/new")
|
||||||
assert html =~ "Speichern"
|
assert html =~ "Speichern"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows translated button text in English", %{conn: conn} do
|
test "shows translated button text in English", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
Gettext.put_locale(MvWeb.Gettext, "en")
|
Gettext.put_locale(MvWeb.Gettext, "en")
|
||||||
{:ok, _view, html} = live(conn, "/members/new")
|
{:ok, _view, html} = live(conn, "/members/new")
|
||||||
assert html =~ "Save"
|
assert html =~ "Save"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows translated flash message after creating a member in German", %{conn: conn} do
|
test "shows translated flash message after creating a member in German", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
conn = Plug.Test.init_test_session(conn, locale: "de")
|
conn = Plug.Test.init_test_session(conn, locale: "de")
|
||||||
{:ok, view, _html} = live(conn, "/members")
|
{:ok, view, _html} = live(conn, "/members")
|
||||||
view |> element("a", "Neues Mitglied") |> render_click()
|
view |> element("a", "Neues Mitglied") |> render_click()
|
||||||
|
|
@ -44,6 +49,7 @@ defmodule MvWeb.MemberLive.IndexTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows translated flash message after creating a member in English", %{conn: conn} do
|
test "shows translated flash message after creating a member in English", %{conn: conn} do
|
||||||
|
conn = conn_with_oidc_user(conn)
|
||||||
conn = Plug.Test.init_test_session(conn, locale: "en")
|
conn = Plug.Test.init_test_session(conn, locale: "en")
|
||||||
{:ok, view, _html} = live(conn, "/members")
|
{:ok, view, _html} = live(conn, "/members")
|
||||||
view |> element("a", "New Member") |> render_click()
|
view |> element("a", "New Member") |> render_click()
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,38 @@ defmodule MvWeb.ConnCase do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Creates a test user and returns the user struct.
|
||||||
|
"""
|
||||||
|
def create_test_user(attrs \\ %{}) do
|
||||||
|
email = "user@example.com"
|
||||||
|
password = "password"
|
||||||
|
{:ok, hashed_password} = AshAuthentication.BcryptProvider.hash(password)
|
||||||
|
|
||||||
|
Ash.Seed.seed!(Mv.Accounts.User, %{
|
||||||
|
email: email,
|
||||||
|
hashed_password: hashed_password
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Signs in a user via OIDC for testing by creating a session with the user's token.
|
||||||
|
"""
|
||||||
|
def sign_in_user_via_oidc(conn, user) do
|
||||||
|
# Mock OIDC sign-in by creating a token directly
|
||||||
|
conn
|
||||||
|
|> Phoenix.ConnTest.init_test_session(%{})
|
||||||
|
|> AshAuthentication.Plug.Helpers.store_in_session(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Signs in a user via OIDC and returns a connection with the user authenticated.
|
||||||
|
"""
|
||||||
|
def conn_with_oidc_user(conn, user_attrs \\ %{}) do
|
||||||
|
user = create_test_user(user_attrs)
|
||||||
|
sign_in_user_via_oidc(conn, user)
|
||||||
|
end
|
||||||
|
|
||||||
setup tags do
|
setup tags do
|
||||||
Mv.DataCase.setup_sandbox(tags)
|
Mv.DataCase.setup_sandbox(tags)
|
||||||
{:ok, conn: Phoenix.ConnTest.build_conn()}
|
{:ok, conn: Phoenix.ConnTest.build_conn()}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue