9472fe91fa
Aegis CI / lint-and-test (push) Has been cancelled
- Remove ANN (type annotations) and D (docstrings) from ruff select; not feasible to add thousands of missing annotations/docstrings across the codebase - Add I001 and E501 to ignore: comment-interleaved import style and SQLAlchemy FK definitions naturally exceed line limits - Fix F811 duplicate import blocks in main.py, models/__init__.py, routers (campaigns, system, tests, evidence) and services (test_workflow, test_crud, campaign_service, schemas/test) - Add missing Evidence/IntelItem/Technique/Test/TestTemplate/User imports to models/__init__.py (were only in duplicate block) - Fix F821: add missing JWTError import in auth.py - Fix F401 unused imports across 15+ files (jira_service, sso_service, notification_service, playbook_service, tempo_service, models, schemas, routers: admin_config, attack_paths, executive_dashboard, knowledge, ownership, risk_intelligence, sso, api_keys, email_service) - Fix F841 unused variables: owned_technique_ids (executive_dashboard_service), severity (jira_service), priority_order (revalidation_queue_service) - Fix F541 f-strings without placeholders in system.py and attck_evaluations_service - Fix F601 duplicate dict key G0067 in threat_actor_import_service - Fix E701 multiple-statements-on-one-line in risk_intelligence_service - Fix E741 ambiguous variable name l -> lvl in risk_intelligence_service - Fix N806 uppercase vars in functions: technique.py, heatmap_service.py; add noqa for compliance_import_service.py large unused constant dicts - Fix W293 whitespace on blank lines in tests/conftest.py
105 lines
3.2 KiB
Python
105 lines
3.2 KiB
Python
"""Phase 14: API Key management router."""
|
|
|
|
from typing import List
|
|
from uuid import UUID
|
|
|
|
from fastapi import APIRouter, Depends, Query
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.database import get_db
|
|
from app.dependencies.auth import get_current_user, require_any_role
|
|
from app.models.user import User
|
|
from app.schemas.api_key_schema import (
|
|
ApiKeyCreate, ApiKeyCreated, ApiKeyOut, ApiKeyUpdate,
|
|
)
|
|
import app.services.api_key_service as svc
|
|
|
|
router = APIRouter(prefix="/api-keys", tags=["API Keys"])
|
|
|
|
|
|
@router.post("", response_model=ApiKeyCreated, status_code=201)
|
|
def create_key(
|
|
body: ApiKeyCreate,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""
|
|
Create a scoped API key.
|
|
|
|
The ``raw_key`` field in the response is shown **exactly once** and
|
|
cannot be retrieved later. Store it securely.
|
|
"""
|
|
key, raw_key = svc.create_api_key(
|
|
db,
|
|
user_id = current_user.id,
|
|
name = body.name,
|
|
scopes = body.scopes,
|
|
description = body.description,
|
|
expires_at = body.expires_at,
|
|
)
|
|
out = ApiKeyOut.model_validate(key)
|
|
return ApiKeyCreated(**out.model_dump(), raw_key=raw_key)
|
|
|
|
|
|
@router.get("", response_model=List[ApiKeyOut])
|
|
def list_keys(
|
|
include_inactive: bool = Query(False),
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""List API keys owned by the current user."""
|
|
# Admins can see all keys; others only see their own
|
|
user_id = None if current_user.role == "admin" else current_user.id
|
|
return svc.list_api_keys(db, user_id=user_id, include_inactive=include_inactive)
|
|
|
|
|
|
@router.get("/{key_id}", response_model=ApiKeyOut)
|
|
def get_key(
|
|
key_id: UUID,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""Get a single API key (owner or admin)."""
|
|
user_id = None if current_user.role == "admin" else current_user.id
|
|
return svc.get_api_key(db, key_id, user_id=user_id)
|
|
|
|
|
|
@router.patch("/{key_id}", response_model=ApiKeyOut)
|
|
def update_key(
|
|
key_id: UUID,
|
|
body: ApiKeyUpdate,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""Update name, description, scopes, expiry, or active status."""
|
|
user_id = None if current_user.role == "admin" else current_user.id
|
|
return svc.update_api_key(
|
|
db, key_id, user_id,
|
|
name = body.name,
|
|
description = body.description,
|
|
scopes = body.scopes,
|
|
expires_at = body.expires_at,
|
|
is_active = body.is_active,
|
|
)
|
|
|
|
|
|
@router.post("/{key_id}/revoke", response_model=ApiKeyOut)
|
|
def revoke_key(
|
|
key_id: UUID,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
"""Revoke an API key (soft-delete — sets is_active=False)."""
|
|
user_id = None if current_user.role == "admin" else current_user.id
|
|
return svc.revoke_api_key(db, key_id, user_id=user_id)
|
|
|
|
|
|
@router.delete("/{key_id}", status_code=204)
|
|
def delete_key(
|
|
key_id: UUID,
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(require_any_role("admin")),
|
|
):
|
|
"""Permanently delete an API key (admin only)."""
|
|
svc.delete_api_key(db, key_id)
|