This commit is contained in:
@@ -23,8 +23,13 @@ use shared_contracts::assets::{
|
||||
use spacetime_client::SpacetimeClientError;
|
||||
|
||||
use crate::{
|
||||
api_response::json_success_body, auth::AuthenticatedAccessToken, http_error::AppError,
|
||||
platform_errors::map_oss_error, request_context::RequestContext, state::AppState,
|
||||
api_response::json_success_body,
|
||||
auth::AuthenticatedAccessToken,
|
||||
http_error::AppError,
|
||||
platform_errors::map_oss_error,
|
||||
request_context::RequestContext,
|
||||
state::AppState,
|
||||
tracking::{TrackingEventDraft, record_tracking_event_after_success},
|
||||
};
|
||||
|
||||
// 历史素材类型需要与 SpacetimeDB 侧白名单保持同一口径,避免新增素材类型时 HTTP 门面漏同步。
|
||||
@@ -41,6 +46,7 @@ const SUPPORTED_ASSET_HISTORY_KINDS: [&str; 7] = [
|
||||
pub async fn create_direct_upload_ticket(
|
||||
State(state): State<AppState>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
Json(payload): Json<CreateDirectUploadTicketRequest>,
|
||||
) -> Result<Json<Value>, AppError> {
|
||||
let oss_client = state.oss_client().ok_or_else(|| {
|
||||
@@ -75,12 +81,33 @@ pub async fn create_direct_upload_ticket(
|
||||
"message": error.to_string(),
|
||||
}))
|
||||
})?;
|
||||
let upload = DirectUploadTicketPayload::from(signed);
|
||||
|
||||
record_asset_tracking_event(
|
||||
&state,
|
||||
&request_context,
|
||||
&authenticated,
|
||||
"asset_upload_ticket_create",
|
||||
json!({
|
||||
"asset": {
|
||||
"operation": "asset_upload_ticket_create",
|
||||
"operationFamily": "upload_ticket",
|
||||
"objectKey": upload.object_key.clone(),
|
||||
"legacyPublicPath": upload.legacy_public_path.clone(),
|
||||
"bucket": upload.bucket.clone(),
|
||||
"contentType": upload.content_type.clone(),
|
||||
"access": upload.access,
|
||||
"keyPrefix": upload.key_prefix.clone(),
|
||||
"maxSizeBytes": upload.max_size_bytes,
|
||||
"successActionStatus": upload.success_action_status,
|
||||
}
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
CreateDirectUploadTicketResponse {
|
||||
upload: DirectUploadTicketPayload::from(signed),
|
||||
},
|
||||
CreateDirectUploadTicketResponse { upload },
|
||||
))
|
||||
}
|
||||
|
||||
@@ -190,6 +217,7 @@ pub async fn create_sts_upload_credentials(
|
||||
pub async fn confirm_asset_object(
|
||||
State(state): State<AppState>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
Json(payload): Json<ConfirmAssetObjectRequest>,
|
||||
) -> Result<Json<Value>, AppError> {
|
||||
let oss_client = state.oss_client().ok_or_else(|| {
|
||||
@@ -209,33 +237,60 @@ pub async fn confirm_asset_object(
|
||||
.await
|
||||
.map_err(map_confirm_asset_object_error)?;
|
||||
|
||||
let asset_object = AssetObjectPayload {
|
||||
asset_object_id: result.asset_object_id,
|
||||
bucket: result.bucket,
|
||||
object_key: result.object_key,
|
||||
access_policy: result.access_policy.as_str().to_string(),
|
||||
content_type: result.content_type,
|
||||
content_length: result.content_length,
|
||||
content_hash: result.content_hash,
|
||||
version: result.version,
|
||||
source_job_id: result.source_job_id,
|
||||
owner_user_id: result.owner_user_id,
|
||||
profile_id: result.profile_id,
|
||||
entity_id: result.entity_id,
|
||||
asset_kind: result.asset_kind,
|
||||
created_at: result.created_at,
|
||||
updated_at: result.updated_at,
|
||||
};
|
||||
|
||||
record_asset_tracking_event(
|
||||
&state,
|
||||
&request_context,
|
||||
&authenticated,
|
||||
"asset_upload_confirm",
|
||||
json!({
|
||||
"asset": {
|
||||
"operation": "asset_upload_confirm",
|
||||
"operationFamily": "object_confirm",
|
||||
"assetObjectId": asset_object.asset_object_id,
|
||||
"assetKind": asset_object.asset_kind,
|
||||
"objectKey": asset_object.object_key,
|
||||
"bucket": asset_object.bucket,
|
||||
"accessPolicy": asset_object.access_policy,
|
||||
"contentType": asset_object.content_type,
|
||||
"contentLength": asset_object.content_length,
|
||||
"version": asset_object.version,
|
||||
"sourceJobId": asset_object.source_job_id,
|
||||
"ownerUserId": asset_object.owner_user_id,
|
||||
"profileId": asset_object.profile_id,
|
||||
"entityId": asset_object.entity_id,
|
||||
}
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
ConfirmAssetObjectResponse {
|
||||
asset_object: AssetObjectPayload {
|
||||
asset_object_id: result.asset_object_id,
|
||||
bucket: result.bucket,
|
||||
object_key: result.object_key,
|
||||
access_policy: result.access_policy.as_str().to_string(),
|
||||
content_type: result.content_type,
|
||||
content_length: result.content_length,
|
||||
content_hash: result.content_hash,
|
||||
version: result.version,
|
||||
source_job_id: result.source_job_id,
|
||||
owner_user_id: result.owner_user_id,
|
||||
profile_id: result.profile_id,
|
||||
entity_id: result.entity_id,
|
||||
asset_kind: result.asset_kind,
|
||||
created_at: result.created_at,
|
||||
updated_at: result.updated_at,
|
||||
},
|
||||
},
|
||||
ConfirmAssetObjectResponse { asset_object },
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn bind_asset_object_to_entity(
|
||||
State(state): State<AppState>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
Json(payload): Json<BindAssetObjectRequest>,
|
||||
) -> Result<Json<Value>, AppError> {
|
||||
let now_micros = current_utc_micros();
|
||||
@@ -258,25 +313,60 @@ pub async fn bind_asset_object_to_entity(
|
||||
.await
|
||||
.map_err(map_confirm_asset_object_error)?;
|
||||
|
||||
let asset_binding = AssetBindingPayload {
|
||||
binding_id: result.binding_id,
|
||||
asset_object_id: result.asset_object_id,
|
||||
entity_kind: result.entity_kind,
|
||||
entity_id: result.entity_id,
|
||||
slot: result.slot,
|
||||
asset_kind: result.asset_kind,
|
||||
owner_user_id: result.owner_user_id,
|
||||
profile_id: result.profile_id,
|
||||
created_at: result.created_at,
|
||||
updated_at: result.updated_at,
|
||||
};
|
||||
|
||||
record_asset_tracking_event(
|
||||
&state,
|
||||
&request_context,
|
||||
&authenticated,
|
||||
"asset_bind",
|
||||
json!({
|
||||
"asset": {
|
||||
"operation": "asset_bind",
|
||||
"operationFamily": "object_bind",
|
||||
"bindingId": asset_binding.binding_id,
|
||||
"assetObjectId": asset_binding.asset_object_id,
|
||||
"assetKind": asset_binding.asset_kind,
|
||||
"entityKind": asset_binding.entity_kind,
|
||||
"entityId": asset_binding.entity_id,
|
||||
"slot": asset_binding.slot,
|
||||
"ownerUserId": asset_binding.owner_user_id,
|
||||
"profileId": asset_binding.profile_id,
|
||||
}
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
BindAssetObjectResponse {
|
||||
asset_binding: AssetBindingPayload {
|
||||
binding_id: result.binding_id,
|
||||
asset_object_id: result.asset_object_id,
|
||||
entity_kind: result.entity_kind,
|
||||
entity_id: result.entity_id,
|
||||
slot: result.slot,
|
||||
asset_kind: result.asset_kind,
|
||||
owner_user_id: result.owner_user_id,
|
||||
profile_id: result.profile_id,
|
||||
created_at: result.created_at,
|
||||
updated_at: result.updated_at,
|
||||
},
|
||||
},
|
||||
BindAssetObjectResponse { asset_binding },
|
||||
))
|
||||
}
|
||||
|
||||
async fn record_asset_tracking_event(
|
||||
state: &AppState,
|
||||
request_context: &RequestContext,
|
||||
authenticated: &AuthenticatedAccessToken,
|
||||
event_key: &'static str,
|
||||
metadata: Value,
|
||||
) {
|
||||
let user_id = authenticated.claims().user_id().to_string();
|
||||
let mut draft = TrackingEventDraft::user(event_key, "asset", user_id.as_str());
|
||||
draft.metadata = metadata;
|
||||
record_tracking_event_after_success(state, request_context, draft).await;
|
||||
}
|
||||
|
||||
fn resolve_object_key_from_query(query: &GetReadUrlQuery) -> Option<String> {
|
||||
if let Some(object_key) = query
|
||||
.object_key
|
||||
|
||||
Reference in New Issue
Block a user