Access rules let you go beyond coarse “can read / can write” toggles: you can allow or deny specific operations on specific database objects or file paths, optionally driven by a SQL expression (a full SQL query, not a bare condition). At the time of writing, rules are configured per role (there is no separate rules UI for users without going through a role).
Roles and database-backed user storage are covered in Users & auth. For rules to be meaningful in production, you typically want users stored in the database and roles assigned as described there.
Open Users & Auth details → Edit roles, choose a role, then scroll to the bottom of Role Details. You will see two buttons:
This screen lists rules for database access (subtitle: “Database access rules management”). Use Add rule to create a rule.
Each rule defines:
* to match any table/view (as described in the app).
This screen lists rules for file system access (subtitle: “File system access rules management”). Again, use Add rule to create a rule.
Each rule defines:
The SQL expression field must contain a complete, valid SQL query (not just a predicate or WHERE fragment). It must return at least one column and one row; the engine uses that cell as the outcome (allow/deny). A standalone condition such as :operation = 'READ_TABLE' is unlikely to work because it is not a proper SELECT with a result set.
You can reference bound values using placeholders in the form :name.
Placeholders must match PARAM_PATTERN: :([a-zA-Z_][a-zA-Z0-9_.[\]]*) — so names like :param.files[] are valid.
Variable in expression (:name) | Meaning |
|---|---|
:user.id | User name |
:user.role | User role |
:user.rootDir | User root directory |
:user.usedStorage | User used storage |
:subject | Table name, path, or special constant (see below) |
:operation | Operation string (see below) |
param.* keys are provided by the handler (and depend on operation and subject).
Each operation in the tables below (READ_TABLE, READ_CELL, ZIP_DOWNLOAD, and so on) is triggered by the same server-side paths as the corresponding REST API entry points. Full endpoint documentation is in the API Documentation section of this site.
subject unless noted| Operation | Extra param.* keys | Notes |
|---|---|---|
READ_TABLE | columns, offset, limit, sort, sortDir, includeRowId, rowsAsObjects, includeTotal, filters | filters is JSON; several fields use "" when absent; booleans as Boolean. |
READ_CELL | column, filters | column from request; filters JSON string. |
INSERT | values | JSON string of row. |
UPDATE | values, filters | Both JSON strings. |
DELETE | filters | JSON string. |
READ_SCHEMA | (none) | operationParams is null; subject is table name or *. |
EXECUTE | (none) |
subject| Operation | Extra param.* keys | Notes |
|---|---|---|
DOWNLOAD | (none) | null params. |
THUMBNAIL | (none) | null params. |
LIST_CONTENTS | sort, search, sort-reversed | Defaults applied when query params are missing; fixed map: "default", "", "false". |
RENAME | name | New file name. |
NEW_FOLDER | name | New folder name. |
UPLOAD | contentLength | long; request body size. |
DELETE | files.size, files[] | Count + JSON array string of names. Keys become param.files.size and param.files[]. |
COPY_MOVE | action, files.size, files[] | action is "copy" or "move"; same files.* as delete. |
ZIP_DOWNLOAD | level, uncompressed, files.size, files[] | level may be null; uncompressed is List<String>; files[] is JSON array string. |
Each example is a full SELECT that always returns one row and one numeric column (1 = allow, 0 = deny in this pattern). The dialect matches the app’s SQLite usage; adapt placeholders to your rule.
orders table — SELECT CASE WHEN :operation = 'READ_TABLE' AND :subject = 'orders' THEN 1 ELSE 0 ENDSELECT CASE WHEN :operation = 'UPLOAD' AND CAST(:param.contentLength AS INTEGER) > 10485760 THEN 0 ELSE 1 ENDThese are illustrative; combine with :user.* and :param.* as needed for your policy.