1mod mock;
8mod readonly;
9
10use std::{collections::HashSet, sync::Arc};
11
12use ruma_common::UserId;
13
14pub use self::{
15 mock::HomeserverConnection as MockHomeserverConnection, readonly::ReadOnlyHomeserverConnection,
16};
17
18#[derive(Debug)]
19pub struct MatrixUser {
20 pub displayname: Option<String>,
21 pub avatar_url: Option<String>,
22 pub deactivated: bool,
23}
24
25#[derive(Debug, Default)]
26enum FieldAction<T> {
27 #[default]
28 DoNothing,
29 Set(T),
30 Unset,
31}
32
33pub struct ProvisionRequest {
34 mxid: String,
35 sub: String,
36 displayname: FieldAction<String>,
37 avatar_url: FieldAction<String>,
38 emails: FieldAction<Vec<String>>,
39}
40
41impl ProvisionRequest {
42 #[must_use]
49 pub fn new(mxid: impl Into<String>, sub: impl Into<String>) -> Self {
50 Self {
51 mxid: mxid.into(),
52 sub: sub.into(),
53 displayname: FieldAction::DoNothing,
54 avatar_url: FieldAction::DoNothing,
55 emails: FieldAction::DoNothing,
56 }
57 }
58
59 #[must_use]
61 pub fn sub(&self) -> &str {
62 &self.sub
63 }
64
65 #[must_use]
67 pub fn mxid(&self) -> &str {
68 &self.mxid
69 }
70
71 #[must_use]
77 pub fn set_displayname(mut self, displayname: String) -> Self {
78 self.displayname = FieldAction::Set(displayname);
79 self
80 }
81
82 #[must_use]
84 pub fn unset_displayname(mut self) -> Self {
85 self.displayname = FieldAction::Unset;
86 self
87 }
88
89 pub fn on_displayname<F>(&self, callback: F) -> &Self
95 where
96 F: FnOnce(Option<&str>),
97 {
98 match &self.displayname {
99 FieldAction::Unset => callback(None),
100 FieldAction::Set(displayname) => callback(Some(displayname)),
101 FieldAction::DoNothing => {}
102 }
103
104 self
105 }
106
107 #[must_use]
113 pub fn set_avatar_url(mut self, avatar_url: String) -> Self {
114 self.avatar_url = FieldAction::Set(avatar_url);
115 self
116 }
117
118 #[must_use]
120 pub fn unset_avatar_url(mut self) -> Self {
121 self.avatar_url = FieldAction::Unset;
122 self
123 }
124
125 pub fn on_avatar_url<F>(&self, callback: F) -> &Self
131 where
132 F: FnOnce(Option<&str>),
133 {
134 match &self.avatar_url {
135 FieldAction::Unset => callback(None),
136 FieldAction::Set(avatar_url) => callback(Some(avatar_url)),
137 FieldAction::DoNothing => {}
138 }
139
140 self
141 }
142
143 #[must_use]
149 pub fn set_emails(mut self, emails: Vec<String>) -> Self {
150 self.emails = FieldAction::Set(emails);
151 self
152 }
153
154 #[must_use]
156 pub fn unset_emails(mut self) -> Self {
157 self.emails = FieldAction::Unset;
158 self
159 }
160
161 pub fn on_emails<F>(&self, callback: F) -> &Self
167 where
168 F: FnOnce(Option<&[String]>),
169 {
170 match &self.emails {
171 FieldAction::Unset => callback(None),
172 FieldAction::Set(emails) => callback(Some(emails)),
173 FieldAction::DoNothing => {}
174 }
175
176 self
177 }
178}
179
180#[async_trait::async_trait]
181pub trait HomeserverConnection: Send + Sync {
182 fn homeserver(&self) -> &str;
184
185 fn mxid(&self, localpart: &str) -> String {
191 format!("@{}:{}", localpart, self.homeserver())
192 }
193
194 fn localpart<'a>(&self, mxid: &'a str) -> Option<&'a str> {
203 let mxid = <&UserId>::try_from(mxid).ok()?;
204 if mxid.server_name() != self.homeserver() {
205 return None;
206 }
207 Some(mxid.localpart())
208 }
209
210 async fn query_user(&self, mxid: &str) -> Result<MatrixUser, anyhow::Error>;
221
222 async fn provision_user(&self, request: &ProvisionRequest) -> Result<bool, anyhow::Error>;
234
235 async fn is_localpart_available(&self, localpart: &str) -> Result<bool, anyhow::Error>;
245
246 async fn create_device(
258 &self,
259 mxid: &str,
260 device_id: &str,
261 initial_display_name: Option<&str>,
262 ) -> Result<(), anyhow::Error>;
263
264 async fn update_device_display_name(
277 &self,
278 mxid: &str,
279 device_id: &str,
280 display_name: &str,
281 ) -> Result<(), anyhow::Error>;
282
283 async fn delete_device(&self, mxid: &str, device_id: &str) -> Result<(), anyhow::Error>;
295
296 async fn sync_devices(&self, mxid: &str, devices: HashSet<String>)
308 -> Result<(), anyhow::Error>;
309
310 async fn delete_user(&self, mxid: &str, erase: bool) -> Result<(), anyhow::Error>;
322
323 async fn reactivate_user(&self, mxid: &str) -> Result<(), anyhow::Error>;
334
335 async fn set_displayname(&self, mxid: &str, displayname: &str) -> Result<(), anyhow::Error>;
347
348 async fn unset_displayname(&self, mxid: &str) -> Result<(), anyhow::Error>;
359
360 async fn allow_cross_signing_reset(&self, mxid: &str) -> Result<(), anyhow::Error>;
371}
372
373#[async_trait::async_trait]
374impl<T: HomeserverConnection + Send + Sync + ?Sized> HomeserverConnection for &T {
375 fn homeserver(&self) -> &str {
376 (**self).homeserver()
377 }
378
379 async fn query_user(&self, mxid: &str) -> Result<MatrixUser, anyhow::Error> {
380 (**self).query_user(mxid).await
381 }
382
383 async fn provision_user(&self, request: &ProvisionRequest) -> Result<bool, anyhow::Error> {
384 (**self).provision_user(request).await
385 }
386
387 async fn is_localpart_available(&self, localpart: &str) -> Result<bool, anyhow::Error> {
388 (**self).is_localpart_available(localpart).await
389 }
390
391 async fn create_device(
392 &self,
393 mxid: &str,
394 device_id: &str,
395 initial_display_name: Option<&str>,
396 ) -> Result<(), anyhow::Error> {
397 (**self)
398 .create_device(mxid, device_id, initial_display_name)
399 .await
400 }
401
402 async fn update_device_display_name(
403 &self,
404 mxid: &str,
405 device_id: &str,
406 display_name: &str,
407 ) -> Result<(), anyhow::Error> {
408 (**self)
409 .update_device_display_name(mxid, device_id, display_name)
410 .await
411 }
412
413 async fn delete_device(&self, mxid: &str, device_id: &str) -> Result<(), anyhow::Error> {
414 (**self).delete_device(mxid, device_id).await
415 }
416
417 async fn sync_devices(
418 &self,
419 mxid: &str,
420 devices: HashSet<String>,
421 ) -> Result<(), anyhow::Error> {
422 (**self).sync_devices(mxid, devices).await
423 }
424
425 async fn delete_user(&self, mxid: &str, erase: bool) -> Result<(), anyhow::Error> {
426 (**self).delete_user(mxid, erase).await
427 }
428
429 async fn reactivate_user(&self, mxid: &str) -> Result<(), anyhow::Error> {
430 (**self).reactivate_user(mxid).await
431 }
432
433 async fn set_displayname(&self, mxid: &str, displayname: &str) -> Result<(), anyhow::Error> {
434 (**self).set_displayname(mxid, displayname).await
435 }
436
437 async fn unset_displayname(&self, mxid: &str) -> Result<(), anyhow::Error> {
438 (**self).unset_displayname(mxid).await
439 }
440
441 async fn allow_cross_signing_reset(&self, mxid: &str) -> Result<(), anyhow::Error> {
442 (**self).allow_cross_signing_reset(mxid).await
443 }
444}
445
446#[async_trait::async_trait]
448impl<T: HomeserverConnection + ?Sized> HomeserverConnection for Arc<T> {
449 fn homeserver(&self) -> &str {
450 (**self).homeserver()
451 }
452
453 async fn query_user(&self, mxid: &str) -> Result<MatrixUser, anyhow::Error> {
454 (**self).query_user(mxid).await
455 }
456
457 async fn provision_user(&self, request: &ProvisionRequest) -> Result<bool, anyhow::Error> {
458 (**self).provision_user(request).await
459 }
460
461 async fn is_localpart_available(&self, localpart: &str) -> Result<bool, anyhow::Error> {
462 (**self).is_localpart_available(localpart).await
463 }
464
465 async fn create_device(
466 &self,
467 mxid: &str,
468 device_id: &str,
469 initial_display_name: Option<&str>,
470 ) -> Result<(), anyhow::Error> {
471 (**self)
472 .create_device(mxid, device_id, initial_display_name)
473 .await
474 }
475
476 async fn update_device_display_name(
477 &self,
478 mxid: &str,
479 device_id: &str,
480 display_name: &str,
481 ) -> Result<(), anyhow::Error> {
482 (**self)
483 .update_device_display_name(mxid, device_id, display_name)
484 .await
485 }
486
487 async fn delete_device(&self, mxid: &str, device_id: &str) -> Result<(), anyhow::Error> {
488 (**self).delete_device(mxid, device_id).await
489 }
490
491 async fn sync_devices(
492 &self,
493 mxid: &str,
494 devices: HashSet<String>,
495 ) -> Result<(), anyhow::Error> {
496 (**self).sync_devices(mxid, devices).await
497 }
498
499 async fn delete_user(&self, mxid: &str, erase: bool) -> Result<(), anyhow::Error> {
500 (**self).delete_user(mxid, erase).await
501 }
502
503 async fn reactivate_user(&self, mxid: &str) -> Result<(), anyhow::Error> {
504 (**self).reactivate_user(mxid).await
505 }
506
507 async fn set_displayname(&self, mxid: &str, displayname: &str) -> Result<(), anyhow::Error> {
508 (**self).set_displayname(mxid, displayname).await
509 }
510
511 async fn unset_displayname(&self, mxid: &str) -> Result<(), anyhow::Error> {
512 (**self).unset_displayname(mxid).await
513 }
514
515 async fn allow_cross_signing_reset(&self, mxid: &str) -> Result<(), anyhow::Error> {
516 (**self).allow_cross_signing_reset(mxid).await
517 }
518}