Skip to content

RBAC (Role-Based Access Control) Examples

Last Updated: 2025-11-23

Complete examples for managing roles, permissions, and access control in ocmonica.


Table of Contents


List Roles

Get all roles in an organization including built-in and custom roles.

REST API

Endpoint: GET /organizations/:orgId/roles

curl Example

curl -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  http://localhost:8080/organizations/org-789/roles

JavaScript/TypeScript Example

async function listRoles(orgId: string) {
  const response = await fetch(`http://localhost:8080/organizations/${orgId}/roles`, {
    headers: {
      'Authorization': `Bearer ${accessToken}`
    }
  });

  return await response.json();
}

// Usage
const roles = await listRoles('org-789');
roles.forEach(role => {
  console.log(`Role: ${role.name}`);
  console.log(`Permissions: ${role.permissions.join(', ')}`);
});

Python Example

import requests

def list_roles(org_id, access_token):
    response = requests.get(
        f'http://localhost:8080/organizations/{org_id}/roles',
        headers={'Authorization': f'Bearer {access_token}'}
    )

    return response.json()

# Usage
roles = list_roles('org-789', access_token)
for role in roles:
    print(f"Role: {role['name']}")
    print(f"Permissions: {', '.join(role['permissions'])}")

Go Example

type Role struct {
    ID             string   `json:"id"`
    Name           string   `json:"name"`
    Description    string   `json:"description"`
    Permissions    []string `json:"permissions"`
    OrganizationID string   `json:"organization_id"`
    IsBuiltin      bool     `json:"is_builtin"`
}

func listRoles(orgID, accessToken string) ([]Role, error) {
    req, _ := http.NewRequest("GET",
        fmt.Sprintf("http://localhost:8080/organizations/%s/roles", orgID),
        nil)

    req.Header.Set("Authorization", "Bearer "+accessToken)

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    var roles []Role
    json.NewDecoder(resp.Body).Decode(&roles)
    return roles, nil
}

Response

[
  {
    "id": "role-admin",
    "name": "admin",
    "description": "Full access to all resources",
    "permissions": ["file:*", "org:*", "user:*", "role:*", "group:*"],
    "organization_id": "org-789",
    "is_builtin": true
  },
  {
    "id": "role-member",
    "name": "member",
    "description": "Limited access to files and organization",
    "permissions": ["file:read", "file:write", "org:read"],
    "organization_id": "org-789",
    "is_builtin": true
  }
]

Create Custom Role

Create a custom role with specific permissions.

REST API

Endpoint: POST /organizations/:orgId/roles

Requires: role:create permission (admin only)

curl Example

curl -X POST http://localhost:8080/organizations/org-789/roles \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "editor",
    "description": "Can edit files but not delete",
    "permissions": ["file:read", "file:write", "org:read"]
  }'

JavaScript/TypeScript Example

interface CreateRoleRequest {
  name: string;
  description?: string;
  permissions: string[];
}

async function createRole(
  orgId: string,
  name: string,
  permissions: string[],
  description?: string
) {
  const response = await fetch(`http://localhost:8080/organizations/${orgId}/roles`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name,
      description,
      permissions
    })
  });

  return await response.json();
}

// Usage
const editorRole = await createRole(
  'org-789',
  'editor',
  ['file:read', 'file:write', 'org:read'],
  'Can edit files but not delete'
);

console.log(`Role created: ${editorRole.id}`);

Python Example

import requests

def create_role(org_id, name, permissions, access_token, description=None):
    data = {
        'name': name,
        'permissions': permissions
    }

    if description:
        data['description'] = description

    response = requests.post(
        f'http://localhost:8080/organizations/{org_id}/roles',
        headers={'Authorization': f'Bearer {access_token}'},
        json=data
    )

    return response.json()

# Usage
editor_role = create_role(
    'org-789',
    'editor',
    ['file:read', 'file:write', 'org:read'],
    access_token,
    description='Can edit files but not delete'
)

print(f"Role created: {editor_role['id']}")

Go Example

type CreateRoleRequest struct {
    Name        string   `json:"name"`
    Description string   `json:"description,omitempty"`
    Permissions []string `json:"permissions"`
}

func createRole(orgID, name, description, accessToken string, permissions []string) (*Role, error) {
    reqData := CreateRoleRequest{
        Name:        name,
        Description: description,
        Permissions: permissions,
    }

    jsonData, _ := json.Marshal(reqData)
    req, _ := http.NewRequest("POST",
        fmt.Sprintf("http://localhost:8080/organizations/%s/roles", orgID),
        bytes.NewBuffer(jsonData))

    req.Header.Set("Authorization", "Bearer "+accessToken)
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    var role Role
    json.NewDecoder(resp.Body).Decode(&role)
    return &role, nil
}

