feat: add trusted ticket intake backend
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
from django.db import IntegrityError
|
||||
from django.utils import timezone
|
||||
from ninja import Router
|
||||
from ninja.errors import HttpError
|
||||
|
||||
@@ -31,6 +32,14 @@ def serialize_provider(provider: ModelProvider) -> dict:
|
||||
"default_timeout_seconds": provider.default_timeout_seconds,
|
||||
"credential_set": bool(provider.api_key_encrypted),
|
||||
"credential_masked": mask_secret(provider.api_key_encrypted),
|
||||
"image_egress_approved": provider.image_egress_approved,
|
||||
"image_egress_approved_by": (
|
||||
provider.image_egress_approved_by.get_full_name()
|
||||
or provider.image_egress_approved_by.username
|
||||
if provider.image_egress_approved_by_id
|
||||
else None
|
||||
),
|
||||
"image_egress_approved_at": provider.image_egress_approved_at,
|
||||
"created_at": provider.created_at,
|
||||
"updated_at": provider.updated_at,
|
||||
}
|
||||
@@ -65,7 +74,10 @@ def audit(user, action: str, target_type: str, target_id: str, snapshot: dict) -
|
||||
@router.get("/providers", response=list[ModelProviderOut])
|
||||
def list_providers(request):
|
||||
require_permission(request, "model.manage")
|
||||
return [serialize_provider(provider) for provider in ModelProvider.objects.all()]
|
||||
return [
|
||||
serialize_provider(provider)
|
||||
for provider in ModelProvider.objects.select_related("image_egress_approved_by")
|
||||
]
|
||||
|
||||
|
||||
@router.post("/providers", response=ModelProviderOut)
|
||||
@@ -81,6 +93,9 @@ def create_provider(request, payload: ModelProviderIn):
|
||||
api_key_encrypted=encrypted,
|
||||
enabled=payload.enabled,
|
||||
default_timeout_seconds=payload.default_timeout_seconds,
|
||||
image_egress_approved=payload.image_egress_approved,
|
||||
image_egress_approved_by=request.user if payload.image_egress_approved else None,
|
||||
image_egress_approved_at=timezone.now() if payload.image_egress_approved else None,
|
||||
created_by=request.user,
|
||||
)
|
||||
except CredentialEncryptionError as error:
|
||||
@@ -97,6 +112,7 @@ def update_provider(request, provider_id: int, payload: ModelProviderUpdateIn):
|
||||
provider = ModelProvider.objects.get(id=provider_id)
|
||||
values = payload.dict(exclude_unset=True)
|
||||
api_key = values.pop("api_key", None)
|
||||
image_egress_approved = values.pop("image_egress_approved", None)
|
||||
if api_key:
|
||||
try:
|
||||
provider.api_key_encrypted = encrypt_secret(api_key)
|
||||
@@ -106,13 +122,22 @@ def update_provider(request, provider_id: int, payload: ModelProviderUpdateIn):
|
||||
raise HttpError(400, "Timeout must be between 1 and 300 seconds")
|
||||
for field, value in values.items():
|
||||
setattr(provider, field, value.rstrip("/") if field == "base_url" else value)
|
||||
if image_egress_approved is not None:
|
||||
provider.image_egress_approved = image_egress_approved
|
||||
provider.image_egress_approved_by = request.user if image_egress_approved else None
|
||||
provider.image_egress_approved_at = timezone.now() if image_egress_approved else None
|
||||
provider.save()
|
||||
audit(
|
||||
request.user,
|
||||
"update",
|
||||
"model_provider",
|
||||
str(provider.id),
|
||||
{"fields": sorted(values), "credential_replaced": bool(api_key)},
|
||||
{
|
||||
"fields": sorted(
|
||||
[*values, *(["image_egress_approved"] if image_egress_approved is not None else [])]
|
||||
),
|
||||
"credential_replaced": bool(api_key),
|
||||
},
|
||||
)
|
||||
return serialize_provider(provider)
|
||||
|
||||
@@ -133,6 +158,8 @@ def create_deployment(request, payload: ModelDeploymentIn):
|
||||
raise HttpError(400, "Temperature must be between 0 and 2")
|
||||
if not 1 <= payload.max_output_tokens <= 32768:
|
||||
raise HttpError(400, "Max output tokens are out of range")
|
||||
if payload.capability not in {"text_chat", "vision_chat"}:
|
||||
raise HttpError(400, "Unknown model capability")
|
||||
deployment = ModelDeployment.objects.create(**payload.dict())
|
||||
deployment = ModelDeployment.objects.select_related("provider").get(id=deployment.id)
|
||||
audit(
|
||||
@@ -150,6 +177,8 @@ def update_deployment(request, deployment_id: int, payload: ModelDeploymentUpdat
|
||||
require_permission(request, "model.manage")
|
||||
deployment = ModelDeployment.objects.select_related("provider").get(id=deployment_id)
|
||||
values = payload.dict(exclude_unset=True)
|
||||
if "capability" in values and values["capability"] not in {"text_chat", "vision_chat"}:
|
||||
raise HttpError(400, "Unknown model capability")
|
||||
for field, value in values.items():
|
||||
setattr(deployment, field, value)
|
||||
deployment.save()
|
||||
|
||||
Reference in New Issue
Block a user