Skip to content
🚀 This documentation is for unreal-orm 1.0.0 alpha which requires SurrealDB 2.0 SDK. For use with version 1.x, see here.

Security and Permissions

SurrealDB has a built-in permissions system. UnrealORM exposes it through permissions on tables and fields. Values are either true (always allowed), false (never allowed), or a surql expression that evaluates to a boolean.

import { Table, Field } from 'unreal-orm';
import { surql } from 'surrealdb';
class Post extends Table.normal({
name: 'post',
schemafull: true,
fields: {
title: Field.string(),
content: Field.string(),
author: Field.record(() => User),
},
permissions: {
select: true,
create: surql`$auth.id != NONE`,
update: surql`author = $auth.id`,
delete: surql`author = $auth.id`,
},
}) {}

Hide or protect individual fields:

class User extends Table.normal({
name: 'user',
fields: {
name: Field.string(),
email: Field.string({
permissions: {
select: surql`id = $auth.id`,
update: surql`id = $auth.id`,
},
}),
},
}) {}

$auth is the currently authenticated record. Its exact shape depends on how you sign in. With scope authentication it is the record from the scope’s user table:

await db.connect('ws://localhost:8000', {
namespace: 'app',
database: 'app',
authentication: {
access: 'user',
variables: {
email: 'alice@example.com',
password: 'password',
},
},
});

Note: Pass authentication details directly to .connect() so the SDK can automatically re-authenticate on reconnect. Using separate .signin() calls means tokens will not be refreshed automatically.

After sign in, $auth.id is the RecordId of the authenticated user.

Use the in-memory engine and set $auth through query bindings for fast unit tests:

await expect(
db.query(surql`DELETE $id`, { id: post.id, auth: { id: new RecordId('user', 'bob') } })
).rejects.toThrow();

For real integration tests, sign in as different users and run the ORM calls against a clean mem:// database.