Get Role Details

Get detailed information about a specific role.

REST API

Endpoint: GET /api/v1/roles/:id

curl Example

curl -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  http://localhost:8080/api/v1/roles/role-editor

JavaScript/TypeScript Example

async function getRole(roleId: string) {
  const response = await fetch(
    `http://localhost:8080/api/v1/roles/${roleId}`,
    {
      headers: {
        'Authorization': `Bearer ${accessToken}`
      }
    }
  );

  return await response.json();
}

// Usage
const role = await getRole('role-editor');
console.log(`Role: ${role.name}`);
console.log(`Permissions: ${role.permissions.join(', ')}`);

Update Role

Update role name, description, or permissions.

REST API

Endpoint: PUT /api/v1/roles/:id

Requires: role:update permission (admin only)

Note: Cannot update built-in roles.

curl Example

curl -X PUT http://localhost:8080/api/v1/roles/role-editor \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "content_editor",
    "description": "Can edit and delete files",
    "permissions": ["file:read", "file:write", "file:delete", "org:read"]
  }'

JavaScript/TypeScript Example

async function updateRole(
  roleId: string,
  updates: {
    name?: string;
    description?: string;
    permissions?: string[];
  }
) {
  const response = await fetch(
    `http://localhost:8080/api/v1/roles/${roleId}`,
    {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(updates)
    }
  );

  return await response.json();
}

// Usage
const updated = await updateRole('role-editor', {
  name: 'content_editor',
  description: 'Can edit and delete files',
  permissions: ['file:read', 'file:write', 'file:delete', 'org:read']
});

Python Example

import requests

def update_role(role_id, access_token, **updates):
    response = requests.put(
        f'http://localhost:8080/api/v1/roles/{role_id}',
        headers={'Authorization': f'Bearer {access_token}'},
        json=updates
    )

    return response.json()

# Usage
updated = update_role(
    'role-editor',
    access_token,
    name='content_editor',
    description='Can edit and delete files',
    permissions=['file:read', 'file:write', 'file:delete', 'org:read']
)

Delete Role

Delete a custom role from the organization.

REST API

Endpoint: DELETE /api/v1/roles/:id

Requires: role:delete permission (admin only)

Note: Cannot delete built-in roles.

curl Example

curl -X DELETE \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  http://localhost:8080/api/v1/roles/role-editor

JavaScript/TypeScript Example

async function deleteRole(roleId: string) {
  const response = await fetch(
    `http://localhost:8080/api/v1/roles/${roleId}`,
    {
      method: 'DELETE',
      headers: {
        'Authorization': `Bearer ${accessToken}`
      }
    }
  );

  if (response.ok) {
    console.log('Role deleted successfully');
  }
}

// Usage with confirmation
if (confirm('Delete this role? Users will lose these permissions.')) {
  await deleteRole('role-editor');
}

Warning: Users with this role will lose associated permissions. Reassign users before deleting.


Assign Role to User

Assign a role to a user in the organization.

Note: Role assignment is handled via the organization member role update endpoint. See organization member management for details.

REST API

Endpoint: PUT /organizations/:id/members/:userId/role

Requires: role:assign permission (admin only)

curl Example

curl -X PUT http://localhost:8080/organizations/org-789/members/user-456/role \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "editor"
  }'

JavaScript/TypeScript Example

async function assignRoleToUser(orgId: string, userId: string, role: string) {
  const response = await fetch(
    `http://localhost:8080/organizations/${orgId}/members/${userId}/role`,
    {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        role: role
      })
    }
  );

  return await response.json();
}

// Usage
await assignRoleToUser('org-789', 'user-456', 'editor');
console.log('Role assigned successfully');

Python Example

import requests

def assign_role_to_user(org_id, user_id, role, access_token):
    response = requests.put(
        f'http://localhost:8080/organizations/{org_id}/members/{user_id}/role',
        headers={'Authorization': f'Bearer {access_token}'},
        json={'role': role}
    )

    return response.json()

# Usage
assign_role_to_user('org-789', 'user-456', 'editor', access_token)
print('Role assigned successfully')

Go Example

type AssignRoleRequest struct {
    Role string `json:"role"`
}

func assignRoleToUser(orgID, userID, role, accessToken string) error {
    reqData := AssignRoleRequest{Role: role}
    jsonData, _ := json.Marshal(reqData)

    req, _ := http.NewRequest("PUT",
        fmt.Sprintf("http://localhost:8080/organizations/%s/members/%s/role", orgID, userID),
        bytes.NewBuffer(jsonData))

    req.Header.Set("Authorization", "Bearer "+accessToken)
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    return nil
}

Remove Role from User

