mas_handlers/views/
logout.rs1use 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 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}