Skip to main content

Roles

The Role entity defines the permissions and capabilities available to users within an organization. It is a fundamental component of Wrkbelt's role-based access control (RBAC) system, providing a flexible and secure way to manage user permissions.

Schema Definition

type Role = {
// Base Properties
_id: string; // MongoDB ObjectId
name: AllRoles; // Required, Unique, Predefined role types
description: string; // Required, Role description
permissions: string[]; // Array of Permission ObjectIds

// Timestamps
createdAt: Date; // Auto-generated
updatedAt: Date; // Auto-updated
} & BaseEntity;

Field Descriptions

Base Properties

FieldTypeRequiredUniqueDescription
_idObjectIdYesYesUnique identifier for the role
nameAllRolesYesYesPredefined role type (e.g., 'Owner', 'Admin')
descriptionstringYesNoHuman-readable description of the role
permissionsObjectId[]NoNoArray of references to associated Permission documents

Timestamps

FieldTypeDescription
createdAtDateAutomatically set when the role is created
updatedAtDateAutomatically updated when the role changes

Predefined Roles

note

The role system is designed to be extensible. The roles documented here represent the current set of roles at the time of writing. As the platform evolves, additional roles will be added to support new features and use cases.

The system currently defines the following standard roles through the AllRoles enum:

enum AllRoles {
OWNER = 'Owner',
ADMIN = 'Admin'
}

Role Metadata

Each role comes with predefined metadata:

const AllRolesMetadata = {
[AllRoles.OWNER]: {
name: 'Owner',
description: 'Owner of an organization'
},
[AllRoles.ADMIN]: {
name: 'Admin',
description: 'Admin for an organization'
}
} as const;

Type Variations

RolePopulated

A fully populated version with resolved permission references:

type RolePopulated = Omit<Role, 'permissions'> & {
permissions: Permission[]; // Full permission objects
};

Relationships

Primary Relationships

  • Role → Permissions (Many-to-Many)

    • Each role can have multiple permissions
    • Permissions can be assigned to multiple roles
    • Referenced via permissions array field
  • Role → Memberships (Many-to-Many)

    • Roles are assigned to users through memberships
    • Multiple users can have the same role
    • Relationship managed through Membership entity

Hierarchy

The role system follows a hierarchical structure:

  1. Owner: Highest level of access, complete control over organization
  2. Admin: Administrative access with elevated privileges

Validation

  • name: Required enum value from AllRoles
  • description: Required string
  • permissions: Optional array of ObjectId references to Permission

Security Considerations

  1. Role Assignment

    • Roles can only be assigned by users with appropriate permissions
    • Role changes should be audited for security tracking
    • System roles (Owner, Admin) have special protections
  2. Permission Management

    • Permissions are aggregated from all assigned roles
    • Permission checks should be performed at both role and individual permission levels
    • Caching may be used to optimize permission checks
  3. Role Hierarchy

    • Higher-level roles inherit permissions from lower-level roles
    • Some operations may require specific roles (e.g., Owner-only actions)
    • Role elevation should be properly authenticated and authorized

Usage Examples

Creating a Role

const role = {
name: AllRoles.ADMIN,
description: "Administrator with elevated privileges",
permissions: ["permission123", "permission456"]
};

Checking Role Assignments

// Check if user has specific role
const isAdmin = membership.roles.some(role => role.name === AllRoles.ADMIN);

// Get all permissions for a role
const roleWithPermissions = await Role.findById(roleId).populate('permissions');

Common Operations

  1. Permission Management

    // Add permissions to role
    await Role.updateOne(
    { _id: roleId },
    { $addToSet: { permissions: newPermissionId } }
    );
  2. Role Validation

    // Ensure role name is valid
    if (!Object.values(AllRoles).includes(roleName)) {
    throw new Error('Invalid role name');
    }