mas_matrix/
readonly.rs

1// Copyright 2025 New Vector Ltd.
2//
3// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
4// Please see LICENSE files in the repository root for full details.
5
6use std::collections::HashSet;
7
8use crate::{HomeserverConnection, MatrixUser, ProvisionRequest};
9
10/// A wrapper around a [`HomeserverConnection`] that only allows read
11/// operations.
12pub struct ReadOnlyHomeserverConnection<C> {
13    inner: C,
14}
15
16impl<C> ReadOnlyHomeserverConnection<C> {
17    pub fn new(inner: C) -> Self
18    where
19        C: HomeserverConnection,
20    {
21        Self { inner }
22    }
23}
24
25#[async_trait::async_trait]
26impl<C: HomeserverConnection> HomeserverConnection for ReadOnlyHomeserverConnection<C> {
27    fn homeserver(&self) -> &str {
28        self.inner.homeserver()
29    }
30
31    async fn verify_token(&self, token: &str) -> Result<bool, anyhow::Error> {
32        self.inner.verify_token(token).await
33    }
34
35    async fn query_user(&self, localpart: &str) -> Result<MatrixUser, anyhow::Error> {
36        self.inner.query_user(localpart).await
37    }
38
39    async fn provision_user(&self, _request: &ProvisionRequest) -> Result<bool, anyhow::Error> {
40        anyhow::bail!("Provisioning is not supported in read-only mode");
41    }
42
43    async fn is_localpart_available(&self, localpart: &str) -> Result<bool, anyhow::Error> {
44        self.inner.is_localpart_available(localpart).await
45    }
46
47    async fn upsert_device(
48        &self,
49        _localpart: &str,
50        _device_id: &str,
51        _initial_display_name: Option<&str>,
52    ) -> Result<(), anyhow::Error> {
53        anyhow::bail!("Device creation is not supported in read-only mode");
54    }
55
56    async fn update_device_display_name(
57        &self,
58        _localpart: &str,
59        _device_id: &str,
60        _display_name: &str,
61    ) -> Result<(), anyhow::Error> {
62        anyhow::bail!("Device display name update is not supported in read-only mode");
63    }
64
65    async fn delete_device(&self, _localpart: &str, _device_id: &str) -> Result<(), anyhow::Error> {
66        anyhow::bail!("Device deletion is not supported in read-only mode");
67    }
68
69    async fn sync_devices(
70        &self,
71        _localpart: &str,
72        _devices: HashSet<String>,
73    ) -> Result<(), anyhow::Error> {
74        anyhow::bail!("Device synchronization is not supported in read-only mode");
75    }
76
77    async fn delete_user(&self, _localpart: &str, _erase: bool) -> Result<(), anyhow::Error> {
78        anyhow::bail!("User deletion is not supported in read-only mode");
79    }
80
81    async fn reactivate_user(&self, _localpart: &str) -> Result<(), anyhow::Error> {
82        anyhow::bail!("User reactivation is not supported in read-only mode");
83    }
84
85    async fn set_displayname(
86        &self,
87        _localpart: &str,
88        _displayname: &str,
89    ) -> Result<(), anyhow::Error> {
90        anyhow::bail!("User displayname update is not supported in read-only mode");
91    }
92
93    async fn unset_displayname(&self, _localpart: &str) -> Result<(), anyhow::Error> {
94        anyhow::bail!("User displayname update is not supported in read-only mode");
95    }
96
97    async fn allow_cross_signing_reset(&self, _localpart: &str) -> Result<(), anyhow::Error> {
98        anyhow::bail!("Allowing cross-signing reset is not supported in read-only mode");
99    }
100}