Admin Permissions Quick Reference¶
The Correct Way to Check Admin Access¶
In Jinja2 Templates¶
CORRECT - Check for wildcard scope:
WRONG - This is legacy and won't work:
In Python Routers¶
CORRECT - Use the dependency:
from app.auth.permissions import require_admin
@router.get("/admin-only", dependencies=[Depends(require_admin())])
async def admin_endpoint(request: Request):
# This endpoint is protected - only admins can access
pass
CORRECT - Use in handler:
from app.auth.auth import SessionData, verifier
@router.get("/admin-only")
async def admin_endpoint(session: SessionData = Depends(verifier)):
if not session.has_scope("*"):
raise HTTPException(status_code=403, detail="Admin access required")
# Admin content here
For Specific Scopes¶
Check for a specific scope:
from app.auth.permissions import require_scope
@router.post("/templates", dependencies=[Depends(require_scope("templates:write"))])
async def create_template(...):
pass
Check for multiple scopes (AND):
from app.auth.permissions import require_all_scopes
@router.delete("/resource", dependencies=[Depends(require_all_scopes("templates:write", "templates:delete"))])
async def delete_resource(...):
pass
Check for any scope (OR):
from app.auth.permissions import require_any_scope
@router.get("/dashboard", dependencies=[Depends(require_any_scope("*", "admin:read"))])
async def dashboard(...):
pass
Creating Admin Users¶
Using the CLI:
# Create an admin user (has "*" scope - full access)
slidefactory user create-local admin@example.com --name "Admin User" --preset admin
# View the user's scopes
slidefactory user show admin@example.com
Creating via database (if needed):
from app.auth.users.models import User
from app.util.auth_utils import hash_password
admin_user = User(
email="admin@example.com",
name="Admin User",
password_hash=hash_password("secure_password"),
active=True,
scopes=['*'], # Full admin access
auth_provider='local'
)
db.add(admin_user)
db.commit()
What is an Admin?¶
A user is an admin if they have the "*" scope in their user.scopes list.
When a user logs in, their scopes are loaded from the database into the session:
The "*" scope is a wildcard that grants access to everything: - All endpoints with require_admin() - All scope checks (the has_scope() method returns True for any scope if "*" is present)
Scope Hierarchy¶
Scopes follow a hierarchical naming convention:
* Full admin access (wildcard)
templates:read Can view templates
templates:write Can create/update templates
templates:delete Can delete templates
workflows:read Can list workflows
workflows:execute Can run workflows
presentations:read Can view presentations
presentations:write Can create presentations
presentations:delete Can delete presentations
results:read Can view results
results:delete Can delete results
contexts:read Can view document contexts
contexts:write Can manage contexts
users:read Can view users (admin)
users:write Can manage users (admin)
Admin users have ["*"] which bypasses all these checks.
Checking User Scopes¶
To see what scopes a user has:
Output will show something like:
Or for a limited user:
Migration Notes¶
The system migrated from attribute-based access control to scope-based access control.
Legacy (don't use): - user.attributes["users"] - This is deprecated - Admin check via attributes - Don't use this pattern
Current (use this): - user.scopes - The current source of truth - Admin check via "*" in user.scopes - Use require_admin() and require_scope() dependencies
File Locations¶
Models: - User model: /app/auth/users/models.py - SessionData model: /app/auth/auth.py
Permission Helpers: - Permission dependencies: /app/auth/permissions.py
Navigation: - Main navigation: /templates/includes/base.html.j2 (line 230-239)