Skip to main content

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}