fix: allow overriding strategy defaults (#766)

This commit is contained in:
Zach Daniel 2024-08-18 18:16:28 -04:00 committed by GitHub
parent ef1b12258b
commit c4f570380f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 74 additions and 55 deletions

View file

@ -1,2 +1,2 @@
elixir 1.15.6
erlang 26.1
elixir 1.17.2-otp-27
erlang 27.0

View file

@ -65,9 +65,14 @@ The following defaults are applied:
| [`redirect_uri`](#authentication-strategies-auth0-redirect_uri){: #authentication-strategies-auth0-redirect_uri .spark-required} | `(any, any -> any) \| module \| String.t` | | The callback URI *base*. Not the whole URI back to the callback endpoint, but the URI to your `AuthPlug`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`base_url`](#authentication-strategies-auth0-base_url){: #authentication-strategies-auth0-base_url } | `(any, any -> any) \| module \| String.t` | | The base URL of the OAuth2 server - including the leading protocol (ie `https://`). Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`site`](#authentication-strategies-auth0-site){: #authentication-strategies-auth0-site } | `(any, any -> any) \| module \| String.t` | | Deprecated: Use `base_url` instead. |
| [`auth_method`](#authentication-strategies-auth0-auth_method){: #authentication-strategies-auth0-auth_method } | `nil \| :client_secret_basic \| :client_secret_post \| :client_secret_jwt \| :private_key_jwt` | `:client_secret_post` | The authentication strategy used, optional. If not set, no authentication will be used during the access token request. |
| [`client_secret`](#authentication-strategies-auth0-client_secret){: #authentication-strategies-auth0-client_secret } | `(any, any -> any) \| module \| String.t` | | The OAuth2 client secret. Required if :auth_method is `:client_secret_basic`, `:client_secret_post` or `:client_secret_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`authorize_url`](#authentication-strategies-auth0-authorize_url){: #authentication-strategies-auth0-authorize_url } | `(any, any -> any) \| module \| String.t` | `"/authorize"` | The API url to the OAuth2 authorize endpoint, relative to `site`, e.g `authorize_url fn _, _ -> {:ok, "https://exampe.com/authorize"} end`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`token_url`](#authentication-strategies-auth0-token_url){: #authentication-strategies-auth0-token_url } | `(any, any -> any) \| module \| String.t` | `"/oauth/token"` | The API url to access the token endpoint, relative to `site`, e.g `token_url fn _, _ -> {:ok, "https://example.com/oauth_token"} end`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`trusted_audiences`](#authentication-strategies-auth0-trusted_audiences){: #authentication-strategies-auth0-trusted_audiences } | `(any, any -> any) \| module \| list(any) \| nil` | | A list of audiences which are trusted. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`user_url`](#authentication-strategies-auth0-user_url){: #authentication-strategies-auth0-user_url } | `(any, any -> any) \| module \| String.t` | `"/userinfo"` | The API url to access the user endpoint, relative to `site`, e.g `user_url fn _, _ -> {:ok, "https://example.com/userinfo"} end`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`private_key`](#authentication-strategies-auth0-private_key){: #authentication-strategies-auth0-private_key } | `(any, any -> any) \| module \| String.t` | | The private key to use if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`authorization_params`](#authentication-strategies-auth0-authorization_params){: #authentication-strategies-auth0-authorization_params } | `keyword` | `[scope: "openid profile email"]` | Any additional parameters to encode in the request phase. eg: `authorization_params scope: "openid profile email"` |
| [`registration_enabled?`](#authentication-strategies-auth0-registration_enabled?){: #authentication-strategies-auth0-registration_enabled? } | `boolean` | `true` | If enabled, new users will be able to register for your site when authenticating and not already present. If not, only existing users will be able to authenticate. |
| [`register_action_name`](#authentication-strategies-auth0-register_action_name){: #authentication-strategies-auth0-register_action_name } | `atom` | | The name of the action to use to register a user, if `registration_enabled?` is `true`. Defaults to `register_with_<name>` See the "Registration and Sign-in" section of the strategy docs for more. |
| [`sign_in_action_name`](#authentication-strategies-auth0-sign_in_action_name){: #authentication-strategies-auth0-sign_in_action_name } | `atom` | | The name of the action to use to sign in an existing user, if `sign_in_enabled?` is `true`. Defaults to `sign_in_with_<strategy>`, which is generated for you by default. See the "Registration and Sign-in" section of the strategy docs for more information. |

View file

@ -64,10 +64,16 @@ The following defaults are applied:
|------|------|---------|------|
| [`client_id`](#authentication-strategies-github-client_id){: #authentication-strategies-github-client_id .spark-required} | `(any, any -> any) \| module \| String.t` | | The OAuth2 client ID. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`redirect_uri`](#authentication-strategies-github-redirect_uri){: #authentication-strategies-github-redirect_uri .spark-required} | `(any, any -> any) \| module \| String.t` | | The callback URI *base*. Not the whole URI back to the callback endpoint, but the URI to your `AuthPlug`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`base_url`](#authentication-strategies-github-base_url){: #authentication-strategies-github-base_url } | `(any, any -> any) \| module \| String.t` | `"https://api.github.com"` | The base URL of the OAuth2 server - including the leading protocol (ie `https://`). Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`site`](#authentication-strategies-github-site){: #authentication-strategies-github-site } | `(any, any -> any) \| module \| String.t` | | Deprecated: Use `base_url` instead. |
| [`auth_method`](#authentication-strategies-github-auth_method){: #authentication-strategies-github-auth_method } | `nil \| :client_secret_basic \| :client_secret_post \| :client_secret_jwt \| :private_key_jwt` | `:client_secret_post` | The authentication strategy used, optional. If not set, no authentication will be used during the access token request. |
| [`client_secret`](#authentication-strategies-github-client_secret){: #authentication-strategies-github-client_secret } | `(any, any -> any) \| module \| String.t` | | The OAuth2 client secret. Required if :auth_method is `:client_secret_basic`, `:client_secret_post` or `:client_secret_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`authorize_url`](#authentication-strategies-github-authorize_url){: #authentication-strategies-github-authorize_url } | `(any, any -> any) \| module \| String.t` | `"https://github.com/login/oauth/authorize"` | The API url to the OAuth2 authorize endpoint, relative to `site`, e.g `authorize_url fn _, _ -> {:ok, "https://exampe.com/authorize"} end`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`token_url`](#authentication-strategies-github-token_url){: #authentication-strategies-github-token_url } | `(any, any -> any) \| module \| String.t` | `"https://github.com/login/oauth/access_token"` | The API url to access the token endpoint, relative to `site`, e.g `token_url fn _, _ -> {:ok, "https://example.com/oauth_token"} end`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`trusted_audiences`](#authentication-strategies-github-trusted_audiences){: #authentication-strategies-github-trusted_audiences } | `(any, any -> any) \| module \| list(any) \| nil` | | A list of audiences which are trusted. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`user_url`](#authentication-strategies-github-user_url){: #authentication-strategies-github-user_url } | `(any, any -> any) \| module \| String.t` | `"/user"` | The API url to access the user endpoint, relative to `site`, e.g `user_url fn _, _ -> {:ok, "https://example.com/userinfo"} end`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`private_key`](#authentication-strategies-github-private_key){: #authentication-strategies-github-private_key } | `(any, any -> any) \| module \| String.t` | | The private key to use if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`authorization_params`](#authentication-strategies-github-authorization_params){: #authentication-strategies-github-authorization_params } | `keyword` | `[scope: "read:user,user:email"]` | Any additional parameters to encode in the request phase. eg: `authorization_params scope: "openid profile email"` |
| [`registration_enabled?`](#authentication-strategies-github-registration_enabled?){: #authentication-strategies-github-registration_enabled? } | `boolean` | `true` | If enabled, new users will be able to register for your site when authenticating and not already present. If not, only existing users will be able to authenticate. |
| [`register_action_name`](#authentication-strategies-github-register_action_name){: #authentication-strategies-github-register_action_name } | `atom` | | The name of the action to use to register a user, if `registration_enabled?` is `true`. Defaults to `register_with_<name>` See the "Registration and Sign-in" section of the strategy docs for more. |
| [`sign_in_action_name`](#authentication-strategies-github-sign_in_action_name){: #authentication-strategies-github-sign_in_action_name } | `atom` | | The name of the action to use to sign in an existing user, if `sign_in_enabled?` is `true`. Defaults to `sign_in_with_<strategy>`, which is generated for you by default. See the "Registration and Sign-in" section of the strategy docs for more information. |

View file

@ -66,10 +66,16 @@ The following defaults are applied:
|------|------|---------|------|
| [`client_id`](#authentication-strategies-google-client_id){: #authentication-strategies-google-client_id .spark-required} | `(any, any -> any) \| module \| String.t` | | The OAuth2 client ID. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`redirect_uri`](#authentication-strategies-google-redirect_uri){: #authentication-strategies-google-redirect_uri .spark-required} | `(any, any -> any) \| module \| String.t` | | The callback URI *base*. Not the whole URI back to the callback endpoint, but the URI to your `AuthPlug`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`base_url`](#authentication-strategies-google-base_url){: #authentication-strategies-google-base_url } | `(any, any -> any) \| module \| String.t` | `"https://www.googleapis.com"` | The base URL of the OAuth2 server - including the leading protocol (ie `https://`). Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`site`](#authentication-strategies-google-site){: #authentication-strategies-google-site } | `(any, any -> any) \| module \| String.t` | | Deprecated: Use `base_url` instead. |
| [`auth_method`](#authentication-strategies-google-auth_method){: #authentication-strategies-google-auth_method } | `nil \| :client_secret_basic \| :client_secret_post \| :client_secret_jwt \| :private_key_jwt` | `:client_secret_post` | The authentication strategy used, optional. If not set, no authentication will be used during the access token request. |
| [`client_secret`](#authentication-strategies-google-client_secret){: #authentication-strategies-google-client_secret } | `(any, any -> any) \| module \| String.t` | | The OAuth2 client secret. Required if :auth_method is `:client_secret_basic`, `:client_secret_post` or `:client_secret_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`authorize_url`](#authentication-strategies-google-authorize_url){: #authentication-strategies-google-authorize_url } | `(any, any -> any) \| module \| String.t` | `"https://accounts.google.com/o/oauth2/v2/auth"` | The API url to the OAuth2 authorize endpoint, relative to `site`, e.g `authorize_url fn _, _ -> {:ok, "https://exampe.com/authorize"} end`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`token_url`](#authentication-strategies-google-token_url){: #authentication-strategies-google-token_url } | `(any, any -> any) \| module \| String.t` | `"/oauth2/v4/token"` | The API url to access the token endpoint, relative to `site`, e.g `token_url fn _, _ -> {:ok, "https://example.com/oauth_token"} end`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`trusted_audiences`](#authentication-strategies-google-trusted_audiences){: #authentication-strategies-google-trusted_audiences } | `(any, any -> any) \| module \| list(any) \| nil` | | A list of audiences which are trusted. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`user_url`](#authentication-strategies-google-user_url){: #authentication-strategies-google-user_url } | `(any, any -> any) \| module \| String.t` | `"/oauth2/v3/userinfo"` | The API url to access the user endpoint, relative to `site`, e.g `user_url fn _, _ -> {:ok, "https://example.com/userinfo"} end`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`private_key`](#authentication-strategies-google-private_key){: #authentication-strategies-google-private_key } | `(any, any -> any) \| module \| String.t` | | The private key to use if `:auth_method` is `:private_key_jwt`. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. |
| [`authorization_params`](#authentication-strategies-google-authorization_params){: #authentication-strategies-google-authorization_params } | `keyword` | `[scope: "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"]` | Any additional parameters to encode in the request phase. eg: `authorization_params scope: "openid profile email"` |
| [`registration_enabled?`](#authentication-strategies-google-registration_enabled?){: #authentication-strategies-google-registration_enabled? } | `boolean` | `true` | If enabled, new users will be able to register for your site when authenticating and not already present. If not, only existing users will be able to authenticate. |
| [`register_action_name`](#authentication-strategies-google-register_action_name){: #authentication-strategies-google-register_action_name } | `atom` | | The name of the action to use to register a user, if `registration_enabled?` is `true`. Defaults to `register_with_<name>` See the "Registration and Sign-in" section of the strategy docs for more. |
| [`sign_in_action_name`](#authentication-strategies-google-sign_in_action_name){: #authentication-strategies-google-sign_in_action_name } | `atom` | | The name of the action to use to sign in an existing user, if `sign_in_enabled?` is `true`. Defaults to `sign_in_with_<strategy>`, which is generated for you by default. See the "Registration and Sign-in" section of the strategy docs for more information. |

View file

@ -189,19 +189,8 @@ defmodule AshAuthentication.AddOn.Confirmation.Transformer do
with {:ok, resource} <- persisted_option(dsl_state, :module),
{:ok, attribute} <- find_attribute(dsl_state, strategy.confirmed_at_field),
:ok <- validate_attribute_option(attribute, resource, :writable?, [true]),
:ok <- validate_attribute_option(attribute, resource, :allow_nil?, [true]),
:ok <- validate_attribute_option(attribute, resource, :type, [Type.UtcDatetimeUsec]) do
:ok
else
:error ->
{:error,
DslError.exception(
path: [:confirmation],
message: "The `confirmed_at_field` option must be set."
)}
{:error, reason} ->
{:error, reason}
:ok <- validate_attribute_option(attribute, resource, :allow_nil?, [true]) do
validate_attribute_option(attribute, resource, :type, [Type.UtcDatetimeUsec])
end
end

View file

@ -2,6 +2,7 @@ defmodule AshAuthentication.Strategy.Auth0.Dsl do
@moduledoc false
alias AshAuthentication.Strategy.{Custom, OAuth2}
alias Assent.Strategy.Auth0
@doc false
@spec dsl :: Custom.entity()
@ -22,17 +23,11 @@ defmodule AshAuthentication.Strategy.Auth0.Dsl do
#### Strategy defaults:
#{strategy_override_docs(Assent.Strategy.Auth0)}
#{strategy_override_docs(Auth0)}
""",
auto_set_fields: strategy_fields(Assent.Strategy.Auth0, icon: :auth0)
auto_set_fields: [assent_strategy: Auth0, icon: :auth0]
})
end
defp strategy_fields(strategy, params) do
[]
|> strategy.default_config()
|> Keyword.put(:assent_strategy, strategy)
|> Keyword.merge(params)
|> Custom.set_defaults(Auth0.default_config([]))
end
defp strategy_override_docs(strategy) do

View file

@ -109,4 +109,41 @@ defmodule AshAuthentication.Strategy.Custom do
dsl_patches: [%Dsl.Patch.AddEntity{section_path: path, entity: entity}]
end
end
@doc """
Sets default values for a DSL schema based on a set of defaults.
If a given default is in the schema, it can be overriden, so we just set the default
and mark it not required.
If not, then we add it to `auto_set_fields`, and the user cannot override it.
"""
def set_defaults(dsl, defaults) do
Enum.reduce(defaults, dsl, fn {key, value}, dsl ->
if dsl.schema[key] do
set_default(dsl, key, value)
else
Map.update!(dsl, :auto_set_fields, &Keyword.put(&1, key, value))
end
end)
end
defp set_default(dsl, key, value) do
Map.update!(dsl, :schema, fn schema ->
Keyword.update(
schema,
key,
[
type: :any,
default: value,
hide: true
],
fn config ->
config
|> Keyword.put(:default, value)
|> Keyword.delete(:required)
end
)
end)
end
end

View file

@ -2,6 +2,7 @@ defmodule AshAuthentication.Strategy.Github.Dsl do
@moduledoc false
alias AshAuthentication.Strategy.{Custom, OAuth2}
alias Assent.Strategy.Github
@doc false
@spec dsl :: Custom.entity()
@ -22,17 +23,11 @@ defmodule AshAuthentication.Strategy.Github.Dsl do
#### Strategy defaults:
#{strategy_override_docs(Assent.Strategy.Github)}
#{strategy_override_docs(Github)}
""",
auto_set_fields: strategy_fields(Assent.Strategy.Github, icon: :github)
auto_set_fields: [icon: :github, assent_strategy: Github]
})
end
defp strategy_fields(strategy, params) do
[]
|> strategy.default_config()
|> Keyword.put(:assent_strategy, strategy)
|> Keyword.merge(params)
|> Custom.set_defaults(Github.default_config([]))
end
defp strategy_override_docs(strategy) do

View file

@ -2,6 +2,7 @@ defmodule AshAuthentication.Strategy.Google.Dsl do
@moduledoc false
alias AshAuthentication.Strategy.{Custom, OAuth2}
alias Assent.Strategy.Google
@doc false
@spec dsl :: Custom.entity()
@ -23,17 +24,11 @@ defmodule AshAuthentication.Strategy.Google.Dsl do
#### Strategy defaults:
#{strategy_override_docs(Assent.Strategy.Google)}
#{strategy_override_docs(Google)}
""",
auto_set_fields: strategy_fields(Assent.Strategy.Google, icon: :google)
auto_set_fields: [icon: :google, assent_strategy: Google]
})
end
defp strategy_fields(strategy, params) do
[]
|> strategy.default_config()
|> Keyword.put(:assent_strategy, strategy)
|> Keyword.merge(params)
|> Custom.set_defaults(Google.default_config([]))
end
defp strategy_override_docs(strategy) do

View file

@ -31,11 +31,9 @@ defmodule AshAuthentication.Strategy.OAuth2.IdentityChange do
changeset
|> Changeset.after_action(fn changeset, user ->
with {:ok, user_id_attribute_name} <-
strategy.identity_resource
|> UserIdentity.Info.user_identity_user_id_attribute_name(),
UserIdentity.Info.user_identity_user_id_attribute_name(strategy.identity_resource),
{:ok, _identity} <-
strategy.identity_resource
|> UserIdentity.Actions.upsert(%{
UserIdentity.Actions.upsert(strategy.identity_resource, %{
user_info: Changeset.get_argument(changeset, :user_info),
oauth_tokens: Changeset.get_argument(changeset, :oauth_tokens),
strategy: Strategy.name(strategy),
@ -44,7 +42,6 @@ defmodule AshAuthentication.Strategy.OAuth2.IdentityChange do
user
|> Ash.load(strategy.identity_relationship_name, domain: Info.domain!(strategy.resource))
else
:error -> :error
{:error, reason} -> {:error, reason}
end
end)

View file

@ -96,9 +96,6 @@ defmodule AshAuthentication.Strategy.OAuth2.Transformer do
:ok <- maybe_validate_action_has_identity_change(action, strategy) do
:ok
else
:error ->
{:error, "Unable to validate register action"}
{:error, reason} when is_binary(reason) ->
{:error, "`#{inspect(strategy.register_action_name)}` action: #{reason}"}
@ -139,7 +136,6 @@ defmodule AshAuthentication.Strategy.OAuth2.Transformer do
:ok <- validate_action_has_preparation(action, OAuth2.SignInPreparation) do
:ok
else
:error -> {:error, "Unable to validate sign in action"}
{:error, reason} -> {:error, reason}
end
end

View file

@ -124,9 +124,6 @@ defmodule AshAuthentication.Verifier do
{:ok, falsy} when is_falsy(falsy) ->
:ok
{:error, reason} ->
{:error, reason}
{false, bad_token_resource} ->
{:error,
DslError.exception(

View file

@ -1,5 +1,5 @@
%{
"absinthe": {:hex, :absinthe, "1.7.6", "0b897365f98d068cfcb4533c0200a8e58825a4aeeae6ec33633ebed6de11773b", [:mix], [{:dataloader, "~> 1.0.0 or ~> 2.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:opentelemetry_process_propagator, "~> 0.2.1", [hex: :opentelemetry_process_propagator, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7626951ca5eec627da960615b51009f3a774765406ff02722b1d818f17e5778"},
"absinthe": {:hex, :absinthe, "1.7.8", "43443d12ad2b4fcce60e257ac71caf3081f3d5c4ddd5eac63a02628bcaf5b556", [:mix], [{:dataloader, "~> 1.0.0 or ~> 2.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:opentelemetry_process_propagator, "~> 0.2.1 or ~> 0.3", [hex: :opentelemetry_process_propagator, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c4085df201892a498384f997649aedb37a4ce8a726c170d5b5617ed3bf45d40b"},
"absinthe_plug": {:hex, :absinthe_plug, "1.5.8", "38d230641ba9dca8f72f1fed2dfc8abd53b3907d1996363da32434ab6ee5d6ab", [:mix], [{:absinthe, "~> 1.5", [hex: :absinthe, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bbb04176647b735828861e7b2705465e53e2cf54ccf5a73ddd1ebd855f996e5a"},
"ash": {:hex, :ash, "3.3.2", "e5bb78f4fde87e3b445675e0d1691c81aecc3f5835bac625b6cc72ab8da13061", [:mix], [{:comparable, "~> 1.0", [hex: :comparable, repo: "hexpm", optional: false]}, {: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.3.11 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: false]}, {: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.9", [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.8 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [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", "dd264da49cf737318506f8b6b3c3b1aeb925e5ad6ec8ca27786b341ef9566446"},
"ash_graphql": {:hex, :ash_graphql, "1.2.0", "b4b7a754ef722cff1c84cf35291e2ff0402fc91d805e2a01405157087f908a9b", [:mix], [{:absinthe, "~> 1.7", [hex: :absinthe, repo: "hexpm", optional: false]}, {:absinthe_plug, "~> 1.4", [hex: :absinthe_plug, repo: "hexpm", optional: false]}, {:ash, "~> 3.0", [hex: :ash, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "d16986527788f74b2fe8085827d81bad08f1574d8562bc52619c00d43e75aa52"},

View file

@ -231,6 +231,7 @@ defmodule Example.User do
client_id &get_config/2
redirect_uri &get_config/2
client_secret &get_config/2
authorization_params scope: "openid profile email"
end
only_marty do