Remove a role assignment from a user by assigning them a different role (e.g., default 'member' role).


Check User Permissions

Verify if the current user has specific permissions.

REST API

Endpoint: GET /auth/permissions

curl Example

# Get all permissions
curl -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  http://localhost:8080/auth/permissions

# Check specific permission
curl -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  "http://localhost:8080/auth/permissions?check=file:delete"

JavaScript/TypeScript Example

async function getUserPermissions() {
  const response = await fetch(
    'http://localhost:8080/auth/permissions',
    {
      headers: {
        'Authorization': `Bearer ${accessToken}`
      }
    }
  );

  return await response.json();
}

async function hasPermission(permission: string): Promise<boolean> {
  const response = await fetch(
    `http://localhost:8080/auth/permissions?check=${permission}`,
    {
      headers: {
        'Authorization': `Bearer ${accessToken}`
      }
    }
  );

  const result = await response.json();
  return result.has_permission;
}

// Usage
const permissions = await getUserPermissions();
console.log('User permissions:', permissions);

if (await hasPermission('file:delete')) {
  console.log('User can delete files');
}

Python Example

import requests

def get_user_permissions(access_token):
    response = requests.get(
        'http://localhost:8080/auth/permissions',
        headers={'Authorization': f'Bearer {access_token}'}
    )

    return response.json()

def has_permission(permission, access_token):
    response = requests.get(
        f'http://localhost:8080/auth/permissions?check={permission}',
        headers={'Authorization': f'Bearer {access_token}'}
    )

    result = response.json()
    return result.get('has_permission', False)

# Usage
permissions = get_user_permissions(access_token)
print(f"User permissions: {permissions}")

if has_permission('file:delete', access_token):
    print('User can delete files')

Permission Enforcement Examples

Client-Side Permission Checks

// Conditionally render UI elements based on permissions
function FileActions({ file }: { file: File }) {
  const [canDelete, setCanDelete] = useState(false);
  const [canEdit, setCanEdit] = useState(false);

  useEffect(() => {
    Promise.all([
      hasPermission('file:delete'),
      hasPermission('file:write')
    ]).then(([deletePermission, writePermission]) => {
      setCanDelete(deletePermission);
      setCanEdit(writePermission);
    });
  }, []);

  return (
    <div>
      {canEdit && <button onClick={() => editFile(file.id)}>Edit</button>}
      {canDelete && <button onClick={() => deleteFile(file.id)}>Delete</button>}
    </div>
  );
}

Server-Side Permission Enforcement

The server enforces permissions at multiple levels:

  1. Middleware/Interceptor: First line of defense
  2. Service Layer: Business logic checks
  3. Repository: Organization scoping
// Example API call that will be checked server-side
async function deleteFile(fileId: string) {
  try {
    const response = await fetch(
      `http://localhost:8080/api/v1/files/${fileId}`,
      {
        method: 'DELETE',
        headers: {
          'Authorization': `Bearer ${accessToken}`
        }
      }
    );

    if (response.status === 403) {
      throw new Error('Permission denied: You do not have permission to delete files');
    }

    if (!response.ok) {
      throw new Error('Failed to delete file');
    }
  } catch (error) {
    console.error('Delete failed:', error);
    throw error;
  }
}

Permission Format

Permission Structure

Format: resource:action

Resources: - file - File operations - org - Organization management - user - User management - role - Role management - group - Group management

Actions: - read - Read/view resources - write - Create/update resources - delete - Delete resources - * - All actions (wildcard)

Common Permissions

const COMMON_PERMISSIONS = {
  // File permissions
  FILE_READ: 'file:read',
  FILE_WRITE: 'file:write',
  FILE_DELETE: 'file:delete',
  FILE_ALL: 'file:*',

  // Organization permissions
  ORG_READ: 'org:read',
  ORG_ADMIN: 'org:admin',
  ORG_ALL: 'org:*',

  // User management
  USER_READ: 'user:read',
  USER_MANAGE: 'user:manage',
  USER_ALL: 'user:*',

  // Role management
  ROLE_READ: 'role:read',
  ROLE_CREATE: 'role:create',
  ROLE_UPDATE: 'role:update',
  ROLE_DELETE: 'role:delete',
  ROLE_ASSIGN: 'role:assign',
  ROLE_ALL: 'role:*',
};

Built-in Role Definitions

const BUILTIN_ROLES = {
  admin: {
    name: 'admin',
    description: 'Full access to all resources',
    permissions: ['file:*', 'org:*', 'user:*', 'role:*', 'group:*']
  },
  member: {
    name: 'member',
    description: 'Limited access to files and organization',
    permissions: ['file:read', 'file:write', 'org:read']
  }
};

See Also