use axum::{ Json, extract::{Extension, Query, State}, http::StatusCode, }; use serde_json::{Value, json}; use shared_contracts::assets::{ ConfirmAssetObjectRequest, CreateDirectUploadTicketRequest, GetReadUrlQuery, }; use crate::{ assets::{ AssetReadAuthorization, confirm_asset_object_for_owner, create_direct_upload_ticket_for_owner, get_asset_read_url_with_query, }, external_api_auth::ExternalApiPrincipal, http_error::AppError, request_context::RequestContext, state::AppState, }; const SCOPE_EDITOR_ASSET: &str = "editor:asset"; const EXTERNAL_ASSET_PROVIDER: &str = "external-assets-api"; pub async fn create_external_direct_upload_ticket( State(state): State, Extension(request_context): Extension, Extension(principal): Extension, Json(payload): Json, ) -> Result, AppError> { require_scope(&principal, SCOPE_EDITOR_ASSET)?; create_direct_upload_ticket_for_owner( &state, &request_context, principal.owner_user_id(), payload, ) .await } pub async fn confirm_external_asset_object( State(state): State, Extension(request_context): Extension, Extension(principal): Extension, Json(mut payload): Json, ) -> Result, AppError> { require_scope(&principal, SCOPE_EDITOR_ASSET)?; payload.owner_user_id = Some(principal.owner_user_id().to_string()); confirm_asset_object_for_owner(&state, &request_context, principal.owner_user_id(), payload) .await } pub async fn get_external_asset_read_url( State(state): State, Extension(request_context): Extension, Extension(principal): Extension, Query(query): Query, ) -> Result, AppError> { require_scope(&principal, SCOPE_EDITOR_ASSET)?; get_asset_read_url_with_query( &state, &request_context, query, AssetReadAuthorization::Owner(principal.owner_user_id().to_string()), ) .await } fn require_scope(principal: &ExternalApiPrincipal, scope: &str) -> Result<(), AppError> { if principal.has_scope(scope) { return Ok(()); } Err( AppError::from_status(StatusCode::FORBIDDEN).with_details(json!({ "provider": EXTERNAL_ASSET_PROVIDER, "keyId": principal.key_id(), "scope": scope, "message": "API Key 缺少所需权限", })), ) }