Checks
Ask whether a subject has a relation or permission on an object.
The examples on this page run after the tuples from Write tuples: Alice owns the roadmap, and Bob can view it.
Check
check returns the verdict in allowed. The relation can be a relation or a permission.
import { peretyn } from '@peretyn/sdk';
import type { schema } from './schema';
const authz = peretyn<typeof schema>({ token: process.env.PERETYN_TOKEN! });
const { allowed } = await authz.check({
subject: { type: 'user', id: 'bob' },
relation: 'can_view',
object: { type: 'document', id: 'roadmap' },
});
console.log(allowed ? 'allowed' : 'denied');The script prints allowed. Bob is a viewer, and viewers can view.
Assert
assert runs the same check, and throws a PeretynError with status 403 when the verdict is denied. Use it where a deny should stop the request, such as at the top of an HTTP handler.
import { peretyn, PeretynError } from '@peretyn/sdk';
import type { schema } from './schema';
const FORBIDDEN = 403;
const authz = peretyn<typeof schema>({ token: process.env.PERETYN_TOKEN! });
function isDenied(error: unknown): boolean {
return error instanceof PeretynError && error.status === FORBIDDEN;
}
try {
await authz.assert({
subject: { type: 'user', id: 'bob' },
relation: 'can_edit',
object: { type: 'document', id: 'roadmap' },
});
console.log('allowed');
} catch (error) {
if (!isDenied(error)) throw error;
console.log('denied');
}The script prints denied. Bob is a viewer, and viewers can't edit.
Batch check
batchCheck runs many checks in one call. Each result carries the check it answers, in the order you passed them.
import { peretyn } from '@peretyn/sdk';
import type { schema } from './schema';
const authz = peretyn<typeof schema>({ token: process.env.PERETYN_TOKEN! });
const results = await authz.batchCheck([
{
subject: { type: 'user', id: 'alice' },
relation: 'can_edit',
object: { type: 'document', id: 'roadmap' },
},
{
subject: { type: 'user', id: 'bob' },
relation: 'can_edit',
object: { type: 'document', id: 'roadmap' },
},
]);
for (const { check, allowed } of results) {
console.log(`${check.subject.id}: ${allowed ? 'allowed' : 'denied'}`);
}The script prints:
alice: allowed
bob: deniedThe SDK sends the checks in batches of 50, at most 4 batches at a time, all within one timeoutMs. If one batch fails, the call rejects and the SDK cancels the rest.
A check that the runtime can't evaluate comes back with allowed: false and an error message.
Lookups
A lookup lists what a check would allow, instead of answering for one subject and one object:
lookupResourcesreturns the ids of the objects of one type on which a subject has a relation.lookupSubjectsreturns the subjects of one type that have a relation on an object.
import { peretyn } from '@peretyn/sdk';
import type { schema } from './schema';
const authz = peretyn<typeof schema>({ token: process.env.PERETYN_TOKEN! });
const { ids } = await authz.lookupResources({
subject: { type: 'user', id: 'bob' },
relation: 'can_view',
resourceType: 'document',
});
const { subjects } = await authz.lookupSubjects({
resource: { type: 'document', id: 'roadmap' },
relation: 'can_edit',
subjectType: 'user',
});
console.log(`bob can view: ${ids.join(', ')}`);
console.log(`can edit the roadmap: ${subjects.join(', ')}`);The script prints:
bob can view: roadmap
can edit the roadmap: user:alicelookupResources returns ids without the type. lookupSubjects returns full subjects, such as user:alice, team:design#member, or user:* for a wildcard.
Options
Checks and lookups accept these options:
| Option | Effect |
|---|---|
contextualTuples | Tuples that count for this call only. Peretyn doesn't store them. |
consistency | MINIMIZE_LATENCY (default) can answer from a cache. HIGHER_CONSISTENCY skips the cache, so the call sees writes made just before it. |
expand returns the tree of relations that grant a permission on an object. Use it to explain why a check was allowed.