mas_handlers/views/
logout.rs

1// Copyright 2024, 2025 New Vector Ltd.
2// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
3//
4// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5// Please see LICENSE files in the repository root for full details.
6
7use axum::{
8    extract::{Form, State},
9    response::IntoResponse,
10};
11use mas_axum_utils::{
12    InternalError, SessionInfoExt,
13    cookies::CookieJar,
14    csrf::{CsrfExt, ProtectedForm},
15};
16use mas_data_model::BoxClock;
17use mas_router::{PostAuthAction, UrlBuilder};
18use mas_storage::{BoxRepository, user::BrowserSessionRepository};
19
20use crate::BoundActivityTracker;
21
22#[tracing::instrument(name = "handlers.views.logout.post", skip_all)]
23pub(crate) async fn post(
24    clock: BoxClock,
25    mut repo: BoxRepository,
26    cookie_jar: CookieJar,
27    State(url_builder): State<UrlBuilder>,
28    activity_tracker: BoundActivityTracker,
29    Form(form): Form<ProtectedForm<Option<PostAuthAction>>>,
30) -> Result<impl IntoResponse, InternalError> {
31    let form = cookie_jar.verify_form(&clock, form)?;
32
33    let (session_info, cookie_jar) = cookie_jar.session_info();
34
35    if let Some(session_id) = session_info.current_session_id() {
36        let maybe_session = repo.browser_session().lookup(session_id).await?;
37        if let Some(session) = maybe_session
38            && session.finished_at.is_none()
39        {
40            activity_tracker
41                .record_browser_session(&clock, &session)
42                .await;
43
44            repo.browser_session().finish(&clock, session).await?;
45        }
46    }
47
48    repo.save().await?;
49
50    // We always want to clear out the session cookie, even if the session was
51    // invalid
52    let cookie_jar = cookie_jar.update_session_info(&session_info.mark_session_ended());
53
54    let destination = if let Some(action) = form {
55        action.go_next(&url_builder)
56    } else {
57        url_builder.redirect(&mas_router::Login::default())
58    };
59
60    Ok((cookie_jar, destination))
61}