Updating an action visibility using Ash 3.15 does not compile

actions do
  # The public?: true MUST be an option to the read macro
  read :get_tenant, public?: true do
    get? true
    primary? true
    
    argument :id, :uuid, allow_nil?: false
    filter expr(id == ^arg(:id))
  end
  
  # ... other actions
end

get_teant wont compile. Any help will be appreciated

In general you’d need to provide more information than this (like what the error message you’re getting is). However, what you’re asking for is not supported. There is no public?: true option on actions. It hasn’t been added: Allow marking actions as internal to prevent exposing them via APIs · Issue #1271 · ash-project/ash · GitHub

Thanks Zack for your time.

below is the error == Compilation error in file lib/eloni/accounts/tenant.ex ==
** (CompileError) lib/eloni/accounts/tenant.ex: cannot compile module Eloni.Accounts.Tenant (errors have been logged)
(ash 3.15.0) expanding macro: Ash.Resource.Dsl.actions/1

and heres my tenant resource:

defmodule Eloni.Accounts.Tenant do

use Ash.Resource,

otp_app: :eloni,

domain: Eloni.Accounts,

data_layer: AshPostgres.DataLayer,

authorizers: [Ash.Policy.Authorizer]

postgres do

table “tenants”

repo Eloni.Repo

end

attributes do

uuid_primary_key :id, default: &Ash.UUID.generate/0

attribute :name, :string, allow_nil?: false

attribute :national_identity, :string, allow_nil?: false

attribute :nationality, :string, allow_nil?: false, default: “Nigerian”

attribute :tenant_type, :atom do

allow_nil? false

constraints one_of: [:seller, :wholesale_market, :cluster_manager]

default :seller

end

attribute :currency_code, :atom do

allow_nil? false

default :NGN

end

attribute :slug, :string, allow_nil?: false

timestamps()

end

relationships do

belongs_to :owner, Eloni.Accounts.User

belongs_to :lga, Eloni.Locations.Lga

has_one :tenant_profile, Eloni.Accounts.TenantProfile

has_many :memberships, Eloni.Accounts.UserTenant

many_to_many :users, Eloni.Accounts.User do

through Eloni.Accounts.UserTenant

source_attribute_on_join_resource :tenant_id

destination_attribute_on_join_resource :user_id

end

# Sellers can belong to a Cluster

belongs_to :parent_cluster, Eloni.Accounts.Tenant do

domain Eloni.Accounts

attribute_type :uuid

end

# Cluster Managers can have many Sellers

has_many :managed_sellers, Eloni.Accounts.Tenant do

destination_attribute :parent_cluster_id

end

end

identities do

identity :unique_tenant, [:name, :national_identity]

end

actions do

defaults [:read, :destroy, update: :*]

# Internal primary read (no arguments, no filters)

read :read do

primary? true

end

# Your public interface action

read :get_tenant, public?: true do

get? true

argument :id, :uuid, allow_nil?: false

filter expr(id == ^arg(:id))

end

create :register do

accept [:name, :national_identity, :nationality, :tenant_type, :slug]

argument :owner_id, :uuid, allow_nil?: false

# This triggers the ‘UserTenant’ primary create action

change manage_relationship(:owner_id, :users, type: :append)

end

update :invite_user do

argument :user_id, :uuid, allow_nil?: false

# manage_relationship handles the creation of the UserTenant row

change manage_relationship(:user_id, :users, type: :append)

end

update :add_user do

# Accept a map like %{user_id: “…”, role: “admin”}

argument :user_data, :map

require_atomic? false

# join_keys tells Ash which fields to set on the join table

change manage_relationship(:user_data, :users,

type: :append,

join_keys: [:role, :joined_at]

  )

end

update :add_seller do

# Accepts the UUID of the seller tenant to be managed

argument :seller_id, :uuid, allow_nil?: false

# Logic: Find the seller by ID and set its parent_cluster_id to THIS cluster

change manage_relationship(:seller_id, :managed_sellers, type: :append, on_lookup: :relate)

end

end

policies do

# 1. ALLOW the Plug/Cache to fetch basic tenant info (No actor required)

# Lock this to ONLY the :get_tenant action for security

policy action(:get_tenant) do

authorize_if always()

end

# 2. REQUIRE membership for other general reads

policy action_type(:read) do

authorize_if relates_to_actor_via(:users)

end

# 3. Super Admin bypass

bypass actor_attribute_equals(:system_role, :super_admin), do: authorize_if always()

end

end

i want an interface to get_tenant by other operations in my project. heres my domain if that helps

defmodule Eloni.Accounts do

use Ash.Domain,

otp_app: :eloni

resources do

resource Eloni.Accounts.User

resource Eloni.Accounts.Token

resource Eloni.Accounts.Tenant do

# # This creates the Eloni.Accounts.get_tenant!(id, opts) function

define :get_tenant, action: :get_tenant, args: [:id]

end

resource Eloni.Accounts.TenantProfile

resource Eloni.Accounts.UserTenant

end

end

Thanks once more

It’s right there. Also please format your stuff with tripple backticks. ```

Thanks but cant figure it still.

i came by this option, because i need to extract tenant currency….heres my plug

defmodule EloniWeb.SetAshTenantContext do

@moduledoc “”"

Sets the Ash actor, tenant, and custom currency context for the request.

“”"

import Plug.Conn

def init(opts), do: opts

def call(conn, _opts) do

user = conn.assigns[:current_user]

tenant_id = get_session(conn, :current_tenant_id) || conn.assigns[:current_tenant_id]

# 1. Set the Actor (Essential for Policies)

if user, do: Ash.PlugHelpers.set_actor(conn, user)

# 2. Set the Tenant (Essential for Data Isolation)

if tenant_id do

Ash.PlugHelpers.set_tenant(conn, tenant_id)

# 3. Set Custom Context for your Currency Calculations

# This allows your ‘ConvertCurrency’ calculation to access the tenant’s default

currency = Eloni.Cache.get_tenant_currency(tenant_id) || :NGN

Ash.PlugHelpers.set_context(conn, %{tenant_currency: currency})

end

conn

end

end

Maybe my design is the challenge.

i want to add the tenant currency to the tenant context. the tenant must be in that context for it to work.

I think basic elixir understanding is your challenge. You need to know elixir at a basic level before you can dive into ash.

Check out exercism for elixir exercises.

Really? Thanks for your time. Will lookup exercism