Modifying the argument clashes with AshCloak changing the argument's type

Hello! I have a resource Platform with an attribute called credentials I want to have encrypted. This attribute is a union of embedded resources (representing credentials for different platforms). I have a change that sets the type attribute on the credentials union changeset to the same value as the platform.type is set - to avoid having to pass the same value twice and ensure the credentials type matches the platform type. After adding the AshCloak encryption, it replaces my argument :credentials, :map with its own argument typed as a union.This causes my change to fail, because: 1. AshCloak's argument expects a properly-typed union value 2. My change can't set the type before Ash attempts to cast the argument 3. Without the type field, Ash considers the argument invalid when casting to the union How can I either apply my change before AshCloak's union casting, or configure AshCloak to somehow work with my existing argument definition? I was thinking of renaming my argument to credentials_input an setting the value of AshCloaks credentials argument inside the change - but I feel this duplicates the logic and the action now accepts two arguments for credentials which might be confusing.
defmodule Intranet.Synchronizer.Platform do
cloak do
...
attributes [:credentials]
end

actions do
...
create :create do
accept [:name, :type]
argument :credentials, :map
end

update :update do
# similar to above
end
end

changes do
...
change {Intranet.Synchronizer.Changes.SetCredentialsType, []}
end

attributes do
uuid_primary_key :id

attribute :type, Intranet.Synchronizer.Types.PlatformType do
allow_nil? false
public? true
end

attribute :credentials, Intranet.Synchronizer.Types.PlatformCredentials do
allow_nil? false
public? true
end

timestamps(public?: true)
end
end
defmodule Intranet.Synchronizer.Platform do
cloak do
...
attributes [:credentials]
end

actions do
...
create :create do
accept [:name, :type]
argument :credentials, :map
end

update :update do
# similar to above
end
end

changes do
...
change {Intranet.Synchronizer.Changes.SetCredentialsType, []}
end

attributes do
uuid_primary_key :id

attribute :type, Intranet.Synchronizer.Types.PlatformType do
allow_nil? false
public? true
end

attribute :credentials, Intranet.Synchronizer.Types.PlatformCredentials do
allow_nil? false
public? true
end

timestamps(public?: true)
end
end
6 Replies
ZachDaniel
ZachDaniel2mo ago
You should be able to make your change not accept the input in question and set the input manually and encrypt it manually
burekogorek
burekogorekOP2mo ago
Thanks for taking the time to answer a newbie, Zach! I have to admit, though, I'm not sure I understand - AshCloak adds credentials argument (and, in fact, any attribute that's supposed to be encrypted) to all of the resources create, update and destroy actions - even if that argument was not there to begin with. Thus, I don't see a way to "not accept the input in question" in my action. There's a high chance I'm missing something simple, as this is my first attempt at using Ash after reading the book, so thank you for your patience! I think what I'm looking for is a way to somehow avoid AshCloak overriding the arguments specified on the action. I'm thinking if maybe AshCloak could skip adding its own argument definition if there's already one?
ZachDaniel
ZachDaniel2mo ago
Ash cloak should only add arguments to actions where the action "accepts" the input So it should be in your accept list If you remove it, you can add your own argument and handle it
burekogorek
burekogorekOP2mo ago
I don't think this is currently the case - for this setup:
cloak do
vault Intranet.Vault
attributes [:credentials]

decrypt_by_default :credentials
end

actions do
defaults [:read, :destroy]

create :create do
accept [:name, :type]
end
end
cloak do
vault Intranet.Vault
attributes [:credentials]

decrypt_by_default :credentials
end

actions do
defaults [:read, :destroy]

create :create do
accept [:name, :type]
end
end
this is what I see in IEx
iex(1)> h Intranet.Synchronizer.create_platform

def create_platform(params \\ nil, opts \\ nil)

Calls the create action on Intranet.Synchronizer.Platform.

# Inputs

• name
• type
• credentials
iex(1)> h Intranet.Synchronizer.create_platform

def create_platform(params \\ nil, opts \\ nil)

Calls the create action on Intranet.Synchronizer.Platform.

# Inputs

• name
• type
• credentials
As you can see the attribute is added to the list of inputs even though it's not in the accept list Removing the credentials from the list of encrypted attributes results in it being removed from the list of inputs as well. If this is not an intended behavior I'm happy to fill a bug report in AshCloak repo (and possibly try my hand at fixing it of course!) I've found a specific commit which modified said behavior - https://github.com/ash-project/ash_cloak/commit/4018ed30796cf096bc1b3af859e92bb970484c9c and here is a PR discussion on this change, for context https://github.com/ash-project/ash_cloak/pull/45
ZachDaniel
ZachDaniel2mo ago
Ah damn That's wrong Can you open an issue?
burekogorek
burekogorekOP2mo ago
Of course, will get to it tomorrow

Did you find this page helpful?