Custom Roles

Role System

RoleSourceDescription
ownerBuilt-inOrg creator, cannot be changed or transferred
memberBuilt-inDefault role
CustomConfig fileAdditional roles defined by developers

Config File

Define roles in api/src/config/website/tenant.{suffix}.ts:

import type { TenantConfig } from "@readystart/api-core"

export const getTenantConfig = (): TenantConfig => ({
  roles: [
    { value: "admin", label: "Admin" },
    { value: "editor", label: "Editor" },
    { value: "viewer", label: "Viewer" },
  ]
})

Rules

Frontend Behavior

When Inviting

Member Management

Backend Validation

Three layers of protection:

  1. Config loading: filters invalid values and reserved words
  2. validateRole: Controller-level check that role exists in config
  3. Service layer: role === 'owner' fallback guard
// In Controller
private async validateRole(role: string) {
  const roles = await getTenantRoles()
  const allowed = roles.filter(r => r.value !== 'owner').map(r => r.value)
  if (!allowed.includes(role)) {
    throw new ForbiddenException(`Invalid role: ${role}`)
  }
}

Usage in Business Code

// Check for a specific role
if (req.tenant?.role === 'admin' || req.tenant?.role === 'owner') {
  // Has admin permissions
}

// Filter menu by role
{ index: "/reports", title: "Reports", icon: FileText, tenantRoles: ["owner", "admin"] }