mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2025-09-11 13:23:01 +02:00
Compare commits
23 commits
cda40e8f9f
...
3df64bd931
Author | SHA1 | Date | |
---|---|---|---|
|
3df64bd931 | ||
|
cb80b1839b | ||
|
e545e5abe4 | ||
|
560881d481 | ||
|
28d5c15738 | ||
|
fe46b18279 | ||
|
0975200711 | ||
|
194c6c23e7 | ||
|
f8e4cf1efc | ||
|
c9082a61f7 | ||
|
8317e32873 | ||
|
cb4cbc6070 | ||
|
5f1095c800 | ||
|
f9ae2375d8 | ||
|
8c264d64bc | ||
|
a1403ca748 | ||
|
10b111a777 | ||
|
373df527a3 | ||
|
5833aedc99 | ||
|
cd238219de | ||
|
d3dd435ead | ||
|
9b83368458 | ||
|
920fc0c54b |
23 changed files with 90 additions and 318 deletions
5
.github/FUNDING.yml
vendored
5
.github/FUNDING.yml
vendored
|
@ -1,5 +0,0 @@
|
|||
github: [JadedBlueEyes]
|
||||
# Doesn't support an array, so we can only list nex
|
||||
ko_fi: nexy7574
|
||||
custom:
|
||||
- https://ko-fi.com/JadedBlueEyes
|
22
Cargo.lock
generated
22
Cargo.lock
generated
|
@ -3798,7 +3798,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma"
|
||||
version = "0.10.1"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=9b65f83981f6f53d185ce77da37aaef9dfd764a9#9b65f83981f6f53d185ce77da37aaef9dfd764a9"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=d6870a7fb7f6cccff63f7fd0ff6c581bad80e983#d6870a7fb7f6cccff63f7fd0ff6c581bad80e983"
|
||||
dependencies = [
|
||||
"assign",
|
||||
"js_int",
|
||||
|
@ -3818,7 +3818,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-appservice-api"
|
||||
version = "0.10.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=9b65f83981f6f53d185ce77da37aaef9dfd764a9#9b65f83981f6f53d185ce77da37aaef9dfd764a9"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=d6870a7fb7f6cccff63f7fd0ff6c581bad80e983#d6870a7fb7f6cccff63f7fd0ff6c581bad80e983"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
|
@ -3830,7 +3830,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-client-api"
|
||||
version = "0.18.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=9b65f83981f6f53d185ce77da37aaef9dfd764a9#9b65f83981f6f53d185ce77da37aaef9dfd764a9"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=d6870a7fb7f6cccff63f7fd0ff6c581bad80e983#d6870a7fb7f6cccff63f7fd0ff6c581bad80e983"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"assign",
|
||||
|
@ -3853,7 +3853,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-common"
|
||||
version = "0.13.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=9b65f83981f6f53d185ce77da37aaef9dfd764a9#9b65f83981f6f53d185ce77da37aaef9dfd764a9"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=d6870a7fb7f6cccff63f7fd0ff6c581bad80e983#d6870a7fb7f6cccff63f7fd0ff6c581bad80e983"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"base64 0.22.1",
|
||||
|
@ -3885,7 +3885,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-events"
|
||||
version = "0.28.1"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=9b65f83981f6f53d185ce77da37aaef9dfd764a9#9b65f83981f6f53d185ce77da37aaef9dfd764a9"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=d6870a7fb7f6cccff63f7fd0ff6c581bad80e983#d6870a7fb7f6cccff63f7fd0ff6c581bad80e983"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"indexmap 2.9.0",
|
||||
|
@ -3910,7 +3910,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-federation-api"
|
||||
version = "0.9.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=9b65f83981f6f53d185ce77da37aaef9dfd764a9#9b65f83981f6f53d185ce77da37aaef9dfd764a9"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=d6870a7fb7f6cccff63f7fd0ff6c581bad80e983#d6870a7fb7f6cccff63f7fd0ff6c581bad80e983"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"headers",
|
||||
|
@ -3932,7 +3932,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-identifiers-validation"
|
||||
version = "0.9.5"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=9b65f83981f6f53d185ce77da37aaef9dfd764a9#9b65f83981f6f53d185ce77da37aaef9dfd764a9"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=d6870a7fb7f6cccff63f7fd0ff6c581bad80e983#d6870a7fb7f6cccff63f7fd0ff6c581bad80e983"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"thiserror 2.0.12",
|
||||
|
@ -3941,7 +3941,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-identity-service-api"
|
||||
version = "0.9.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=9b65f83981f6f53d185ce77da37aaef9dfd764a9#9b65f83981f6f53d185ce77da37aaef9dfd764a9"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=d6870a7fb7f6cccff63f7fd0ff6c581bad80e983#d6870a7fb7f6cccff63f7fd0ff6c581bad80e983"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
|
@ -3951,7 +3951,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-macros"
|
||||
version = "0.13.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=9b65f83981f6f53d185ce77da37aaef9dfd764a9#9b65f83981f6f53d185ce77da37aaef9dfd764a9"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=d6870a7fb7f6cccff63f7fd0ff6c581bad80e983#d6870a7fb7f6cccff63f7fd0ff6c581bad80e983"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"proc-macro-crate",
|
||||
|
@ -3966,7 +3966,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-push-gateway-api"
|
||||
version = "0.9.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=9b65f83981f6f53d185ce77da37aaef9dfd764a9#9b65f83981f6f53d185ce77da37aaef9dfd764a9"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=d6870a7fb7f6cccff63f7fd0ff6c581bad80e983#d6870a7fb7f6cccff63f7fd0ff6c581bad80e983"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
|
@ -3978,7 +3978,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ruma-signatures"
|
||||
version = "0.15.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=9b65f83981f6f53d185ce77da37aaef9dfd764a9#9b65f83981f6f53d185ce77da37aaef9dfd764a9"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=d6870a7fb7f6cccff63f7fd0ff6c581bad80e983#d6870a7fb7f6cccff63f7fd0ff6c581bad80e983"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"ed25519-dalek",
|
||||
|
|
|
@ -350,7 +350,7 @@ version = "0.1.2"
|
|||
[workspace.dependencies.ruma]
|
||||
git = "https://forgejo.ellis.link/continuwuation/ruwuma"
|
||||
#branch = "conduwuit-changes"
|
||||
rev = "9b65f83981f6f53d185ce77da37aaef9dfd764a9"
|
||||
rev = "d6870a7fb7f6cccff63f7fd0ff6c581bad80e983"
|
||||
features = [
|
||||
"compat",
|
||||
"rand",
|
||||
|
|
|
@ -7,14 +7,13 @@ use futures::{
|
|||
io::{AsyncWriteExt, BufWriter},
|
||||
lock::Mutex,
|
||||
};
|
||||
use ruma::{EventId, UserId};
|
||||
use ruma::EventId;
|
||||
|
||||
pub(crate) struct Context<'a> {
|
||||
pub(crate) services: &'a Services,
|
||||
pub(crate) body: &'a [&'a str],
|
||||
pub(crate) timer: SystemTime,
|
||||
pub(crate) reply_id: Option<&'a EventId>,
|
||||
pub(crate) sender: Option<&'a UserId>,
|
||||
pub(crate) output: Mutex<BufWriter<Vec<u8>>>,
|
||||
}
|
||||
|
||||
|
@ -37,10 +36,4 @@ impl Context<'_> {
|
|||
output.write_all(s.as_bytes()).map_err(Into::into).await
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the sender as a string, or service user ID if not available
|
||||
pub(crate) fn sender_or_service_user(&self) -> &UserId {
|
||||
self.sender
|
||||
.unwrap_or_else(|| self.services.globals.server_user.as_ref())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,6 @@ async fn process_command(services: Arc<Services>, input: &CommandInput) -> Proce
|
|||
body: &body,
|
||||
timer: SystemTime::now(),
|
||||
reply_id: input.reply_id.as_deref(),
|
||||
sender: input.sender.as_deref(),
|
||||
output: BufWriter::new(Vec::new()).into(),
|
||||
};
|
||||
|
||||
|
|
|
@ -225,47 +225,6 @@ pub(super) async fn deactivate(&self, no_leave_rooms: bool, user_id: String) ->
|
|||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn suspend(&self, user_id: String) -> Result {
|
||||
let user_id = parse_local_user_id(self.services, &user_id)?;
|
||||
|
||||
if user_id == self.services.globals.server_user {
|
||||
return Err!("Not allowed to suspend the server service account.",);
|
||||
}
|
||||
|
||||
if !self.services.users.exists(&user_id).await {
|
||||
return Err!("User {user_id} does not exist.");
|
||||
}
|
||||
if self.services.users.is_admin(&user_id).await {
|
||||
return Err!("Admin users cannot be suspended.");
|
||||
}
|
||||
// TODO: Record the actual user that sent the suspension where possible
|
||||
self.services
|
||||
.users
|
||||
.suspend_account(&user_id, self.sender_or_service_user())
|
||||
.await;
|
||||
|
||||
self.write_str(&format!("User {user_id} has been suspended."))
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn unsuspend(&self, user_id: String) -> Result {
|
||||
let user_id = parse_local_user_id(self.services, &user_id)?;
|
||||
|
||||
if user_id == self.services.globals.server_user {
|
||||
return Err!("Not allowed to unsuspend the server service account.",);
|
||||
}
|
||||
|
||||
if !self.services.users.exists(&user_id).await {
|
||||
return Err!("User {user_id} does not exist.");
|
||||
}
|
||||
self.services.users.unsuspend_account(&user_id).await;
|
||||
|
||||
self.write_str(&format!("User {user_id} has been unsuspended."))
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn reset_password(&self, username: String, password: Option<String>) -> Result {
|
||||
let user_id = parse_local_user_id(self.services, &username)?;
|
||||
|
|
|
@ -59,28 +59,6 @@ pub(super) enum UserCommand {
|
|||
force: bool,
|
||||
},
|
||||
|
||||
/// - Suspend a user
|
||||
///
|
||||
/// Suspended users are able to log in, sync, and read messages, but are not
|
||||
/// able to send events nor redact them, cannot change their profile, and
|
||||
/// are unable to join, invite to, or knock on rooms.
|
||||
///
|
||||
/// Suspended users can still leave rooms and deactivate their account.
|
||||
/// Suspending them effectively makes them read-only.
|
||||
Suspend {
|
||||
/// Username of the user to suspend
|
||||
user_id: String,
|
||||
},
|
||||
|
||||
/// - Unsuspend a user
|
||||
///
|
||||
/// Reverses the effects of the `suspend` command, allowing the user to send
|
||||
/// messages, change their profile, create room invites, etc.
|
||||
Unsuspend {
|
||||
/// Username of the user to unsuspend
|
||||
user_id: String,
|
||||
},
|
||||
|
||||
/// - List local users in the database
|
||||
#[clap(alias = "list")]
|
||||
ListUsers,
|
||||
|
|
|
@ -18,9 +18,6 @@ pub(crate) async fn create_alias_route(
|
|||
body: Ruma<create_alias::v3::Request>,
|
||||
) -> Result<create_alias::v3::Response> {
|
||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
services
|
||||
.rooms
|
||||
|
@ -66,9 +63,6 @@ pub(crate) async fn delete_alias_route(
|
|||
body: Ruma<delete_alias::v3::Request>,
|
||||
) -> Result<delete_alias::v3::Response> {
|
||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
services
|
||||
.rooms
|
||||
|
|
|
@ -128,9 +128,6 @@ pub(crate) async fn set_room_visibility_route(
|
|||
// Return 404 if the room doesn't exist
|
||||
return Err!(Request(NotFound("Room not found")));
|
||||
}
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
if services
|
||||
.users
|
||||
|
|
|
@ -52,9 +52,6 @@ pub(crate) async fn create_content_route(
|
|||
body: Ruma<create_content::v3::Request>,
|
||||
) -> Result<create_content::v3::Response> {
|
||||
let user = body.sender_user.as_ref().expect("user is authenticated");
|
||||
if services.users.is_suspended(user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
let filename = body.filename.as_deref();
|
||||
let content_type = body.content_type.as_deref();
|
||||
|
|
|
@ -182,9 +182,6 @@ pub(crate) async fn join_room_by_id_route(
|
|||
body: Ruma<join_room_by_id::v3::Request>,
|
||||
) -> Result<join_room_by_id::v3::Response> {
|
||||
let sender_user = body.sender_user();
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
banned_room_check(
|
||||
&services,
|
||||
|
@ -256,9 +253,6 @@ pub(crate) async fn join_room_by_id_or_alias_route(
|
|||
let sender_user = body.sender_user.as_deref().expect("user is authenticated");
|
||||
let appservice_info = &body.appservice_info;
|
||||
let body = body.body;
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
let (servers, room_id) = match OwnedRoomId::try_from(body.room_id_or_alias) {
|
||||
| Ok(room_id) => {
|
||||
|
@ -380,9 +374,6 @@ pub(crate) async fn knock_room_route(
|
|||
) -> Result<knock_room::v3::Response> {
|
||||
let sender_user = body.sender_user();
|
||||
let body = &body.body;
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
let (servers, room_id) = match OwnedRoomId::try_from(body.room_id_or_alias.clone()) {
|
||||
| Ok(room_id) => {
|
||||
|
@ -507,9 +498,6 @@ pub(crate) async fn invite_user_route(
|
|||
body: Ruma<invite_user::v3::Request>,
|
||||
) -> Result<invite_user::v3::Response> {
|
||||
let sender_user = body.sender_user();
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
if !services.users.is_admin(sender_user).await && services.config.block_non_admin_invites {
|
||||
debug_error!(
|
||||
|
@ -584,10 +572,6 @@ pub(crate) async fn kick_user_route(
|
|||
State(services): State<crate::State>,
|
||||
body: Ruma<kick_user::v3::Request>,
|
||||
) -> Result<kick_user::v3::Response> {
|
||||
let sender_user = body.sender_user();
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
||||
|
||||
let Ok(event) = services
|
||||
|
@ -623,7 +607,7 @@ pub(crate) async fn kick_user_route(
|
|||
third_party_invite: None,
|
||||
..event
|
||||
}),
|
||||
sender_user,
|
||||
body.sender_user(),
|
||||
&body.room_id,
|
||||
&state_lock,
|
||||
)
|
||||
|
@ -647,10 +631,6 @@ pub(crate) async fn ban_user_route(
|
|||
return Err!(Request(Forbidden("You cannot ban yourself.")));
|
||||
}
|
||||
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
||||
|
||||
let current_member_content = services
|
||||
|
@ -672,7 +652,6 @@ pub(crate) async fn ban_user_route(
|
|||
is_direct: None,
|
||||
join_authorized_via_users_server: None,
|
||||
third_party_invite: None,
|
||||
redact_events: body.redact_events,
|
||||
..current_member_content
|
||||
}),
|
||||
sender_user,
|
||||
|
@ -693,10 +672,6 @@ pub(crate) async fn unban_user_route(
|
|||
State(services): State<crate::State>,
|
||||
body: Ruma<unban_user::v3::Request>,
|
||||
) -> Result<unban_user::v3::Response> {
|
||||
let sender_user = body.sender_user();
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
||||
|
||||
let current_member_content = services
|
||||
|
@ -725,7 +700,7 @@ pub(crate) async fn unban_user_route(
|
|||
is_direct: None,
|
||||
..current_member_content
|
||||
}),
|
||||
sender_user,
|
||||
body.sender_user(),
|
||||
&body.room_id,
|
||||
&state_lock,
|
||||
)
|
||||
|
@ -956,32 +931,24 @@ pub async fn join_room_by_id_helper(
|
|||
return Ok(join_room_by_id::v3::Response { room_id: room_id.into() });
|
||||
}
|
||||
|
||||
if let Ok(membership) = services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_member(room_id, sender_user)
|
||||
.await
|
||||
{
|
||||
if membership.membership == MembershipState::Ban {
|
||||
debug_warn!("{sender_user} is banned from {room_id} but attempted to join");
|
||||
return Err!(Request(Forbidden("You are banned from the room.")));
|
||||
}
|
||||
}
|
||||
|
||||
let server_in_room = services
|
||||
.rooms
|
||||
.state_cache
|
||||
.server_in_room(services.globals.server_name(), room_id)
|
||||
.await;
|
||||
|
||||
// Only check our known membership if we're already in the room.
|
||||
// See: https://forgejo.ellis.link/continuwuation/continuwuity/issues/855
|
||||
let membership = if server_in_room {
|
||||
services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.get_member(room_id, sender_user)
|
||||
.await
|
||||
} else {
|
||||
debug!("Ignoring local state for join {room_id}, we aren't in the room yet.");
|
||||
Ok(RoomMemberEventContent::new(MembershipState::Leave))
|
||||
};
|
||||
if let Ok(m) = membership {
|
||||
if m.membership == MembershipState::Ban {
|
||||
debug_warn!("{sender_user} is banned from {room_id} but attempted to join");
|
||||
// TODO: return reason
|
||||
return Err!(Request(Forbidden("You are banned from the room.")));
|
||||
}
|
||||
}
|
||||
|
||||
let local_join = server_in_room
|
||||
|| servers.is_empty()
|
||||
|| (servers.len() == 1 && services.globals.server_is_ours(&servers[0]));
|
||||
|
@ -1858,7 +1825,6 @@ pub async fn leave_room(
|
|||
displayname: None,
|
||||
third_party_invite: None,
|
||||
blurhash: None,
|
||||
redact_events: None,
|
||||
};
|
||||
|
||||
let is_banned = services.rooms.metadata.is_banned(room_id);
|
||||
|
|
|
@ -36,9 +36,6 @@ pub(crate) async fn set_displayname_route(
|
|||
body: Ruma<set_display_name::v3::Request>,
|
||||
) -> Result<set_display_name::v3::Response> {
|
||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
||||
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
||||
|
@ -128,9 +125,6 @@ pub(crate) async fn set_avatar_url_route(
|
|||
body: Ruma<set_avatar_url::v3::Request>,
|
||||
) -> Result<set_avatar_url::v3::Response> {
|
||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
||||
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
||||
|
@ -349,7 +343,6 @@ pub async fn update_displayname(
|
|||
reason: None,
|
||||
is_direct: None,
|
||||
third_party_invite: None,
|
||||
redact_events: None,
|
||||
});
|
||||
|
||||
Ok((pdu, room_id))
|
||||
|
@ -403,7 +396,6 @@ pub async fn update_avatar_url(
|
|||
reason: None,
|
||||
is_direct: None,
|
||||
third_party_invite: None,
|
||||
redact_events: None,
|
||||
});
|
||||
|
||||
Ok((pdu, room_id))
|
||||
|
|
|
@ -58,34 +58,29 @@ pub(crate) async fn set_read_marker_route(
|
|||
}
|
||||
|
||||
if let Some(event) = &body.read_receipt {
|
||||
if !services.users.is_suspended(sender_user).await? {
|
||||
let receipt_content = BTreeMap::from_iter([(
|
||||
event.to_owned(),
|
||||
BTreeMap::from_iter([(
|
||||
ReceiptType::Read,
|
||||
BTreeMap::from_iter([(
|
||||
sender_user.to_owned(),
|
||||
ruma::events::receipt::Receipt {
|
||||
ts: Some(MilliSecondsSinceUnixEpoch::now()),
|
||||
thread: ReceiptThread::Unthreaded,
|
||||
},
|
||||
)]),
|
||||
)]),
|
||||
)]);
|
||||
let receipt_content = BTreeMap::from_iter([(
|
||||
event.to_owned(),
|
||||
BTreeMap::from_iter([(
|
||||
ReceiptType::Read,
|
||||
BTreeMap::from_iter([(sender_user.to_owned(), ruma::events::receipt::Receipt {
|
||||
ts: Some(MilliSecondsSinceUnixEpoch::now()),
|
||||
thread: ReceiptThread::Unthreaded,
|
||||
})]),
|
||||
)]),
|
||||
)]);
|
||||
|
||||
services
|
||||
.rooms
|
||||
.read_receipt
|
||||
.readreceipt_update(
|
||||
sender_user,
|
||||
&body.room_id,
|
||||
&ruma::events::receipt::ReceiptEvent {
|
||||
content: ruma::events::receipt::ReceiptEventContent(receipt_content),
|
||||
room_id: body.room_id.clone(),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
}
|
||||
services
|
||||
.rooms
|
||||
.read_receipt
|
||||
.readreceipt_update(
|
||||
sender_user,
|
||||
&body.room_id,
|
||||
&ruma::events::receipt::ReceiptEvent {
|
||||
content: ruma::events::receipt::ReceiptEventContent(receipt_content),
|
||||
room_id: body.room_id.clone(),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
if let Some(event) = &body.private_read_receipt {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use axum::extract::State;
|
||||
use conduwuit::{Err, Result, matrix::pdu::PduBuilder};
|
||||
use conduwuit::{Result, matrix::pdu::PduBuilder};
|
||||
use ruma::{
|
||||
api::client::redact::redact_event, events::room::redaction::RoomRedactionEventContent,
|
||||
};
|
||||
|
@ -17,10 +17,6 @@ pub(crate) async fn redact_event_route(
|
|||
) -> Result<redact_event::v3::Response> {
|
||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||
let body = body.body;
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
// TODO: Users can redact their own messages while suspended
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
||||
|
||||
|
|
|
@ -70,10 +70,6 @@ pub(crate) async fn create_room_route(
|
|||
));
|
||||
}
|
||||
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
let room_id: OwnedRoomId = match &body.room_id {
|
||||
| Some(custom_room_id) => custom_room_id_check(&services, custom_room_id)?,
|
||||
| _ => RoomId::new(&services.server.name),
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::cmp::max;
|
|||
|
||||
use axum::extract::State;
|
||||
use conduwuit::{
|
||||
Err, Error, Result, err, info,
|
||||
Error, Result, err, info,
|
||||
matrix::{StateKey, pdu::PduBuilder},
|
||||
};
|
||||
use futures::StreamExt;
|
||||
|
@ -63,10 +63,6 @@ pub(crate) async fn upgrade_room_route(
|
|||
));
|
||||
}
|
||||
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
// Create a replacement room
|
||||
let replacement_room = RoomId::new(services.globals.server_name());
|
||||
|
||||
|
@ -193,7 +189,6 @@ pub(crate) async fn upgrade_room_route(
|
|||
blurhash: services.users.blurhash(sender_user).await.ok(),
|
||||
reason: None,
|
||||
join_authorized_via_users_server: None,
|
||||
redact_events: None,
|
||||
})
|
||||
.expect("event is valid, we just created it"),
|
||||
unsigned: None,
|
||||
|
|
|
@ -23,9 +23,6 @@ pub(crate) async fn send_message_event_route(
|
|||
let sender_user = body.sender_user();
|
||||
let sender_device = body.sender_device.as_deref();
|
||||
let appservice_info = body.appservice_info.as_ref();
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
// Forbid m.room.encrypted if encryption is disabled
|
||||
if MessageLikeEventType::RoomEncrypted == body.event_type && !services.config.allow_encryption
|
||||
|
|
|
@ -34,10 +34,6 @@ pub(crate) async fn send_state_event_for_key_route(
|
|||
) -> Result<send_state_event::v3::Response> {
|
||||
let sender_user = body.sender_user();
|
||||
|
||||
if services.users.is_suspended(sender_user).await? {
|
||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||
}
|
||||
|
||||
Ok(send_state_event::v3::Response {
|
||||
event_id: send_state_event_for_key_helper(
|
||||
&services,
|
||||
|
|
|
@ -26,42 +26,41 @@ pub(crate) async fn create_typing_event_route(
|
|||
{
|
||||
return Err!(Request(Forbidden("You are not in this room.")));
|
||||
}
|
||||
if !services.users.is_suspended(sender_user).await? {
|
||||
match body.state {
|
||||
| Typing::Yes(duration) => {
|
||||
let duration = utils::clamp(
|
||||
duration.as_millis().try_into().unwrap_or(u64::MAX),
|
||||
services
|
||||
.server
|
||||
.config
|
||||
.typing_client_timeout_min_s
|
||||
.try_mul(1000)?,
|
||||
services
|
||||
.server
|
||||
.config
|
||||
.typing_client_timeout_max_s
|
||||
.try_mul(1000)?,
|
||||
);
|
||||
|
||||
match body.state {
|
||||
| Typing::Yes(duration) => {
|
||||
let duration = utils::clamp(
|
||||
duration.as_millis().try_into().unwrap_or(u64::MAX),
|
||||
services
|
||||
.rooms
|
||||
.typing
|
||||
.typing_add(
|
||||
sender_user,
|
||||
&body.room_id,
|
||||
utils::millis_since_unix_epoch()
|
||||
.checked_add(duration)
|
||||
.expect("user typing timeout should not get this high"),
|
||||
)
|
||||
.await?;
|
||||
},
|
||||
| _ => {
|
||||
.server
|
||||
.config
|
||||
.typing_client_timeout_min_s
|
||||
.try_mul(1000)?,
|
||||
services
|
||||
.rooms
|
||||
.typing
|
||||
.typing_remove(sender_user, &body.room_id)
|
||||
.await?;
|
||||
},
|
||||
}
|
||||
.server
|
||||
.config
|
||||
.typing_client_timeout_max_s
|
||||
.try_mul(1000)?,
|
||||
);
|
||||
services
|
||||
.rooms
|
||||
.typing
|
||||
.typing_add(
|
||||
sender_user,
|
||||
&body.room_id,
|
||||
utils::millis_since_unix_epoch()
|
||||
.checked_add(duration)
|
||||
.expect("user typing timeout should not get this high"),
|
||||
)
|
||||
.await?;
|
||||
},
|
||||
| _ => {
|
||||
services
|
||||
.rooms
|
||||
.typing
|
||||
.typing_remove(sender_user, &body.room_id)
|
||||
.await?;
|
||||
},
|
||||
}
|
||||
|
||||
// ping presence
|
||||
|
|
|
@ -378,10 +378,6 @@ pub(super) static MAPS: &[Descriptor] = &[
|
|||
name: "userid_password",
|
||||
..descriptor::RANDOM
|
||||
},
|
||||
Descriptor {
|
||||
name: "userid_suspension",
|
||||
..descriptor::RANDOM_SMALL
|
||||
},
|
||||
Descriptor {
|
||||
name: "userid_presenceid",
|
||||
..descriptor::RANDOM_SMALL
|
||||
|
|
|
@ -44,13 +44,11 @@ struct Services {
|
|||
services: StdRwLock<Option<Weak<crate::Services>>>,
|
||||
}
|
||||
|
||||
/// Inputs to a command are a multi-line string, optional reply_id, and optional
|
||||
/// sender.
|
||||
/// Inputs to a command are a multi-line string and optional reply_id.
|
||||
#[derive(Debug)]
|
||||
pub struct CommandInput {
|
||||
pub command: String,
|
||||
pub reply_id: Option<OwnedEventId>,
|
||||
pub sender: Option<Box<UserId>>,
|
||||
}
|
||||
|
||||
/// Prototype of the tab-completer. The input is buffered text when tab
|
||||
|
@ -163,22 +161,7 @@ impl Service {
|
|||
pub fn command(&self, command: String, reply_id: Option<OwnedEventId>) -> Result<()> {
|
||||
self.channel
|
||||
.0
|
||||
.send(CommandInput { command, reply_id, sender: None })
|
||||
.map_err(|e| err!("Failed to enqueue admin command: {e:?}"))
|
||||
}
|
||||
|
||||
/// Posts a command to the command processor queue with sender information
|
||||
/// and returns. Processing will take place on the service worker's task
|
||||
/// asynchronously. Errors if the queue is full.
|
||||
pub fn command_with_sender(
|
||||
&self,
|
||||
command: String,
|
||||
reply_id: Option<OwnedEventId>,
|
||||
sender: Box<UserId>,
|
||||
) -> Result<()> {
|
||||
self.channel
|
||||
.0
|
||||
.send(CommandInput { command, reply_id, sender: Some(sender) })
|
||||
.send(CommandInput { command, reply_id })
|
||||
.map_err(|e| err!("Failed to enqueue admin command: {e:?}"))
|
||||
}
|
||||
|
||||
|
@ -189,7 +172,7 @@ impl Service {
|
|||
command: String,
|
||||
reply_id: Option<OwnedEventId>,
|
||||
) -> ProcessorResult {
|
||||
self.process_command(CommandInput { command, reply_id, sender: None })
|
||||
self.process_command(CommandInput { command, reply_id })
|
||||
.await
|
||||
}
|
||||
|
||||
|
|
|
@ -532,11 +532,9 @@ impl Service {
|
|||
self.services.search.index_pdu(shortroomid, &pdu_id, &body);
|
||||
|
||||
if self.services.admin.is_admin_command(pdu, &body).await {
|
||||
self.services.admin.command_with_sender(
|
||||
body,
|
||||
Some((*pdu.event_id).into()),
|
||||
pdu.sender.clone().into(),
|
||||
)?;
|
||||
self.services
|
||||
.admin
|
||||
.command(body, Some((*pdu.event_id).into()))?;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -16,21 +16,10 @@ use ruma::{
|
|||
},
|
||||
serde::Raw,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{Dep, account_data, admin, globals, rooms};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct UserSuspension {
|
||||
/// Whether the user is currently suspended
|
||||
pub suspended: bool,
|
||||
/// When the user was suspended (Unix timestamp in milliseconds)
|
||||
pub suspended_at: u64,
|
||||
/// User ID of who suspended this user
|
||||
pub suspended_by: String,
|
||||
}
|
||||
|
||||
pub struct Service {
|
||||
services: Services,
|
||||
db: Data,
|
||||
|
@ -63,7 +52,6 @@ struct Data {
|
|||
userid_lastonetimekeyupdate: Arc<Map>,
|
||||
userid_masterkeyid: Arc<Map>,
|
||||
userid_password: Arc<Map>,
|
||||
userid_suspension: Arc<Map>,
|
||||
userid_selfsigningkeyid: Arc<Map>,
|
||||
userid_usersigningkeyid: Arc<Map>,
|
||||
useridprofilekey_value: Arc<Map>,
|
||||
|
@ -99,7 +87,6 @@ impl crate::Service for Service {
|
|||
userid_lastonetimekeyupdate: args.db["userid_lastonetimekeyupdate"].clone(),
|
||||
userid_masterkeyid: args.db["userid_masterkeyid"].clone(),
|
||||
userid_password: args.db["userid_password"].clone(),
|
||||
userid_suspension: args.db["userid_suspension"].clone(),
|
||||
userid_selfsigningkeyid: args.db["userid_selfsigningkeyid"].clone(),
|
||||
userid_usersigningkeyid: args.db["userid_usersigningkeyid"].clone(),
|
||||
useridprofilekey_value: args.db["useridprofilekey_value"].clone(),
|
||||
|
@ -156,23 +143,6 @@ impl Service {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Suspend account, placing it in a read-only state
|
||||
pub async fn suspend_account(&self, user_id: &UserId, suspending_user: &UserId) {
|
||||
self.db.userid_suspension.raw_put(
|
||||
user_id,
|
||||
Json(UserSuspension {
|
||||
suspended: true,
|
||||
suspended_at: MilliSecondsSinceUnixEpoch::now().get().into(),
|
||||
suspended_by: suspending_user.to_string(),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/// Unsuspend account, placing it in a read-write state
|
||||
pub async fn unsuspend_account(&self, user_id: &UserId) {
|
||||
self.db.userid_suspension.remove(user_id);
|
||||
}
|
||||
|
||||
/// Check if a user has an account on this homeserver.
|
||||
#[inline]
|
||||
pub async fn exists(&self, user_id: &UserId) -> bool {
|
||||
|
@ -189,25 +159,6 @@ impl Service {
|
|||
.await
|
||||
}
|
||||
|
||||
/// Check if account is suspended
|
||||
pub async fn is_suspended(&self, user_id: &UserId) -> Result<bool> {
|
||||
match self
|
||||
.db
|
||||
.userid_suspension
|
||||
.get(user_id)
|
||||
.await
|
||||
.deserialized::<UserSuspension>()
|
||||
{
|
||||
| Ok(s) => Ok(s.suspended),
|
||||
| Err(e) =>
|
||||
if e.is_not_found() {
|
||||
Ok(false)
|
||||
} else {
|
||||
Err(e)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if account is active, infallible
|
||||
pub async fn is_active(&self, user_id: &UserId) -> bool {
|
||||
!self.is_deactivated(user_id).await.unwrap_or(true)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue