Skip to main content

Check access at runtime

Check access from Python (client.policy), JavaScript (Policy), or Refine (accessControlProvider, 1.3.7 and later). Checks evaluate the authenticated caller configured on the client; don't supply a principal override in application code.

A caller with organization access (an organization owner, admin, or member, a superuser, or an API key created by one of them) is allowed every action it asks about, without evaluating any policy. To check what an app user may do, build the client from that user's session token; see Act for a signed-in user.

Prerequisites#

  • Configure the JavaScript client, Python client, or Refine integration for the target app with an authenticated caller. The examples call the JavaScript client taruvi and the synchronous Python client client.
  • Identify a concrete policy resource such as datatable:orders, an existing record identifier such as order-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.

  1. Place the example in a request path whose configured client represents the authenticated caller.
  2. Replace the resource kind, ID, attributes, and candidate actions with the values reviewed for your policy.
  3. Treat every error as a denial, then test with both an allowed and a denied caller before relying on the result. Use site users for both: a caller with organization access is always allowed.
import {Policy} from '@taruvi/sdk';
import type {Resource} from '@taruvi/sdk';

const policy = new Policy(taruvi);
const existingResource: Resource = {
kind: 'datatable:orders', id: 'order-123', attr: {status: 'active'},
};
const proposedResource: Resource = {
kind: 'datatable:orders', id: 'new', attr: {status: 'draft', total: 12500},
};
const existingActions = ['read', 'update', 'delete'];
let readAllowed = false;
let createAllowed = false;
let visible: Resource[] = [];
let allowedActions: string[] = [];

try {
const result = await policy.checkResource([
{
resource: existingResource.kind,
recordId: existingResource.id,
attributes: existingResource.attr,
actions: ['read'],
},
{
resource: proposedResource.kind,
recordId: proposedResource.id,
attributes: proposedResource.attr,
actions: ['create'],
},
]);
readAllowed = result.results?.[0]?.actions?.read === 'EFFECT_ALLOW';
createAllowed = result.results?.[1]?.actions?.create === 'EFFECT_ALLOW';
visible = readAllowed ? [existingResource] : [];
allowedActions = await policy.getAllowedActions(existingResource, {
actions: existingActions,
});
} catch {
readAllowed = false;
createAllowed = false;
visible = [];
allowedActions = [];
}

checkResource takes resource, recordId, attributes, and actions for each check. getAllowedActions takes a resource with kind, id, and attr. Filter your input list after the corresponding check returns EFFECT_ALLOW.

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.

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.