Refactor admin rooms moderation
Split alias.*_alias_by from alias.*_ailias
This commit is contained in:
@@ -44,7 +44,6 @@ pub(crate) enum RoomAliasCommand {
|
||||
|
||||
pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) -> Result {
|
||||
let services = context.services;
|
||||
let server_user = &services.globals.server_user;
|
||||
|
||||
match command {
|
||||
| RoomAliasCommand::Set { ref room_alias_localpart, .. }
|
||||
@@ -68,10 +67,7 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) ->
|
||||
.await,
|
||||
) {
|
||||
| (true, Ok(id)) => {
|
||||
match services
|
||||
.alias
|
||||
.set_alias(&room_alias, &room_id, server_user)
|
||||
{
|
||||
match services.alias.set_alias(&room_alias, &room_id) {
|
||||
| Err(err) => Err!("Failed to remove alias: {err}"),
|
||||
| Ok(()) =>
|
||||
context
|
||||
@@ -85,14 +81,9 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) ->
|
||||
"Refusing to overwrite in use alias for {id}, use -f or --force to \
|
||||
overwrite"
|
||||
),
|
||||
| (_, Err(_)) => {
|
||||
match services
|
||||
.alias
|
||||
.set_alias(&room_alias, &room_id, server_user)
|
||||
{
|
||||
| Err(err) => Err!("Failed to remove alias: {err}"),
|
||||
| Ok(()) => context.write_str("Successfully set alias").await,
|
||||
}
|
||||
| (_, Err(_)) => match services.alias.set_alias(&room_alias, &room_id) {
|
||||
| Err(err) => Err!("Failed to remove alias: {err}"),
|
||||
| Ok(()) => context.write_str("Successfully set alias").await,
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -103,11 +94,7 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) ->
|
||||
.await
|
||||
{
|
||||
| Err(_) => Err!("Alias isn't in use."),
|
||||
| Ok(id) => match services
|
||||
.alias
|
||||
.remove_alias(&room_alias, server_user)
|
||||
.await
|
||||
{
|
||||
| Ok(id) => match services.alias.remove_alias(&room_alias).await {
|
||||
| Err(err) => Err!("Failed to remove alias: {err}"),
|
||||
| Ok(()) =>
|
||||
context
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use clap::Subcommand;
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use ruma::{OwnedRoomId, OwnedRoomOrAliasId, RoomAliasId, RoomId, RoomOrAliasId};
|
||||
use ruma::{OwnedRoomId, OwnedRoomOrAliasId, RoomId, RoomOrAliasId};
|
||||
use tuwunel_core::{
|
||||
Err, Result, debug,
|
||||
Err, Result, debug, is_equal_to,
|
||||
utils::{IterStream, ReadyExt},
|
||||
warn,
|
||||
};
|
||||
use tuwunel_service::Services;
|
||||
|
||||
use crate::{admin_command, admin_command_dispatch, get_room_info};
|
||||
|
||||
@@ -44,6 +45,59 @@ pub(crate) enum RoomModerationCommand {
|
||||
},
|
||||
}
|
||||
|
||||
async fn do_ban_room(services: &Services, room_id: &RoomId) {
|
||||
services.metadata.ban_room(room_id);
|
||||
|
||||
debug!("Banned {room_id} successfully");
|
||||
|
||||
debug!("Making all users leave the room {room_id} and forgetting it");
|
||||
let mut users = services
|
||||
.state_cache
|
||||
.room_members(room_id)
|
||||
.ready_filter(|user| services.globals.user_is_local(user))
|
||||
.map(ToOwned::to_owned)
|
||||
.boxed();
|
||||
|
||||
while let Some(ref user_id) = users.next().await {
|
||||
debug!(
|
||||
"Attempting leave for user {user_id} in room {room_id} (ignoring all errors, \
|
||||
evicting admins too)",
|
||||
);
|
||||
|
||||
let state_lock = services.state.mutex.lock(room_id).await;
|
||||
|
||||
if let Err(e) = services
|
||||
.membership
|
||||
.leave(user_id, room_id, None, false, &state_lock)
|
||||
.boxed()
|
||||
.await
|
||||
{
|
||||
warn!("Failed to leave room: {e}");
|
||||
}
|
||||
|
||||
drop(state_lock);
|
||||
|
||||
services.state_cache.forget(room_id, user_id);
|
||||
}
|
||||
|
||||
// remove any local aliases, ignore errors
|
||||
services
|
||||
.alias
|
||||
.local_aliases_for_room(room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
.for_each(async |local_alias| {
|
||||
if let Err(e) = services.alias.remove_alias(&local_alias).await {
|
||||
warn!("Error removing alias {local_alias} for {room_id}: {e}");
|
||||
}
|
||||
})
|
||||
.await;
|
||||
|
||||
// unpublish from room directory, ignore errors
|
||||
services.directory.set_not_public(room_id);
|
||||
|
||||
services.metadata.disable_room(room_id);
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
debug!("Got room alias or ID: {}", room);
|
||||
@@ -56,137 +110,9 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
return Err!("Not allowed to ban the admin room.");
|
||||
}
|
||||
|
||||
let room_id = if room.is_room_id() {
|
||||
let room_id = match RoomId::parse(&room) {
|
||||
| Ok(room_id) => room_id,
|
||||
| Err(e) => {
|
||||
return Err!(
|
||||
"Failed to parse room ID {room}. Please note that this requires a full room \
|
||||
ID (`!awIh6gGInaS5wLQJwa:example.com`) or a room alias \
|
||||
(`#roomalias:example.com`): {e}"
|
||||
);
|
||||
},
|
||||
};
|
||||
let room_id = self.services.alias.maybe_resolve(&room).await?;
|
||||
|
||||
debug!("Room specified is a room ID, banning room ID");
|
||||
self.services.metadata.ban_room(room_id);
|
||||
|
||||
room_id.to_owned()
|
||||
} else if room.is_room_alias_id() {
|
||||
let room_alias = match RoomAliasId::parse(&room) {
|
||||
| Ok(room_alias) => room_alias,
|
||||
| Err(e) => {
|
||||
return Err!(
|
||||
"Failed to parse room ID {room}. Please note that this requires a full room \
|
||||
ID (`!awIh6gGInaS5wLQJwa:example.com`) or a room alias \
|
||||
(`#roomalias:example.com`): {e}"
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
debug!(
|
||||
"Room specified is not a room ID, attempting to resolve room alias to a room ID \
|
||||
locally, if not using get_alias_helper to fetch room ID remotely"
|
||||
);
|
||||
|
||||
let room_id = match self
|
||||
.services
|
||||
.alias
|
||||
.resolve_local_alias(room_alias)
|
||||
.await
|
||||
{
|
||||
| Ok(room_id) => room_id,
|
||||
| _ => {
|
||||
debug!(
|
||||
"We don't have this room alias to a room ID locally, attempting to fetch \
|
||||
room ID over federation"
|
||||
);
|
||||
|
||||
match self
|
||||
.services
|
||||
.alias
|
||||
.resolve_alias(room_alias)
|
||||
.await
|
||||
{
|
||||
| Ok((room_id, servers)) => {
|
||||
debug!(
|
||||
?room_id,
|
||||
?servers,
|
||||
"Got federation response fetching room ID for {room_id}"
|
||||
);
|
||||
room_id
|
||||
},
|
||||
| Err(e) => {
|
||||
return Err!(
|
||||
"Failed to resolve room alias {room_alias} to a room ID: {e}"
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
self.services.metadata.ban_room(&room_id);
|
||||
|
||||
room_id
|
||||
} else {
|
||||
return Err!(
|
||||
"Room specified is not a room ID or room alias. Please note that this requires a \
|
||||
full room ID (`!awIh6gGInaS5wLQJwa:example.com`) or a room alias \
|
||||
(`#roomalias:example.com`)",
|
||||
);
|
||||
};
|
||||
|
||||
debug!("Making all users leave the room {room_id} and forgetting it");
|
||||
let mut users = self
|
||||
.services
|
||||
.state_cache
|
||||
.room_members(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
.ready_filter(|user| self.services.globals.user_is_local(user))
|
||||
.boxed();
|
||||
|
||||
while let Some(ref user_id) = users.next().await {
|
||||
debug!(
|
||||
"Attempting leave for user {user_id} in room {room_id} (ignoring all errors, \
|
||||
evicting admins too)",
|
||||
);
|
||||
|
||||
let state_lock = self.services.state.mutex.lock(&room_id).await;
|
||||
|
||||
if let Err(e) = self
|
||||
.services
|
||||
.membership
|
||||
.leave(user_id, &room_id, None, false, &state_lock)
|
||||
.boxed()
|
||||
.await
|
||||
{
|
||||
warn!("Failed to leave room: {e}");
|
||||
}
|
||||
|
||||
drop(state_lock);
|
||||
|
||||
self.services
|
||||
.state_cache
|
||||
.forget(&room_id, user_id);
|
||||
}
|
||||
|
||||
self.services
|
||||
.alias
|
||||
.local_aliases_for_room(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
.for_each(async |local_alias| {
|
||||
self.services
|
||||
.alias
|
||||
.remove_alias(&local_alias, &self.services.globals.server_user)
|
||||
.await
|
||||
.ok();
|
||||
})
|
||||
.await;
|
||||
|
||||
// unpublish from room directory
|
||||
self.services.directory.set_not_public(&room_id);
|
||||
|
||||
self.services.metadata.disable_room(&room_id);
|
||||
do_ban_room(self.services, &room_id).await;
|
||||
|
||||
self.write_str(
|
||||
"Room banned, removed all our local users, and disabled incoming federation with room.",
|
||||
@@ -209,164 +135,51 @@ async fn ban_list_of_rooms(&self) -> Result {
|
||||
.drain(1..self.body.len().saturating_sub(1))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let admin_room_alias = &self.services.admin.admin_alias;
|
||||
let admin_room_id = self.services.admin.get_admin_room().await.ok();
|
||||
|
||||
let mut room_ban_count: usize = 0;
|
||||
let mut room_ids: Vec<OwnedRoomId> = Vec::new();
|
||||
let mut room_ids: Vec<OwnedRoomId> = Vec::with_capacity(rooms_s.len());
|
||||
|
||||
for &room in &rooms_s {
|
||||
match <&RoomOrAliasId>::try_from(room) {
|
||||
| Ok(room_alias_or_id) => {
|
||||
if let Ok(admin_room_id) = self.services.admin.get_admin_room().await
|
||||
&& (room.to_owned().eq(&admin_room_id)
|
||||
|| room.to_owned().eq(admin_room_alias))
|
||||
{
|
||||
warn!("User specified admin room in bulk ban list, ignoring");
|
||||
continue;
|
||||
}
|
||||
|
||||
if room_alias_or_id.is_room_id() {
|
||||
let room_id = match RoomId::parse(room_alias_or_id) {
|
||||
| Ok(room_id) => room_id,
|
||||
| Err(e) => {
|
||||
// ignore rooms we failed to parse
|
||||
warn!(
|
||||
"Error parsing room \"{room}\" during bulk room banning, \
|
||||
ignoring error and logging here: {e}"
|
||||
);
|
||||
continue;
|
||||
},
|
||||
};
|
||||
|
||||
room_ids.push(room_id.to_owned());
|
||||
}
|
||||
|
||||
if room_alias_or_id.is_room_alias_id() {
|
||||
match RoomAliasId::parse(room_alias_or_id) {
|
||||
| Ok(room_alias) => {
|
||||
let room_id = match self
|
||||
.services
|
||||
.alias
|
||||
.resolve_local_alias(room_alias)
|
||||
.await
|
||||
{
|
||||
| Ok(room_id) => room_id,
|
||||
| _ => {
|
||||
debug!(
|
||||
"We don't have this room alias to a room ID locally, \
|
||||
attempting to fetch room ID over federation"
|
||||
);
|
||||
|
||||
match self
|
||||
.services
|
||||
.alias
|
||||
.resolve_alias(room_alias)
|
||||
.await
|
||||
{
|
||||
| Ok((room_id, servers)) => {
|
||||
debug!(
|
||||
?room_id,
|
||||
?servers,
|
||||
"Got federation response fetching room ID for \
|
||||
{room}",
|
||||
);
|
||||
room_id
|
||||
},
|
||||
| Err(e) => {
|
||||
warn!(
|
||||
"Failed to resolve room alias {room} to a room \
|
||||
ID: {e}"
|
||||
);
|
||||
continue;
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
room_ids.push(room_id);
|
||||
},
|
||||
| Err(e) => {
|
||||
warn!(
|
||||
"Error parsing room \"{room}\" during bulk room banning, \
|
||||
ignoring error and logging here: {e}"
|
||||
);
|
||||
continue;
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
for room in rooms_s {
|
||||
let room_alias_or_id = match <&RoomOrAliasId>::try_from(room) {
|
||||
| Ok(room_alias_or_id) => room_alias_or_id,
|
||||
| Err(e) => {
|
||||
warn!(
|
||||
"Error parsing room \"{room}\" during bulk room banning, ignoring error and \
|
||||
logging here: {e}"
|
||||
);
|
||||
warn!("Error parsing room {room} during bulk room banning, ignoring: {e}");
|
||||
continue;
|
||||
},
|
||||
};
|
||||
|
||||
let room_id = match self
|
||||
.services
|
||||
.alias
|
||||
.maybe_resolve(room_alias_or_id)
|
||||
.await
|
||||
{
|
||||
| Ok(room_id) => room_id,
|
||||
| Err(e) => {
|
||||
warn!("Failed to resolve room alias {room_alias_or_id} to a room ID: {e}");
|
||||
continue;
|
||||
},
|
||||
};
|
||||
|
||||
if admin_room_id
|
||||
.as_ref()
|
||||
.is_some_and(is_equal_to!(&room_id))
|
||||
{
|
||||
warn!("User specified admin room in bulk ban list, ignoring");
|
||||
continue;
|
||||
}
|
||||
|
||||
room_ids.push(room_id);
|
||||
}
|
||||
|
||||
let rooms_len = room_ids.len();
|
||||
|
||||
for room_id in room_ids {
|
||||
self.services.metadata.ban_room(&room_id);
|
||||
|
||||
debug!("Banned {room_id} successfully");
|
||||
room_ban_count = room_ban_count.saturating_add(1);
|
||||
|
||||
debug!("Making all users leave the room {room_id} and forgetting it");
|
||||
let mut users = self
|
||||
.services
|
||||
.state_cache
|
||||
.room_members(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
.ready_filter(|user| self.services.globals.user_is_local(user))
|
||||
.boxed();
|
||||
|
||||
while let Some(ref user_id) = users.next().await {
|
||||
debug!(
|
||||
"Attempting leave for user {user_id} in room {room_id} (ignoring all errors, \
|
||||
evicting admins too)",
|
||||
);
|
||||
|
||||
let state_lock = self.services.state.mutex.lock(&room_id).await;
|
||||
|
||||
if let Err(e) = self
|
||||
.services
|
||||
.membership
|
||||
.leave(user_id, &room_id, None, false, &state_lock)
|
||||
.boxed()
|
||||
.await
|
||||
{
|
||||
warn!("Failed to leave room: {e}");
|
||||
}
|
||||
|
||||
drop(state_lock);
|
||||
|
||||
self.services
|
||||
.state_cache
|
||||
.forget(&room_id, user_id);
|
||||
}
|
||||
|
||||
// remove any local aliases, ignore errors
|
||||
self.services
|
||||
.alias
|
||||
.local_aliases_for_room(&room_id)
|
||||
.map(ToOwned::to_owned)
|
||||
.for_each(async |local_alias| {
|
||||
self.services
|
||||
.alias
|
||||
.remove_alias(&local_alias, &self.services.globals.server_user)
|
||||
.await
|
||||
.ok();
|
||||
})
|
||||
.await;
|
||||
|
||||
// unpublish from room directory, ignore errors
|
||||
self.services.directory.set_not_public(&room_id);
|
||||
|
||||
self.services.metadata.disable_room(&room_id);
|
||||
do_ban_room(self.services, &room_id).await;
|
||||
}
|
||||
|
||||
self.write_str(&format!(
|
||||
"Finished bulk room ban, banned {room_ban_count} total rooms, evicted all users, and \
|
||||
"Finished bulk room ban, banned {rooms_len} total rooms, evicted all users, and \
|
||||
disabled incoming federation with the room."
|
||||
))
|
||||
.await
|
||||
@@ -374,84 +187,9 @@ async fn ban_list_of_rooms(&self) -> Result {
|
||||
|
||||
#[admin_command]
|
||||
async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
let room_id = if room.is_room_id() {
|
||||
let room_id = match RoomId::parse(&room) {
|
||||
| Ok(room_id) => room_id,
|
||||
| Err(e) => {
|
||||
return Err!(
|
||||
"Failed to parse room ID {room}. Please note that this requires a full room \
|
||||
ID (`!awIh6gGInaS5wLQJwa:example.com`) or a room alias \
|
||||
(`#roomalias:example.com`): {e}"
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
debug!("Room specified is a room ID, unbanning room ID");
|
||||
self.services.metadata.unban_room(room_id);
|
||||
|
||||
room_id.to_owned()
|
||||
} else if room.is_room_alias_id() {
|
||||
let room_alias = match RoomAliasId::parse(&room) {
|
||||
| Ok(room_alias) => room_alias,
|
||||
| Err(e) => {
|
||||
return Err!(
|
||||
"Failed to parse room ID {room}. Please note that this requires a full room \
|
||||
ID (`!awIh6gGInaS5wLQJwa:example.com`) or a room alias \
|
||||
(`#roomalias:example.com`): {e}"
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
debug!(
|
||||
"Room specified is not a room ID, attempting to resolve room alias to a room ID \
|
||||
locally, if not using get_alias_helper to fetch room ID remotely"
|
||||
);
|
||||
|
||||
let room_id = match self
|
||||
.services
|
||||
.alias
|
||||
.resolve_local_alias(room_alias)
|
||||
.await
|
||||
{
|
||||
| Ok(room_id) => room_id,
|
||||
| _ => {
|
||||
debug!(
|
||||
"We don't have this room alias to a room ID locally, attempting to fetch \
|
||||
room ID over federation"
|
||||
);
|
||||
|
||||
match self
|
||||
.services
|
||||
.alias
|
||||
.resolve_alias(room_alias)
|
||||
.await
|
||||
{
|
||||
| Ok((room_id, servers)) => {
|
||||
debug!(
|
||||
?room_id,
|
||||
?servers,
|
||||
"Got federation response fetching room ID for room {room}"
|
||||
);
|
||||
room_id
|
||||
},
|
||||
| Err(e) => {
|
||||
return Err!("Failed to resolve room alias {room} to a room ID: {e}");
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
self.services.metadata.unban_room(&room_id);
|
||||
|
||||
room_id
|
||||
} else {
|
||||
return Err!(
|
||||
"Room specified is not a room ID or room alias. Please note that this requires a \
|
||||
full room ID (`!awIh6gGInaS5wLQJwa:example.com`) or a room alias \
|
||||
(`#roomalias:example.com`)",
|
||||
);
|
||||
};
|
||||
let room_id = self.services.alias.maybe_resolve(&room).await?;
|
||||
|
||||
self.services.metadata.unban_room(&room_id);
|
||||
self.services.metadata.enable_room(&room_id);
|
||||
self.write_str("Room unbanned and federation re-enabled.")
|
||||
.await
|
||||
|
||||
@@ -44,7 +44,7 @@ pub(crate) async fn create_alias_route(
|
||||
|
||||
services
|
||||
.alias
|
||||
.set_alias(&body.room_alias, &body.room_id, sender_user)?;
|
||||
.set_alias_by(&body.room_alias, &body.room_id, sender_user)?;
|
||||
|
||||
Ok(create_alias::v3::Response::new())
|
||||
}
|
||||
@@ -66,7 +66,7 @@ pub(crate) async fn delete_alias_route(
|
||||
|
||||
services
|
||||
.alias
|
||||
.remove_alias(&body.room_alias, sender_user)
|
||||
.remove_alias_by(&body.room_alias, sender_user)
|
||||
.await?;
|
||||
|
||||
// TODO: update alt_aliases?
|
||||
|
||||
@@ -406,7 +406,7 @@ pub(crate) async fn create_room_route(
|
||||
if let Some(alias) = alias {
|
||||
services
|
||||
.alias
|
||||
.set_alias(&alias, &room_id, sender_user)?;
|
||||
.set_alias_by(&alias, &room_id, sender_user)?;
|
||||
}
|
||||
|
||||
if body.visibility == room::Visibility::Public {
|
||||
|
||||
@@ -448,7 +448,7 @@ async fn move_local_aliases(&self) -> Result {
|
||||
.filter_map(|alias| {
|
||||
self.services
|
||||
.alias
|
||||
.remove_alias(alias, self.sender_user)
|
||||
.remove_alias_by(alias, self.sender_user)
|
||||
.inspect_err(move |e| error!(?alias, ?self, "Failed to remove alias: {e}"))
|
||||
.map_ok(move |()| alias)
|
||||
.ok()
|
||||
@@ -456,7 +456,7 @@ async fn move_local_aliases(&self) -> Result {
|
||||
.ready_for_each(|alias| {
|
||||
self.services
|
||||
.alias
|
||||
.set_alias(alias, self.new_room_id, self.sender_user)
|
||||
.set_alias_by(alias, self.new_room_id, self.sender_user)
|
||||
.inspect_err(|e| error!(?self, "Failed to add alias: {e}"))
|
||||
.ok();
|
||||
})
|
||||
|
||||
@@ -201,9 +201,7 @@ pub async fn create_admin_room(services: &Services) -> Result {
|
||||
.boxed()
|
||||
.await?;
|
||||
|
||||
services
|
||||
.alias
|
||||
.set_alias(alias, &room_id, server_user)?;
|
||||
services.alias.set_alias(alias, &room_id)?;
|
||||
|
||||
// 7. (ad-hoc) Disable room URL previews for everyone by default
|
||||
services
|
||||
|
||||
@@ -223,6 +223,10 @@ impl Service {
|
||||
|
||||
/// Checks whether a given user is an admin of this server
|
||||
pub async fn user_is_admin(&self, user_id: &UserId) -> bool {
|
||||
if user_id == self.services.globals.server_user {
|
||||
return true;
|
||||
}
|
||||
|
||||
let Ok(admin_room) = self.get_admin_room().await else {
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -41,8 +41,19 @@ impl crate::Service for Service {
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn set_alias(&self, alias: &RoomAliasId, room_id: &RoomId) -> Result {
|
||||
self.check_alias_local(alias)?;
|
||||
|
||||
self.set_alias_by(alias, room_id, &self.services.globals.server_user)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn set_alias(&self, alias: &RoomAliasId, room_id: &RoomId, user_id: &UserId) -> Result {
|
||||
pub fn set_alias_by(
|
||||
&self,
|
||||
alias: &RoomAliasId,
|
||||
room_id: &RoomId,
|
||||
user_id: &UserId,
|
||||
) -> Result {
|
||||
self.check_alias_local(alias)?;
|
||||
|
||||
if alias == self.services.admin.admin_alias
|
||||
@@ -53,32 +64,30 @@ impl Service {
|
||||
|
||||
let count = self.services.globals.next_count();
|
||||
|
||||
let localpart = alias.alias();
|
||||
|
||||
// Comes first as we don't want a stuck alias
|
||||
self.db
|
||||
.alias_userid
|
||||
.insert(alias.alias().as_bytes(), user_id.as_bytes());
|
||||
self.db.alias_userid.insert(localpart, user_id);
|
||||
|
||||
self.db
|
||||
.alias_roomid
|
||||
.insert(alias.alias().as_bytes(), room_id.as_bytes());
|
||||
|
||||
let mut aliasid = room_id.as_bytes().to_vec();
|
||||
aliasid.push(0xFF);
|
||||
aliasid.extend_from_slice(&count.to_be_bytes());
|
||||
self.db.alias_roomid.insert(localpart, room_id);
|
||||
|
||||
self.db
|
||||
.aliasid_alias
|
||||
.insert(&aliasid, alias.as_bytes());
|
||||
.put_raw((room_id, *count), alias);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub async fn remove_alias(&self, alias: &RoomAliasId, user_id: &UserId) -> Result {
|
||||
pub async fn remove_alias_by(&self, alias: &RoomAliasId, user_id: &UserId) -> Result {
|
||||
if !self.user_can_remove_alias(alias, user_id).await? {
|
||||
return Err!(Request(Forbidden("User is not permitted to remove this alias.")));
|
||||
}
|
||||
|
||||
self.remove_alias(alias).await
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub async fn remove_alias(&self, alias: &RoomAliasId) -> Result {
|
||||
let alias = alias.alias();
|
||||
let Ok(room_id) = self.db.alias_roomid.get(&alias).await else {
|
||||
return Err!(Request(NotFound("Alias does not exist or is invalid.")));
|
||||
@@ -198,16 +207,12 @@ impl Service {
|
||||
.await
|
||||
.map_err(|_| err!(Request(NotFound("Alias not found."))))?;
|
||||
|
||||
let server_user = &self.services.globals.server_user;
|
||||
|
||||
// The creator of an alias can remove it
|
||||
if self
|
||||
.who_created_alias(alias).await
|
||||
.is_ok_and(|user| user == user_id)
|
||||
// Server admins can remove any local alias
|
||||
|| self.services.admin.user_is_admin(user_id).await
|
||||
// Always allow the server service account to remove the alias, since there may not be an admin room
|
||||
|| server_user == user_id
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ impl Service {
|
||||
.for_each(async |local_alias| {
|
||||
self.services
|
||||
.alias
|
||||
.remove_alias(local_alias, &self.services.globals.server_user)
|
||||
.remove_alias(local_alias)
|
||||
.await
|
||||
.log_err()
|
||||
.ok();
|
||||
|
||||
Reference in New Issue
Block a user