tuwunel_service/users/
register.rs1use futures::FutureExt;
2use ruma::{UserId, events::GlobalAccountDataEventType, push};
3use tuwunel_core::{Err, Result, error, implement, info, is_equal_to, warn};
4
5use crate::profile::Propagation;
6
7#[derive(Debug, Default)]
8pub struct Register<'a> {
9 pub user_id: Option<&'a UserId>,
10 pub username: Option<&'a str>,
11 pub password: Option<&'a str>,
12 pub origin: Option<&'a str>,
13 pub is_appservice: bool,
14 pub is_guest: bool,
15 pub grant_first_user_admin: bool,
16 pub displayname: Option<&'a str>,
17 pub omit_displayname_suffix: bool,
18}
19
20#[implement(super::Service)]
24#[tracing::instrument(level = "info", skip(self, password))]
25pub async fn full_register(
26 &self,
27 Register {
28 username,
29 user_id,
30 password,
31 origin,
32 is_appservice,
33 is_guest,
34 grant_first_user_admin,
35 displayname,
36 omit_displayname_suffix,
37 }: Register<'_>,
38) -> Result {
39 let ref user_id = user_id
40 .map(ToOwned::to_owned)
41 .map(Ok)
42 .or_else(|| {
43 username.map(|username| {
44 UserId::parse_with_server_name(username, self.services.globals.server_name())
45 })
46 })
47 .transpose()?
48 .expect("Caller failed to supply either user_id or username parameter");
49
50 if !self.services.globals.user_is_local(user_id) {
51 return Err!("Cannot register remote user");
52 }
53
54 if self.services.users.exists(user_id).await {
55 return Err!(Request(UserInUse("User ID is not available.")));
56 }
57
58 self.services
60 .users
61 .create(user_id, password, origin)
62 .await?;
63
64 let displayname_suffix = self
65 .services
66 .config
67 .new_user_displayname_suffix
68 .as_str();
69
70 let mut displayname = displayname.unwrap_or_else(|| user_id.localpart());
71
72 let displayname_with_suffix;
73 if !displayname_suffix.is_empty() && !omit_displayname_suffix {
74 displayname_with_suffix = format!("{displayname} {displayname_suffix}");
75 displayname = &displayname_with_suffix;
76 }
77
78 self.services
79 .profile
80 .set_displayname(user_id, Some(displayname), Some(Propagation::None))
81 .await?;
82
83 self.services
85 .account_data
86 .update(
87 None,
88 user_id,
89 GlobalAccountDataEventType::PushRules
90 .to_string()
91 .into(),
92 &serde_json::to_value(ruma::events::push_rules::PushRulesEvent {
93 content: ruma::events::push_rules::PushRulesEventContent {
94 global: push::Ruleset::server_default(user_id),
95 },
96 })?,
97 )
98 .await?;
99
100 if !is_guest
104 && !is_appservice
105 && grant_first_user_admin
106 && self.services.config.grant_admin_to_first_user
107 && let Ok(admin_room) = self.services.admin.get_admin_room().await
108 && self
109 .services
110 .state_cache
111 .room_joined_count(&admin_room)
112 .await
113 .is_ok_and(is_equal_to!(1))
114 {
115 self.services
116 .admin
117 .make_user_admin(user_id)
118 .boxed()
119 .await?;
120 warn!("Granting {user_id} admin privileges as the first user");
121 }
122
123 if !is_appservice && (self.services.config.allow_guests_auto_join_rooms || !is_guest) {
124 for room in &self.services.server.config.auto_join_rooms {
125 let Ok(room_id) = self.services.alias.maybe_resolve(room).await else {
126 error!(
127 "Failed to resolve room alias to room ID when attempting to auto join \
128 {room}, skipping"
129 );
130 continue;
131 };
132
133 if !self
134 .services
135 .state_cache
136 .server_in_room(self.services.globals.server_name(), &room_id)
137 .await
138 {
139 warn!(
140 "Skipping room {room} to automatically join as we have never joined before."
141 );
142 continue;
143 }
144
145 match self
146 .services
147 .membership
148 .join(
149 user_id,
150 &room_id,
151 Some(room),
152 Some("Automatically joining this room upon registration".to_owned()),
153 &[],
154 false,
155 None,
156 )
157 .boxed()
158 .await
159 {
160 | Err(e) => {
161 error!("Failed to automatically join room {room} for user {user_id}: {e}");
163 },
164 | _ => {
165 info!("Automatically joined room {room} for user {user_id}");
166 },
167 }
168 }
169 }
170
171 Ok(())
172}