feat(api): expose object created_at/updated_at in AdminObjectView (#44)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -45,6 +45,10 @@ pub(crate) struct AdminObjectView {
|
||||
/// Flexible field values (key -> value).
|
||||
#[schema(value_type = std::collections::HashMap<String, serde_json::Value>)]
|
||||
pub fields: serde_json::Value,
|
||||
/// RFC3339 UTC timestamp.
|
||||
pub created_at: String,
|
||||
/// RFC3339 UTC timestamp.
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
impl AdminObjectView {
|
||||
@@ -61,6 +65,14 @@ impl AdminObjectView {
|
||||
recording_date: o.recording_date.map(format_date),
|
||||
visibility: o.visibility.as_str().to_owned(),
|
||||
fields: o.fields.clone(),
|
||||
created_at: o
|
||||
.created_at
|
||||
.format(&time::format_description::well_known::Rfc3339)
|
||||
.unwrap_or_default(),
|
||||
updated_at: o
|
||||
.updated_at
|
||||
.format(&time::format_description::well_known::Rfc3339)
|
||||
.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -843,6 +843,40 @@ async fn delete_field_definition_referenced_is_409(pool: PgPool) {
|
||||
assert_eq!(body["count"], 1);
|
||||
}
|
||||
|
||||
#[sqlx::test(migrations = "../db/migrations")]
|
||||
async fn listed_object_carries_timestamps(pool: PgPool) {
|
||||
migrate_sessions(&db::Db::from_pool(pool.clone()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
seed_user(&pool, "ed@example.com", "pw-editor-123", Role::Editor).await;
|
||||
|
||||
let app = build_app(state(pool));
|
||||
let cookie = login(&app, "ed@example.com", "pw-editor-123").await;
|
||||
|
||||
let created = send(
|
||||
&app,
|
||||
&cookie,
|
||||
"POST",
|
||||
"/api/admin/objects",
|
||||
Some(r#"{"object_number":"TS-1","object_name":"clock","number_of_objects":1,"visibility":"draft"}"#),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(created.status(), StatusCode::CREATED);
|
||||
|
||||
let list = send(&app, &cookie, "GET", "/api/admin/objects", None).await;
|
||||
assert_eq!(list.status(), StatusCode::OK);
|
||||
|
||||
let body: serde_json::Value =
|
||||
serde_json::from_slice(&list.into_body().collect().await.unwrap().to_bytes()).unwrap();
|
||||
|
||||
let item = &body["items"][0];
|
||||
let created_at = item["created_at"].as_str().unwrap();
|
||||
let updated_at = item["updated_at"].as_str().unwrap();
|
||||
assert!(!created_at.is_empty(), "created_at must be non-empty");
|
||||
assert!(!updated_at.is_empty(), "updated_at must be non-empty");
|
||||
}
|
||||
|
||||
#[sqlx::test(migrations = "../db/migrations")]
|
||||
async fn field_definition_edit_delete_requires_auth(pool: PgPool) {
|
||||
migrate_sessions(&db::Db::from_pool(pool.clone()))
|
||||
|
||||
Reference in New Issue
Block a user