mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
improvement: add dynamic allow list
improvement: uniqify list_references
This commit is contained in:
parent
5bf8c39975
commit
c98910add6
6 changed files with 35 additions and 5 deletions
|
@ -3,6 +3,7 @@
|
||||||
locals_without_parens = [
|
locals_without_parens = [
|
||||||
accept: 1,
|
accept: 1,
|
||||||
action: 1,
|
action: 1,
|
||||||
|
allow: 1,
|
||||||
allow_async?: 1,
|
allow_async?: 1,
|
||||||
allow_nil?: 1,
|
allow_nil?: 1,
|
||||||
allow_nil_input: 1,
|
allow_nil_input: 1,
|
||||||
|
|
|
@ -549,11 +549,25 @@ defmodule Ash.Api do
|
||||||
|> Enum.find(&(&1 == resource))
|
|> Enum.find(&(&1 == resource))
|
||||||
end
|
end
|
||||||
|> case do
|
|> case do
|
||||||
nil -> {:error, NoSuchResource.exception(resource: resource)}
|
nil ->
|
||||||
resource -> {:ok, resource}
|
if allowed?(allow(api), resource) do
|
||||||
|
{:ok, resource}
|
||||||
|
else
|
||||||
|
{:error, NoSuchResource.exception(resource: resource)}
|
||||||
|
end
|
||||||
|
|
||||||
|
resource ->
|
||||||
|
{:ok, resource}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec allowed?(mfa | nil, module()) :: boolean
|
||||||
|
defp allowed?({m, f, a}, resource) do
|
||||||
|
apply(m, f, List.wrap(a) ++ [resource])
|
||||||
|
end
|
||||||
|
|
||||||
|
defp allowed?(_, _), do: false
|
||||||
|
|
||||||
@spec resources(Ash.Api.t()) :: list(Ash.Resource.t())
|
@spec resources(Ash.Api.t()) :: list(Ash.Resource.t())
|
||||||
def resources(api) do
|
def resources(api) do
|
||||||
api
|
api
|
||||||
|
@ -577,7 +591,12 @@ defmodule Ash.Api do
|
||||||
Extension.get_opt(api, [:resources], :registry, nil, true)
|
Extension.get_opt(api, [:resources], :registry, nil, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec timeout(atom) :: :timeout | integer()
|
@spec allow(atom) :: mfa() | nil
|
||||||
|
def allow(api) do
|
||||||
|
Extension.get_opt(api, [:resources], :allow, nil, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec timeout(atom) :: nil | :infinity | integer()
|
||||||
def timeout(api) do
|
def timeout(api) do
|
||||||
Extension.get_opt(api, [:execution], :timeout, 30_000, true)
|
Extension.get_opt(api, [:execution], :timeout, 30_000, true)
|
||||||
end
|
end
|
||||||
|
|
|
@ -31,12 +31,16 @@ defmodule Ash.Api.Dsl do
|
||||||
"""
|
"""
|
||||||
],
|
],
|
||||||
schema: [
|
schema: [
|
||||||
|
allow: [
|
||||||
|
type: :mfa,
|
||||||
|
doc: """
|
||||||
|
Support a dynamic resource list by providing a callback that checks wether or not the resource should be allowed.
|
||||||
|
"""
|
||||||
|
],
|
||||||
allow_unregistered?: [
|
allow_unregistered?: [
|
||||||
type: :boolean,
|
type: :boolean,
|
||||||
default: false,
|
default: false,
|
||||||
doc: """
|
doc: """
|
||||||
This is still experimental, but will be supported if you run into any issues.
|
|
||||||
|
|
||||||
By default, an api will only work with resources that are explicitly included in the provided registry. In order to separate your
|
By default, an api will only work with resources that are explicitly included in the provided registry. In order to separate your
|
||||||
application into multiple domains, you may wish to "mix and match" your resources across contexts. Specifying this option allows you
|
application into multiple domains, you may wish to "mix and match" your resources across contexts. Specifying this option allows you
|
||||||
to refer to resources in different apis in your resources, and allows providing any resource to api actions (to facilitate that requirement).
|
to refer to resources in different apis in your resources, and allows providing any resource to api actions (to facilitate that requirement).
|
||||||
|
|
|
@ -54,6 +54,10 @@ defmodule Ash.EmbeddableType do
|
||||||
resources do
|
resources do
|
||||||
allow_unregistered? true
|
allow_unregistered? true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
execution do
|
||||||
|
timeout :infinity
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
|
|
|
@ -791,6 +791,7 @@ defmodule Ash.Filter do
|
||||||
else
|
else
|
||||||
Enum.map(refs, & &1.attribute)
|
Enum.map(refs, & &1.attribute)
|
||||||
end
|
end
|
||||||
|
|> Enum.uniq()
|
||||||
end
|
end
|
||||||
|
|
||||||
def put_at_path(value, []), do: value
|
def put_at_path(value, []), do: value
|
||||||
|
|
|
@ -129,6 +129,7 @@ defmodule Ash.Query.Aggregate do
|
||||||
|> Enum.map(fn {key, value} ->
|
|> Enum.map(fn {key, value} ->
|
||||||
{key, Enum.uniq_by(Enum.map(value, &elem(&1, 1)), & &1.name)}
|
{key, Enum.uniq_by(Enum.map(value, &elem(&1, 1)), & &1.name)}
|
||||||
end)
|
end)
|
||||||
|
|> Enum.uniq()
|
||||||
|> Enum.reduce({[], [], []}, fn {{aggregate_resource, relationship_path, ref_path},
|
|> Enum.reduce({[], [], []}, fn {{aggregate_resource, relationship_path, ref_path},
|
||||||
aggregates},
|
aggregates},
|
||||||
{auth_requests, value_requests, aggregates_in_query} ->
|
{auth_requests, value_requests, aggregates_in_query} ->
|
||||||
|
|
Loading…
Reference in a new issue