Files
crank/crates/crank-core/src/auth.rs
T
2026-04-12 22:20:19 +00:00

98 lines
3.0 KiB
Rust

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"));
}
}