use std::sync::Arc;
use log::{info, log_enabled, trace};
use crate::api::admin::Token;
use crate::commons::httpclient;
use crate::commons::KrillResult;
use crate::commons::error::{ApiAuthError, Error};
use crate::config::Config;
use crate::daemon::http::auth::{AuthInfo, LoggedInUser, Role};
use crate::daemon::http::request::HyperRequest;
use crate::daemon::http::response::HttpResponse;
const LAGOSTA_LOGIN_ROUTE_PATH: &str = "/login";
pub struct AuthProvider {
required_token: Token,
user_id: Arc<str>,
role: Arc<Role>,
}
impl AuthProvider {
pub fn new(config: Arc<Config>) -> Self {
AuthProvider {
required_token: config.admin_token.clone(),
user_id: "admin-token".into(),
role: Role::admin().into(),
}
}
pub fn authenticate(
&self, request: &HyperRequest,
) -> Result<Option<(AuthInfo, Option<Token>)>, ApiAuthError> {
if log_enabled!(log::Level::Trace) {
trace!("Attempting to authenticate the request..");
}
let res = match httpclient::get_bearer_token(request) {
Some(token) if token == self.required_token => {
Ok(Some((
AuthInfo::user(self.user_id.clone(), self.role.clone()),
None
)))
}
Some(_) => Err(ApiAuthError::ApiInvalidCredentials(
"Invalid bearer token".to_string(),
)),
None => Ok(None),
};
if log_enabled!(log::Level::Trace) {
trace!("Authentication result: {res:?}");
}
res
}
pub fn get_login_url(&self) -> KrillResult<HttpResponse> {
Ok(HttpResponse::text_no_cache(LAGOSTA_LOGIN_ROUTE_PATH.into()))
}
pub fn login(&self, request: &HyperRequest) -> KrillResult<LoggedInUser> {
match self.authenticate(request)? {
Some(_actor) => Ok(LoggedInUser::new(
self.required_token.clone(),
self.user_id.as_ref().into(),
"admin".into(),
)),
None => Err(Error::ApiInvalidCredentials(
"Missing bearer token".to_string(),
)),
}
}
pub fn logout(
&self,
request: &HyperRequest,
) -> KrillResult<HttpResponse> {
if let Ok(Some((info, _))) = self.authenticate(request) {
info!("User logged out: {}", info.actor().name());
}
Ok(HttpResponse::text_no_cache(b"/".to_vec()))
}
}