1
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
use axum::{extract::State, http::StatusCode, response::IntoResponse, Json};
|
||||
use diesel::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
auth::{password, AuthenticatedUser},
|
||||
error::{AppError, AppResult},
|
||||
models::User,
|
||||
schema::users::dsl,
|
||||
state::AppState,
|
||||
};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct LoginRequest {
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct LoginResponse {
|
||||
pub access_token: String,
|
||||
pub token_type: String,
|
||||
pub expires_in: i64,
|
||||
}
|
||||
|
||||
pub async fn login(
|
||||
State(state): State<AppState>,
|
||||
Json(payload): Json<LoginRequest>,
|
||||
) -> AppResult<Json<LoginResponse>> {
|
||||
let mut conn = state.db()?;
|
||||
|
||||
let user: User = dsl::users
|
||||
.filter(dsl::username.eq(&payload.username))
|
||||
.first(&mut conn)?;
|
||||
|
||||
let valid = password::verify_password(&payload.password, &user.password_hash)
|
||||
.map_err(|_| AppError::unauthorized())?;
|
||||
|
||||
if !valid {
|
||||
return Err(AppError::unauthorized());
|
||||
}
|
||||
|
||||
let token = state
|
||||
.jwt
|
||||
.generate_token(user.id, &user.username, &user.role)
|
||||
.map_err(AppError::from)?;
|
||||
|
||||
Ok(Json(LoginResponse {
|
||||
access_token: token,
|
||||
token_type: "Bearer".to_string(),
|
||||
expires_in: state.config.jwt_expiry_minutes * 60,
|
||||
}))
|
||||
}
|
||||
|
||||
pub async fn logout(_user: AuthenticatedUser) -> impl IntoResponse {
|
||||
StatusCode::NO_CONTENT
|
||||
}
|
||||
|
||||
pub async fn me(user: AuthenticatedUser) -> Json<AuthenticatedUser> {
|
||||
Json(user)
|
||||
}
|
||||
Reference in New Issue
Block a user