ores.refdata.portfolio_right

Table of Contents

A portfolio right says that one account holds one named right at one node of the portfolio tree. A right held at a node applies to every node below it, so a right granted on a desk covers its sub-desks and not its sibling desks.

Two rights exist, the ones sandboxes need: read, to see what a node holds, and open_sandbox, to open a sandbox anchored at the node. ores_refdata_account_holds_portfolio_right_fn answers whether an account holds a right at a node, directly or through an ancestor. It runs with the caller's rights, so it answers only within the session's tenant, and a closed account holds no right. A right granted to an account stays on record after the account closes; the function stops honouring it.

1. Flags

2. Columns

2.1. id

UUID uniquely identifying this grant.

Surrogate key for the portfolio right record.

2.2. account_id

The account that holds the right.

References the IAM accounts table.

ctx.generate_uuid()

2.3. portfolio_id

The node the right is held at.

The right also applies to every node below it.

ctx.generate_uuid()

2.4. right_code

The right held.

read or open_sandbox.

std::string("read")

3. SQL

3.1. Flags

3.2. Checks

expression
"right_code" in ('read', 'open_sandbox')

4. Foreign keys

4.1. account_id

The seeded account is a service account. A user account would end the test tenant's bootstrap, after which every write that names a system user is refused, and the other tests in the binary share the database.

#include "ores.iam.api/generators/account_generator.hpp"
#include "ores.iam.core/repository/account_repository.hpp"
{
    auto account = ores::iam::generators::generate_synthetic_account(ctx);
    account.account_type = "service";
    account.change_reason_code = "system.test";
    ores::iam::repository::account_repository account_repo;
    account_repo.write(party_ctx, account);
    v.account_id = account.id;
}

4.2. portfolio_id

5. Insert trigger

-- Whether an account is live. Security definer and narrow: the services that
-- check rights may not read the accounts table, and this answers one yes or
-- no about one account id.
create or replace function ores_refdata_account_is_live_fn(
    p_account_id uuid
) returns boolean as $$
begin
    return exists (
        select 1 from ores_iam_accounts_tbl
        where id = p_account_id
          and valid_to = ores_utility_infinity_timestamp_fn()
    );
end;
$$ language plpgsql stable security definer set search_path = public, pg_temp;

-- Whether an account holds a right at a portfolio node, directly or through
-- an ancestor. The function runs with the caller's rights, so row-level
-- security confines it to the session's tenant whatever tenant is passed.
-- A closed account holds nothing. Portfolio inserts refuse cycles; the depth
-- bound only keeps a corrupt tree from looping.
create or replace function ores_refdata_account_holds_portfolio_right_fn(
    p_tenant_id uuid,
    p_account_id uuid,
    p_portfolio_id uuid,
    p_right_code text
) returns boolean as $$
begin
    return exists (
    with recursive ancestry as (
        select id, parent_portfolio_id, 0 as depth
        from ores_refdata_portfolios_tbl
        where tenant_id = p_tenant_id
          and id = p_portfolio_id
          and valid_to = ores_utility_infinity_timestamp_fn()
        union all
        select p.id, p.parent_portfolio_id, a.depth + 1
        from ores_refdata_portfolios_tbl p
        join ancestry a on p.id = a.parent_portfolio_id
        where p.tenant_id = p_tenant_id
          and p.valid_to = ores_utility_infinity_timestamp_fn()
          and a.depth < 64
    )
        select 1
        from ores_refdata_portfolio_rights_tbl r
        join ancestry a on r.portfolio_id = a.id
        where r.tenant_id = p_tenant_id
          and r.account_id = p_account_id
          and r.right_code = p_right_code
          and r.valid_to = ores_utility_infinity_timestamp_fn()
    ) and ores_refdata_account_is_live_fn(p_account_id);
end;
$$ language plpgsql stable set search_path = public, pg_temp;

6. C++

6.1. Flags

6.2. Repository

6.3. Domain includes

#include <string>
#include <boost/uuid/uuid.hpp>

6.4. Entity includes

#include <string>

6.5. Conventions

6.6. Table display

column header
account_id Account
portfolio_id Portfolio
right_code Right
modified_by Modified By
version Version

6.7. Presentation

6.7.1. Detail fields

field label widget type is_key is_required placeholder
right_code Right rightCodeEdit line_edit true true read or open_sandbox

6.7.2. Columns

enum_name field header type width
RightCode right_code Right string 120
Version version Version int 80
ModifiedBy modified_by Modified By string 120
RecordedAt recorded_at Recorded At timestamp 150

6.8. Paste blocks

6.8.1. Extra drop statements

drop function if exists ores_refdata_account_holds_portfolio_right_fn;
drop function if exists ores_refdata_account_is_live_fn;

7. See also

Emacs 29.3 (Org mode 9.6.15)