tba-durability-authorization-policy 0.4.0.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tba_durability_authorization_policy-0.4.0.dev2/PKG-INFO +25 -0
- tba_durability_authorization_policy-0.4.0.dev2/README.md +3 -0
- tba_durability_authorization_policy-0.4.0.dev2/pyproject.toml +23 -0
- tba_durability_authorization_policy-0.4.0.dev2/src/tba_durability_authorization_policy/__init__.py +12 -0
- tba_durability_authorization_policy-0.4.0.dev2/src/tba_durability_authorization_policy/inventory.py +22 -0
- tba_durability_authorization_policy-0.4.0.dev2/src/tba_durability_authorization_policy/legacy.py +45 -0
- tba_durability_authorization_policy-0.4.0.dev2/src/tba_durability_authorization_policy/operations/__init__.py +1 -0
- tba_durability_authorization_policy-0.4.0.dev2/src/tba_durability_authorization_policy/operations/authorization.py +231 -0
- tba_durability_authorization_policy-0.4.0.dev2/src/tba_durability_authorization_policy/py.typed +1 -0
- tba_durability_authorization_policy-0.4.0.dev2/src/tba_durability_authorization_policy/specifications/__init__.py +1 -0
- tba_durability_authorization_policy-0.4.0.dev2/src/tba_durability_authorization_policy/specifications/authorization.py +172 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tba-durability-authorization-policy
|
|
3
|
+
Version: 0.4.0.dev2
|
|
4
|
+
Summary: Carrier-neutral layer-30 durable table operations.
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
Requires-Python: >=3.10,<3.15
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
13
|
+
Requires-Dist: tba-bases-replay (==0.4.0.dev2)
|
|
14
|
+
Requires-Dist: tba-contracts-authorization (==0.4.0.dev3)
|
|
15
|
+
Requires-Dist: tba-contracts-identity (==0.4.0.dev2)
|
|
16
|
+
Requires-Dist: tba-contracts-security-trust (==0.1.0)
|
|
17
|
+
Requires-Dist: tba-primitives-identity (==0.4.0.dev2)
|
|
18
|
+
Requires-Dist: tba-storage-authorization-policy (==0.4.0.dev2)
|
|
19
|
+
Requires-Dist: tigrbl (==0.4.5.dev8)
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# tba-durability-authorization-policy
|
|
23
|
+
|
|
24
|
+
Carrier-neutral layer-30 durable operations and derived table specifications.
|
|
25
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "tba-durability-authorization-policy"
|
|
3
|
+
version = "0.4.0.dev2"
|
|
4
|
+
description = "Carrier-neutral layer-30 durable table operations."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10,<3.15"
|
|
7
|
+
license = "Apache-2.0"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"tba-contracts-authorization==0.4.0.dev3",
|
|
10
|
+
"tigrbl==0.4.5.dev8",
|
|
11
|
+
"tba-primitives-identity==0.4.0.dev2",
|
|
12
|
+
"tba-contracts-identity==0.4.0.dev2",
|
|
13
|
+
"tba-bases-replay==0.4.0.dev2",
|
|
14
|
+
"tba-contracts-security-trust==0.1.0",
|
|
15
|
+
"tba-storage-authorization-policy==0.4.0.dev2",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[build-system]
|
|
19
|
+
requires = ["poetry-core>=1.0.0"]
|
|
20
|
+
build-backend = "poetry.core.masonry.api"
|
|
21
|
+
|
|
22
|
+
[tool.poetry]
|
|
23
|
+
packages = [{ include = "tba_durability_authorization_policy", from = "src" }]
|
tba_durability_authorization_policy-0.4.0.dev2/src/tba_durability_authorization_policy/__init__.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from .legacy import NormalizedAuthorization, NormalizedRoleGrant, normalize_legacy_authorization
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
from .operations import *
|
|
5
|
+
from .specifications import *
|
|
6
|
+
from .inventory import *
|
|
7
|
+
except ImportError:
|
|
8
|
+
# Normalization is dependency-free so schema migration tooling can run before
|
|
9
|
+
# the optional Tigrbl storage runtime is installed.
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
__all__ = [name for name in globals() if not name.startswith("_")]
|
tba_durability_authorization_policy-0.4.0.dev2/src/tba_durability_authorization_policy/inventory.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Immutable inventory of this durable family's table specifications."""
|
|
2
|
+
|
|
3
|
+
from . import specifications as _specifications
|
|
4
|
+
|
|
5
|
+
RUNTIME_TABLE_SPECS = tuple(
|
|
6
|
+
value
|
|
7
|
+
for name, value in vars(_specifications).items()
|
|
8
|
+
if name.endswith("RuntimeSpec") and getattr(value, "model", None) is not None
|
|
9
|
+
)
|
|
10
|
+
RUNTIME_TABLES = tuple(spec.model for spec in RUNTIME_TABLE_SPECS)
|
|
11
|
+
RUNTIME_OPERATION_BY_ALIAS = {
|
|
12
|
+
operation.alias: operation
|
|
13
|
+
for spec in RUNTIME_TABLE_SPECS
|
|
14
|
+
for operation in spec.ops
|
|
15
|
+
if operation.extra.get("owner_layer") == "30-storage-runtime"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"RUNTIME_OPERATION_BY_ALIAS",
|
|
20
|
+
"RUNTIME_TABLE_SPECS",
|
|
21
|
+
"RUNTIME_TABLES",
|
|
22
|
+
]
|
tba_durability_authorization_policy-0.4.0.dev2/src/tba_durability_authorization_policy/legacy.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Fail-closed normalization for the legacy role JSON representation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Iterable, Mapping
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True, slots=True)
|
|
10
|
+
class NormalizedRoleGrant:
|
|
11
|
+
grant_id: str
|
|
12
|
+
tenant_id: str
|
|
13
|
+
principal_id: str
|
|
14
|
+
role_id: str
|
|
15
|
+
resource_type: str
|
|
16
|
+
resource_id: str
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True, slots=True)
|
|
20
|
+
class NormalizedAuthorization:
|
|
21
|
+
role_permissions: tuple[tuple[str, str, str], ...]
|
|
22
|
+
role_grants: tuple[NormalizedRoleGrant, ...]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def normalize_legacy_authorization(*, roles: Iterable[Mapping[str, object]], memberships: Iterable[Mapping[str, object]]) -> NormalizedAuthorization:
|
|
26
|
+
by_key: dict[tuple[str, str], Mapping[str, object]] = {}
|
|
27
|
+
permissions: list[tuple[str, str, str]] = []
|
|
28
|
+
for role in roles:
|
|
29
|
+
tenant_id, name, role_id = str(role["tenant_id"]), str(role["name"]), str(role["id"])
|
|
30
|
+
key = (tenant_id, name)
|
|
31
|
+
if key in by_key:
|
|
32
|
+
raise ValueError(f"duplicate legacy role {tenant_id}/{name}")
|
|
33
|
+
by_key[key] = role
|
|
34
|
+
permissions.extend((role_id, str(permission), "allow") for permission in role.get("permissions", ()))
|
|
35
|
+
grants: list[NormalizedRoleGrant] = []
|
|
36
|
+
for membership in memberships:
|
|
37
|
+
tenant_id = str(membership["tenant_id"])
|
|
38
|
+
principal_id = str(membership["principal_id"])
|
|
39
|
+
for name in membership.get("roles", ()):
|
|
40
|
+
role = by_key.get((tenant_id, str(name)))
|
|
41
|
+
if role is None:
|
|
42
|
+
raise ValueError(f"unknown legacy role {tenant_id}/{name}")
|
|
43
|
+
role_id = str(role["id"])
|
|
44
|
+
grants.append(NormalizedRoleGrant(f"legacy:{tenant_id}:{principal_id}:{role_id}", tenant_id, principal_id, role_id, "tenant", tenant_id))
|
|
45
|
+
return NormalizedAuthorization(tuple(permissions), tuple(grants))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .authorization import *
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"""Durable authorization membership and delegated-scope operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Mapping
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from tba_storage_authorization_policy.tables import AttributePolicy, DelegatedAdminScope, PolicyCondition, Role, TenantMembership
|
|
9
|
+
|
|
10
|
+
from tigrbl import (
|
|
11
|
+
create_table_record,
|
|
12
|
+
clear_table_records,
|
|
13
|
+
database_from_context,
|
|
14
|
+
field_value,
|
|
15
|
+
first_table_record,
|
|
16
|
+
list_table_records,
|
|
17
|
+
payload_from_context,
|
|
18
|
+
record_identifier,
|
|
19
|
+
update_table_record,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _strings(values: Any) -> tuple[str, ...]:
|
|
24
|
+
if values is None or values == "" or values is False:
|
|
25
|
+
return ()
|
|
26
|
+
if isinstance(values, str):
|
|
27
|
+
return (values,)
|
|
28
|
+
return tuple(sorted({str(value) for value in values if value not in {None, ""}}))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
async def grant_membership(ctx: Mapping[str, Any]) -> object:
|
|
32
|
+
values = dict(payload_from_context(ctx))
|
|
33
|
+
db = database_from_context(ctx)
|
|
34
|
+
tenant_id = str(values["tenant_id"])
|
|
35
|
+
principal_id = str(values["principal_id"])
|
|
36
|
+
payload = {
|
|
37
|
+
"tenant_id": tenant_id,
|
|
38
|
+
"principal_id": principal_id,
|
|
39
|
+
"roles": list(_strings(values.get("roles", ()))),
|
|
40
|
+
"status": str(values.get("status", "active")),
|
|
41
|
+
}
|
|
42
|
+
existing = await first_table_record(
|
|
43
|
+
TenantMembership,
|
|
44
|
+
db,
|
|
45
|
+
{"tenant_id": tenant_id, "principal_id": principal_id},
|
|
46
|
+
)
|
|
47
|
+
if existing is None:
|
|
48
|
+
return await create_table_record(TenantMembership, db, payload)
|
|
49
|
+
return await update_table_record(
|
|
50
|
+
TenantMembership, db, record_identifier(existing), payload
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def assign_role(ctx: Mapping[str, Any]) -> object:
|
|
55
|
+
values = dict(payload_from_context(ctx))
|
|
56
|
+
db = database_from_context(ctx)
|
|
57
|
+
filters = {
|
|
58
|
+
"tenant_id": values["tenant_id"],
|
|
59
|
+
"principal_id": values["principal_id"],
|
|
60
|
+
}
|
|
61
|
+
existing = await first_table_record(TenantMembership, db, filters)
|
|
62
|
+
roles = set(_strings(field_value(existing, "roles", ()))) if existing else set()
|
|
63
|
+
roles.add(str(values["role_name"]))
|
|
64
|
+
return await grant_membership(
|
|
65
|
+
{
|
|
66
|
+
"db": db,
|
|
67
|
+
"payload": {**filters, "roles": roles, "status": "active"},
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
async def role_names_for_principal(ctx: Mapping[str, Any]) -> tuple[str, ...]:
|
|
73
|
+
values = dict(payload_from_context(ctx))
|
|
74
|
+
filters = {"principal_id": values["principal_id"]}
|
|
75
|
+
if values.get("tenant_id") is not None:
|
|
76
|
+
filters["tenant_id"] = values["tenant_id"]
|
|
77
|
+
rows = await list_table_records(
|
|
78
|
+
TenantMembership, database_from_context(ctx), filters
|
|
79
|
+
)
|
|
80
|
+
roles: set[str] = set()
|
|
81
|
+
for row in rows:
|
|
82
|
+
if field_value(row, "status", "active") == "active":
|
|
83
|
+
roles.update(_strings(field_value(row, "roles", ())))
|
|
84
|
+
return tuple(sorted(roles))
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
async def upsert_role(ctx: Mapping[str, Any]) -> object:
|
|
88
|
+
values = dict(payload_from_context(ctx))
|
|
89
|
+
db = database_from_context(ctx)
|
|
90
|
+
filters = {
|
|
91
|
+
"name": str(values["name"]),
|
|
92
|
+
"tenant_id": values.get("tenant_id"),
|
|
93
|
+
}
|
|
94
|
+
payload = {
|
|
95
|
+
**filters,
|
|
96
|
+
"permissions": list(_strings(values.get("permissions", ()))),
|
|
97
|
+
"denied_permissions": list(_strings(values.get("denied_permissions", ()))),
|
|
98
|
+
"inherited_roles": list(_strings(values.get("inherited_roles", ()))),
|
|
99
|
+
"status": str(values.get("status", "active")),
|
|
100
|
+
}
|
|
101
|
+
existing = await first_table_record(Role, db, filters)
|
|
102
|
+
if existing is None:
|
|
103
|
+
return await create_table_record(Role, db, payload)
|
|
104
|
+
return await update_table_record(Role, db, record_identifier(existing), payload)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
async def list_roles_for_tenant(ctx: Mapping[str, Any]) -> tuple[object, ...]:
|
|
108
|
+
values = dict(payload_from_context(ctx))
|
|
109
|
+
tenant_id = values.get("tenant_id")
|
|
110
|
+
rows = await list_table_records(Role, database_from_context(ctx))
|
|
111
|
+
return tuple(
|
|
112
|
+
row for row in rows if field_value(row, "tenant_id") in {None, tenant_id}
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
async def upsert_attribute_policy(
|
|
117
|
+
ctx: Mapping[str, Any],
|
|
118
|
+
) -> tuple[object, list[object]]:
|
|
119
|
+
values = dict(payload_from_context(ctx))
|
|
120
|
+
db = database_from_context(ctx)
|
|
121
|
+
filters = {
|
|
122
|
+
"name": values["name"],
|
|
123
|
+
"tenant_id": values.get("tenant_id"),
|
|
124
|
+
}
|
|
125
|
+
existing = await first_table_record(AttributePolicy, db, filters)
|
|
126
|
+
payload = {
|
|
127
|
+
"name": values["name"],
|
|
128
|
+
"tenant_id": values.get("tenant_id"),
|
|
129
|
+
"client_id": values.get("client_id"),
|
|
130
|
+
"permission": values["permission"],
|
|
131
|
+
"effect": str(values.get("effect", "allow")),
|
|
132
|
+
"required_attributes": dict(values.get("required_attributes") or {}),
|
|
133
|
+
"status": "active",
|
|
134
|
+
}
|
|
135
|
+
if existing is None:
|
|
136
|
+
row = await create_table_record(AttributePolicy, db, payload)
|
|
137
|
+
else:
|
|
138
|
+
row = await update_table_record(
|
|
139
|
+
AttributePolicy, db, record_identifier(existing), payload
|
|
140
|
+
)
|
|
141
|
+
policy_id = record_identifier(row)
|
|
142
|
+
await clear_table_records(PolicyCondition, db, {"policy_id": policy_id})
|
|
143
|
+
conditions = [
|
|
144
|
+
await create_table_record(
|
|
145
|
+
PolicyCondition,
|
|
146
|
+
db,
|
|
147
|
+
{"policy_id": policy_id, **dict(condition)},
|
|
148
|
+
)
|
|
149
|
+
for condition in values.get("dynamic_conditions", ())
|
|
150
|
+
]
|
|
151
|
+
return row, conditions
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
async def list_active_attribute_policies(
|
|
155
|
+
ctx: Mapping[str, Any],
|
|
156
|
+
) -> tuple[tuple[object, list[object]], ...]:
|
|
157
|
+
values = dict(payload_from_context(ctx))
|
|
158
|
+
filters: dict[str, Any] = {"status": "active"}
|
|
159
|
+
if values.get("tenant_id") is not None:
|
|
160
|
+
filters["tenant_id"] = values["tenant_id"]
|
|
161
|
+
db = database_from_context(ctx)
|
|
162
|
+
rows = await list_table_records(AttributePolicy, db, filters)
|
|
163
|
+
collected = []
|
|
164
|
+
for row in rows:
|
|
165
|
+
conditions = await list_table_records(
|
|
166
|
+
PolicyCondition, db, {"policy_id": record_identifier(row)}
|
|
167
|
+
)
|
|
168
|
+
collected.append((row, conditions))
|
|
169
|
+
return tuple(collected)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
async def grant_delegated_scope(ctx: Mapping[str, Any]) -> object:
|
|
173
|
+
values = dict(payload_from_context(ctx))
|
|
174
|
+
db = database_from_context(ctx)
|
|
175
|
+
subject = str(values.pop("subject"))
|
|
176
|
+
payload = {"subject": subject, "status": "active", **values}
|
|
177
|
+
existing = await first_table_record(DelegatedAdminScope, db, {"subject": subject})
|
|
178
|
+
if existing is None:
|
|
179
|
+
return await create_table_record(DelegatedAdminScope, db, payload)
|
|
180
|
+
return await update_table_record(
|
|
181
|
+
DelegatedAdminScope, db, record_identifier(existing), payload
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
async def revoke_delegated_scope(ctx: Mapping[str, Any]) -> object:
|
|
186
|
+
subject = str(payload_from_context(ctx).get("subject") or "")
|
|
187
|
+
db = database_from_context(ctx)
|
|
188
|
+
existing = await first_table_record(DelegatedAdminScope, db, {"subject": subject})
|
|
189
|
+
if existing is None:
|
|
190
|
+
raise LookupError(subject)
|
|
191
|
+
return await update_table_record(
|
|
192
|
+
DelegatedAdminScope,
|
|
193
|
+
db,
|
|
194
|
+
record_identifier(existing),
|
|
195
|
+
{"status": "revoked"},
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
async def delegated_scope_for_subject(ctx: Mapping[str, Any]) -> object | None:
|
|
200
|
+
subject = str(payload_from_context(ctx).get("subject") or "")
|
|
201
|
+
return await first_table_record(
|
|
202
|
+
DelegatedAdminScope,
|
|
203
|
+
database_from_context(ctx),
|
|
204
|
+
{"subject": subject},
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
async def list_active_delegated_scopes(
|
|
209
|
+
ctx: Mapping[str, Any],
|
|
210
|
+
) -> tuple[object, ...]:
|
|
211
|
+
rows = await list_table_records(
|
|
212
|
+
DelegatedAdminScope,
|
|
213
|
+
database_from_context(ctx),
|
|
214
|
+
{"status": "active"},
|
|
215
|
+
)
|
|
216
|
+
return tuple(rows)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
__all__ = [
|
|
220
|
+
"assign_role",
|
|
221
|
+
"delegated_scope_for_subject",
|
|
222
|
+
"grant_delegated_scope",
|
|
223
|
+
"grant_membership",
|
|
224
|
+
"list_active_attribute_policies",
|
|
225
|
+
"list_active_delegated_scopes",
|
|
226
|
+
"list_roles_for_tenant",
|
|
227
|
+
"revoke_delegated_scope",
|
|
228
|
+
"role_names_for_principal",
|
|
229
|
+
"upsert_role",
|
|
230
|
+
"upsert_attribute_policy",
|
|
231
|
+
]
|
tba_durability_authorization_policy-0.4.0.dev2/src/tba_durability_authorization_policy/py.typed
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .authorization import *
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""Authorization table aliases and executable runtime specifications."""
|
|
2
|
+
|
|
3
|
+
from tba_storage_authorization_policy.tables import AttributePolicy, AuthorizationInvariant, DelegatedAdminScope, InvariantEvaluation, InvariantViolation, Policy, PolicyVersion, Role, TenantMembership
|
|
4
|
+
|
|
5
|
+
from tigrbl import deriveTableSpec
|
|
6
|
+
from tigrbl import makeOp
|
|
7
|
+
from tba_durability_authorization_policy.operations.authorization import (
|
|
8
|
+
assign_role,
|
|
9
|
+
delegated_scope_for_subject,
|
|
10
|
+
grant_delegated_scope,
|
|
11
|
+
grant_membership,
|
|
12
|
+
list_active_attribute_policies,
|
|
13
|
+
list_active_delegated_scopes,
|
|
14
|
+
list_roles_for_tenant,
|
|
15
|
+
revoke_delegated_scope,
|
|
16
|
+
role_names_for_principal,
|
|
17
|
+
upsert_role,
|
|
18
|
+
upsert_attribute_policy,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
TenantMembershipTable = TenantMembership
|
|
22
|
+
DelegatedAdminScopeTable = DelegatedAdminScope
|
|
23
|
+
RoleTable = Role
|
|
24
|
+
AttributePolicyTable = AttributePolicy
|
|
25
|
+
AuthorizationInvariantTable = AuthorizationInvariant
|
|
26
|
+
InvariantEvaluationTable = InvariantEvaluation
|
|
27
|
+
InvariantViolationTable = InvariantViolation
|
|
28
|
+
PolicyTable = Policy
|
|
29
|
+
PolicyVersionTable = PolicyVersion
|
|
30
|
+
|
|
31
|
+
AttributePolicyRuntimeSpec = deriveTableSpec(
|
|
32
|
+
AttributePolicyTable,
|
|
33
|
+
ops=(
|
|
34
|
+
makeOp(
|
|
35
|
+
extra={"owner_layer": "30-storage-runtime"},
|
|
36
|
+
expose_routes=False,
|
|
37
|
+
expose_rpc=False,
|
|
38
|
+
expose_method=True,
|
|
39
|
+
tx_scope="read_write",
|
|
40
|
+
alias="upsert_with_conditions",
|
|
41
|
+
handler=upsert_attribute_policy,
|
|
42
|
+
),
|
|
43
|
+
makeOp(
|
|
44
|
+
extra={"owner_layer": "30-storage-runtime"},
|
|
45
|
+
expose_routes=False,
|
|
46
|
+
expose_rpc=False,
|
|
47
|
+
expose_method=True,
|
|
48
|
+
alias="list_active_with_conditions",
|
|
49
|
+
handler=list_active_attribute_policies,
|
|
50
|
+
tx_scope="read_only",
|
|
51
|
+
persist="skip",
|
|
52
|
+
),
|
|
53
|
+
),
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
RoleRuntimeSpec = deriveTableSpec(
|
|
57
|
+
RoleTable,
|
|
58
|
+
ops=(
|
|
59
|
+
makeOp(
|
|
60
|
+
extra={"owner_layer": "30-storage-runtime"},
|
|
61
|
+
expose_routes=False,
|
|
62
|
+
expose_rpc=False,
|
|
63
|
+
expose_method=True,
|
|
64
|
+
tx_scope="read_write",
|
|
65
|
+
alias="create_role",
|
|
66
|
+
handler=upsert_role,
|
|
67
|
+
),
|
|
68
|
+
makeOp(
|
|
69
|
+
extra={"owner_layer": "30-storage-runtime"},
|
|
70
|
+
expose_routes=False,
|
|
71
|
+
expose_rpc=False,
|
|
72
|
+
expose_method=True,
|
|
73
|
+
alias="list_for_tenant",
|
|
74
|
+
handler=list_roles_for_tenant,
|
|
75
|
+
tx_scope="read_only",
|
|
76
|
+
persist="skip",
|
|
77
|
+
),
|
|
78
|
+
),
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
TenantMembershipRuntimeSpec = deriveTableSpec(
|
|
82
|
+
TenantMembershipTable,
|
|
83
|
+
ops=(
|
|
84
|
+
makeOp(
|
|
85
|
+
extra={"owner_layer": "30-storage-runtime"},
|
|
86
|
+
expose_routes=False,
|
|
87
|
+
expose_rpc=False,
|
|
88
|
+
expose_method=True,
|
|
89
|
+
tx_scope="read_write",
|
|
90
|
+
alias="grant_membership",
|
|
91
|
+
handler=grant_membership,
|
|
92
|
+
),
|
|
93
|
+
makeOp(
|
|
94
|
+
extra={"owner_layer": "30-storage-runtime"},
|
|
95
|
+
expose_routes=False,
|
|
96
|
+
expose_rpc=False,
|
|
97
|
+
expose_method=True,
|
|
98
|
+
tx_scope="read_write",
|
|
99
|
+
alias="assign_role",
|
|
100
|
+
handler=assign_role,
|
|
101
|
+
),
|
|
102
|
+
makeOp(
|
|
103
|
+
extra={"owner_layer": "30-storage-runtime"},
|
|
104
|
+
expose_routes=False,
|
|
105
|
+
expose_rpc=False,
|
|
106
|
+
expose_method=True,
|
|
107
|
+
alias="role_names_for_principal",
|
|
108
|
+
handler=role_names_for_principal,
|
|
109
|
+
tx_scope="read_only",
|
|
110
|
+
persist="skip",
|
|
111
|
+
),
|
|
112
|
+
),
|
|
113
|
+
)
|
|
114
|
+
DelegatedAdminScopeRuntimeSpec = deriveTableSpec(
|
|
115
|
+
DelegatedAdminScopeTable,
|
|
116
|
+
ops=(
|
|
117
|
+
makeOp(
|
|
118
|
+
extra={"owner_layer": "30-storage-runtime"},
|
|
119
|
+
expose_routes=False,
|
|
120
|
+
expose_rpc=False,
|
|
121
|
+
expose_method=True,
|
|
122
|
+
tx_scope="read_write",
|
|
123
|
+
alias="grant_scope",
|
|
124
|
+
handler=grant_delegated_scope,
|
|
125
|
+
),
|
|
126
|
+
makeOp(
|
|
127
|
+
extra={"owner_layer": "30-storage-runtime"},
|
|
128
|
+
expose_routes=False,
|
|
129
|
+
expose_rpc=False,
|
|
130
|
+
expose_method=True,
|
|
131
|
+
tx_scope="read_write",
|
|
132
|
+
alias="revoke_scope",
|
|
133
|
+
handler=revoke_delegated_scope,
|
|
134
|
+
),
|
|
135
|
+
makeOp(
|
|
136
|
+
extra={"owner_layer": "30-storage-runtime"},
|
|
137
|
+
expose_routes=False,
|
|
138
|
+
expose_rpc=False,
|
|
139
|
+
expose_method=True,
|
|
140
|
+
alias="lookup",
|
|
141
|
+
handler=delegated_scope_for_subject,
|
|
142
|
+
tx_scope="read_only",
|
|
143
|
+
persist="skip",
|
|
144
|
+
),
|
|
145
|
+
makeOp(
|
|
146
|
+
extra={"owner_layer": "30-storage-runtime"},
|
|
147
|
+
expose_routes=False,
|
|
148
|
+
expose_rpc=False,
|
|
149
|
+
expose_method=True,
|
|
150
|
+
alias="list_active",
|
|
151
|
+
handler=list_active_delegated_scopes,
|
|
152
|
+
tx_scope="read_only",
|
|
153
|
+
persist="skip",
|
|
154
|
+
),
|
|
155
|
+
),
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
__all__ = [
|
|
159
|
+
"AttributePolicyRuntimeSpec",
|
|
160
|
+
"AttributePolicyTable",
|
|
161
|
+
"AuthorizationInvariantTable",
|
|
162
|
+
"DelegatedAdminScopeRuntimeSpec",
|
|
163
|
+
"DelegatedAdminScopeTable",
|
|
164
|
+
"InvariantEvaluationTable",
|
|
165
|
+
"InvariantViolationTable",
|
|
166
|
+
"PolicyTable",
|
|
167
|
+
"PolicyVersionTable",
|
|
168
|
+
"TenantMembershipRuntimeSpec",
|
|
169
|
+
"TenantMembershipTable",
|
|
170
|
+
"RoleRuntimeSpec",
|
|
171
|
+
"RoleTable",
|
|
172
|
+
]
|