Check access at runtime
Runtime checks are published for Python SDK 0.2.1. They evaluate the authenticated caller configured on the client; do not supply a principal override in application code.
Prerequisites
- Configure the Python client for the target app with an authenticated caller.
- Identify a concrete policy resource such as
datatable:orders, an existing record identifier such asorder-123, and the proposed attributes for a new record. - Choose only actions supported by that resource. For Database, use the resource-action reference.
Check what the caller can do
Keep existing-record checks separate from create checks. For an existing record,
use its real ID and only read, update, or delete. For a proposed create,
use ID new, action create, and the attributes that will be submitted.
new:i is the batch form, where i identifies each proposed record.
new represents the proposed record and must carry the submitted attributes
that the create policy evaluates.
The full Database action inventory is read, create, update, and delete.
Do not rely on the SDK's default candidate actions because that default includes
write, which is not a Database system action.
- Place the example in a request path whose configured client represents the authenticated caller.
- Replace the resource kind, ID, attributes, and candidate actions with the values reviewed for your policy.
- Treat every error as a denial, then test with both an allowed and a denied caller before relying on the result.
import logging
from taruvi import (
AuthenticationError,
AuthorizationError,
ConnectionError,
ResponseError,
ServiceUnavailableError,
TaruviError,
TimeoutError,
ValidationError,
)
logger = logging.getLogger(__name__)
existing_resource = {
"kind": "datatable:orders",
"id": "order-123",
"attr": {"status": "active"},
}
proposed_resource = {
"kind": "datatable:orders",
"id": "new",
"attr": {"status": "draft", "total": 12500},
}
database_actions = ["read", "create", "update", "delete"]
existing_actions = [action for action in database_actions if action != "create"]
create_actions = ["create"]
read_allowed = False
create_allowed = False
visible = []
allowed_actions = []
try:
read_result = client.policy.check_resources([
{"resource": existing_resource, "actions": ["read"]}
])
read_results = read_result.get("results") or []
read_effect = (
(read_results[0].get("actions") or {}).get("read")
if read_results else None
)
# EFFECT_DENY, a missing result, or a missing effect all remain denied.
read_allowed = read_effect == "EFFECT_ALLOW"
create_result = client.policy.check_resources([
{"resource": proposed_resource, "actions": create_actions}
])
create_results = create_result.get("results") or []
create_effect = (
(create_results[0].get("actions") or {}).get("create")
if create_results else None
)
create_allowed = create_effect == "EFFECT_ALLOW"
visible = client.policy.filter_allowed([existing_resource], ["read"])
allowed_actions = client.policy.get_allowed_actions(
existing_resource, existing_actions
)
except (
ValidationError,
AuthenticationError,
AuthorizationError,
ServiceUnavailableError,
TimeoutError,
ConnectionError,
ResponseError,
) as error:
read_allowed = False
create_allowed = False
visible = []
allowed_actions = []
logger.warning("Policy check failed: %s", type(error).__name__)
except TaruviError as error:
read_allowed = False
create_allowed = False
visible = []
allowed_actions = []
logger.warning("Policy check failed: %s", type(error).__name__)
check_resources returns a response dictionary. Each requested action maps to
EFFECT_ALLOW or EFFECT_DENY under results[].actions. A missing result or
effect must deny. filter_allowed returns only input resources for which every
requested action is EFFECT_ALLOW. get_allowed_actions returns allowed names
from the explicit existing-record candidate set. A create decision applies only
to the proposed new resource and its submitted attributes; it is not a create
grant for order-123.
Verification
The expected result is a caller-bound read decision for order-123, a separate
create decision for the proposed new record, a conservatively filtered
resource list, and existing-record actions drawn only from the explicit set.
On an API, service, timeout, connection, or response error, treat the request
as denied. Do not log credentials, personal attributes, raw policy definitions, or tokens.
The JavaScript SDK's policy calls and the Refine accessControlProvider don't
work with the current API yet, so use the Python SDK for runtime checks. UI
checks such as Refine's CanAccess and useCan only decide what to show;
TaruviBase always enforces policies on the server.
Review Security and limits and Troubleshooting before using the decision in a production request path.