Skip to content
Back to skills

Controller Roles

ASecurity

Role-based access control with RoleHandler

  • 666 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added February 8, 2026
toolsgodatabase

Security analysis

A100/100

Scanned February 12, 2026

npx -y skills add majiayu000/claude-skill-registry --skill controller-roles --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Controller Roles?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Controller Roles
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-controller-roles/badge)](https://www.skillsdirectory.com/skills/majiayu000-controller-roles)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: controller-roles
description: Role-based access control with RoleHandler
---

# Role-Based Access Control

The `helpers.RoleHandler` function provides role-based access control by mapping roles to specific handler functions.

## Basic Usage

```go
helpers.RoleHandler(helpers.RoleHandlerMap{
    constants.ROLE_READ_ADMIN: helpers.StandardRequestWrapper(adminGet),
    constants.ROLE_ADMIN: helpers.StandardRequestWrapper(adminCreate),
})
```

## Role Hierarchy

Roles are defined as integer constants in descending order of privilege:

| Role | Value | Description |
|------|-------|-------------|
| `ROLE_ADMIN` | 100 | Full system administrator access |
| `ROLE_READ_ADMIN` | 90 | Read-only administrator access |
| `ROLE_ANY_AUTHORIZED` | 0 | Any authenticated user |
| `ROLE_UNAUTHORIZED` | -1 | Unauthenticated requests |

## How RoleHandler Works

1. **Extracts session** from request headers/cookies
2. **Looks up user's role** from the database
3. **Finds highest-privilege handler** the user can access
4. **Falls back** to lower privilege handlers if exact role match isn't found
5. **Returns 401 Unauthorized** if no suitable handler is found

### Fallback Behavior

If a user's role doesn't exactly match a handler, the system checks lower-privilege handlers:

```go
helpers.RoleHandler(helpers.RoleHandlerMap{
    constants.ROLE_READ_ADMIN: helpers.StandardRequestWrapper(adminGet),
    constants.ROLE_ANY_AUTHORIZED: helpers.StandardRequestWrapper(authGet),
})
```

**Examples:**
- User with `ROLE_ADMIN` (100) → Uses `ROLE_READ_ADMIN` handler (fallback)
- User with `ROLE_READ_ADMIN` (90) → Uses `ROLE_READ_ADMIN` handler (exact match)
- User with `ROLE_ANY_AUTHORIZED` (0) → Uses `ROLE_ANY_AUTHORIZED` handler (exact match)
- Unauthenticated user → Returns 401 Unauthorized

## Session Context

The `RoleHandler` automatically injects the session into the request context, making it available via:

```go
userSession := helpers.GetReqSession(req)
```

**Session Fields:**
```go
type Session struct {
    User       coremodel.Model // thin wrapper over session data if you only need the users ID, i.e. sessionObj.User.ID(), or used to save data so we can track who saved it.
	LoadedUser any // fully loaded user from the database, dont access directly, use the helper.GetLoadedUser(req)
}
```

## Common Role Patterns

### Admin-Only Endpoints

Full admin access required:

```go
r.Post("/", helpers.RoleHandler(helpers.RoleHandlerMap{
    constants.ROLE_ADMIN: helpers.StandardRequestWrapper(adminCreate),
}))

r.Put("/{id}", helpers.RoleHandler(helpers.RoleHandlerMap{
    constants.ROLE_ADMIN: helpers.StandardRequestWrapper(adminUpdate),
}))

r.Delete("/{id}", helpers.RoleHandler(helpers.RoleHandlerMap{
    constants.ROLE_ADMIN: helpers.StandardRequestWrapper(adminDelete),
}))
```

### Read-Only Admin Access

Both full admins and read-only admins can access:

```go
r.Get("/", helpers.RoleHandler(helpers.RoleHandlerMap{
    constants.ROLE_READ_ADMIN: helpers.StandardRequestWrapper(adminIndex),
}))

r.Get("/{id}", helpers.RoleHandler(helpers.RoleHandlerMap{
    constants.ROLE_READ_ADMIN: helpers.StandardRequestWrapper(adminGet),
}))

r.Get("/count", helpers.RoleHandler(helpers.RoleHandlerMap{
    constants.ROLE_READ_ADMIN: helpers.StandardRequestWrapper(adminCount),
}))
```

### Authenticated User Endpoints

Any authenticated user can access:

```go
r.Get("/", helpers.RoleHandler(helpers.RoleHandlerMap{
    constants.ROLE_ANY_AUTHORIZED: helpers.StandardPublicRequestWrapper(authIndex),
}))

r.Get("/{id}", helpers.RoleHandler(helpers.RoleHandlerMap{
    constants.ROLE_ANY_AUTHORIZED: helpers.StandardPublicRequestWrapper(authGet),
}))
```

### Mixed Role Handlers

Different handlers for different roles on the same route:

```go
r.Get("/{id}", helpers.RoleHandler(helpers.RoleHandlerMap{
    constants.ROLE_ADMIN: helpers.StandardRequestWrapper(adminGetFull),
    constants.ROLE_ANY_AUTHORIZED: helpers.StandardPublicRequestWrapper(authGetLimited),
}))
```

**Example:**
- Admin users → Get full details via `adminGetFull`
- Regular users → Get limited details via `authGetLimited`



## Related Skills
- [controller-handlers](../controller-handlers/SKILL.md) - Writing handler functions
- [controller-generation](../controller-generation/SKILL.md) - Code generation

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.