use super::backend::{AuthBackend, AuthError, Principal, Role};
use super::env_backend::EnvAuthBackend;
use async_trait::async_trait;
use kyma_core::catalog::Catalog;
use std::sync::Arc;
pub fn hash_token(token: &str) -> Vec<u8> {
use sha2::{Digest, Sha256};
let mut h = Sha256::new();
h.update(token.as_bytes());
h.finalize().to_vec()
}
pub struct SessionAuthBackend {
catalog: Arc<dyn Catalog>,
env: EnvAuthBackend,
users_exist: bool,
}
impl SessionAuthBackend {
pub fn new(catalog: Arc<dyn Catalog>, env: EnvAuthBackend, users_exist: bool) -> Self {
Self {
catalog,
env,
users_exist,
}
}
}
#[async_trait]
impl AuthBackend for SessionAuthBackend {
fn enabled(&self) -> bool {
self.env.enabled() || self.users_exist
}
async fn authenticate(&self, token: &str) -> Result<Principal, AuthError> {
match self.env.authenticate(token).await {
Ok(p) => return Ok(p),
Err(AuthError::UnknownToken) => {}
Err(other) => return Err(other),
}
let hash = hash_token(token);
let result = self
.catalog
.lookup_api_token(&hash)
.await
.map_err(|e| AuthError::Backend(e.to_string()))?;
match result {
Some(tp) => Ok(Principal {
tenant: tp.tenant,
role: Role::parse(&tp.role).unwrap_or(Role::Read),
subject: tp.subject,
}),
None => Err(AuthError::UnknownToken),
}
}
}