mud_server.api.permissions

Role-based permission system (RBAC).

This module implements a Role-Based Access Control (RBAC) system for the MUD server. It defines: 1. User roles with different privilege levels 2. Specific permissions that can be checked 3. Mapping of which roles have which permissions 4. Helper functions to check permissions and role hierarchy

Role Hierarchy (lowest to highest):

Player → World Builder → Admin → Superuser

Permission Design: - Each role has an explicit set of permissions - Roles DO NOT automatically inherit lower role permissions (must be explicit) - Superuser has a special FULL_ACCESS permission that grants everything - Permissions are granular to allow fine-grained access control

Usage in API Routes: 1. Use validate_session_with_permission() to check specific permissions 2. Use require_permission() decorator for route-level protection 3. Use require_role() decorator for minimum role requirements 4. Use can_manage_role() to prevent privilege escalation

Security Considerations: - Never allow users to elevate their own privileges - Always check role hierarchy for user management operations - Superusers can manage everyone, admins can manage lower roles - Players and World Builders cannot manage other users

Attributes

ROLE_PERMISSIONS

Classes

Role

User roles in the system, ordered by privilege level.

Permission

Specific permissions that can be granted to roles.

Functions

has_permission(role, permission)

Check if a role has a specific permission.

get_role_hierarchy_level(role)

Get the numeric hierarchy level of a role.

can_manage_role(manager_role, target_role)

Check if a manager can manage (promote/demote/ban) a target user.

require_permission(permission)

Decorator to require a specific permission for a route.

require_role(min_role)

Decorator to require a minimum role level for a route.

Module Contents

class mud_server.api.permissions.Role(*args, **kwds)[source]

Bases: enum.Enum

User roles in the system, ordered by privilege level.

Each role represents a different level of access and trust in the system. Roles are stored as lowercase strings in the database but represented as enum values in code for type safety.

Roles (in order of privilege):

PLAYER: Standard game player (lowest privilege) WORLDBUILDER: Player with world editing capabilities ADMIN: Administrator with user management powers SUPERUSER: Super administrator with full system access (highest privilege)

PLAYER = 'player'
WORLDBUILDER = 'worldbuilder'
ADMIN = 'admin'
SUPERUSER = 'superuser'
class mud_server.api.permissions.Permission(*args, **kwds)[source]

Bases: enum.Enum

Specific permissions that can be granted to roles.

Permissions are organized by category and represent specific actions that users can perform. Each permission should be as granular as possible to allow fine-grained access control.

Permission Categories:
  • Player: Basic gameplay actions

  • World Builder: Content creation and editing

  • Admin: User management and system administration

  • Superuser: Full unrestricted access

PLAY_GAME = 'play_game'
CHAT = 'chat'
EDIT_WORLD = 'edit_world'
CREATE_ROOMS = 'create_rooms'
CREATE_ITEMS = 'create_items'
CREATE_USERS = 'create_users'
KICK_USERS = 'kick_users'
BAN_USERS = 'ban_users'
VIEW_LOGS = 'view_logs'
STOP_SERVER = 'stop_server'
MANAGE_USERS = 'manage_users'
CHANGE_ROLES = 'change_roles'
FULL_ACCESS = 'full_access'
mud_server.api.permissions.ROLE_PERMISSIONS: dict[Role, set[Permission]]
mud_server.api.permissions.has_permission(role, permission)[source]

Check if a role has a specific permission.

This is the core permission checking function used throughout the application. It converts the role string to an enum, looks up the role’s permissions, and checks if the requested permission is granted.

Special Case:

Superusers automatically have ALL permissions due to the FULL_ACCESS permission. This is checked first before looking up specific permissions.

Parameters:
  • role (str) – Role string (case-insensitive: “player”, “worldbuilder”, “admin”, “superuser”)

  • permission (Permission) – Permission enum value to check (e.g., Permission.MANAGE_USERS)

Returns:

True if the role has the permission, False if not or if role is invalid

Return type:

bool

Example

