Managing Roles
Create and manage roles for your tenants
Managing Roles
Roles are collections of permissions that can be assigned to users. Each tenant manages their own roles independently, giving tenant admins full control over access levels within their organization.
How Roles Work
Each tenant has its own isolated set of roles:
┌───────────────────────────────────────┐
│ Tenant: Acme Corp │
│ ├── owner (required) │
│ ├── admin (custom) │
│ └── developer (custom) │
└───────────────────────────────────────┘
┌───────────────────────────────────────┐
│ Tenant: Beta Inc │
│ ├── owner (required) │
│ ├── manager (custom) │
│ └── viewer (custom) │
└───────────────────────────────────────┘Role changes in one tenant do not affect other tenants. Each organization has complete control over their role structure.
The Owner Role (Required)
The owner role is created automatically when a tenant is created. The user who creates the tenant is automatically assigned this role. Every tenant must have at least one owner.
Owner Role Behavior
- Auto-assigned: The tenant creator automatically receives the
ownerrole - Required: Cannot be deleted; every tenant must have at least one owner
- Full control: Owners typically have all tenant management permissions
Role Suggestions from Permissions
When defining permissions with JSDoc annotations, you can specify which roles should typically have each permission using the @role tag:
/**
* @group User Management
* @displayName Invite Users
* @role owner
* @role admin
*/
can_invite_user: User[];These @role annotations serve as suggestions when creating new roles in the UI. The permission metadata is returned by the API:
const { data } = await tenantsApi.getRoleDefinitions({ subject: 'User' });
// Each relation includes suggested roles
for (const namespace of data.data.namespaces) {
for (const relation of namespace.relations) {
console.log(`${relation.name}: suggested for ${relation.roles?.join(', ')}`);
}
}UI Components
OmniBase provides pre-built shadcn components for role management:
Managing Roles via API
Creating Roles
Create a new role for the current tenant:
import { V1TenantsApi } from '@omnibase/core-js';
const tenantsApi = new V1TenantsApi(config);
const { data } = await tenantsApi.createRole({
createRoleRequest: {
roleName: 'developer',
permissions: [
'tenant#can_view_users',
'tenant#can_create_api_keys',
'tenant#can_view_api_keys',
],
},
});
console.log('Created role:', data.data.role.id);Listing Roles
const { data } = await tenantsApi.listRoles();
for (const role of data.data.roles) {
console.log(`${role.role_name} (${role.id})`);
console.log(` Permissions: ${role.permissions.join(', ')}`);
console.log(` Users: ${role.user_ids.length}`);
}Updating Role Permissions
await tenantsApi.updateRole({
roleId: roleId,
updateRoleRequest: {
permissions: [
'tenant#can_view_users',
'tenant#can_invite_user', // Added permission
],
},
});Permission changes propagate immediately. All users with this role will have updated permissions on their next request.
Deleting Roles
await tenantsApi.deleteRole({
roleId: roleId,
});Before deleting a role, all users must be reassigned to a different role. The owner role cannot be deleted.
Assigning Users to Roles
Via Invitation
When inviting users, specify their role:
await tenantsApi.createInvite({
createTenantUserInviteRequest: {
email: 'teammate@example.com',
role: 'developer', // Role name
inviteUrl: 'https://app.example.com/auth/onboarding',
},
});Updating Existing User's Role
await tenantsApi.updateTenantUserRole({
updateTenantUserRoleRequest: {
userId: targetUserId,
role: 'admin', // New role name
},
});Common Role Patterns
Full Control — Auto-assigned to tenant creator
Typical permissions:
- All user management permissions
- All API key permissions
- All sensitive data access
- Tenant deletion
const ownerPermissions = [
'tenant#can_delete_tenant',
'tenant#can_invite_user',
'tenant#can_remove_user',
'tenant#can_update_user_role',
'tenant#can_view_users',
'tenant#can_update_roles',
'tenant#can_create_api_keys',
'tenant#can_view_api_keys',
'tenant#can_revoke_api_keys',
'tenant#can_view_database_password',
'tenant#can_rotate_keys',
];Team Management — For team managers
Typical permissions:
- User management (invite, remove, update roles)
- API key management
- Cannot delete tenant
const adminPermissions = [
'tenant#can_invite_user',
'tenant#can_remove_user',
'tenant#can_update_user_role',
'tenant#can_view_users',
'tenant#can_update_roles',
'tenant#can_create_api_keys',
'tenant#can_view_api_keys',
'tenant#can_revoke_api_keys',
];Development Access — For developers
Typical permissions:
- View team members
- API key management
- Database connection access
const developerPermissions = [
'tenant#can_view_users',
'tenant#can_create_api_keys',
'tenant#can_view_api_keys',
'tenant#can_view_database_connection_string',
'tenant#can_view_project_env',
];Read-Only Access — For external collaborators
Typical permissions:
- View team members only
const viewerPermissions = [
'tenant#can_view_users',
];Resource-Level Permissions
For fine-grained access to specific resources (projects, documents, etc.), use direct permission relationships:
// Grant project-specific access
await permissionsApi.createRelationship({
createRelationshipRequest: {
namespace: 'Project',
object: projectId,
relation: 'can_write',
subjectId: userId,
subjectNamespace: 'User',
},
});This allows scenarios like:
- Contractor: No tenant-wide permissions, only specific project access
- Project Lead: Manage specific projects without tenant admin access
- Auditor: Read-only access to specific resources
Example: Setting Up a New Tenant
When a new tenant is created, you might want to set up default roles:
async function setupTenantRoles(tenantsApi: V1TenantsApi) {
// Owner role is created automatically
// Create admin role
await tenantsApi.createRole({
createRoleRequest: {
roleName: 'admin',
permissions: [
'tenant#can_invite_user',
'tenant#can_remove_user',
'tenant#can_update_user_role',
'tenant#can_view_users',
'tenant#can_create_api_keys',
'tenant#can_view_api_keys',
],
},
});
// Create developer role
await tenantsApi.createRole({
createRoleRequest: {
roleName: 'developer',
permissions: [
'tenant#can_view_users',
'tenant#can_create_api_keys',
'tenant#can_view_api_keys',
'tenant#can_view_database_connection_string',
],
},
});
// Create member role
await tenantsApi.createRole({
createRoleRequest: {
roleName: 'member',
permissions: [
'tenant#can_view_users',
],
},
});
}Next Steps
- Defining Permissions — Create permission namespaces with JSDoc metadata
- Team Invitations — Invite users with specific roles
- Permissions Concept — Deep dive into ReBAC internals