data2 / backend /app /admin.py
system's picture
system HF Staff
Deploy gateway e062ef52b65ba61a8a7a891b6b583130528f3164
e8aac63 verified
Raw History Blame Contribute Delete
6.76 kB
"""Restricted management. Roles are granted using the server CLI, never public signup."""
from typing import Annotated
from fastapi import APIRouter, Depends, Query, Request
from pydantic import BaseModel, ConfigDict, Field
from sqlalchemy import delete, func, select
from .auth import DB, CurrentUser, user_view
from .errors import fail
from .models import (
AuditLog,
Provider,
PublishedModel,
RegistryModel,
RequestLog,
Session,
SiteConfiguration,
User,
)
from .site_config import SiteOptions, site_options
router = APIRouter(prefix="/api", tags=["Administration"])
async def administrator(user: CurrentUser) -> User:
if not user.is_admin:
raise fail(403, "Administrator access is required.", "admin_required")
return user
AdminUser = Annotated[User, Depends(administrator)]
@router.get("/site")
async def public_settings(request: Request, db: DB) -> dict:
options = await site_options(db, request.app.state.settings)
return options.model_dump(
include={
"site_name",
"tagline",
"welcome_text",
"accent",
"default_mode",
"default_stream",
"default_retries",
"shared_models_enabled",
}
)
@router.get("/admin/settings")
async def get_settings(request: Request, db: DB, user: AdminUser) -> dict:
options = await site_options(db, request.app.state.settings)
return {
"settings": options.model_dump(),
"limits": {
"requests_per_minute": request.app.state.settings.requests_per_minute,
"max_retries": request.app.state.settings.max_retries,
"registration_allowed": request.app.state.settings.allow_registration,
},
}
@router.put("/admin/settings")
async def save_settings(body: SiteOptions, request: Request, db: DB, user: AdminUser) -> dict:
config = request.app.state.settings
if (
body.requests_per_minute > config.requests_per_minute
or body.default_retries > config.max_retries
):
raise fail(422, "Keep rate and retry limits within the server's configured maximums.")
if body.registration_open and not config.allow_registration:
raise fail(422, "Registration is disabled in the server configuration.")
row = await db.get(SiteConfiguration, "global")
if not row:
row = SiteConfiguration(id="global")
db.add(row)
row.settings = body.model_dump()
db.add(AuditLog(user_id=user.id, action="admin.settings.updated", target_id="global"))
await db.commit()
return body.model_dump()
@router.get("/admin/summary")
async def summary(db: DB, user: AdminUser) -> dict:
return {
"users": await db.scalar(select(func.count(User.id))),
"suspended_users": await db.scalar(
select(func.count(User.id)).where(User.disabled.is_(True))
),
"requests": await db.scalar(select(func.count(RequestLog.id))),
"published_models": await db.scalar(
select(func.count(PublishedModel.model_id)).where(PublishedModel.enabled.is_(True))
),
"sponsored_cost": await db.scalar(select(func.sum(RequestLog.sponsored_cost))),
}
@router.get("/admin/users")
async def users(db: DB, user: AdminUser, search: str = "", offset: int = Query(0, ge=0)) -> dict:
query = select(User)
if search:
query = query.where(User.email.icontains(search[:120], autoescape=True))
total = await db.scalar(select(func.count()).select_from(query.subquery()))
rows = (
await db.scalars(query.order_by(User.created_at, User.id).limit(50).offset(offset))
).all()
return {
"data": [user_view(u) | {"disabled": u.disabled, "created_at": u.created_at} for u in rows],
"total": total,
}
class AccountStatus(BaseModel):
model_config = ConfigDict(extra="forbid")
disabled: bool
@router.patch("/admin/users/{uid}")
async def account_status(uid: str, body: AccountStatus, db: DB, user: AdminUser) -> dict:
target = await db.get(User, uid)
if not target:
raise fail(404, "Account not found.")
if target.id == user.id or target.is_admin:
raise fail(
403, "Administrator accounts can only be changed using the server admin command."
)
target.disabled = body.disabled
if body.disabled:
await db.execute(delete(Session).where(Session.user_id == target.id))
db.add(
AuditLog(
user_id=user.id,
action="admin.user.suspended" if body.disabled else "admin.user.restored",
target_id=uid,
)
)
await db.commit()
return {"id": uid, "disabled": target.disabled}
class PublishOptions(BaseModel):
model_config = ConfigDict(extra="forbid")
enabled: bool = True
requests_per_minute: int = Field(default=5, ge=1, le=120)
max_output_tokens: int = Field(default=1024, ge=128, le=8192)
@router.get("/admin/shared-models")
async def shared_models(db: DB, user: AdminUser) -> list[dict]:
rows = (
await db.execute(
select(PublishedModel, RegistryModel, Provider)
.join(RegistryModel, RegistryModel.id == PublishedModel.model_id)
.join(Provider, Provider.id == RegistryModel.provider_id)
.order_by(RegistryModel.name)
)
).all()
return [
{
"id": m.id,
"name": m.name,
"model_id": m.model_id,
"provider_name": p.name,
"enabled": shared.enabled,
"requests_per_minute": shared.requests_per_minute,
"max_output_tokens": shared.max_output_tokens,
"owned": p.user_id == user.id,
}
for shared, m, p in rows
]
@router.put("/admin/shared-models/{mid}")
async def publish(mid: str, body: PublishOptions, db: DB, user: AdminUser) -> dict:
model = await db.scalar(
select(RegistryModel)
.join(Provider)
.where(
RegistryModel.id == mid,
Provider.user_id == user.id,
)
)
if not model:
raise fail(404, "Select a model from a provider you own.")
if model.capabilities.get("chat") is not True:
raise fail(422, "Shared models must have confirmed chat capability.")
row = await db.get(PublishedModel, mid)
if not row:
row = PublishedModel(model_id=mid)
db.add(row)
for key, value in body.model_dump().items():
setattr(row, key, value)
db.add(
AuditLog(
user_id=user.id,
action="admin.model.published" if body.enabled else "admin.model.unpublished",
target_id=mid,
)
)
await db.commit()
return {"id": mid, **body.model_dump()}