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