后端重写提交
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
use std::{error::Error, fmt};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use shared_kernel::{
|
||||
build_prefixed_seed_id, format_timestamp_micros, normalize_optional_string,
|
||||
normalize_required_string,
|
||||
};
|
||||
#[cfg(feature = "spacetime-types")]
|
||||
use spacetimedb::SpacetimeType;
|
||||
|
||||
@@ -175,6 +179,28 @@ impl AssetObjectAccessPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
// 资产核心对象字段需要继续保留模块自己的错误语义,但基础必填字符串归一化统一走 shared-kernel。
|
||||
fn normalize_required_asset_field(
|
||||
value: impl AsRef<str>,
|
||||
error: AssetObjectFieldError,
|
||||
) -> Result<String, AssetObjectFieldError> {
|
||||
normalize_required_string(value).ok_or(error)
|
||||
}
|
||||
|
||||
fn normalize_asset_object_key(value: impl AsRef<str>) -> Result<String, AssetObjectFieldError> {
|
||||
let normalized = value.as_ref().trim();
|
||||
let normalized = normalized.trim_start_matches('/');
|
||||
normalize_required_string(normalized).ok_or(AssetObjectFieldError::MissingObjectKey)
|
||||
}
|
||||
|
||||
fn validate_asset_object_version(version: u32) -> Result<(), AssetObjectFieldError> {
|
||||
if version == 0 {
|
||||
return Err(AssetObjectFieldError::InvalidVersion);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// bucket 与 object_key 是正式真相字段,因此这里只做字段校验,不回退成单字符串路径字段。
|
||||
pub fn validate_asset_object_fields(
|
||||
bucket: &str,
|
||||
@@ -182,22 +208,10 @@ pub fn validate_asset_object_fields(
|
||||
asset_kind: &str,
|
||||
version: u32,
|
||||
) -> Result<(), AssetObjectFieldError> {
|
||||
if bucket.trim().is_empty() {
|
||||
return Err(AssetObjectFieldError::MissingBucket);
|
||||
}
|
||||
|
||||
if object_key.trim().trim_start_matches('/').is_empty() {
|
||||
return Err(AssetObjectFieldError::MissingObjectKey);
|
||||
}
|
||||
|
||||
if asset_kind.trim().is_empty() {
|
||||
return Err(AssetObjectFieldError::MissingAssetKind);
|
||||
}
|
||||
|
||||
if version == 0 {
|
||||
return Err(AssetObjectFieldError::InvalidVersion);
|
||||
}
|
||||
|
||||
normalize_required_asset_field(bucket, AssetObjectFieldError::MissingBucket)?;
|
||||
normalize_asset_object_key(object_key)?;
|
||||
normalize_required_asset_field(asset_kind, AssetObjectFieldError::MissingAssetKind)?;
|
||||
validate_asset_object_version(version)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -210,30 +224,12 @@ pub fn validate_asset_entity_binding_fields(
|
||||
slot: &str,
|
||||
asset_kind: &str,
|
||||
) -> Result<(), AssetObjectFieldError> {
|
||||
if binding_id.trim().is_empty() {
|
||||
return Err(AssetObjectFieldError::MissingBindingId);
|
||||
}
|
||||
|
||||
if asset_object_id.trim().is_empty() {
|
||||
return Err(AssetObjectFieldError::MissingAssetObjectId);
|
||||
}
|
||||
|
||||
if entity_kind.trim().is_empty() {
|
||||
return Err(AssetObjectFieldError::MissingEntityKind);
|
||||
}
|
||||
|
||||
if entity_id.trim().is_empty() {
|
||||
return Err(AssetObjectFieldError::MissingEntityId);
|
||||
}
|
||||
|
||||
if slot.trim().is_empty() {
|
||||
return Err(AssetObjectFieldError::MissingSlot);
|
||||
}
|
||||
|
||||
if asset_kind.trim().is_empty() {
|
||||
return Err(AssetObjectFieldError::MissingAssetKind);
|
||||
}
|
||||
|
||||
normalize_required_asset_field(binding_id, AssetObjectFieldError::MissingBindingId)?;
|
||||
normalize_required_asset_field(asset_object_id, AssetObjectFieldError::MissingAssetObjectId)?;
|
||||
normalize_required_asset_field(entity_kind, AssetObjectFieldError::MissingEntityKind)?;
|
||||
normalize_required_asset_field(entity_id, AssetObjectFieldError::MissingEntityId)?;
|
||||
normalize_required_asset_field(slot, AssetObjectFieldError::MissingSlot)?;
|
||||
normalize_required_asset_field(asset_kind, AssetObjectFieldError::MissingAssetKind)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -253,21 +249,20 @@ pub fn build_asset_object_upsert_input(
|
||||
entity_id: Option<String>,
|
||||
updated_at_micros: i64,
|
||||
) -> Result<AssetObjectUpsertInput, AssetObjectFieldError> {
|
||||
if asset_object_id.trim().is_empty() {
|
||||
return Err(AssetObjectFieldError::MissingAssetObjectId);
|
||||
}
|
||||
|
||||
validate_asset_object_fields(
|
||||
&bucket,
|
||||
&object_key,
|
||||
&asset_kind,
|
||||
INITIAL_ASSET_OBJECT_VERSION,
|
||||
let asset_object_id = normalize_required_asset_field(
|
||||
asset_object_id,
|
||||
AssetObjectFieldError::MissingAssetObjectId,
|
||||
)?;
|
||||
let bucket = normalize_required_asset_field(bucket, AssetObjectFieldError::MissingBucket)?;
|
||||
let object_key = normalize_asset_object_key(object_key)?;
|
||||
let asset_kind =
|
||||
normalize_required_asset_field(asset_kind, AssetObjectFieldError::MissingAssetKind)?;
|
||||
validate_asset_object_version(INITIAL_ASSET_OBJECT_VERSION)?;
|
||||
|
||||
Ok(AssetObjectUpsertInput {
|
||||
asset_object_id: asset_object_id.trim().to_string(),
|
||||
bucket: bucket.trim().to_string(),
|
||||
object_key: object_key.trim().trim_start_matches('/').to_string(),
|
||||
asset_object_id,
|
||||
bucket,
|
||||
object_key,
|
||||
access_policy,
|
||||
content_type: normalize_optional_value(content_type),
|
||||
content_length,
|
||||
@@ -277,7 +272,7 @@ pub fn build_asset_object_upsert_input(
|
||||
owner_user_id: normalize_optional_value(owner_user_id),
|
||||
profile_id: normalize_optional_value(profile_id),
|
||||
entity_id: normalize_optional_value(entity_id),
|
||||
asset_kind: asset_kind.trim().to_string(),
|
||||
asset_kind,
|
||||
updated_at_micros,
|
||||
})
|
||||
}
|
||||
@@ -314,22 +309,27 @@ pub fn build_asset_entity_binding_input(
|
||||
profile_id: Option<String>,
|
||||
updated_at_micros: i64,
|
||||
) -> Result<AssetEntityBindingInput, AssetObjectFieldError> {
|
||||
validate_asset_entity_binding_fields(
|
||||
&binding_id,
|
||||
&asset_object_id,
|
||||
&entity_kind,
|
||||
&entity_id,
|
||||
&slot,
|
||||
&asset_kind,
|
||||
let binding_id =
|
||||
normalize_required_asset_field(binding_id, AssetObjectFieldError::MissingBindingId)?;
|
||||
let asset_object_id = normalize_required_asset_field(
|
||||
asset_object_id,
|
||||
AssetObjectFieldError::MissingAssetObjectId,
|
||||
)?;
|
||||
let entity_kind =
|
||||
normalize_required_asset_field(entity_kind, AssetObjectFieldError::MissingEntityKind)?;
|
||||
let entity_id =
|
||||
normalize_required_asset_field(entity_id, AssetObjectFieldError::MissingEntityId)?;
|
||||
let slot = normalize_required_asset_field(slot, AssetObjectFieldError::MissingSlot)?;
|
||||
let asset_kind =
|
||||
normalize_required_asset_field(asset_kind, AssetObjectFieldError::MissingAssetKind)?;
|
||||
|
||||
Ok(AssetEntityBindingInput {
|
||||
binding_id: binding_id.trim().to_string(),
|
||||
asset_object_id: asset_object_id.trim().to_string(),
|
||||
entity_kind: entity_kind.trim().to_string(),
|
||||
entity_id: entity_id.trim().to_string(),
|
||||
slot: slot.trim().to_string(),
|
||||
asset_kind: asset_kind.trim().to_string(),
|
||||
binding_id,
|
||||
asset_object_id,
|
||||
entity_kind,
|
||||
entity_id,
|
||||
slot,
|
||||
asset_kind,
|
||||
owner_user_id: normalize_optional_value(owner_user_id),
|
||||
profile_id: normalize_optional_value(profile_id),
|
||||
updated_at_micros,
|
||||
@@ -354,24 +354,15 @@ pub fn build_asset_entity_binding_record(
|
||||
}
|
||||
|
||||
pub fn generate_asset_object_id(seed_micros: i64) -> String {
|
||||
format!("{}{:x}", ASSET_OBJECT_ID_PREFIX, seed_micros)
|
||||
build_prefixed_seed_id(ASSET_OBJECT_ID_PREFIX, seed_micros)
|
||||
}
|
||||
|
||||
pub fn generate_asset_binding_id(seed_micros: i64) -> String {
|
||||
format!("{}{:x}", ASSET_BINDING_ID_PREFIX, seed_micros)
|
||||
build_prefixed_seed_id(ASSET_BINDING_ID_PREFIX, seed_micros)
|
||||
}
|
||||
|
||||
pub fn normalize_optional_value(value: Option<String>) -> Option<String> {
|
||||
value.and_then(|value| {
|
||||
let value = value.trim().to_string();
|
||||
if value.is_empty() { None } else { Some(value) }
|
||||
})
|
||||
}
|
||||
|
||||
fn format_timestamp_micros(micros: i64) -> String {
|
||||
let seconds = micros.div_euclid(1_000_000);
|
||||
let subsec_micros = micros.rem_euclid(1_000_000);
|
||||
format!("{seconds}.{subsec_micros:06}Z")
|
||||
normalize_optional_string(value)
|
||||
}
|
||||
|
||||
impl fmt::Display for AssetObjectFieldError {
|
||||
|
||||
Reference in New Issue
Block a user