refactor: rename require_admin_auth/require_admin_or_agent to require_user_auth/require_user_or_agent
These dependencies check actor type (human user vs agent), not admin privilege. The old names were misleading and could cause authorization mistakes when wiring new endpoints. Renamed across all 10 consumer files along with their local ADMIN_AUTH_DEP / ADMIN_OR_AGENT_DEP aliases. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Abhimanyu Saharan
parent
ea78b41a36
commit
cc50877131
@@ -14,7 +14,7 @@ from sqlalchemy import and_, asc, desc, func, or_
|
||||
from sqlmodel import col, select
|
||||
from sse_starlette.sse import EventSourceResponse
|
||||
|
||||
from app.api.deps import ActorContext, require_admin_or_agent, require_org_member
|
||||
from app.api.deps import ActorContext, require_user_or_agent, require_org_member
|
||||
from app.core.time import utcnow
|
||||
from app.db.pagination import paginate
|
||||
from app.db.session import async_session_maker, get_session
|
||||
@@ -42,7 +42,7 @@ SSE_SEEN_MAX = 2000
|
||||
STREAM_POLL_SECONDS = 2
|
||||
TASK_COMMENT_ROW_LEN = 4
|
||||
SESSION_DEP = Depends(get_session)
|
||||
ACTOR_DEP = Depends(require_admin_or_agent)
|
||||
ACTOR_DEP = Depends(require_user_or_agent)
|
||||
ORG_MEMBER_DEP = Depends(require_org_member)
|
||||
BOARD_ID_QUERY = Query(default=None)
|
||||
SINCE_QUERY = Query(default=None)
|
||||
|
||||
@@ -9,7 +9,7 @@ from uuid import UUID
|
||||
from fastapi import APIRouter, Depends, Query, Request
|
||||
from sse_starlette.sse import EventSourceResponse
|
||||
|
||||
from app.api.deps import ActorContext, require_admin_or_agent, require_org_admin
|
||||
from app.api.deps import ActorContext, require_user_or_agent, require_org_admin
|
||||
from app.core.auth import AuthContext, get_auth_context
|
||||
from app.db.session import get_session
|
||||
from app.schemas.agents import (
|
||||
@@ -35,7 +35,7 @@ GATEWAY_ID_QUERY = Query(default=None)
|
||||
SINCE_QUERY = Query(default=None)
|
||||
SESSION_DEP = Depends(get_session)
|
||||
ORG_ADMIN_DEP = Depends(require_org_admin)
|
||||
ACTOR_DEP = Depends(require_admin_or_agent)
|
||||
ACTOR_DEP = Depends(require_user_or_agent)
|
||||
AUTH_DEP = Depends(get_auth_context)
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ from app.api.deps import (
|
||||
get_board_for_actor_read,
|
||||
get_board_for_actor_write,
|
||||
get_board_for_user_write,
|
||||
require_admin_or_agent,
|
||||
require_user_or_agent,
|
||||
)
|
||||
from app.core.logging import get_logger
|
||||
from app.core.time import utcnow
|
||||
@@ -58,7 +58,7 @@ BOARD_READ_DEP = Depends(get_board_for_actor_read)
|
||||
BOARD_WRITE_DEP = Depends(get_board_for_actor_write)
|
||||
BOARD_USER_WRITE_DEP = Depends(get_board_for_user_write)
|
||||
SESSION_DEP = Depends(get_session)
|
||||
ACTOR_DEP = Depends(require_admin_or_agent)
|
||||
ACTOR_DEP = Depends(require_user_or_agent)
|
||||
|
||||
|
||||
def _parse_since(value: str | None) -> datetime | None:
|
||||
|
||||
@@ -19,7 +19,7 @@ from app.api.deps import (
|
||||
ActorContext,
|
||||
get_board_for_actor_read,
|
||||
get_board_for_actor_write,
|
||||
require_admin_or_agent,
|
||||
require_user_or_agent,
|
||||
require_org_member,
|
||||
)
|
||||
from app.core.config import settings
|
||||
@@ -65,7 +65,7 @@ SESSION_DEP = Depends(get_session)
|
||||
ORG_MEMBER_DEP = Depends(require_org_member)
|
||||
BOARD_READ_DEP = Depends(get_board_for_actor_read)
|
||||
BOARD_WRITE_DEP = Depends(get_board_for_actor_write)
|
||||
ACTOR_DEP = Depends(require_admin_or_agent)
|
||||
ACTOR_DEP = Depends(require_user_or_agent)
|
||||
IS_CHAT_QUERY = Query(default=None)
|
||||
SINCE_QUERY = Query(default=None)
|
||||
_RUNTIME_TYPE_REFERENCES = (UUID,)
|
||||
|
||||
@@ -10,7 +10,7 @@ from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy import func
|
||||
from sqlmodel import col, select
|
||||
|
||||
from app.api.deps import ActorContext, require_admin_or_agent, require_org_admin, require_org_member
|
||||
from app.api.deps import ActorContext, require_user_or_agent, require_org_admin, require_org_member
|
||||
from app.core.time import utcnow
|
||||
from app.db import crud
|
||||
from app.db.pagination import paginate
|
||||
@@ -52,7 +52,7 @@ router = APIRouter(prefix="/board-groups", tags=["board-groups"])
|
||||
SESSION_DEP = Depends(get_session)
|
||||
ORG_MEMBER_DEP = Depends(require_org_member)
|
||||
ORG_ADMIN_DEP = Depends(require_org_admin)
|
||||
ACTOR_DEP = Depends(require_admin_or_agent)
|
||||
ACTOR_DEP = Depends(require_user_or_agent)
|
||||
|
||||
|
||||
def _slugify(value: str) -> str:
|
||||
|
||||
@@ -17,7 +17,7 @@ from app.api.deps import (
|
||||
ActorContext,
|
||||
get_board_for_actor_read,
|
||||
get_board_for_actor_write,
|
||||
require_admin_or_agent,
|
||||
require_user_or_agent,
|
||||
)
|
||||
from app.core.config import settings
|
||||
from app.core.time import utcnow
|
||||
@@ -47,7 +47,7 @@ SINCE_QUERY = Query(default=None)
|
||||
BOARD_READ_DEP = Depends(get_board_for_actor_read)
|
||||
BOARD_WRITE_DEP = Depends(get_board_for_actor_write)
|
||||
SESSION_DEP = Depends(get_session)
|
||||
ACTOR_DEP = Depends(require_admin_or_agent)
|
||||
ACTOR_DEP = Depends(require_user_or_agent)
|
||||
_RUNTIME_TYPE_REFERENCES = (UUID,)
|
||||
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ from app.api.deps import (
|
||||
get_board_for_user_read,
|
||||
get_board_for_user_write,
|
||||
get_board_or_404,
|
||||
require_admin_auth,
|
||||
require_admin_or_agent,
|
||||
require_user_auth,
|
||||
require_user_or_agent,
|
||||
)
|
||||
from app.core.config import settings
|
||||
from app.core.logging import get_logger
|
||||
@@ -54,8 +54,8 @@ BOARD_USER_READ_DEP = Depends(get_board_for_user_read)
|
||||
BOARD_USER_WRITE_DEP = Depends(get_board_for_user_write)
|
||||
BOARD_OR_404_DEP = Depends(get_board_or_404)
|
||||
SESSION_DEP = Depends(get_session)
|
||||
ACTOR_DEP = Depends(require_admin_or_agent)
|
||||
ADMIN_AUTH_DEP = Depends(require_admin_auth)
|
||||
ACTOR_DEP = Depends(require_user_or_agent)
|
||||
USER_AUTH_DEP = Depends(require_user_auth)
|
||||
|
||||
|
||||
def _parse_draft_user_profile(
|
||||
@@ -426,7 +426,7 @@ async def confirm_onboarding(
|
||||
payload: BoardOnboardingConfirm,
|
||||
board: Board = BOARD_USER_WRITE_DEP,
|
||||
session: AsyncSession = SESSION_DEP,
|
||||
auth: AuthContext = ADMIN_AUTH_DEP,
|
||||
auth: AuthContext = USER_AUTH_DEP,
|
||||
) -> Board:
|
||||
"""Confirm onboarding results and provision the board lead agent."""
|
||||
onboarding = (
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
These dependencies are the main "policy wiring" layer for the API.
|
||||
|
||||
They:
|
||||
- resolve the authenticated actor (admin user vs agent)
|
||||
- resolve the authenticated actor (human user vs agent)
|
||||
- enforce organization/board access rules
|
||||
- provide common "load or 404" helpers (board/task)
|
||||
|
||||
Why this exists:
|
||||
- Keeping authorization logic centralized makes it easier to reason about (and
|
||||
audit) permissions as the API surface grows.
|
||||
- Some routes allow either admin users or agents; others require user auth.
|
||||
- Some routes allow either human users or agents; others require user auth.
|
||||
|
||||
If you're adding a new endpoint, prefer composing from these dependencies instead
|
||||
of re-implementing permission checks in the router.
|
||||
@@ -51,7 +51,7 @@ AGENT_AUTH_OPTIONAL_DEP = Depends(get_agent_auth_context_optional)
|
||||
SESSION_DEP = Depends(get_session)
|
||||
|
||||
|
||||
def require_admin_auth(auth: AuthContext = AUTH_DEP) -> AuthContext:
|
||||
def require_user_auth(auth: AuthContext = AUTH_DEP) -> AuthContext:
|
||||
"""Require an authenticated human user (not an agent)."""
|
||||
require_user_actor(auth)
|
||||
return auth
|
||||
@@ -66,7 +66,7 @@ class ActorContext:
|
||||
agent: Agent | None = None
|
||||
|
||||
|
||||
def require_admin_or_agent(
|
||||
def require_user_or_agent(
|
||||
auth: AuthContext | None = AUTH_OPTIONAL_DEP,
|
||||
agent_auth: AgentAuthContext | None = AGENT_AUTH_OPTIONAL_DEP,
|
||||
) -> ActorContext:
|
||||
@@ -79,7 +79,7 @@ def require_admin_or_agent(
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
|
||||
ACTOR_DEP = Depends(require_admin_or_agent)
|
||||
ACTOR_DEP = Depends(require_user_or_agent)
|
||||
|
||||
|
||||
async def require_org_member(
|
||||
|
||||
@@ -6,7 +6,7 @@ import re
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||||
|
||||
from app.api.deps import ActorContext, require_admin_or_agent
|
||||
from app.api.deps import ActorContext, require_user_or_agent
|
||||
from app.schemas.souls_directory import (
|
||||
SoulsDirectoryMarkdownResponse,
|
||||
SoulsDirectorySearchResponse,
|
||||
@@ -15,7 +15,7 @@ from app.schemas.souls_directory import (
|
||||
from app.services import souls_directory
|
||||
|
||||
router = APIRouter(prefix="/souls-directory", tags=["souls-directory"])
|
||||
ADMIN_OR_AGENT_DEP = Depends(require_admin_or_agent)
|
||||
USER_OR_AGENT_DEP = Depends(require_user_or_agent)
|
||||
|
||||
_SAFE_SEGMENT_RE = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9_-]*$")
|
||||
_SAFE_SLUG_RE = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9_-]*$")
|
||||
@@ -44,7 +44,7 @@ def _validate_segment(value: str, *, field: str) -> str:
|
||||
async def search(
|
||||
q: str = Query(default="", min_length=0),
|
||||
limit: int = Query(default=20, ge=1, le=100),
|
||||
_actor: ActorContext = ADMIN_OR_AGENT_DEP,
|
||||
_actor: ActorContext = USER_OR_AGENT_DEP,
|
||||
) -> SoulsDirectorySearchResponse:
|
||||
"""Search souls-directory entries by handle/slug query text."""
|
||||
refs = await souls_directory.list_souls_directory_refs()
|
||||
@@ -66,7 +66,7 @@ async def search(
|
||||
async def get_markdown(
|
||||
handle: str,
|
||||
slug: str,
|
||||
_actor: ActorContext = ADMIN_OR_AGENT_DEP,
|
||||
_actor: ActorContext = USER_OR_AGENT_DEP,
|
||||
) -> SoulsDirectoryMarkdownResponse:
|
||||
"""Fetch markdown content for a validated souls-directory handle and slug."""
|
||||
safe_handle = _validate_segment(handle, field="handle")
|
||||
|
||||
@@ -20,8 +20,8 @@ from app.api.deps import (
|
||||
get_board_for_actor_read,
|
||||
get_board_for_user_write,
|
||||
get_task_or_404,
|
||||
require_admin_auth,
|
||||
require_admin_or_agent,
|
||||
require_user_auth,
|
||||
require_user_or_agent,
|
||||
)
|
||||
from app.core.time import utcnow
|
||||
from app.db import crud
|
||||
@@ -100,12 +100,12 @@ TASK_SNIPPET_MAX_LEN = 500
|
||||
TASK_SNIPPET_TRUNCATED_LEN = 497
|
||||
TASK_EVENT_ROW_LEN = 2
|
||||
BOARD_READ_DEP = Depends(get_board_for_actor_read)
|
||||
ACTOR_DEP = Depends(require_admin_or_agent)
|
||||
ACTOR_DEP = Depends(require_user_or_agent)
|
||||
SINCE_QUERY = Query(default=None)
|
||||
STATUS_QUERY = Query(default=None, alias="status")
|
||||
BOARD_WRITE_DEP = Depends(get_board_for_user_write)
|
||||
SESSION_DEP = Depends(get_session)
|
||||
ADMIN_AUTH_DEP = Depends(require_admin_auth)
|
||||
USER_AUTH_DEP = Depends(require_user_auth)
|
||||
TASK_DEP = Depends(get_task_or_404)
|
||||
|
||||
|
||||
@@ -1449,7 +1449,7 @@ async def create_task(
|
||||
payload: TaskCreate,
|
||||
board: Board = BOARD_WRITE_DEP,
|
||||
session: AsyncSession = SESSION_DEP,
|
||||
auth: AuthContext = ADMIN_AUTH_DEP,
|
||||
auth: AuthContext = USER_AUTH_DEP,
|
||||
) -> TaskRead:
|
||||
"""Create a task and initialize dependency rows."""
|
||||
data = payload.model_dump(exclude={"depends_on_task_ids", "tag_ids", "custom_field_values"})
|
||||
@@ -1672,7 +1672,7 @@ async def delete_task_and_related_records(
|
||||
async def delete_task(
|
||||
session: AsyncSession = SESSION_DEP,
|
||||
task: Task = TASK_DEP,
|
||||
auth: AuthContext = ADMIN_AUTH_DEP,
|
||||
auth: AuthContext = USER_AUTH_DEP,
|
||||
) -> OkResponse:
|
||||
"""Delete a task and related records."""
|
||||
if task.board_id is None:
|
||||
|
||||
Reference in New Issue
Block a user