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