mas_handlers/views/
logout.rs1use axum::{
8 extract::{Form, State},
9 response::IntoResponse,
10};
11use mas_axum_utils::{
12 FancyError, SessionInfoExt,
13 cookies::CookieJar,
14 csrf::{CsrfExt, ProtectedForm},
15};
16use mas_router::{PostAuthAction, UrlBuilder};
17use mas_storage::{BoxClock, BoxRepository, user::BrowserSessionRepository};
18
19use crate::BoundActivityTracker;
20
21#[tracing::instrument(name = "handlers.views.logout.post", skip_all, err)]
22pub(crate) async fn post(
23 clock: BoxClock,
24 mut repo: BoxRepository,
25 cookie_jar: CookieJar,
26 State(url_builder): State<UrlBuilder>,
27 activity_tracker: BoundActivityTracker,
28 Form(form): Form<ProtectedForm<Option<PostAuthAction>>>,
29) -> Result<impl IntoResponse, FancyError> {
30 let form = cookie_jar.verify_form(&clock, form)?;
31
32 let (session_info, cookie_jar) = cookie_jar.session_info();
33
34 if let Some(session_id) = session_info.current_session_id() {
35 let maybe_session = repo.browser_session().lookup(session_id).await?;
36 if let Some(session) = maybe_session {
37 if session.finished_at.is_none() {
38 activity_tracker
39 .record_browser_session(&clock, &session)
40 .await;
41
42 repo.browser_session().finish(&clock, session).await?;
43 }
44 }
45 }
46
47 repo.save().await?;
48
49 let cookie_jar = cookie_jar.update_session_info(&session_info.mark_session_ended());
52
53 let destination = if let Some(action) = form {
54 action.go_next(&url_builder)
55 } else {
56 url_builder.redirect(&mas_router::Login::default())
57 };
58
59 Ok((cookie_jar, destination))
60}