555e282cc4
pi-agent-plugin checks / lint (push) Has been cancelled
pi-agent-plugin checks / test (20) (push) Has been cancelled
pi-agent-plugin checks / test (22) (push) Has been cancelled
pi-agent-plugin checks / build (push) Has been cancelled
TypeScript SDK CI / check_changes (push) Has been cancelled
TypeScript SDK CI / changelog_check (push) Has been cancelled
ci / changelog_check (push) Has been cancelled
ci / check_changes (push) Has been cancelled
ci / build_mem0 (3.10) (push) Has been cancelled
ci / build_mem0 (3.11) (push) Has been cancelled
ci / build_mem0 (3.12) (push) Has been cancelled
CLI Node CI / lint (push) Has been cancelled
CLI Node CI / test (20) (push) Has been cancelled
CLI Node CI / test (22) (push) Has been cancelled
CLI Node CI / build (push) Has been cancelled
CLI Python CI / lint (push) Has been cancelled
CLI Python CI / test (3.10) (push) Has been cancelled
CLI Python CI / test (3.11) (push) Has been cancelled
CLI Python CI / test (3.12) (push) Has been cancelled
CLI Python CI / build (push) Has been cancelled
openclaw checks / lint (push) Has been cancelled
openclaw checks / test (20) (push) Has been cancelled
openclaw checks / test (22) (push) Has been cancelled
openclaw checks / build (push) Has been cancelled
opencode-plugin checks / build (push) Has been cancelled
TypeScript SDK CI / build_ts_sdk (20) (push) Has been cancelled
TypeScript SDK CI / build_ts_sdk (22) (push) Has been cancelled
TypeScript SDK CI / integration_ts_sdk (20) (push) Has been cancelled
TypeScript SDK CI / integration_ts_sdk (22) (push) Has been cancelled
94 lines
2.6 KiB
Python
94 lines
2.6 KiB
Python
import uuid
|
|
from datetime import datetime, timezone
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from pydantic import BaseModel
|
|
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
|
|
from auth import generate_api_key, require_auth
|
|
from db import get_db
|
|
from models import APIKey, User
|
|
from schemas import MessageResponse
|
|
|
|
router = APIRouter(prefix="/api-keys", tags=["api-keys"])
|
|
|
|
|
|
class CreateKeyRequest(BaseModel):
|
|
label: str
|
|
|
|
|
|
class CreateKeyResponse(BaseModel):
|
|
id: str
|
|
key: str
|
|
label: str
|
|
key_prefix: str
|
|
created_at: datetime
|
|
|
|
|
|
class KeyListItem(BaseModel):
|
|
id: str
|
|
label: str
|
|
key_prefix: str
|
|
created_at: datetime
|
|
last_used_at: datetime | None
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
@router.get("", response_model=list[KeyListItem])
|
|
def list_keys(user: User = Depends(require_auth), db: Session = Depends(get_db)):
|
|
keys = (
|
|
db.execute(
|
|
select(APIKey)
|
|
.where(APIKey.created_by == user.id, APIKey.revoked_at.is_(None))
|
|
.order_by(APIKey.created_at.desc())
|
|
)
|
|
.scalars()
|
|
.all()
|
|
)
|
|
return [
|
|
KeyListItem(
|
|
id=str(k.id),
|
|
label=k.label,
|
|
key_prefix=k.key_prefix,
|
|
created_at=k.created_at,
|
|
last_used_at=k.last_used_at,
|
|
)
|
|
for k in keys
|
|
]
|
|
|
|
|
|
@router.post("", response_model=CreateKeyResponse, status_code=201)
|
|
def create_key(body: CreateKeyRequest, user: User = Depends(require_auth), db: Session = Depends(get_db)):
|
|
full_key, prefix, key_hash = generate_api_key()
|
|
api_key = APIKey(key_prefix=prefix, key_hash=key_hash, label=body.label, created_by=user.id)
|
|
db.add(api_key)
|
|
db.commit()
|
|
db.refresh(api_key)
|
|
|
|
return CreateKeyResponse(
|
|
id=str(api_key.id),
|
|
key=full_key,
|
|
label=api_key.label,
|
|
key_prefix=prefix,
|
|
created_at=api_key.created_at,
|
|
)
|
|
|
|
|
|
@router.delete("/{key_id}", response_model=MessageResponse)
|
|
def revoke_key(key_id: str, user: User = Depends(require_auth), db: Session = Depends(get_db)):
|
|
try:
|
|
key_uuid = uuid.UUID(key_id)
|
|
except (TypeError, ValueError):
|
|
raise HTTPException(status_code=404, detail="API key not found.")
|
|
api_key = db.get(APIKey, key_uuid)
|
|
if api_key is None or api_key.created_by != user.id:
|
|
raise HTTPException(status_code=404, detail="API key not found.")
|
|
if api_key.revoked_at is not None:
|
|
raise HTTPException(status_code=400, detail="API key is already revoked.")
|
|
|
|
api_key.revoked_at = datetime.now(timezone.utc)
|
|
db.commit()
|
|
return MessageResponse(message="API key revoked.")
|