Refractored code and implemented logout

This commit is contained in:
2025-02-20 18:40:10 +01:00
parent 6395df6cec
commit 9eb92ffff1
4 changed files with 104 additions and 37 deletions

View File

@@ -11,21 +11,12 @@ use rand_chacha::ChaCha20Rng;
use sqlx::PgPool;
use tokio::task;
use crate::{
database::model::Session,
model::User,
};
use crate::{database::model::Session, model::User};
mod error;
pub async fn get_user_from_header(pool: &PgPool, headers: &HeaderMap) -> Result<User, AuthError> {
let bearer_value = headers.get(header::AUTHORIZATION);
let bearer_value = bearer_value
.ok_or(AuthError::InvalidToken)?
.to_str()
.map_err(|_| AuthError::InvalidToken)?;
let token = get_token_from_bearer(bearer_value)?;
let token = get_token_from_headers(&headers)?;
let session = match Session::from_token(pool, &token).await {
Ok(s) => s,
@@ -44,7 +35,13 @@ pub async fn get_user_from_header(pool: &PgPool, headers: &HeaderMap) -> Result<
Ok(db_user.into())
}
pub fn get_token_from_bearer(bearer: &str) -> Result<String, AuthError> {
pub fn get_token_from_headers(headers: &HeaderMap) -> Result<String, AuthError> {
let bearer = headers.get(header::AUTHORIZATION);
let bearer = bearer
.ok_or(AuthError::InvalidToken)?
.to_str()
.map_err(|_| AuthError::InvalidToken)?;
match bearer.strip_prefix("Bearer ") {
Some(token) => Ok(token.to_string()),
None => Err(AuthError::InvalidToken),

View File

@@ -43,4 +43,54 @@ impl Session {
Ok(session)
}
pub async fn remove_many(
session_ids: &[uuid::Uuid],
transaction: &mut sqlx::Transaction<'_, Postgres>,
) -> Result<(), sqlx::Error> {
let deleted_count = sqlx::query_scalar!(
"
WITH deleted AS (
DELETE FROM sessions
WHERE session_id = ANY($1)
RETURNING 1
)
SELECT COUNT(*) FROM deleted
",
session_ids
)
.fetch_one(&mut **transaction)
.await?;
if !deleted_count.is_some_and(|c| c >= 1) {
return Err(sqlx::Error::RowNotFound);
}
Ok(())
}
pub async fn remove_many_from_token(
transaction: &mut sqlx::Transaction<'_, Postgres>,
session_tokens: &[String],
) -> Result<(), sqlx::Error> {
let deleted_count = sqlx::query_scalar!(
"
WITH deleted AS (
DELETE FROM sessions
WHERE token = ANY($1)
RETURNING 1
)
SELECT COUNT(*) FROM deleted
",
session_tokens
)
.fetch_one(&mut **transaction)
.await?;
if !deleted_count.is_some_and(|c| c >= 1) {
return Err(sqlx::Error::RowNotFound);
}
Ok(())
}
}

View File

@@ -1,8 +1,12 @@
use axum::http::HeaderMap;
use axum::{extract::State, routing::post, Json, Router};
use axum::{
extract::State,
routing::{get, post},
Json, Router,
};
use serde::Deserialize;
use crate::auth::verify_password_hash;
use crate::auth::{get_token_from_headers, verify_password_hash};
use crate::auth::{get_user_from_header, AuthError};
use crate::database::model::user::UpdateUser;
use crate::database::model::Member as DbMember;
@@ -16,6 +20,7 @@ pub fn routes() -> Router<AppState> {
Router::new()
.route("/auth/login", post(login))
.route("/auth/register", post(register))
.route("/auth/logout", get(logout))
.route("/auth/change_password", post(change_password))
.route("/auth/change_email", post(change_email))
}
@@ -88,6 +93,18 @@ pub async fn register(
Ok(db_session.token)
}
pub async fn logout(State(state): State<AppState>, headers: HeaderMap) -> Result<(), crate::Error> {
let registration_token = get_token_from_headers(&headers)?;
let mut transaction = state.pool.begin().await?;
DbSession::remove_many_from_token(&mut transaction, &[registration_token]).await?;
transaction.commit().await?;
Ok(())
}
#[derive(Debug, Deserialize)]
pub struct ChangePasswordRequest {
pub old_password: String,