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
- ores.refdata — component group overview.
- ores.refdata.portfolio — the tree the rights are held on.
- Sandbox — why the rights exist.