use actix_web::{post, web, HttpResponse}; use serde::{Deserialize, Serialize}; use crate::core::*; use crate::model::Account; use crate::state::AppState; use crate::util::password::ClearPassword; use crate::util::{password, token}; #[derive(Deserialize)] struct AuthRequest { email: String, password: ClearPassword, } #[derive(Serialize)] struct AuthResponse { token: String, account: Account, } #[post("")] async fn auth(body: web::Json, state: AppState) -> Result { let body = body.into_inner(); // make sure unknown email address returns the same error as invalid password let user = state .repo .users .by_email(body.email) .await .map_err(|e| match e { Error::NotFound => Error::BadCredentials, e => e, })?; password::verify(&body.password, &user.password)?; let account = state.repo.accounts.by_id(user.account_id).await?; let token = token::issue(&state, &account)?; info!(target: "auth", "Successful login for user {}", &account.name); Ok(HttpResponse::Ok().json(AuthResponse { account, token })) } pub fn configure(cfg: &mut web::ServiceConfig) { cfg.service(auth); }