36 lines
1.1 KiB
Rust
36 lines
1.1 KiB
Rust
use axum::{extract::State, http::StatusCode, Json};
|
|
use serde_json::{json, Value};
|
|
|
|
use crate::{auth::encode_jwt, models::user::LoginRequest, state::AppState};
|
|
|
|
pub async fn login(
|
|
State(state): State<AppState>,
|
|
Json(body): Json<LoginRequest>,
|
|
) -> Result<Json<Value>, StatusCode> {
|
|
let user = sqlx::query_as::<_, crate::models::user::User>(
|
|
"SELECT id, username, password_hash, permissions_mask, created_at FROM users WHERE username = $1",
|
|
)
|
|
.bind(&body.username)
|
|
.fetch_optional(&state.pool)
|
|
.await
|
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?
|
|
.ok_or(StatusCode::UNAUTHORIZED)?;
|
|
|
|
let valid = bcrypt::verify(&body.password, &user.password_hash)
|
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
|
|
|
if !valid {
|
|
return Err(StatusCode::UNAUTHORIZED);
|
|
}
|
|
|
|
let mask: u128 = user.permissions_mask.parse().unwrap_or(0);
|
|
let token = encode_jwt(
|
|
&user.username,
|
|
mask,
|
|
&state.config.jwt_secret,
|
|
state.config.jwt_expiry_secs,
|
|
)
|
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
|
|
|
Ok(Json(json!({ "token": token })))
|
|
}
|