mas_handlers/graphql/mutations/
browser_session.rs

1// Copyright 2024 New Vector Ltd.
2// Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
3//
4// SPDX-License-Identifier: AGPL-3.0-only
5// Please see LICENSE in the repository root for full details.
6
7use 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/// The input of the `endBrowserSession` mutation.
21#[derive(InputObject)]
22pub struct EndBrowserSessionInput {
23    /// The ID of the session to end.
24    browser_session_id: ID,
25}
26
27/// The payload of the `endBrowserSession` mutation.
28pub enum EndBrowserSessionPayload {
29    NotFound,
30    Ended(Box<mas_data_model::BrowserSession>),
31}
32
33/// The status of the `endBrowserSession` mutation.
34#[derive(Enum, Copy, Clone, PartialEq, Eq, Debug)]
35enum EndBrowserSessionStatus {
36    /// The session was ended.
37    Ended,
38
39    /// The session was not found.
40    NotFound,
41}
42
43#[Object]
44impl EndBrowserSessionPayload {
45    /// The status of the mutation.
46    async fn status(&self) -> EndBrowserSessionStatus {
47        match self {
48            Self::Ended(_) => EndBrowserSessionStatus::Ended,
49            Self::NotFound => EndBrowserSessionStatus::NotFound,
50        }
51    }
52
53    /// Returns the ended session.
54    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}