---
name: redash-permisos-cerberus
description: Query who has privileged permissions or is an admin in a Humand community. Translates the question to the correct model depending on whether the instance has Cerberus enabled or not. Use when CX or a PM asks "who are admins", "who has permissions", "users with privileged access", "list administrators", or any query about user permissions.
disable-model-invocation: true
---

# Permissions and Admins

Answers the question "who are admins / has privileged permissions" in a Humand community. The permissions model depends on whether the instance has Cerberus enabled.

## Prerequisite

Read skill `redash-connect` for client configuration and core tables.

## Flow

### Step 1 — Determine the permissions model

```sql
SELECT "code", "value"
FROM "FeatureFlags"
WHERE "instanceId" = :instance_id
  AND "code" = 'CERBERUS_ENABLED'
```

**If `value` = `'true'`** → use DS 25 (Cerberus). Go to Step 2A.
**If NOT found or `value` != `'true'`** → use DS 1 (Capabilities). Go to Step 2B.

### Step 2A — With Cerberus (DS 25)

"Admin" in Cerberus = users with roles that have management permissions.

**Key: the `origin` column in `permissions` distinguishes where the permission applies:**

| origin | Meaning |
|--------|---------|
| `ADMIN` | Admin panel permission (backoffice) |
| `APP` | User-side permission (mobile/web app) |
| `INTERNAL` | Humand internal permission |

A user **has admin panel access** if they have at least one permission with `origin = 'ADMIN'`.

#### Users with admin panel access

```sql
-- Run against DS 25
SELECT DISTINCT ur.user_id, r.name AS role, r.type
FROM user_roles ur
JOIN roles r ON r.id = ur.role_id
JOIN role_permissions rp ON rp.role_id = r.id
JOIN permissions p ON p.id = rp.permission_id
WHERE r.instance_id = :instance_id
  AND r.deleted_at IS NULL
  AND p.origin = 'ADMIN'
```

#### List all roles with their permissions

```sql
-- Run against DS 25
SELECT r.name AS role, r.type, r.state,
  COUNT(DISTINCT ur.user_id) AS users,
  ARRAY_AGG(DISTINCT p.code ORDER BY p.code) AS permissions
FROM roles r
LEFT JOIN user_roles ur ON ur.role_id = r.id
LEFT JOIN role_permissions rp ON rp.role_id = r.id
LEFT JOIN permissions p ON p.id = rp.permission_id
WHERE r.instance_id = :instance_id AND r.deleted_at IS NULL
GROUP BY r.id, r.name, r.type, r.state
ORDER BY users DESC
```

#### Users with privileged permissions

```sql
-- Run against DS 25
SELECT DISTINCT ur.user_id, r.name AS role,
  ARRAY_AGG(DISTINCT p.code) AS privileged_permissions
FROM user_roles ur
JOIN roles r ON r.id = ur.role_id
JOIN role_permissions rp ON rp.role_id = r.id
JOIN permissions p ON p.id = rp.permission_id
WHERE r.instance_id = :instance_id
  AND r.deleted_at IS NULL
  AND (p.code LIKE 'can_edit_%'
       OR p.code LIKE 'can_manage_%'
       OR p.code = 'can_create_users'
       OR p.code LIKE '%admin%')
GROUP BY ur.user_id, r.name
ORDER BY r.name, ur.user_id
```

#### Enrich with user data (DS 1)

The `user_id` values from Cerberus are the `id` values from the `Users` table in DS 1. To see names/emails:

```sql
-- Run against DS 1
SELECT id, "employeeInternalId", email, status
FROM "Users"
WHERE id IN ([list_of_user_ids])
  AND "deletedAt" IS NULL
```

### Step 2B — Without Cerberus (DS 1, legacy model)

"Admin" in the legacy model = users with entries in `UserCapabilities`.

```sql
-- Run against DS 1
SELECT u.id, u."employeeInternalId", u.email, u.status,
  uc.capability
FROM "UserCapabilities" uc
JOIN "Users" u ON u.id = uc."userId"
WHERE u."instanceId" = :instance_id
  AND u."deletedAt" IS NULL
ORDER BY uc.capability, u."employeeInternalId"
```

Capabilities indicating "admin":
- `can_edit_users` — can manage users
- `can_manage_*` — per-module management permissions
- `view_metrics` — metrics access (this is a permission, not an app)
- `can_create_users` — can create users

Capabilities that are **apps** (NOT privileged permissions):
- `view_forms`, `view_posts`, `view_benefits`, etc. — only enable module visibility

### Step 3 — Present result

```
🏢 Community: [name] (ID: [id])
🔑 Permissions model: [Cerberus / Legacy (Capabilities)]

👤 Users with privileged permissions: [N]

[table with: user, email/employee ID, role(s), key permissions]
```

If Cerberus, group by role. If legacy, group by capability.
