This guide demonstrates how to manage users, organizations, and authorization in TerminusDB. You'll learn how to invite users to organizations and data products with specific capabilities, creating a complete authorization hierarchy.
Understanding TerminusDB Authorization
TerminusDB uses a capability-based authorization system with three core concepts:
- Users: Individual accounts that can authenticate with TerminusDB
- Organizations: Top-level containers that own data products
- Roles: Collections of actions (permissions) like
Role/adminorRole/consumer - Capabilities: Grant specific roles to users for a given scope (organization or data product)
Key Roles
TerminusDB includes two default built-in roles:
Role/admin (referred to as "Admin Role" in API calls) - Full administrative access over a scope (database or organization) including:
- Create and delete databases (in an organization)
- Read and write schema, instance data, and metadata
- Manage capabilities (invite/remove users in an organization)
- Clone, fetch, push, branch, and rebase operations on a database
Role/consumer (referred to as "Consumer Role" in API calls) - Read-only access over a scope (database or organization) including:
- Read schema and instance data
- Read database metadata
- Clone and fetch operations on a database
- Class frame queries
Understanding Access Levels
Organization-level capabilities grant:
- Ability to create databases
- Manage users and capabilities within the organization
- Access to organization metadata and databases
Database-level capabilities grant:
- Operational access: documents, queries (WOQL, GraphQL), schema
- Grants access to database metadata endpoints
- Scoped to a specific database only
For a comprehensive overview of TerminusDB's role-based access control model, see the Access Control Tutorial.
Prerequisites
Before starting, ensure you have:
- A running TerminusDB instance (default:
http://127.0.0.1:6363) - see Install TerminusDB as a Docker Container for setup instructions - Admin credentials (default: username
admin, passwordroot) curlandjqinstalled for making API requests
Setup: Environment Variables
Let's set up environment variables for easier command execution:
# TerminusDB server configuration
export TERMINUSDB_URL="http://127.0.0.1:6363"
export ADMIN_USER="admin"
export ADMIN_PASS="root"
# Generate a unique suffix for this tutorial (avoids conflicts)
export TUTORIAL_ID=$(date +%s)
# Organization and user names
export ORG_NAME="acme_corp_${TUTORIAL_ID}"
export ORG_ADMIN_USER="alice_${TUTORIAL_ID}"
export ORG_ADMIN_PASS="alice_password_123"
export REGULAR_USER="bob_${TUTORIAL_ID}"
export REGULAR_PASS="bob_password_456"
export DB_USER="charlie_${TUTORIAL_ID}"
export DB_USER_PASS="charlie_password_789"
export DB_NAME="products"Part 1: Creating an Organization
Only system administrators can create organizations. Let's create an organization called "Acme Corp" using the admin account:
curl -X POST "${TERMINUSDB_URL}/api/organizations/${ORG_NAME}" \
-u "${ADMIN_USER}:${ADMIN_PASS}" \
-H "Content-Type: application/json" \
-d '{}'Expected Response:
"terminusdb://system/data/Organization/acme_corp_1234567890"This returns the organization's unique identifier. The organization exists but has no users yet.
Verify Organization Creation
curl -s -X GET "${TERMINUSDB_URL}/api/organizations/${ORG_NAME}" \
-u "${ADMIN_USER}:${ADMIN_PASS}" \
-H "Content-Type: application/json" | jqExpected Response:
{
"@id": "Organization/acme_corp_1234567890",
"@type": "Organization",
"name": "acme_corp_1234567890"
}Part 2: Creating Users
Now let's create three users who will have different roles in our organization:
Create Alice (Future Organization Admin)
curl -X POST "${TERMINUSDB_URL}/api/users" \
-u "${ADMIN_USER}:${ADMIN_PASS}" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"${ORG_ADMIN_USER}\",
\"password\": \"${ORG_ADMIN_PASS}\"
}"Expected Response:
"terminusdb://system/data/User/alice_1234567890"Create Bob (Future Organization Admin via Invitation)
curl -X POST "${TERMINUSDB_URL}/api/users" \
-u "${ADMIN_USER}:${ADMIN_PASS}" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"${REGULAR_USER}\",
\"password\": \"${REGULAR_PASS}\"
}"Create Charlie (Future Data Product User)
curl -X POST "${TERMINUSDB_URL}/api/users" \
-u "${ADMIN_USER}:${ADMIN_PASS}" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"${DB_USER}\",
\"password\": \"${DB_USER_PASS}\"
}"Verify Users Have No Capabilities Yet
Let's check Alice's current capabilities, try manually with the other roles (switch environment variable in the command):
curl -s -X GET "${TERMINUSDB_URL}/api/users/${ORG_ADMIN_USER}?capability=true" \
-u "${ADMIN_USER}:${ADMIN_PASS}" \
-H "Content-Type: application/json" | jqExpected Response:
{
"@id": "User/alice_1234567890",
"@type": "User",
"name": "alice_1234567890",
"capability": []
}Notice the capability array is empty - Alice has no permissions yet.
Part 3: Granting Organization Admin to Alice
As system admin, let's grant Alice administrative access to the Acme Corp organization. With this permission, Alice can manage the organization (also known as a "team" or "project"):
curl -X POST "${TERMINUSDB_URL}/api/capabilities" \
-u "${ADMIN_USER}:${ADMIN_PASS}" \
-H "Content-Type: application/json" \
-d "{
\"operation\": \"grant\",
\"scope\": \"${ORG_NAME}\",
\"user\": \"${ORG_ADMIN_USER}\",
\"roles\": [\"Admin Role\"],
\"scope_type\": \"organization\"
}"Expected Response:
{
"@type": "api:CapabilityResponse",
"api:status": "api:success"
}Verify Alice's New Capabilities
curl -s -X GET "${TERMINUSDB_URL}/api/users/${ORG_ADMIN_USER}?capability=true" \
-u "${ADMIN_USER}:${ADMIN_PASS}" \
-H "Content-Type: application/json" | jqExpected Response:
{
"@id": "User/alice_1234567890",
"@type": "User",
"name": "alice_1234567890",
"capability": [
{
"@id": "Capability/...",
"@type": "Capability",
"role": [
{
"@id": "Admin Role",
"@type": "Role",
"name": "Admin Role",
"action": [
"create_database",
"delete_database",
"instance_read_access",
"instance_write_access",
"schema_read_access",
"schema_write_access",
"manage_capabilities",
...
]
}
],
"scope": {
"@id": "Organization/acme_corp_1234567890",
"@type": "Organization",
"name": "acme_corp_1234567890"
}
}
]
}Alice now has the Admin Role role for the organization, including the crucial manage_capabilities action that enables her to grant other users capabilities on the organization and their databases.
Part 4: Alice Invites Bob as Organization Admin
Now Alice can use her organization admin privileges to invite Bob. Organization admins can grant capabilities using resource IDs (without needing system admin access):
curl -X POST "${TERMINUSDB_URL}/api/capabilities" \
-u "${ORG_ADMIN_USER}:${ORG_ADMIN_PASS}" \
-H "Content-Type: application/json" \
-d "{
\"operation\": \"grant\",
\"scope\": \"Organization/${ORG_NAME}\",
\"user\": \"User/${REGULAR_USER}\",
\"roles\": [\"Role/admin\"]
}"Key Points:
- Alice authenticates using her credentials (not system admin)
- Uses resource IDs:
Organization/{name},User/{name},Role/admin - No
scope_typeparameter needed when using IDs - This demonstrates delegated capability management
Expected Response:
{
"@type": "api:CapabilityResponse",
"api:status": "api:success"
}Verify Bob's Capabilities
Alice can now verify Bob's capabilities using the organization-scoped endpoint (organization admins can query users about the capabilities they hold in their organization):
curl -s -X GET "${TERMINUSDB_URL}/api/organizations/${ORG_NAME}/users/${REGULAR_USER}" \
-u "${ORG_ADMIN_USER}:${ORG_ADMIN_PASS}" | jq '.capability[0].role[0].name'Expected Response:
"Admin Role"Key Points:
- Organization admins can query capabilities for users within their organization using
/api/organizations/{org}/users/{user} - The global
/api/users/{user}?capability=trueendpoint requires system admin access (reads from SystemDatabase) - This allows Alice to manage and audit capabilities she has granted
Bob now has organization admin privileges, granted by Alice (not the system admin).
Part 5: Bob Creates a Data Product (Database)
Now let's demonstrate that Bob can exercise his organization admin privileges by creating a database. Bob has the create_database permission from the Admin Role that Alice granted him:
curl -X POST "${TERMINUSDB_URL}/api/db/${ORG_NAME}/${DB_NAME}" \
-u "${REGULAR_USER}:${REGULAR_PASS}" \
-H "Content-Type: application/json" \
-d '{
"label": "Products Database",
"comment": "Database for product information",
"schema": true
}'Expected Response:
{
"@type": "api:DbCreateResponse",
"api:status": "api:success"
}Verify Database Creation
curl -s -X GET "${TERMINUSDB_URL}/api/db/${ORG_NAME}/${DB_NAME}" \
-u "${ORG_ADMIN_USER}:${ORG_ADMIN_PASS}" \
-H "Content-Type: application/json" | jqPart 6: Alice Invites Charlie to the Data Product
Now Alice will grant Charlie access to just the products database (not the entire organization) using the ID-based API.
Get the Database Resource ID
First, Alice needs to get the database's resource ID:
DB_RESOURCE_ID=$(curl -s -X GET "${TERMINUSDB_URL}/api/db/${ORG_NAME}/${DB_NAME}?verbose=true" \
-u "${ORG_ADMIN_USER}:${ORG_ADMIN_PASS}" | jq -r '."@id"')
echo "Database Resource ID: ${DB_RESOURCE_ID}"Example Output:
Database Resource ID: UserDatabase/SsGIjJtbWy0tHzBfGrant Charlie Access Using Resource ID
Now use the resource ID to grant Charlie admin access to the database:
curl -X POST "${TERMINUSDB_URL}/api/capabilities" \
-u "${ORG_ADMIN_USER}:${ORG_ADMIN_PASS}" \
-H "Content-Type: application/json" \
-d "{
\"operation\": \"grant\",
\"scope\": \"${DB_RESOURCE_ID}\",
\"user\": \"User/${DB_USER}\",
\"roles\": [\"Role/admin\"]
}"Key Points:
- Database resource IDs are hashes (e.g.,
UserDatabase/SsGIjJtbWy0tHzBf), not database names - Get the resource ID from the database metadata endpoint with
?verbose=true - User format:
User/{username}(not hashed) - Role format:
Role/admin(built-in role names) - No
scope_typeparameter (only system admin can use that)
Expected Response:
{
"@type": "api:CapabilityResponse",
"api:status": "api:success"
}Alice Audits Database Access
Alice can audit which users have access to databases in her organization by listing all organization users. This shows all capabilities including database-level grants:
curl -s -X GET "${TERMINUSDB_URL}/api/organizations/${ORG_NAME}/users" \
-u "${ORG_ADMIN_USER}:${ORG_ADMIN_PASS}" | jqExpected Response: Alice can see all users and their capabilities. Charlie's entry will show database-level access:
[
{
"@id": "User/charlie_...",
"name": "charlie_...",
"capability": [
{
"@id": "Capability/...",
"scope": "UserDatabase/...",
"role": [
{
"name": "Admin Role",
"action": ["instance_read_access", "schema_read_access", ...]
}
]
}
]
}
]Key Points:
- Organization admins can see all users and their capabilities in the organization
- This includes both organization-level and database-level grants
- Allows auditing who has access to specific databases
- Can be filtered using
jqto find users with access to a specific database
Part 6.5: Creating Custom Roles
While TerminusDB provides built-in roles (Admin Role and Consumer Role), you can create custom roles tailored to specific use cases. Let's create a custom "Database Analyst" role for users who need read-only access plus metadata viewing.
Create a Custom Role
Custom roles allow you to grant precisely the permissions your users need. Remember that creating roles require system administrator access:
curl -X POST "${TERMINUSDB_URL}/api/roles" \
-u "${ADMIN_USER}:${ADMIN_PASS}" \
-H "Content-Type: application/json" \
-d '{
"name": "Database Analyst",
"action": [
"instance_read_access",
"schema_read_access",
"meta_read_access",
"commit_read_access",
"class_frame"
]
}'Expected Response: Role ID
"terminusdb://system/data/Role/Database%20Analyst"Understanding Role Permissions
The custom "Database Analyst" role includes:
instance_read_access: Required to read documents and query instance dataschema_read_access: Access to schema definitionsmeta_read_access: Access to database metadatacommit_read_access: View commit historyclass_frame: Query class structure
Note: The /api/db/{org}/{db} metadata endpoint checks for instance_read_access permission. However, at the database level (not organization level), capabilities grant operational access to documents and queries, but metadata endpoints typically require organization-level permissions for full access when users are not granted instance access to database contents.
Bob Changes Charlie's Role
Now Bob exercises his organization admin privileges to change Charlie's access from Admin Role to the custom Database Analyst role, providing more restricted database-level access.
First, Bob gets the database resource ID:
DB_RESOURCE_ID=$(curl -s -X GET "${TERMINUSDB_URL}/api/db/${ORG_NAME}/${DB_NAME}?verbose=true" \
-u "${REGULAR_USER}:${REGULAR_PASS}" | jq -r '."@id"')
echo "Database Resource ID: ${DB_RESOURCE_ID}"Revoke Charlie's Admin Role on the database:
curl -X POST "${TERMINUSDB_URL}/api/capabilities" \
-u "${REGULAR_USER}:${REGULAR_PASS}" \
-H "Content-Type: application/json" \
-d "{
\"operation\": \"revoke\",
\"scope\": \"${DB_RESOURCE_ID}\",
\"user\": \"User/${DB_USER}\",
\"roles\": [\"Role/admin\"]
}"Now grant the Database Analyst role to Charlie:
curl -X POST "${TERMINUSDB_URL}/api/capabilities" \
-u "${REGULAR_USER}:${REGULAR_PASS}" \
-H "Content-Type: application/json" \
-d "{
\"operation\": \"grant\",
\"scope\": \"${DB_RESOURCE_ID}\",
\"user\": \"User/${DB_USER}\",
\"roles\": [\"Role/Database%20Analyst\"]
}"Key Points:
- Bob authenticates with his organization admin credentials
- Gets database resource ID first (databases use hashed IDs)
- Revokes Admin Role before granting Database Analyst (role transition)
- Uses ID-based format:
${DB_RESOURCE_ID},User/{username},Role/{rolename} - Role name is URL-encoded:
Database%20Analyst - No
scope_typeparameter needed - Demonstrates Bob can manage database-level access
Expected Response:
{
"@type": "api:CapabilityResponse",
"api:status": "api:success"
}Bob Verifies Custom Role Assignment
Bob can verify Charlie's new capability using the organization users endpoint:
curl -s -X GET "${TERMINUSDB_URL}/api/organizations/${ORG_NAME}/users/${DB_USER}" \
-u "${REGULAR_USER}:${REGULAR_PASS}" | jq '.capability[] | {role: .role[].name, scope: .scope}'Expected Response:
{
"role": "Database Analyst",
"scope": "products"
}View All Available Roles
System administrators can list all roles (built-in and custom) in the system. Other users must know the specific role identifiers or names. The system administrators can list the roles using the /api/roles endpoint. Ask your system administrator to get the list of roles in your system:
curl -s -X GET "${TERMINUSDB_URL}/api/roles" \
-u "${ADMIN_USER}:${ADMIN_PASS}" | jq '.[] | {name: .name, actions: .action}'This returns all roles with their associated permissions, helping you choose or design the right role for each user.
Part 7: Testing Authorization Boundaries
Now let's verify that users can only perform actions they're authorized for.
Test 1: Charlie Cannot Create Databases in the Organization
Charlie has admin access to the products database but NOT the organization. He should not be able to create new databases:
curl -X POST "${TERMINUSDB_URL}/api/db/${ORG_NAME}/unauthorized_db" \
-u "${DB_USER}:${DB_USER_PASS}" \
-H "Content-Type: application/json" \
-d '{
"label": "Unauthorized Database",
"schema": true
}'Expected Response: Error 403 (Forbidden)
{
"@type": "api:DbCreateErrorResponse",
"api:status": "api:not_found",
"api:error": {
"@type": "api:UnknownOrganization",
"api:organization_name": "acme_corp_1234567890"
}
}This demonstrates that Charlie's capabilities are limited to the specific database scope.
Test 2: Charlie Cannot Invite Users to the Organization
Charlie should not be able to grant capabilities at the organization level:
curl -X POST "${TERMINUSDB_URL}/api/capabilities" \
-u "${DB_USER}:${DB_USER_PASS}" \
-H "Content-Type: application/json" \
-d "{
\"operation\": \"grant\",
\"scope\": \"${ORG_NAME}\",
\"user\": \"${REGULAR_USER}\",
\"roles\": [\"Consumer Role\"],
\"scope_type\": \"organization\"
}"Expected Response: Error 403 (Forbidden)
Charlie doesn't have manage_capabilities permission at the organization level.
Test 3: Charlie CAN Access His Authorized Database
Charlie should be able to access database operations (documents and queries) for the products database:
Test 3a: Access Document Schema
curl -s -X GET "${TERMINUSDB_URL}/api/document/${ORG_NAME}/${DB_NAME}?graph_type=schema" \
-u "${DB_USER}:${DB_USER_PASS}" \
-H "Content-Type: application/json" | jqExpected Response: Schema context
{
"@base": "terminusdb:///data/",
"@schema": "terminusdb:///schema#",
"@type": "@context"
}Test 3b: Access via GraphQL
curl -s -X POST "${TERMINUSDB_URL}/api/graphql/${ORG_NAME}/${DB_NAME}" \
-u "${DB_USER}:${DB_USER_PASS}" \
-H "Content-Type: application/json" \
-d '{"query": "{ __schema { types { name } } }"}' | jq '.data.__schema.types[0].name'Expected Response: Returns schema type name
"GraphType"Verify Charlie Can List His Database
Let's verify Charlie can now see the organization's database he was invited, in the list of databases he has access to:
curl -s -X GET "${TERMINUSDB_URL}/api/db" \
-u "${DB_USER}:${DB_USER_PASS}" | jqExpected Response: Charlie should see the database he has access to:
[
{
"path": "acme_corp_1234567890/products"
}
]Verify Charlie Can Access Database Metadata
Charlie can also access the metadata endpoint for his database. By default, it returns minimal information:
curl -s -X GET "${TERMINUSDB_URL}/api/db/${ORG_NAME}/${DB_NAME}" \
-u "${DB_USER}:${DB_USER_PASS}" | jqExpected Response:
{
"path": "acme_corp_1234567890/products"
}To see full metadata (label, comment, creation date), add the verbose=true parameter:
curl -s -X GET "${TERMINUSDB_URL}/api/db/${ORG_NAME}/${DB_NAME}?verbose=true" \
-u "${DB_USER}:${DB_USER_PASS}" | jqExpected Response:
{
"@id": "UserDatabase/...",
"@type": "UserDatabase",
"comment": "Database for product information",
"creation_date": "2026-01-04T11:16:08.219Z",
"label": "Products Database",
"name": "products",
"path": "acme_corp_1234567890/products",
"state": "finalized"
}What Charlie Can and Cannot Do:
With database-level instance_read_access, Charlie can:
- List his accessible database in the organization
- View metadata for his database
- Read documents and query data
- Read schema definitions
- Cannot see or access other databases in the organization
- Cannot create new databases (requires organization-level permissions)
Compare this to Alice and Bob (organization admins) who can see and access all databases in the organization.
Test 4: Bob (Org Admin) CAN Create Databases
Bob has organization admin privileges, so he should be able to create databases:
curl -X POST "${TERMINUSDB_URL}/api/db/${ORG_NAME}/inventory" \
-u "${REGULAR_USER}:${REGULAR_PASS}" \
-H "Content-Type: application/json" \
-d '{
"label": "Inventory Database",
"schema": true
}'Expected Response:
{
"@type": "api:DbCreateResponse",
"api:status": "api:success"
}Test 5: Bob CAN Invite Users
Bob should be able to grant capabilities since he's an organization admin. First, get the inventory database resource ID:
INVENTORY_RESOURCE_ID=$(curl -s -X GET "${TERMINUSDB_URL}/api/db/${ORG_NAME}/inventory?verbose=true" \
-u "${REGULAR_USER}:${REGULAR_PASS}" | jq -r '."@id"')
echo "Inventory Database Resource ID: ${INVENTORY_RESOURCE_ID}"Now Bob grants Charlie the consumer role on the inventory database:
curl -X POST "${TERMINUSDB_URL}/api/capabilities" \
-u "${REGULAR_USER}:${REGULAR_PASS}" \
-H "Content-Type: application/json" \
-d "{
\"operation\": \"grant\",
\"scope\": \"${INVENTORY_RESOURCE_ID}\",
\"user\": \"User/${DB_USER}\",
\"roles\": [\"Role/consumer\"]
}"Key Points:
- Bob uses his organization admin credentials
- Gets inventory database resource ID first (databases use hashed IDs)
- ID-based format:
${INVENTORY_RESOURCE_ID},User/{username},Role/consumer - No
scope_typeparameter (only system admin can use that)
Expected Response:
{
"@type": "api:CapabilityResponse",
"api:status": "api:success"
}Part 8: Understanding Permission Hierarchy
Let's understand how organization-level and database-level permissions interact.
Verify Bob's Write Access Still Works
Bob has organization-level Admin Role. Let's verify he still has write access to the products database:
curl -s -X GET "${TERMINUSDB_URL}/api/organizations/${ORG_NAME}/users/${REGULAR_USER}" \
-u "${ORG_ADMIN_USER}:${ORG_ADMIN_PASS}" | jq '.capability[] | {role: .role[].name, scope: .scope}'Expected Response:
{
"role": "Admin Role",
"scope": "Organization/acme_corp_1234567890"
}Bob's organization-level Admin Role includes instance_write_access, which applies to all databases in the organization.
Important: Organization-level permissions are broader than database-level permissions. If a user has organization-level access, database-level grants don't reduce their permissions—they already have access to all databases.
Consumer Role Demonstration with Charlie
To properly demonstrate read-only Consumer Role access, let's verify Charlie's access with his Database Analyst role (which includes read and write permissions):
Part 9: Listing Users in an Organization
Alice and Bob can see all users with capabilities in their organization:
curl -s -X GET "${TERMINUSDB_URL}/api/organizations/${ORG_NAME}/users/" \
-u "${ORG_ADMIN_USER}:${ORG_ADMIN_PASS}" \
-H "Content-Type: application/json" | jqExpected Response:
[
{
"@id": "User/alice_1234567890",
"name": "alice_1234567890",
"capability": [...]
},
{
"@id": "User/bob_1234567890",
"name": "bob_1234567890",
"capability": [...]
},
{
"@id": "User/charlie_1234567890",
"name": "charlie_1234567890",
"capability": [...]
}
]Part 10: Revoking Access
Alice can revoke Charlie's access to the products database using the ID-based API.
First, get the products database resource ID (if continuing from Part 6, this is already in DB_RESOURCE_ID):
DB_RESOURCE_ID=$(curl -s -X GET "${TERMINUSDB_URL}/api/db/${ORG_NAME}/${DB_NAME}?verbose=true" \
-u "${ORG_ADMIN_USER}:${ORG_ADMIN_PASS}" | jq -r '."@id"')
echo "Database Resource ID: ${DB_RESOURCE_ID}"Now revoke Charlie's Database Analyst role:
curl -X POST "${TERMINUSDB_URL}/api/capabilities" \
-u "${ORG_ADMIN_USER}:${ORG_ADMIN_PASS}" \
-H "Content-Type: application/json" \
-d "{
\"operation\": \"revoke\",
\"scope\": \"${DB_RESOURCE_ID}\",
\"user\": \"User/${DB_USER}\",
\"roles\": [\"Role/Database%20Analyst\"]
}"Expected Response:
{
"@type": "api:CapabilityResponse",
"api:status": "api:success"
}Verify Revocation
Charlie should no longer be able to access documents in the products database:
curl -s -X GET "${TERMINUSDB_URL}/api/document/${ORG_NAME}/${DB_NAME}" \
-u "${DB_USER}:${DB_USER_PASS}" | jqExpected Response: 403 Forbidden
{
"api:status": "api:forbidden",
"api:message": "Access to 'UserDatabase/...' is not authorised with action 'instance_read_access'",
"action": "'@schema':'Action/instance_read_access'"
}Note: Charlie can still access the metadata endpoint (GET /api/db/{org}/{db}) because he retains organization-level Metadata Viewer role. The revocation only removed his database-level Database Analyst role.
Summary
This tutorial demonstrated:
- System Admin Powers: Only system administrators can create organizations
- Organization Admins: Can create databases and invite users to the organization
- Capability Delegation: Organization admins can grant capabilities without system admin involvement
- Scope Hierarchy: Users can have different roles at organization vs. database level
- Capability Precedence: Organization-level capabilities are broader than database-level capabilities—if a user has organization-level admin access, database-level grants don't reduce their permissions
- Authorization Boundaries: Users cannot perform actions outside their granted capabilities
- Role Differences: Admin role includes
manage_capabilities, consumer role provides read-only access
Key Takeaways
- Capabilities = User + Role + Scope (where scope is organization or database)
- Organization admins have the
manage_capabilitiesaction, allowing them to invite users - Database admins can manage the database but cannot create new databases or invite org-level users
- Consumer role provides read-only access
- Delegation works: Org admins can grant capabilities without requiring system admin intervention
Cleanup
To remove all resources created in this tutorial:
# Delete databases
curl -X DELETE "${TERMINUSDB_URL}/api/db/${ORG_NAME}/${DB_NAME}" \
-u "${ADMIN_USER}:${ADMIN_PASS}"
curl -X DELETE "${TERMINUSDB_URL}/api/db/${ORG_NAME}/inventory" \
-u "${ADMIN_USER}:${ADMIN_PASS}"
# Delete organization (must be empty first)
curl -X DELETE "${TERMINUSDB_URL}/api/organizations/${ORG_NAME}" \
-u "${ADMIN_USER}:${ADMIN_PASS}"
# Delete users
curl -X DELETE "${TERMINUSDB_URL}/api/users/${ORG_ADMIN_USER}" \
-u "${ADMIN_USER}:${ADMIN_PASS}"
curl -X DELETE "${TERMINUSDB_URL}/api/users/${REGULAR_USER}" \
-u "${ADMIN_USER}:${ADMIN_PASS}"
curl -X DELETE "${TERMINUSDB_URL}/api/users/${DB_USER}" \
-u "${ADMIN_USER}:${ADMIN_PASS}"
# Delete custom role
curl -X DELETE "${TERMINUSDB_URL}/api/roles/Database%20Analyst" \
-u "${ADMIN_USER}:${ADMIN_PASS}"Next Steps
- Explore Database Management for working with data products
- Learn about WOQL Queries for querying your databases
- Review Authorization Actions for complete list of permissions