use std::collections::HashMap;
use std::net::SocketAddr;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Identity {
pub id: String,
pub scopes: Vec<String>,
pub resources: HashMap<String, Vec<String>>,
}
#[derive(Debug, Clone)]
pub struct AuthToken {
pub raw: Vec<u8>,
}
#[derive(Clone)]
pub struct AuthContext {
pub identity: Option<Identity>,
pub alpn: Vec<u8>,
pub remote_addr: Option<SocketAddr>,
pub tls_client_fingerprint: Option<String>,
}
impl AuthContext {
pub fn anonymous(alpn: impl Into<Vec<u8>>) -> Self {
Self {
identity: None,
alpn: alpn.into(),
remote_addr: None,
tls_client_fingerprint: None,
}
}
}
pub trait IdentityProvider: Send + Sync + 'static {
fn resolve_from_fingerprint(&self, fingerprint: &str) -> Option<Identity>;
fn resolve_from_token(&self, token: &AuthToken) -> Option<Identity>;
}
pub struct NoopIdentityProvider;
impl IdentityProvider for NoopIdentityProvider {
fn resolve_from_fingerprint(&self, _: &str) -> Option<Identity> {
None
}
fn resolve_from_token(&self, _: &AuthToken) -> Option<Identity> {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn identity_fields_and_equality() {
let mut resources = HashMap::new();
resources.insert("service".to_string(), vec!["gitea".to_string()]);
let id = Identity {
id: "SHA256:abc123".to_string(),
scopes: vec!["relay:connect".to_string()],
resources,
};
let id2 = id.clone();
assert_eq!(id, id2);
assert_eq!(id.id, "SHA256:abc123");
}
#[test]
fn auth_token_is_clone() {
let token = AuthToken {
raw: b"alk_test".to_vec(),
};
let cloned = token.clone();
assert_eq!(token.raw, cloned.raw);
}
#[test]
fn auth_context_is_clone() {
let ctx = AuthContext {
identity: None,
alpn: b"alk/test".to_vec(),
remote_addr: None,
tls_client_fingerprint: None,
};
let cloned = ctx.clone();
assert_eq!(cloned.alpn, b"alk/test");
assert!(cloned.identity.is_none());
}
#[test]
fn auth_context_anonymous_sets_alpn_only() {
let ctx = AuthContext::anonymous(b"alk/test");
assert_eq!(ctx.alpn, b"alk/test");
assert!(ctx.identity.is_none());
assert!(ctx.remote_addr.is_none());
assert!(ctx.tls_client_fingerprint.is_none());
}
}