tuwunel_admin/user/mod.rs
1mod add_email;
2mod create_user;
3mod deactivate;
4mod deactivate_all;
5mod del_email;
6mod delete_device;
7mod delete_room_tag;
8mod force_demote;
9mod force_join_all_local_users;
10mod force_join_list_of_local_users;
11mod force_join_room;
12mod force_leave_room;
13mod force_promote;
14mod get_room_tags;
15mod last_active;
16mod list_joined_rooms;
17mod list_users;
18mod make_user_admin;
19mod put_room_tag;
20mod redact_event;
21mod reject_invites;
22mod reset_password;
23
24use clap::Subcommand;
25use futures::FutureExt;
26use ruma::{OwnedDeviceId, OwnedEventId, OwnedRoomId, OwnedRoomOrAliasId, OwnedUserId, UserId};
27use tuwunel_core::Result;
28use tuwunel_service::Services;
29
30use crate::admin_command_dispatch;
31
32const AUTO_GEN_PASSWORD_LENGTH: usize = 25;
33const BULK_JOIN_REASON: &str = "Bulk force joining this room as initiated by the server admin.";
34
35#[admin_command_dispatch]
36#[derive(Debug, Subcommand)]
37pub(super) enum UserCommand {
38 /// - Create a new user
39 #[clap(alias = "create")]
40 CreateUser {
41 /// Username of the new user
42 username: String,
43 /// Password of the new user, if unspecified one is generated
44 password: Option<String>,
45 },
46
47 /// - Reset user password
48 ResetPassword {
49 /// Username of the user for whom the password should be reset
50 username: String,
51 /// New password for the user, if unspecified one is generated
52 password: Option<String>,
53 },
54
55 /// - Bind an email address to a local user without verification
56 AddEmail {
57 /// Local user to bind the email address to
58 username: String,
59 /// Email address to bind
60 address: String,
61 },
62
63 /// - Remove an email address binding from a local user
64 DelEmail {
65 /// Local user to remove the email address from
66 username: String,
67 /// Email address to remove
68 address: String,
69 },
70
71 /// - Deactivate a user
72 ///
73 /// User will be removed from all rooms by default.
74 /// Use --no-leave-rooms to not leave all rooms by default.
75 Deactivate {
76 #[arg(short, long)]
77 no_leave_rooms: bool,
78 user_id: String,
79 },
80
81 /// - Deactivate a list of users
82 ///
83 /// Recommended to use in conjunction with list-local-users.
84 ///
85 /// Users will be removed from joined rooms by default.
86 ///
87 /// Can be overridden with --no-leave-rooms.
88 ///
89 /// Removing a mass amount of users from a room may cause a significant
90 /// amount of leave events. The time to leave rooms may depend significantly
91 /// on joined rooms and servers.
92 ///
93 /// This command needs a newline separated list of users provided in a
94 /// Markdown code block below the command.
95 DeactivateAll {
96 #[arg(short, long)]
97 /// Does not leave any rooms the user is in on deactivation
98 no_leave_rooms: bool,
99 #[arg(short, long)]
100 /// Also deactivate admin accounts and will assume leave all rooms too
101 force: bool,
102 },
103
104 /// - Deletes a user's device.
105 DeleteDevice {
106 user_id: OwnedUserId,
107 device_id: OwnedDeviceId,
108 },
109
110 /// - List local users by recent activity.
111 LastActive {
112 #[arg(short, long)]
113 limit: Option<usize>,
114 },
115
116 /// - List local users in the database
117 #[clap(alias = "list")]
118 ListUsers,
119
120 /// - Lists all the rooms (local and remote) that the specified user is
121 /// joined in
122 ListJoinedRooms {
123 user_id: String,
124 },
125
126 /// - Manually join a local user to a room.
127 ForceJoinRoom {
128 user_id: String,
129 room: OwnedRoomOrAliasId,
130 },
131
132 /// - Manually leave a local user from a room.
133 ForceLeaveRoom {
134 user_id: String,
135 room_id: OwnedRoomOrAliasId,
136 },
137
138 /// - Reject all pending invites for a local user.
139 RejectInvites {
140 user_id: String,
141
142 /// Optional reason attached to each rejection.
143 #[arg(long)]
144 reason: Option<String>,
145 },
146
147 /// - Forces the specified user to drop their power levels to the room
148 /// default, if their permissions allow and the auth check permits
149 ForceDemote {
150 user_id: String,
151 room_id: OwnedRoomOrAliasId,
152 },
153
154 /// - Force promote
155 ForcePromote {
156 user_id: String,
157 room_id: OwnedRoomOrAliasId,
158 },
159
160 /// - Grant server-admin privileges to a user.
161 MakeUserAdmin {
162 user_id: String,
163 },
164
165 /// - Puts a room tag for the specified user and room ID.
166 ///
167 /// This is primarily useful if you'd like to set your admin room
168 /// to the special "System Alerts" section in Element as a way to
169 /// permanently see your admin room without it being buried away in your
170 /// favourites or rooms. To do this, you would pass your user, your admin
171 /// room's internal ID, and the tag name `m.server_notice`.
172 PutRoomTag {
173 user_id: String,
174 room_id: OwnedRoomId,
175 tag: String,
176 },
177
178 /// - Deletes the room tag for the specified user and room ID
179 DeleteRoomTag {
180 user_id: String,
181 room_id: OwnedRoomId,
182 tag: String,
183 },
184
185 /// - Gets all the room tags for the specified user and room ID
186 GetRoomTags {
187 user_id: String,
188 room_id: OwnedRoomId,
189 },
190
191 /// - Attempts to forcefully redact the specified event ID from the sender
192 /// user
193 ///
194 /// This is only valid for local users
195 RedactEvent {
196 event_id: OwnedEventId,
197 },
198
199 /// - Force joins a specified list of local users to join the specified
200 /// room.
201 ///
202 /// Specify a codeblock of usernames.
203 ///
204 /// Requires the `--yes-i-want-to-do-this` flag.
205 ForceJoinListOfLocalUsers {
206 room: OwnedRoomOrAliasId,
207
208 #[arg(long)]
209 yes_i_want_to_do_this: bool,
210 },
211
212 /// - Force joins all local users to the specified room.
213 ///
214 /// Requires the `--yes-i-want-to-do-this` flag.
215 ForceJoinAllLocalUsers {
216 room: OwnedRoomOrAliasId,
217
218 #[arg(long)]
219 yes_i_want_to_do_this: bool,
220 },
221}
222
223async fn deactivate_user(services: &Services, user_id: &UserId, no_leave_rooms: bool) -> Result {
224 if !no_leave_rooms {
225 services
226 .deactivate
227 .full_deactivate(user_id, false)
228 .boxed()
229 .await?;
230 } else {
231 services.users.deactivate_account(user_id).await?;
232 }
233
234 Ok(())
235}