mas_handlers/graphql/mutations/
browser_session.rs
1use async_graphql::{Context, Enum, ID, InputObject, Object};
8use mas_storage::RepositoryAccess;
9
10use crate::graphql::{
11 model::{BrowserSession, NodeType},
12 state::ContextExt,
13};
14
15#[derive(Default)]
16pub struct BrowserSessionMutations {
17 _private: (),
18}
19
20#[derive(InputObject)]
22pub struct EndBrowserSessionInput {
23 browser_session_id: ID,
25}
26
27pub enum EndBrowserSessionPayload {
29 NotFound,
30 Ended(Box<mas_data_model::BrowserSession>),
31}
32
33#[derive(Enum, Copy, Clone, PartialEq, Eq, Debug)]
35enum EndBrowserSessionStatus {
36 Ended,
38
39 NotFound,
41}
42
43#[Object]
44impl EndBrowserSessionPayload {
45 async fn status(&self) -> EndBrowserSessionStatus {
47 match self {
48 Self::Ended(_) => EndBrowserSessionStatus::Ended,
49 Self::NotFound => EndBrowserSessionStatus::NotFound,
50 }
51 }
52
53 async fn browser_session(&self) -> Option<BrowserSession> {
55 match self {
56 Self::Ended(session) => Some(BrowserSession(*session.clone())),
57 Self::NotFound => None,
58 }
59 }
60}
61
62#[Object]
63impl BrowserSessionMutations {
64 async fn end_browser_session(
65 &self,
66 ctx: &Context<'_>,
67 input: EndBrowserSessionInput,
68 ) -> Result<EndBrowserSessionPayload, async_graphql::Error> {
69 let state = ctx.state();
70 let browser_session_id =
71 NodeType::BrowserSession.extract_ulid(&input.browser_session_id)?;
72 let requester = ctx.requester();
73
74 let mut repo = state.repository().await?;
75 let clock = state.clock();
76
77 let session = repo.browser_session().lookup(browser_session_id).await?;
78
79 let Some(session) = session else {
80 return Ok(EndBrowserSessionPayload::NotFound);
81 };
82
83 if !requester.is_owner_or_admin(&session) {
84 return Ok(EndBrowserSessionPayload::NotFound);
85 }
86
87 let session = repo.browser_session().finish(&clock, session).await?;
88
89 repo.save().await?;
90
91 Ok(EndBrowserSessionPayload::Ended(Box::new(session)))
92 }
93}