core: type user and auth session timestamps
This commit is contained in:
@@ -25,6 +25,7 @@ use sqlx::{
|
||||
};
|
||||
use std::{collections::BTreeMap, env, time::Duration};
|
||||
use thiserror::Error;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use crate::{
|
||||
error::RegistryError,
|
||||
@@ -489,7 +490,7 @@ fn build_user(
|
||||
email: String,
|
||||
display_name: String,
|
||||
status: String,
|
||||
created_at: String,
|
||||
created_at: OffsetDateTime,
|
||||
) -> Result<User, RegistryError> {
|
||||
Ok(User {
|
||||
id: UserId::new(id),
|
||||
@@ -1131,12 +1132,13 @@ mod tests {
|
||||
MembershipRole, OperationId, OperationStatus, PlatformApiKey, PlatformApiKeyId,
|
||||
PlatformApiKeyScope, PlatformApiKeyStatus, Protocol, RestTarget, RetryPolicy, Samples,
|
||||
SecretId, StreamSession, StreamSessionId, StreamStatus, Target, ToolDescription,
|
||||
ToolExample, User, UserId, Workspace, WorkspaceId,
|
||||
ToolExample, User, UserId, UserSessionId, Workspace, WorkspaceId,
|
||||
};
|
||||
use crank_mapping::{MappingRule, MappingSet};
|
||||
use crank_schema::{Schema, SchemaKind};
|
||||
use serde_json::json;
|
||||
use sqlx::{Executor, PgPool, postgres::PgPoolOptions};
|
||||
use time::{OffsetDateTime, format_description::well_known::Rfc3339};
|
||||
|
||||
use crate::{
|
||||
PostgresRegistry, RegistryError,
|
||||
@@ -1156,6 +1158,10 @@ mod tests {
|
||||
WorkspaceId::new("ws_default")
|
||||
}
|
||||
|
||||
fn timestamp(value: &str) -> OffsetDateTime {
|
||||
OffsetDateTime::parse(value, &Rfc3339).unwrap()
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn stores_versions_and_published_operations() {
|
||||
let database = TestDatabase::new().await;
|
||||
@@ -1480,7 +1486,7 @@ mod tests {
|
||||
email: "owner@example.com".to_owned(),
|
||||
display_name: "Owner".to_owned(),
|
||||
status: crank_core::UserStatus::Active,
|
||||
created_at: "2026-03-25T11:00:00Z".to_owned(),
|
||||
created_at: timestamp("2026-03-25T11:00:00Z"),
|
||||
};
|
||||
|
||||
registry
|
||||
@@ -1590,6 +1596,62 @@ mod tests {
|
||||
assert_eq!(updated.display_name, "Updated Owner");
|
||||
assert!(has_access);
|
||||
assert!(!lacks_access);
|
||||
assert!(updated.created_at.unix_timestamp() > 0);
|
||||
|
||||
database.cleanup().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn creates_and_loads_user_sessions_with_typed_expiration() {
|
||||
let database = TestDatabase::new().await;
|
||||
let registry = database.registry().await;
|
||||
let workspace = Workspace {
|
||||
id: WorkspaceId::new("ws_session_01"),
|
||||
slug: "session".to_owned(),
|
||||
display_name: "Session Workspace".to_owned(),
|
||||
status: crank_core::WorkspaceStatus::Active,
|
||||
settings: json!({}),
|
||||
created_at: "2026-03-25T12:00:00Z".to_owned(),
|
||||
updated_at: "2026-03-25T12:00:00Z".to_owned(),
|
||||
};
|
||||
let user_id = registry
|
||||
.upsert_bootstrap_user("session@example.com", "Owner", "hashed-password")
|
||||
.await
|
||||
.unwrap();
|
||||
let session_id = UserSessionId::new("sess_01");
|
||||
let expires_at = timestamp("2030-04-06T12:05:00Z");
|
||||
|
||||
registry
|
||||
.create_workspace(CreateWorkspaceRequest {
|
||||
workspace: &workspace,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
registry
|
||||
.ensure_membership(&workspace.id, &user_id, MembershipRole::Owner)
|
||||
.await
|
||||
.unwrap();
|
||||
registry
|
||||
.create_user_session(
|
||||
&session_id,
|
||||
&user_id,
|
||||
Some(&workspace.id),
|
||||
"secret-hash-01",
|
||||
&expires_at,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let session = registry
|
||||
.get_user_session(&session_id, "secret-hash-01")
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(session.session_id, session_id);
|
||||
assert_eq!(session.current_workspace_id, Some(workspace.id.clone()));
|
||||
assert_eq!(session.user.id, user_id);
|
||||
assert!(session.user.created_at.unix_timestamp() > 0);
|
||||
|
||||
database.cleanup().await;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user