core: type workspace and secret timestamps

This commit is contained in:
a.tolmachev
2026-04-13 05:59:11 +00:00
parent 03cb109b40
commit c736b4f5a8
17 changed files with 243 additions and 139 deletions
+6 -3
View File
@@ -58,7 +58,8 @@ pub struct Membership {
pub workspace_id: WorkspaceId,
pub user_id: UserId,
pub role: MembershipRole,
pub created_at: String,
#[serde(with = "time::serde::rfc3339")]
pub created_at: OffsetDateTime,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@@ -69,8 +70,10 @@ pub struct InvitationToken {
pub role: MembershipRole,
pub status: InvitationStatus,
pub token_hash: String,
pub expires_at: String,
pub created_at: String,
#[serde(with = "time::serde::rfc3339")]
pub expires_at: OffsetDateTime,
#[serde(with = "time::serde::rfc3339")]
pub created_at: OffsetDateTime,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
+58 -4
View File
@@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use crate::ids::{SecretId, UserId, WorkspaceId};
@@ -26,9 +27,12 @@ pub struct Secret {
pub kind: SecretKind,
pub status: SecretStatus,
pub current_version: u32,
pub created_at: String,
pub updated_at: String,
pub last_used_at: Option<String>,
#[serde(with = "time::serde::rfc3339")]
pub created_at: OffsetDateTime,
#[serde(with = "time::serde::rfc3339")]
pub updated_at: OffsetDateTime,
#[serde(with = "time::serde::rfc3339::option")]
pub last_used_at: Option<OffsetDateTime>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@@ -37,6 +41,56 @@ pub struct SecretVersion {
pub version: u32,
pub ciphertext: String,
pub key_version: String,
pub created_at: String,
#[serde(with = "time::serde::rfc3339")]
pub created_at: OffsetDateTime,
pub created_by: Option<UserId>,
}
#[cfg(test)]
mod tests {
use serde_json::json;
use time::{OffsetDateTime, format_description::well_known::Rfc3339};
use super::{Secret, SecretKind, SecretStatus, SecretVersion};
use crate::ids::{SecretId, UserId, WorkspaceId};
#[test]
fn secret_serializes_timestamps_as_rfc3339() {
let secret = Secret {
id: SecretId::new("secret_01"),
workspace_id: WorkspaceId::new("ws_01"),
name: "primary".to_owned(),
kind: SecretKind::Token,
status: SecretStatus::Active,
current_version: 2,
created_at: OffsetDateTime::parse("2026-03-25T12:00:00Z", &Rfc3339).unwrap(),
updated_at: OffsetDateTime::parse("2026-03-25T12:05:00Z", &Rfc3339).unwrap(),
last_used_at: Some(OffsetDateTime::parse("2026-03-25T12:07:00Z", &Rfc3339).unwrap()),
};
let value = serde_json::to_value(&secret).unwrap();
assert_eq!(value["created_at"], json!("2026-03-25T12:00:00Z"));
assert_eq!(value["updated_at"], json!("2026-03-25T12:05:00Z"));
assert_eq!(value["last_used_at"], json!("2026-03-25T12:07:00Z"));
}
#[test]
fn secret_version_deserializes_created_at_from_rfc3339() {
let version: SecretVersion = serde_json::from_value(json!({
"secret_id": "secret_01",
"version": 2,
"ciphertext": "opaque",
"key_version": "v2",
"created_at": "2026-03-25T12:07:00Z",
"created_by": "user_01"
}))
.unwrap();
assert_eq!(
version.created_at,
OffsetDateTime::parse("2026-03-25T12:07:00Z", &Rfc3339).unwrap()
);
assert_eq!(version.created_by, Some(UserId::new("user_01")));
}
}
+55 -2
View File
@@ -1,5 +1,6 @@
use serde::{Deserialize, Serialize};
use serde_json::Value;
use time::OffsetDateTime;
use crate::ids::WorkspaceId;
@@ -17,6 +18,58 @@ pub struct Workspace {
pub display_name: String,
pub status: WorkspaceStatus,
pub settings: Value,
pub created_at: String,
pub updated_at: String,
#[serde(with = "time::serde::rfc3339")]
pub created_at: OffsetDateTime,
#[serde(with = "time::serde::rfc3339")]
pub updated_at: OffsetDateTime,
}
#[cfg(test)]
mod tests {
use serde_json::json;
use time::{OffsetDateTime, format_description::well_known::Rfc3339};
use super::{Workspace, WorkspaceStatus};
use crate::ids::WorkspaceId;
#[test]
fn workspace_serializes_timestamps_as_rfc3339() {
let workspace = Workspace {
id: WorkspaceId::new("ws_01"),
slug: "primary".to_owned(),
display_name: "Primary".to_owned(),
status: WorkspaceStatus::Active,
settings: json!({"region":"eu"}),
created_at: OffsetDateTime::parse("2026-03-25T12:00:00Z", &Rfc3339).unwrap(),
updated_at: OffsetDateTime::parse("2026-03-25T12:05:00Z", &Rfc3339).unwrap(),
};
let value = serde_json::to_value(&workspace).unwrap();
assert_eq!(value["created_at"], json!("2026-03-25T12:00:00Z"));
assert_eq!(value["updated_at"], json!("2026-03-25T12:05:00Z"));
}
#[test]
fn workspace_deserializes_timestamps_from_rfc3339() {
let workspace: Workspace = serde_json::from_value(json!({
"id": "ws_01",
"slug": "primary",
"display_name": "Primary",
"status": "active",
"settings": {"region":"eu"},
"created_at": "2026-03-25T12:00:00Z",
"updated_at": "2026-03-25T12:05:00Z"
}))
.unwrap();
assert_eq!(
workspace.created_at,
OffsetDateTime::parse("2026-03-25T12:00:00Z", &Rfc3339).unwrap()
);
assert_eq!(
workspace.updated_at,
OffsetDateTime::parse("2026-03-25T12:05:00Z", &Rfc3339).unwrap()
);
}
}