Resource Types
Define valid relations and permissions for resource types.
Overview
Resource types define the schema for your authorization model. They declare which relations and permissions are valid for each type of object.
Every config example on this page comes in two flavours: Go (programmatic — call the store directly) and DSL (declarative — write .warden source and apply it via warden apply or dsl.ApplyFS). They produce identical state.
ResourceType Fields
| Field | Type | Description |
|---|---|---|
ID | id.ResourceTypeID | TypeID (rtype_...) — auto-assigned on Create when unset |
Name | string | Resource type name (e.g., "document") |
Description | string | Human-readable description |
Relations | []RelationDef | Valid relations for this type |
Permissions | []PermissionDef | Derived permission expressions |
Defining Relations
import "github.com/xraph/warden/resourcetype"
// IDs and CreatedAt/UpdatedAt timestamps are auto-assigned by the
// store on Create — set them only when you need a specific value.
docType := &resourcetype.ResourceType{
Name: "document",
Description: "A document resource",
Relations: []resourcetype.RelationDef{
{Name: "owner", AllowedSubjects: []string{"user"}},
{Name: "editor", AllowedSubjects: []string{"user", "team#member"}},
{Name: "viewer", AllowedSubjects: []string{"user", "team#member", "group#member"}},
{Name: "parent", AllowedSubjects: []string{"folder"}},
},
Permissions: []resourcetype.PermissionDef{
{Name: "read", Expression: "viewer or editor or owner or parent->read"},
{Name: "write", Expression: "editor or owner or parent->write"},
{Name: "delete", Expression: "owner"},
},
}
err := store.CreateResourceType(ctx, docType)
// docType.ID is now populated.warden config 1
tenant t1
resource document {
description = "A document resource"
relation owner: user
relation editor: user | team#member
relation viewer: user | team#member | group#member
relation parent: folder
permission read = viewer or editor or owner or parent->read
permission write = editor or owner or parent->write
permission delete = owner
}The expression algebra (or, and, not, ->) is the same as the Go form — Expression strings parse with the same grammar. See the language reference for precedence rules and traversal semantics.
RelationDef
| Field | Type | Description |
|---|---|---|
Name | string | Relation name (e.g., "viewer") |
AllowedSubjects | []string | Allowed subject types — bare types (user) or subject sets (group#member) |
PermissionDef
| Field | Type | Description |
|---|---|---|
Name | string | Permission name (e.g., "read") |
Expression | string | Boolean expression over relations (e.g., "viewer or editor or owner") |
Example: Google Drive-like Model
// Folder type
folderType := &resourcetype.ResourceType{
Name: "folder",
Relations: []resourcetype.RelationDef{
{Name: "owner", AllowedSubjects: []string{"user"}},
{Name: "editor", AllowedSubjects: []string{"user", "group#member"}},
{Name: "viewer", AllowedSubjects: []string{"user", "group#member"}},
},
Permissions: []resourcetype.PermissionDef{
{Name: "read", Expression: "viewer or editor or owner"},
{Name: "write", Expression: "editor or owner"},
{Name: "share", Expression: "owner"},
},
}
// Document type — `parent->read` traverses the parent relation and
// re-checks read on the resulting folder.
docType := &resourcetype.ResourceType{
Name: "document",
Relations: []resourcetype.RelationDef{
{Name: "owner", AllowedSubjects: []string{"user"}},
{Name: "editor", AllowedSubjects: []string{"user", "group#member"}},
{Name: "viewer", AllowedSubjects: []string{"user", "group#member"}},
{Name: "parent", AllowedSubjects: []string{"folder"}},
},
Permissions: []resourcetype.PermissionDef{
{Name: "read", Expression: "viewer or editor or owner or parent->read"},
{Name: "write", Expression: "editor or owner or parent->write"},
{Name: "delete", Expression: "owner"},
},
}warden config 1
tenant t1
// Folder type
resource folder {
relation owner: user
relation editor: user | group#member
relation viewer: user | group#member
permission read = viewer or editor or owner
permission write = editor or owner
permission share = owner
}
// Document type — `parent->read` traverses the parent relation and
// re-checks read on the resulting folder.
resource document {
relation owner: user
relation editor: user | group#member
relation viewer: user | group#member
relation parent: folder
permission read = viewer or editor or owner or parent->read
permission write = editor or owner or parent->write
permission delete = owner
}CRUD Operations
These are runtime API calls — they don't have a DSL equivalent because the DSL is declarative (you describe the desired end state, not the operation). The applier picks the right CRUD call internally.
// Create
store.CreateResourceType(ctx, rt)
// Get by ID
rt, _ := store.GetResourceType(ctx, rtID)
// Get by name
rt, _ := store.GetResourceTypeByName(ctx, tenantID, "document")
// List
types, _ := store.ListResourceTypes(ctx, &resourcetype.ListFilter{
TenantID: "t1",
Limit: 50,
})
// Update
store.UpdateResourceType(ctx, rt)
// Delete
store.DeleteResourceType(ctx, rtID)