>>> has_permission("admin", Permission.VIEW_LOGS)
True
>>> has_permission("player", Permission.MANAGE_USERS)
False
>>> has_permission("superuser", Permission.ANYTHING)
True  # Superuser has all permissions
mud_server.api.permissions.get_role_hierarchy_level(role)[source]

Get the numeric hierarchy level of a role.

The hierarchy level is used to determine which users can manage other users. Higher numbers indicate more privilege. This prevents lower-privileged users from managing higher-privileged users.

Hierarchy Levels:

0 = Player (lowest privilege) 1 = World Builder 2 = Admin 3 = Superuser (highest privilege)

Parameters:

role (str) – Role string (case-insensitive)

Returns:

Integer hierarchy level (0-3) Returns 0 for invalid/unknown roles (treated as lowest privilege)

Return type:

int

Example

>>> get_role_hierarchy_level("admin")
2
>>> get_role_hierarchy_level("player")
0
>>> get_role_hierarchy_level("invalid")
0
mud_server.api.permissions.can_manage_role(manager_role, target_role)[source]

Check if a manager can manage (promote/demote/ban) a target user.

This function enforces the rule that you can only manage users with a lower hierarchy level than yourself. This prevents privilege escalation and ensures proper administrative boundaries.

Management Rules:
  • Superuser (3) can manage Admin (2), WorldBuilder (1), Player (0)

  • Admin (2) can manage WorldBuilder (1), Player (0)

  • WorldBuilder (1) can manage Player (0)

  • Player (0) cannot manage anyone

  • You CANNOT manage users at the same level or higher

Parameters:
  • manager_role (str) – Role of the user performing the management action

  • target_role (str) – Role of the user being managed

Returns:

True if manager can manage target, False otherwise

Return type:

bool

Security Note:

Always call this function before allowing role changes, bans, or other user management actions to prevent privilege escalation attacks.

Example

>>> can_manage_role("admin", "player")
True
>>> can_manage_role("player", "admin")
False
>>> can_manage_role("admin", "admin")
False  # Cannot manage users at same level
>>> can_manage_role("superuser", "admin")
True
mud_server.api.permissions.require_permission(permission)[source]

Decorator to require a specific permission for a route.

This decorator wraps a route function and checks if the user has the required permission before allowing the function to execute. If the user lacks the permission, an HTTP 403 Forbidden error is raised.

Note

This decorator is currently defined but not actively used in the codebase. Most routes use validate_session_with_permission() directly instead. This decorator could be useful for cleaner route definitions in the future.

Parameters:

permission (Permission) – The permission required to access the route

Returns:

Decorator function that wraps the route handler

Raises:

HTTPException(403) – If user lacks the required permission

Usage:

@app.post(“/admin/action”) @require_permission(Permission.MANAGE_USERS) async def admin_action(username: str, role: str):

# This only executes if user has MANAGE_USERS permission …

Requirements:

The wrapped function must have “role” in its kwargs, typically obtained from validate_session() before calling the route handler.

mud_server.api.permissions.require_role(min_role)[source]

Decorator to require a minimum role level for a route.

This decorator checks role hierarchy level rather than specific permissions. It ensures the user has at least the specified role level (or higher) before allowing access to the route.

Note

This decorator is currently defined but not actively used in the codebase. Most routes use validate_session_with_permission() for permission-based checks instead of role-based checks. However, this could be useful for routes that need role-level restrictions regardless of specific permissions.

Parameters:

min_role (Role) – Minimum role enum value required (e.g., Role.ADMIN)

Returns:

Decorator function that wraps the route handler

Raises:

HTTPException(403) – If user’s role is below the minimum required level

Usage:

@app.post(“/admin/dashboard”) @require_role(Role.ADMIN) async def admin_dashboard(username: str, role: str):

# This only executes if user is Admin or Superuser …

Requirements:

The wrapped function must have “role” in its kwargs, typically obtained from validate_session() before calling the route handler.

Example

If min_role=Role.ADMIN: - Superuser (level 3) ✓ Allowed (3 >= 2) - Admin (level 2) ✓ Allowed (2 >= 2) - WorldBuilder (level 1) ✗ Denied (1 < 2) - Player (level 0) ✗ Denied (0 < 2)