use serde::{Deserialize, Serialize}; use time::OffsetDateTime; use crate::{ ids::{AuthProfileId, SecretId, WorkspaceId}, protocol::AuthKind, }; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct BearerAuthConfig { pub header_name: String, pub secret_id: SecretId, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct BasicAuthConfig { pub username_secret_id: SecretId, pub password_secret_id: SecretId, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct ApiKeyHeaderAuthConfig { pub header_name: String, pub secret_id: SecretId, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct ApiKeyQueryAuthConfig { pub param_name: String, pub secret_id: SecretId, } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum AuthConfig { Bearer(BearerAuthConfig), Basic(BasicAuthConfig), ApiKeyHeader(ApiKeyHeaderAuthConfig), ApiKeyQuery(ApiKeyQueryAuthConfig), } impl AuthConfig { pub fn secret_ids(&self) -> Vec<&SecretId> { match self { Self::Bearer(config) => vec![&config.secret_id], Self::Basic(config) => vec![&config.username_secret_id, &config.password_secret_id], Self::ApiKeyHeader(config) => vec![&config.secret_id], Self::ApiKeyQuery(config) => vec![&config.secret_id], } } } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct AuthProfile { pub id: AuthProfileId, pub workspace_id: WorkspaceId, pub name: String, pub kind: AuthKind, pub config: AuthConfig, #[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::{ApiKeyHeaderAuthConfig, AuthConfig, AuthProfile}; use crate::{ ids::{AuthProfileId, SecretId, WorkspaceId}, protocol::AuthKind, }; #[test] fn auth_profile_serializes_timestamps_as_rfc3339() { let profile = AuthProfile { id: AuthProfileId::new("auth_01"), workspace_id: WorkspaceId::new("ws_default"), name: "header".to_owned(), kind: AuthKind::ApiKeyHeader, config: AuthConfig::ApiKeyHeader(ApiKeyHeaderAuthConfig { header_name: "X-Api-Key".to_owned(), secret_id: SecretId::new("secret_01"), }), 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(&profile).unwrap(); assert_eq!(value["created_at"], json!("2026-03-25T12:00:00Z")); assert_eq!(value["updated_at"], json!("2026-03-25T12:05:00Z")); } }