feat: Suspend new users on registration

This commit is contained in:
nexy7574 2025-07-02 00:41:34 +01:00 committed by Ellis Git
parent 68afb07c27
commit 6e60918584
4 changed files with 57 additions and 1 deletions

View file

@ -398,6 +398,17 @@
# #
#allow_registration = false #allow_registration = false
# If registration is enabled, and this setting is true, new users
# registered after the first admin user will be automatically suspended
# and will require an admin to run `!admin users unsuspend <user_id>`.
#
# Suspended users are still able to read messages, make profile updates,
# leave rooms, and deactivate their account, however cannot send messages,
# invites, or create/join or otherwise modify rooms.
# They are effectively read-only.
#
#suspend_on_register = false
# Enabling this setting opens registration to anyone without restrictions. # Enabling this setting opens registration to anyone without restrictions.
# This makes your server vulnerable to abuse # This makes your server vulnerable to abuse
# #

View file

@ -2,6 +2,7 @@ use std::fmt::Write;
use axum::extract::State; use axum::extract::State;
use axum_client_ip::InsecureClientIp; use axum_client_ip::InsecureClientIp;
use axum_extra::headers::UserAgent;
use conduwuit::{ use conduwuit::{
Err, Error, Result, debug_info, err, error, info, is_equal_to, Err, Error, Result, debug_info, err, error, info, is_equal_to,
matrix::pdu::PduBuilder, matrix::pdu::PduBuilder,
@ -490,6 +491,25 @@ pub(crate) async fn register_route(
{ {
services.admin.make_user_admin(&user_id).await?; services.admin.make_user_admin(&user_id).await?;
warn!("Granting {user_id} admin privileges as the first user"); warn!("Granting {user_id} admin privileges as the first user");
} else if services.config.suspend_on_register {
// This is not an admin, suspend them.
// Note that we can still do auto joins for suspended users
services
.users
.suspend_account(&user_id, &services.globals.server_user)
.await;
// And send an @room notice to the admin room, to prompt admins to review the
// new user and ideally unsuspend them if deemed appropriate.
if services.server.config.admin_room_notices {
services
.admin
.send_loud_message(RoomMessageEventContent::text_plain(format!(
"User {user_id} has been suspended as they are not the first user \
on this server. Please review and unsuspend them if appropriate."
)))
.await
.ok();
}
} }
} }
} }

View file

@ -513,6 +513,17 @@ pub struct Config {
#[serde(default)] #[serde(default)]
pub allow_registration: bool, pub allow_registration: bool,
/// If registration is enabled, and this setting is true, new users
/// registered after the first admin user will be automatically suspended
/// and will require an admin to run `!admin users unsuspend <user_id>`.
///
/// Suspended users are still able to read messages, make profile updates,
/// leave rooms, and deactivate their account, however cannot send messages,
/// invites, or create/join or otherwise modify rooms.
/// They are effectively read-only.
#[serde(default)]
pub suspend_on_register: bool,
/// Enabling this setting opens registration to anyone without restrictions. /// Enabling this setting opens registration to anyone without restrictions.
/// This makes your server vulnerable to abuse /// This makes your server vulnerable to abuse
#[serde(default)] #[serde(default)]

View file

@ -18,7 +18,10 @@ use futures::{FutureExt, TryFutureExt};
use loole::{Receiver, Sender}; use loole::{Receiver, Sender};
use ruma::{ use ruma::{
OwnedEventId, OwnedRoomId, RoomId, UserId, OwnedEventId, OwnedRoomId, RoomId, UserId,
events::room::message::{Relation, RoomMessageEventContent}, events::{
Mentions,
room::message::{Relation, RoomMessageEventContent},
},
}; };
use tokio::sync::RwLock; use tokio::sync::RwLock;
@ -158,6 +161,17 @@ impl Service {
.await .await
} }
/// Sends a message, the same as send_message() but with an @room ping to
/// notify all users in the room.
pub async fn send_loud_message(
&self,
mut message_content: RoomMessageEventContent,
) -> Result<()> {
// Add @room ping
message_content = message_content.add_mentions(Mentions::with_room_mention());
self.send_message(message_content).await
}
/// Posts a command to the command processor queue and returns. Processing /// Posts a command to the command processor queue and returns. Processing
/// will take place on the service worker's task asynchronously. Errors if /// will take place on the service worker's task asynchronously. Errors if
/// the queue is full. /// the queue is full.