How to call actions on an embedded resource with code interface?

I've started working on my custom authentication in my app and the first step is to make a resource representing a logged in user. This resource is embedded cause I plan to only use it as an actor. I won't save it anywhere for now. So as usual, I made some actions and a code interface for them, but I can't call them from IEx. So how do I call them? And while we're at it, how do I call a generic action normally outside a code interface?
Solution:
```elixir code_interface do domain YOur.Domain define :create define :from_token...
Jump to solution
12 Replies
ZachDaniel
ZachDaniel3mo ago
So as usual, I made some actions and a code interface for them, but I can't call them from IEx.
Why can't you call them from iex?
Sienhopist
SienhopistOP3mo ago
The functions don't get generated.
ZachDaniel
ZachDaniel3mo ago
Ah, right add define_for YourDomain into the code interface block
Sienhopist
SienhopistOP3mo ago
This one is short enough that I can share it
defmodule MyApp.User do
@moduledoc """
Represents a logged in user.
"""

use Ash.Resource,
data_layer: :embedded

@admin_tenant_id Application.compile_env!(:my_app, [:auth, :admin_tenant_id])
@admin_role Application.compile_env!(:my_app, [:auth, :admin_role])

attributes do
attribute :tenant_id, :uuid, allow_nil?: false, public?: true
attribute :roles, {:array, :string}, allow_nil?: false, public?: true, default: []

attribute :token_issuer, :atom do
constraints one_of: [:company, :my_app]
allow_nil? false
public? true
default :my_app
end
end

calculations do
calculate :admin?,
:boolean,
fn resources, _ ->
Enum.map(resources, fn %{tenant_id: tenant_id, token_issuer: token_issuer, roles: roles} ->
token_issuer == :company and Plug.Crypto.secure_compare(tenant_id, @admin_tenant_id) and
@admin_role in roles
end)
end
end

actions do
defaults create: :*

action :from_token, :struct do
constraints instance_of: __MODULE__
allow_nil? false

description "Create a user struct from a JSON Web Token (JWT) string or a JSON Web Encryption (JWE) that contains a JWT."

argument :token, :string do
allow_nil? false
public? false
end

run fn a, b -> dbg() end
end
end

code_interface do
define :create
define :from_token
end
end
defmodule MyApp.User do
@moduledoc """
Represents a logged in user.
"""

use Ash.Resource,
data_layer: :embedded

@admin_tenant_id Application.compile_env!(:my_app, [:auth, :admin_tenant_id])
@admin_role Application.compile_env!(:my_app, [:auth, :admin_role])

attributes do
attribute :tenant_id, :uuid, allow_nil?: false, public?: true
attribute :roles, {:array, :string}, allow_nil?: false, public?: true, default: []

attribute :token_issuer, :atom do
constraints one_of: [:company, :my_app]
allow_nil? false
public? true
default :my_app
end
end

calculations do
calculate :admin?,
:boolean,
fn resources, _ ->
Enum.map(resources, fn %{tenant_id: tenant_id, token_issuer: token_issuer, roles: roles} ->
token_issuer == :company and Plug.Crypto.secure_compare(tenant_id, @admin_tenant_id) and
@admin_role in roles
end)
end
end

actions do
defaults create: :*

action :from_token, :struct do
constraints instance_of: __MODULE__
allow_nil? false

description "Create a user struct from a JSON Web Token (JWT) string or a JSON Web Encryption (JWE) that contains a JWT."

argument :token, :string do
allow_nil? false
public? false
end

run fn a, b -> dbg() end
end
end

code_interface do
define :create
define :from_token
end
end
ZachDaniel
ZachDaniel3mo ago
For embedded resources, we don't know what domain's rules to use when defining those functions, you have to use define_for for the functions to be defined
Sienhopist
SienhopistOP3mo ago
I can't put it in my domain cause it's embedded, but I'm not sure if that's related here
ZachDaniel
ZachDaniel3mo ago
code_interface do
define_for YOur.Domain
define :create
define :from_token
end
code_interface do
define_for YOur.Domain
define :create
define :from_token
end
Sienhopist
SienhopistOP3mo ago
But there is no function define_for
ZachDaniel
ZachDaniel3mo ago
Sorry, that may be the old name for it
Solution
ZachDaniel
ZachDaniel3mo ago
code_interface do
domain YOur.Domain
define :create
define :from_token
end
code_interface do
domain YOur.Domain
define :create
define :from_token
end
Sienhopist
SienhopistOP3mo ago
Ah that did it thanks

Did you find this page helpful?