Skip to main content

Authorization

riverbase_http::casbin decides whether an authenticated principal may perform the operation a route represents. Which rows it may touch is a separate check; see Multi-tenancy.

Configuration​

[riverbase.casbin]
enabled = true
omit_inaccessible_openapi = true # each caller sees only operations they may run
# model = """…""" # empty → the framework's default activity model
policy = """
p, todo-admin, riverbase.todo, create-todo.execute, todo, *, allow
p, todo-admin, riverbase.todo, todo.query, todo, *, allow
g, alice, todo-admin
"""

Env: RIVERBASE_CASBIN_ENABLED, RIVERBASE_CASBIN_OMIT_INACCESSIBLE_OPENAPI.

From code:

app.with_casbin_policy(POLICY_CSV);
app.with_casbin_known_roles(["todo-admin", "todo-user"]);
app.require_any_role(["todo-admin", "todo-user"]); // reject callers with none of these roles

An empty policy is deny-all.

Policy rows​

p, <subject|role>, <namespace>, <activity>, <resource>, <object>, <effect>
g, <user>, <role>
ColumnExampleNotes
subject or roletodo-adminA role from g, rows or the principal's roles
namespaceriverbase.todoThe domain
activitycreate-todo.executeSee the mapping below
resourcetodo* matches any
object*An object id, or *
effectallowallow or deny

Route-to-activity mapping​

RouteActivity
POST …/{cmdkey}:post/…, POST …/{cmdkey}:exec/…{cmdkey}.execute
GET …/{resource}.list, .item, .meta; POST …/{report}.rept{resource}.query
Custom route registered with RouteAccess::EnforcedMapped by path; unmapped paths are 403 CAS-011
Custom route registered as publicSkipped, with the recorded reason and sign-off

Startup checks​

With a policy pack, startup verifies the policy against the mounted domains:

CodeProblem
CAS-011A route has no activity mapping
CAS-012Policy and mounted routes have drifted apart
CAS-013A mounted command has no policy row

Authorizer API​

To check activities off the HTTP path, for example in tests:

use riverbase_http::casbin::{build_authorizer, ActivityAuthorizer, ActivityRequest, DomainActivity};

let authz = build_authorizer(pool, None, Some(POLICY_CSV)).await?;
let activity = DomainActivity::new("riverbase.todo", "create-todo.execute").with_resource("todo");
authz.enforce(&ActivityRequest::new("alice", activity)).await?;

For commands invoked by workers, attach a CommandPolicy to the engine. See Permissions.

Denials​

A denied request returns 403 with AUT-003. That means "authenticated but not allowed," as opposed to AUT-001 and AUT-002 for identity failures.