---
title: "Example: User Management System · RUAL Documentation"
description: "Profiles alongside cluster users, teams and role changes."
canonical: https://docs.rual.nl/examples/user-management
language: en
---

# Example: User Management System

Invite, role, suspend, and audit the people using your app. A complete admin section built on cluster accounts and a profiles storage.

Cluster accounts handle sign-in and tokens; your app adds profiles, roles, and lifecycle. This example builds the full admin section on top of both.

### Accounts vs Profiles

- **Cluster user**: credentials, scopes, tokens; created by an admin via [User Access Management](https://docs.rual.nl/cluster/user-access-management) or the users API.

- **Profile document**: your app's data about the person: display name, team, role, settings; stored in a `profiles` storage keyed by the user's guid.

```
{
  "_meta": {
    "cms": 1780531200274,
    "created": 1780531200,
    "entity": 1,
    "expiry": -1,
    "guid": "b9ee6a631b24e78d1aa48aef0dc067fff7bfbacd24a56ef4ed1f08e537d48b6b",
    "removed": 0,
    "ums": 1782166695586,
    "update_hash": "2c6a91e4f7530bd8146ae9c30fb5724d81ea3f06",
    "updated": 1782166695
  },
  "display_name": "sami b",
  "preferences": {
    "digest": "weekly",
    "theme": "dark"
  },
  "role": "manager",
  "status": "active",
  "team": "engineering",
  "user_guid": "b9ee6a631b24e78d1aa48aef0dc067fff7bfbacd24a56ef4ed1f08e537d48b6bd02"
}
```

### The Lifecycle

- **Invite**: admin creates the cluster user (+ their scopes), then a flow creates the profile with `status: invited` and a welcome email ([Email System Setup](https://docs.rual.nl/tutorials/email-system)).

- **First login**. A flow on the member home page sees `status: invited`, flips it to `active`, and shows the onboarding checklist.

- **Role changes**: update the profile's `role` for app behavior, and the user's `custom_scopes` for API/page gating. Keep both in one admin flow so they never drift.

- **Suspend**: `status: suspended` on the profile blocks app screens; removing the user's scopes blocks the APIs. Account deletion is the last resort, suspended keeps history.

### The Admin Pages

- **Directory**: search profiles with filters (team, role, status). The list pattern from [First CRUD App](https://docs.rual.nl/getting-started/first-crud-app), scoped `*loggedin` + `people_admin`.

- **Detail page**: profile fields editable, scopes visible, activity summary (last login from the cluster's user activity).

- **Self-service page**: members edit only their own profile: fetched with `user_current` → [`function_get_document`](https://docs.rual.nl/block-types/storage/function_get_document) on `user_guid`. See [knowing who's calling](https://docs.rual.nl/tutorials/user-authentication#knowing-who-calls).

### Audit Trail

- Every admin action (invite, role change, suspend) writes an event document: actor (from `user_current`), target, before/after. The activity-log model from [Storage Examples](https://docs.rual.nl/blueprints/storage-examples#activity-logs).

- Review per-user history with a term query on `target_guid`, sorted by `_meta.created`.

### Next Steps
