use axum::extract::Extension;
use axum::http::HeaderMap;
use axum::Json;
use chrono::Utc;
use jsonwebtoken::{encode, Header};
use sqlx::{Pool, Postgres};
use dialtone_common::rest::users::user_login::{AuthBody, UserCredential};
use dialtone_sqlx::control::user::authn::authn_user;
use crate::forwarded_for::get_forwarded;
use crate::response::response_error::ResponseError;
use crate::start_server::{Claims, KEYS};
pub async fn post_authenticate_handler(
Json(login): Json<UserCredential>,
headers: HeaderMap,
Extension(pool): Extension<Pool<Postgres>>,
) -> Result<Json<AuthBody>, ResponseError> {
if login.user_acct.is_empty() || login.password.is_empty() {
return Err(ResponseError::MissingCredentials(None));
}
let forwarded_for = get_forwarded(&headers);
tracing::debug!("forwarded_for = {:?}", forwarded_for);
let auth_result = authn_user(
&pool,
&login.user_acct,
&login.password,
&forwarded_for,
Utc::now(),
)
.await?;
if !auth_result {
return Err(ResponseError::WrongCredentials(Some(format!(
"user {} failed to authenticate",
login.user_acct
))));
}
let claims = Claims {
sub: login.user_acct.to_owned(),
exp: 2019331688,
};
let token = encode(&Header::default(), &claims, &KEYS.encoding).map_err(|err| {
ResponseError::TokenCreation(Some(format!(
"encode in post_authenticate_handler: {:?}",
err
)))
})?;
tracing::info!("user {} authenticated", login.user_acct);
Ok(Json(AuthBody::new(token)))
}