Files
uplifting-api/src/v1/auth/login.rs

49 lines
1.2 KiB
Rust

use crate::*;
use argon2::{
password_hash::{PasswordHash, PasswordVerifier},
Argon2,
};
use jwt::SignWithKey;
use sqlx::query;
use util::auth::JWTClaims;
#[derive(Serialize, Deserialize, ToSchema)]
pub struct LoginBody {
username: String,
password: String,
}
/// Login
#[utoipa::path(post, path = "/login", responses((status = OK, body = String)), tag = super::AUTH_TAG)]
pub async fn login(
State(state): State<AppState>,
Json(body): Json<LoginBody>,
) -> Result<String, AppError> {
let user = query!(
"SELECT id, real_name, username, email, password_hash, is_admin, created_at
FROM users
WHERE username = $1",
body.username,
)
.fetch_one(&*state.db)
.await?;
let argon2 = Argon2::default();
let hash = PasswordHash::new(&body.password).expect("Password hashing failed");
if !argon2
.verify_password(body.password.as_bytes(), &hash)
.is_ok()
{
return Err(AppError::Error(Errors::Unauthorized));
}
let claims = JWTClaims::new(user.id, user.username, user.real_name, user.email);
let token_str = claims
.sign_with_key(&state.jwt_key)
.context("Failed to sign JWT")?;
Ok(token_str)
}