Files
nx9-wg/crates/nx9-wg-db/tests/test_auth_repositories.rs
thakaresandCopilot 2ac6c81dfe cli: avoid data-dir initialization for version; create db parent dirs; redact generated passwords in CLI output
- Prevent 'nx9-wg version' from creating data directories by avoiding database initialization.
- Create parent directories when an explicit --database path is provided.
- Redact printed generated administrator passwords; announce file path or redact instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-08-16 16:26:24 +05:30

178 lines
5.1 KiB
Rust

//! Tests for Session and API Token repository operations.
use chrono::{Duration, Utc};
use nx9_wg_core::crypto::{generate_api_token, hash_password};
use nx9_wg_core::types::auth::{ApiToken, Session};
use nx9_wg_db::Store;
use uuid::Uuid;
#[tokio::test]
async fn test_session_lifecycle() {
let store = Store::connect_in_memory().await.expect("connect");
store.migrate().await.expect("migrate");
let pw_hash = hash_password("AdminPass123!").expect("hash");
store.create_admin("admin", &pw_hash).await.expect("admin");
let now = Utc::now().naive_utc();
let session_id = Uuid::new_v4().to_string();
let session = Session {
id: session_id.clone(),
admin_id: 1,
created_at: now,
expires_at: now + Duration::hours(24),
last_seen_at: Some(now),
ip_address: Some("10.0.0.5".to_string()),
user_agent: Some("TestAgent/1.0".to_string()),
};
store
.create_session(&session)
.await
.expect("create_session");
let fetched = store
.get_session(&session_id)
.await
.expect("get_session")
.expect("session found");
assert_eq!(fetched.id, session_id);
assert_eq!(fetched.admin_id, 1);
assert_eq!(fetched.ip_address.as_deref(), Some("10.0.0.5"));
// Touch session
store
.touch_session(&session_id)
.await
.expect("touch_session");
// Test delete expired sessions
let expired_id = Uuid::new_v4().to_string();
let expired_session = Session {
id: expired_id.clone(),
admin_id: 1,
created_at: now - Duration::hours(48),
expires_at: now - Duration::hours(24),
last_seen_at: None,
ip_address: None,
user_agent: None,
};
store
.create_session(&expired_session)
.await
.expect("expired session");
let deleted = store
.delete_expired_sessions()
.await
.expect("delete expired");
assert_eq!(deleted, 1);
assert!(store.get_session(&expired_id).await.expect("get").is_none());
assert!(store.get_session(&session_id).await.expect("get").is_some());
// Delete single session
store
.delete_session(&session_id)
.await
.expect("delete session");
assert!(store.get_session(&session_id).await.expect("get").is_none());
// Test delete_all_admin_sessions
let s1 = Session {
id: "s1".to_string(),
admin_id: 1,
created_at: now,
expires_at: now + Duration::hours(1),
last_seen_at: None,
ip_address: None,
user_agent: None,
};
let s2 = Session {
id: "s2".to_string(),
admin_id: 1,
created_at: now,
expires_at: now + Duration::hours(1),
last_seen_at: None,
ip_address: None,
user_agent: None,
};
store.create_session(&s1).await.expect("s1");
store.create_session(&s2).await.expect("s2");
let deleted_all = store
.delete_all_admin_sessions(1)
.await
.expect("delete all");
assert_eq!(deleted_all, 2);
}
#[tokio::test]
async fn test_api_token_lifecycle() {
let store = Store::connect_in_memory().await.expect("connect");
store.migrate().await.expect("migrate");
let pw_hash = hash_password("AdminPass123!").expect("hash");
store.create_admin("admin", &pw_hash).await.expect("admin");
let (raw_token, token_hash) = generate_api_token();
let token_id = Uuid::new_v4().to_string();
let now = Utc::now().naive_utc();
let token = ApiToken {
id: token_id.clone(),
admin_id: 1,
name: "CI/CD Deployment Token".to_string(),
token_hash: token_hash.clone(),
created_at: now,
expires_at: Some(now + Duration::days(30)),
last_used_at: None,
revoked_at: None,
revoked: false,
};
store.create_token(&token).await.expect("create_token");
// Lookup by hash
let found = store
.find_token_by_hash(&token_hash)
.await
.expect("find by hash")
.expect("token found");
assert_eq!(found.id, token_id);
assert_eq!(found.name, "CI/CD Deployment Token");
assert!(!found.revoked);
// Verify raw token is never in the stored record
let debug_out = format!("{:?}", found);
assert!(debug_out.contains("[REDACTED]"));
assert!(!debug_out.contains(&raw_token));
// Mark token used
store.mark_token_used(&token_id).await.expect("mark used");
let after_use = store
.get_token(&token_id)
.await
.expect("get")
.expect("token");
assert!(after_use.last_used_at.is_some());
// List tokens
let tokens = store.list_tokens().await.expect("list tokens");
assert_eq!(tokens.len(), 1);
// Revoke token
store.revoke_token(&token_id).await.expect("revoke token");
let revoked = store
.get_token(&token_id)
.await
.expect("get")
.expect("token");
assert!(revoked.revoked);
assert!(revoked.revoked_at.is_some());
// Delete token
store.delete_token(&token_id).await.expect("delete token");
assert!(store.get_token(&token_id).await.expect("get").is_none());
}