tuwunel_service/emergency/
mod.rs1use std::sync::Arc;
2
3use async_trait::async_trait;
4use ruma::{
5 events::{
6 GlobalAccountDataEvent, GlobalAccountDataEventType, push_rules::PushRulesEventContent,
7 },
8 push::Ruleset,
9};
10use tuwunel_core::{Result, debug_warn, error, warn};
11
12pub struct Service {
13 services: Arc<crate::services::OnceServices>,
14}
15
16#[async_trait]
17impl crate::Service for Service {
18 fn build(args: &crate::Args<'_>) -> Result<Arc<Self>> {
19 Ok(Arc::new(Self { services: args.services.clone() }))
20 }
21
22 async fn worker(self: Arc<Self>) -> Result {
23 if self
24 .services
25 .config
26 .emergency_password
27 .as_ref()
28 .is_none_or(String::is_empty)
29 {
30 return Ok(());
31 }
32
33 if self.services.globals.is_read_only() {
34 debug_warn!("emergency password feature ignored in read_only mode.");
35 return Ok(());
36 }
37
38 if self.services.config.ldap.enable {
39 warn!("emergency password feature not available with LDAP enabled.");
40 return Ok(());
41 }
42
43 self.set_emergency_access()
44 .await
45 .inspect_err(|e| {
46 error!("Failed to set the emergency password for the server user: {e}");
47 })
48 }
49
50 fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
51}
52
53impl Service {
54 async fn set_emergency_access(&self) -> Result {
57 let server_user = &self.services.globals.server_user;
58
59 self.services
60 .users
61 .set_password(server_user, self.services.config.emergency_password.as_deref())
62 .await?;
63
64 let (ruleset, pwd_set) = match self.services.config.emergency_password {
65 | Some(_) => (Ruleset::server_default(server_user), true),
66 | None => (Ruleset::new(), false),
67 };
68
69 self.services
70 .account_data
71 .update(
72 None,
73 server_user,
74 GlobalAccountDataEventType::PushRules
75 .to_string()
76 .into(),
77 &serde_json::to_value(&GlobalAccountDataEvent {
78 content: PushRulesEventContent { global: ruleset },
79 })
80 .expect("to json value always works"),
81 )
82 .await?;
83
84 if pwd_set {
85 warn!(
86 "The server account emergency password is set! Please unset it as soon as you \
87 finish admin account recovery! You will be logged out of the server service \
88 account when you finish."
89 );
90 Ok(())
91 } else {
92 self.services
94 .users
95 .deactivate_account(server_user)
96 .await
97 }
98 }
99}