fix: feature gate some guest features in the backend

This commit is contained in:
Evan Carroll 2026-01-19 01:03:46 -06:00
parent 39750c1d82
commit 226c2e02b5
3 changed files with 33 additions and 0 deletions

View file

@ -451,6 +451,13 @@ pub struct User {
pub updated_at: DateTime<Utc>, pub updated_at: DateTime<Utc>,
} }
impl User {
/// Check if this user is a guest (has the Guest tag).
pub fn is_guest(&self) -> bool {
self.tags.contains(&UserTag::Guest)
}
}
/// Minimal user info for display purposes. /// Minimal user info for display purposes.
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserSummary { pub struct UserSummary {

View file

@ -53,6 +53,13 @@ pub async fn assign_slot(
Path(slug): Path<String>, Path(slug): Path<String>,
Json(req): Json<AssignSlotRequest>, Json(req): Json<AssignSlotRequest>,
) -> Result<Json<AvatarWithPaths>, AppError> { ) -> Result<Json<AvatarWithPaths>, AppError> {
// Guests cannot customize their avatar
if user.is_guest() {
return Err(AppError::Forbidden(
"Avatar customization is disabled for guests, please register first.".to_string(),
));
}
req.validate()?; req.validate()?;
let mut conn = rls_conn.acquire().await; let mut conn = rls_conn.acquire().await;
@ -93,6 +100,13 @@ pub async fn clear_slot(
Path(slug): Path<String>, Path(slug): Path<String>,
Json(req): Json<ClearSlotRequest>, Json(req): Json<ClearSlotRequest>,
) -> Result<Json<AvatarWithPaths>, AppError> { ) -> Result<Json<AvatarWithPaths>, AppError> {
// Guests cannot customize their avatar
if user.is_guest() {
return Err(AppError::Forbidden(
"Avatar customization is disabled for guests, please register first.".to_string(),
));
}
req.validate()?; req.validate()?;
let mut conn = rls_conn.acquire().await; let mut conn = rls_conn.acquire().await;

View file

@ -353,6 +353,7 @@ async fn handle_socket(
let _ = channel_state.tx.send(join_msg); let _ = channel_state.tx.send(join_msg);
let user_id = user.id; let user_id = user.id;
let is_guest = user.is_guest();
let tx = channel_state.tx.clone(); let tx = channel_state.tx.clone();
// Acquire a second dedicated connection for the receive task // Acquire a second dedicated connection for the receive task
@ -509,6 +510,17 @@ async fn handle_socket(
// Handle whisper (direct message) vs broadcast // Handle whisper (direct message) vs broadcast
if let Some(target_name) = target_display_name { if let Some(target_name) = target_display_name {
// Check if guest is trying to whisper
if is_guest {
let _ = direct_tx
.send(ServerMessage::Error {
code: "GUEST_FEATURE_DISABLED".to_string(),
message: "Private messaging is disabled for guests, please register first.".to_string(),
})
.await;
continue;
}
// Whisper: send directly to target user // Whisper: send directly to target user
if let Some((_target_user_id, target_conn)) = ws_state if let Some((_target_user_id, target_conn)) = ws_state
.find_user_by_display_name(realm_id, &target_name) .find_user_by_display_name(realm_id, &target_name)