use crate::error::{AdminError, Result};
use ::nonce_auth::{CredentialBuilder, NonceCredential};
use actrix_proto::NonceCredential as ProtoCredential;
pub fn to_proto_credential(credential: NonceCredential) -> ProtoCredential {
ProtoCredential {
timestamp: credential.timestamp,
nonce: credential.nonce,
signature: credential.signature,
}
}
pub fn from_proto_credential(proto: &ProtoCredential) -> NonceCredential {
NonceCredential {
timestamp: proto.timestamp,
nonce: proto.nonce.clone(),
signature: proto.signature.clone(),
}
}
pub fn generate_credential(shared_secret: &[u8], payload: &[u8]) -> Result<ProtoCredential> {
let credential = CredentialBuilder::new(shared_secret)
.sign(payload)
.map_err(|e| AdminError::Authentication(format!("Failed to generate credential: {e}")))?;
Ok(to_proto_credential(credential))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_credential_conversion() {
let original = NonceCredential {
timestamp: 1699999999,
nonce: "550e8400-e29b-41d4-a716-446655440000".to_string(),
signature: "YWJjMTIz".to_string(),
};
let proto = to_proto_credential(original.clone());
let converted = from_proto_credential(&proto);
assert_eq!(original.timestamp, converted.timestamp);
assert_eq!(original.nonce, converted.nonce);
assert_eq!(original.signature, converted.signature);
}
#[test]
fn test_generate_credential() {
let secret = b"test-shared-secret-key-32-bytes!";
let payload = b"health_check:test-node";
let result = generate_credential(secret, payload);
assert!(result.is_ok());
let credential = result.unwrap();
assert!(credential.timestamp > 0);
assert!(!credential.nonce.is_empty());
assert!(!credential.signature.is_empty());
}
#[test]
fn test_generate_credential_different_payloads() {
let secret = b"test-shared-secret-key-32-bytes!";
let payload1 = b"health_check:node1";
let payload2 = b"health_check:node2";
let cred1 = generate_credential(secret, payload1).unwrap();
let cred2 = generate_credential(secret, payload2).unwrap();
assert_ne!(cred1.signature, cred2.signature);
assert_ne!(cred1.nonce, cred2.nonce);
}
}