security: rename misleading require_admin to require_user_actor

The function only checked that the caller was an authenticated user
(not an agent) but its name implied privilege enforcement. Rename to
require_user_actor and add docstring clarifying the distinction between
actor-type checks and privilege/role checks (require_org_admin, is_super_admin).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hugh Brown
2026-03-03 13:31:07 -07:00
committed by Abhimanyu Saharan
parent b32a9f5e66
commit c7692e30d3
2 changed files with 13 additions and 8 deletions

View File

@@ -30,7 +30,7 @@ from app.db.session import get_session
from app.models.boards import Board from app.models.boards import Board
from app.models.organizations import Organization from app.models.organizations import Organization
from app.models.tasks import Task from app.models.tasks import Task
from app.services.admin_access import require_admin from app.services.admin_access import require_user_actor
from app.services.organizations import ( from app.services.organizations import (
OrganizationContext, OrganizationContext,
ensure_member_for_user, ensure_member_for_user,
@@ -52,8 +52,8 @@ SESSION_DEP = Depends(get_session)
def require_admin_auth(auth: AuthContext = AUTH_DEP) -> AuthContext: def require_admin_auth(auth: AuthContext = AUTH_DEP) -> AuthContext:
"""Require an authenticated admin user.""" """Require an authenticated human user (not an agent)."""
require_admin(auth) require_user_actor(auth)
return auth return auth
@@ -70,9 +70,9 @@ def require_admin_or_agent(
auth: AuthContext | None = AUTH_OPTIONAL_DEP, auth: AuthContext | None = AUTH_OPTIONAL_DEP,
agent_auth: AgentAuthContext | None = AGENT_AUTH_OPTIONAL_DEP, agent_auth: AgentAuthContext | None = AGENT_AUTH_OPTIONAL_DEP,
) -> ActorContext: ) -> ActorContext:
"""Authorize either an admin user or an authenticated agent.""" """Authorize either a human user or an authenticated agent."""
if auth is not None: if auth is not None:
require_admin(auth) require_user_actor(auth)
return ActorContext(actor_type="user", user=auth.user) return ActorContext(actor_type="user", user=auth.user)
if agent_auth is not None: if agent_auth is not None:
return ActorContext(actor_type="agent", agent=agent_auth.agent) return ActorContext(actor_type="agent", agent=agent_auth.agent)

View File

@@ -1,4 +1,4 @@
"""Access control helpers for admin-only operations.""" """Access control helpers for actor-type checks."""
from __future__ import annotations from __future__ import annotations
@@ -10,7 +10,12 @@ if TYPE_CHECKING:
from app.core.auth import AuthContext from app.core.auth import AuthContext
def require_admin(auth: AuthContext) -> None: def require_user_actor(auth: AuthContext) -> None:
"""Raise HTTP 403 unless the authenticated actor is a user admin.""" """Raise HTTP 403 unless the authenticated actor is a human user (not an agent).
NOTE: This is an actor-type check, NOT a privilege/role check.
For admin privilege enforcement, use ``require_org_admin`` (organization-level)
or check ``user.is_super_admin`` (global-level).
"""
if auth.actor_type != "user" or auth.user is None: if auth.actor_type != "user" or auth.user is None:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN) raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)