User Management

Complete admin/user lifecycle with 27 endpoints, bulk operations, impersonation, and protected admin rules.

Admin vs User Model

SCRIPE separates admins and users as distinct entities. Admins manage the platform and have full RBAC with assigned roles. Users are end-users of the tenant's application with limited, self-service capabilities.

AspectAdminUser
EntityAdmin (extends AuditableEntity)User (extends AuditableEntity)
Auth Prefix/api/auth/admin/*/api/auth/user/*
PermissionsFull RBAC, assigned rolesLimited, self-service
Can Manage OthersYes (CRUD admins/users)No
Tenant ScopedYesYes
Has RolesYes (many-to-many AdminRole)No
Protected FlagIsProtected on super adminNo
ControllerAdminsController (27 endpoints)UsersController

Self-Service Registration Validation Pipeline

User registration undergoes strict validation: unique email verification across the tenant partition, password strength scoring, and tenant-scoped invitation token binding.

RegisterUserCommandValidator.csC#
public sealed class RegisterUserCommandValidator : AbstractValidator<RegisterUserCommand>
{
    public RegisterUserCommandValidator()
    {
        RuleFor(x => x.Username)
            .NotEmpty().MaximumLength(100)
            .Matches("^[a-zA-Z0-9_]+$");

        RuleFor(x => x.Password)
            .NotEmpty().MinimumLength(6);

        RuleFor(x => x.Email)
            .EmailAddress().When(x => !string.IsNullOrEmpty(x.Email));

        RuleFor(x => x.TenantCode)
            .NotEmpty().MaximumLength(100).WithMessage("TenantCode is required.");
    }
}

User Invitation Flow

Administrators invite users by email. A time-limited, cryptographically signed token is issued with pre-assigned roles and organizational group memberships.

User Invitation & Activation Flow
Admin Invites User (CreateAdminCommand, SendSetupEmail=true)
Generate 256-bit Secure Token (RandomNumberGenerator)
Hash Token (SHA256) & Set 24-Hour Expiry
Save Inactive User with Token Hash
Resolve URL (Tenant Custom Domain or Platform URL)
Send Activation Email (Scriban Template & SMTP)
User clicks link, submits new password
Verify Token Hash & Check Expiry
Validate Password against Tenant Password Policy
Hash Password, Set IsAccountActivated=true, Clear Token

AdminsController CRUD Endpoints

MethodEndpointDescriptionAuth
GET/adminsPaginated list (data-scope aware)🔒 Required
GET/admins/{id}Single admin detail🔒 Required
GET/admins/tenant/{tenantId}Admins by specific tenant🔒 Required
GET/admins/my-tenantAdmins in caller's tenant🔒 Required
POST/adminsCreate with explicit TenantId🔒 Required
POST/admins/my-tenantCreate for caller's tenant (from JWT)🔒 Required
PUT/admins/{id}Update admin🔒 Required
DELETE/admins/{id}Soft delete admin🔒 Required

Account Operations

MethodEndpointDescriptionAuth
PUT/admins/{id}/activeActivate/deactivate🔒 Required
PUT/admins/{id}/change-passwordChange own password🔒 Required
PUT/admins/{id}/reset-passwordSuper admin resets password🔒 Required

Role Management Endpoints

MethodEndpointDescriptionAuth
GET/admins/{id}/rolesGet assigned roles🔒 Required
POST/admins/{id}/roles/{roleId}Assign single role🔒 Required
DELETE/admins/{id}/roles/{roleId}Remove single role🔒 Required
PUT/admins/{id}/roles/syncNuke & Pave replace all roles🔒 Required

Bulk Operations

MethodEndpointDescriptionAuth
POST/admins/bulk/activateActivate selected IDs🔒 Required
POST/admins/bulk/deactivateDeactivate selected IDs🔒 Required
POST/admins/bulk/deleteDelete selected IDs🔒 Required
POST/admins/bulk/activate-allActivate ALL matching filter🔒 Required
POST/admins/bulk/deactivate-allDeactivate ALL matching filter🔒 Required
POST/admins/bulk/delete-allDelete ALL matching filter🔒 Required

Enterprise Operations

MethodEndpointDescriptionAuth
POST/admins/{id}/impersonateImpersonate another admin🔒 Required
POST/admins/{id}/transferMove admin to different tenant🔒 Required
POST/admins/{id}/transfer-protectionTransfer 'protected' flag🔒 Required

Protected Admin Rules

Each tenant has exactly one protected admin the super admin who created the tenant. The protected flag prevents accidental deletion or deactivation of the tenant's primary administrator.

  • Each tenant has exactly one protected admin (the super admin who created the tenant)
  • Protected flag can be transferred to another admin via TransferProtection
  • Protected admins cannot be deleted, deactivated, or have roles removed
Protected Admin Rules
Protected Admin
Cannot be Deleted
Cannot be Deactivated
Cannot be Transferred (unless by another protected)
Owns Protected Super Admin Role
Gets All Tenant Permissions

Nuke & Pave Pattern

AdminsController.csC#
// PUT /admins/{id}/roles/sync
// Replaces ALL existing roles with the provided list
// This is safer than individual add/remove in concurrent scenarios

[HttpPut("{id}/roles/sync")]
public async Task<IActionResult> SyncRoles(string id, [FromBody] SyncRolesCommand command)
{
    // Deletes all AdminRole entries for this admin
    // Re-creates entries for each role in the request
    // Single transaction  no partial states
}