1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-29 22:01:14 +03:00

Axum migration: logout route

This commit is contained in:
Quentin Gliech
2022-03-25 15:50:28 +01:00
parent 5e95c705d4
commit 6e7d0a6cfd
5 changed files with 59 additions and 37 deletions

View File

@ -38,6 +38,13 @@ impl SessionInfo {
}
}
/// Mark the session as ended
#[must_use]
pub fn mark_session_ended(mut self) -> Self {
self.current = None;
self
}
/// Load the [`BrowserSession`] from database
pub async fn load_session(
&self,

View File

@ -21,7 +21,12 @@
use std::sync::Arc;
use axum::{body::HttpBody, extract::Extension, routing::get, Router};
use axum::{
body::HttpBody,
extract::Extension,
routing::{get, post},
Router,
};
use mas_axum_utils::UrlBuilder;
use mas_config::{Encrypter, RootConfig};
use mas_email::Mailer;
@ -81,6 +86,7 @@ where
"/login",
get(self::views::login::get).post(self::views::login::post),
)
.route("/logout", post(self::views::logout::post))
.fallback(mas_static_files::Assets)
.layer(Extension(pool.clone()))
.layer(Extension(templates.clone()))

View File

@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#![allow(clippy::trait_duplication_in_bounds)]
use axum::{
extract::{Extension, Form, Query},
response::{Html, IntoResponse, Redirect, Response},

View File

@ -1,4 +1,4 @@
// Copyright 2021 The Matrix.org Foundation C.I.C.
// Copyright 2021, 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -12,34 +12,48 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use mas_config::Encrypter;
use mas_data_model::BrowserSession;
use mas_storage::{user::end_session, PostgresqlBackend};
use mas_warp_utils::{
errors::WrapError,
filters::{self, csrf::protected_form, database::transaction, session::session},
use axum::{
extract::{Extension, Form},
response::{IntoResponse, Redirect},
};
use sqlx::{PgPool, Postgres, Transaction};
use warp::{filters::BoxedFilter, hyper::Uri, Filter, Rejection, Reply};
use hyper::Uri;
use mas_axum_utils::{
csrf::{CsrfExt, ProtectedForm},
fancy_error, FancyError, PrivateCookieJar, SessionInfoExt,
};
use mas_config::Encrypter;
use mas_storage::user::end_session;
use mas_templates::Templates;
use sqlx::PgPool;
pub(super) fn filter(pool: &PgPool, encrypter: &Encrypter) -> BoxedFilter<(Box<dyn Reply>,)> {
warp::path!("logout")
.and(filters::trace::name("POST /logout"))
.and(warp::post())
.and(session(pool, encrypter))
.and(transaction(pool))
.and(protected_form(encrypter))
.and_then(post)
.boxed()
}
async fn post(
session: BrowserSession<PostgresqlBackend>,
mut txn: Transaction<'_, Postgres>,
_form: (),
) -> Result<Box<dyn Reply>, Rejection> {
end_session(&mut txn, &session).await.wrap_error()?;
txn.commit().await.wrap_error()?;
Ok(Box::new(warp::redirect(Uri::from_static("/login"))))
pub(crate) async fn post(
Extension(templates): Extension<Templates>,
Extension(pool): Extension<PgPool>,
cookie_jar: PrivateCookieJar<Encrypter>,
Form(form): Form<ProtectedForm<()>>,
) -> Result<impl IntoResponse, FancyError> {
let mut txn = pool.begin().await.map_err(fancy_error(templates.clone()))?;
cookie_jar
.verify_form(form)
.map_err(fancy_error(templates.clone()))?;
let (session_info, mut cookie_jar) = cookie_jar.session_info();
let maybe_session = session_info
.load_session(&mut txn)
.await
.map_err(fancy_error(templates.clone()))?;
if let Some(session) = maybe_session {
end_session(&mut txn, &session)
.await
.map_err(fancy_error(templates.clone()))?;
cookie_jar = cookie_jar.update_session_info(&session_info.mark_session_ended());
}
txn.commit().await.map_err(fancy_error(templates))?;
let to = Uri::from_static("/login");
Ok((cookie_jar.headers(), Redirect::to(to)))
}

View File

@ -28,8 +28,8 @@ pub mod shared;
pub mod verify;
use self::{
account::filter as account, logout::filter as logout, reauth::filter as reauth,
register::filter as register, verify::filter as verify,
account::filter as account, reauth::filter as reauth, register::filter as register,
verify::filter as verify,
};
pub(crate) use self::{
login::LoginRequest, reauth::ReauthRequest, register::RegisterRequest, shared::PostAuthAction,
@ -45,15 +45,12 @@ pub(super) fn filter(
) -> BoxedFilter<(Box<dyn Reply>,)> {
let account = account(pool, templates, mailer, encrypter, http_config, csrf_config);
let register = register(pool, templates, encrypter, csrf_config);
let logout = logout(pool, encrypter);
let reauth = reauth(pool, templates, encrypter, csrf_config);
let verify = verify(pool, templates, encrypter, csrf_config);
account
.or(register)
.unify()
.or(logout)
.unify()
.or(reauth)
.unify()
.or(verify)