1
0
Fork 0
mirror of https://gitlab.com/famedly/conduit.git synced 2025-04-22 14:10:16 +03:00

Merge branch 'registration-default-rooms' into 'next'

Join-by-default rooms on registration

See merge request 
This commit is contained in:
avdb 2024-11-16 13:11:46 +00:00
commit 65196f560b
5 changed files with 79 additions and 6 deletions
docs
src
api/client_server
config
service/globals

View file

@ -45,6 +45,8 @@ The `global` section contains the following fields:
| `allow_federation` | `boolean` | Allow federation with other servers | `true` |
| `allow_room_creation` | `boolean` | Allow users to create rooms | `true` |
| `allow_unstable_room_versions` | `boolean` | Allow users to create and join rooms with unstable versions | `true` |
| `default_rooms` | `array` | The list of rooms that will be joined by default on registration | [] |
| `default_rooms_join_reason` | `string` | The reason for joining the rooms | "Hello from Conduit!" |
| `default_room_version` | `string` | The default room version (`"6"`-`"10"`)| `"10"` |
| `allow_jaeger` | `boolean` | Allow Jaeger tracing | `false` |
| `tracing_flame` | `boolean` | Enable flame tracing | `false` |
@ -111,3 +113,14 @@ exclude = ["*.clearnet.onion"]
[global]
{{#include ../conduit-example.toml:22:}}
```
### Default rooms
This list should contain either room identifiers or aliases.
Opaque identifiers will be interpreted as incomplete, local aliases.
#### Example
In this example, the opaque identifier and alias are the same:
```toml
default_rooms = ["home", "#home:conduit.rs"]
```

View file

@ -1,5 +1,8 @@
use super::{DEVICE_ID_LENGTH, SESSION_ID_LENGTH, TOKEN_LENGTH};
use crate::{api::client_server, services, utils, Error, Result, Ruma};
use crate::{
api::client_server::{self, membership::join_room_by_id_helper},
services, utils, Error, Result, Ruma,
};
use ruma::{
api::client::{
account::{
@ -287,6 +290,26 @@ pub async fn register_route(body: Ruma<register::v3::Request>) -> Result<registe
warn!("Granting {} admin privileges as the first user", user_id);
}
}
let default_rooms = services().globals.default_rooms().await?;
let servers: Vec<_> = default_rooms
.iter()
.filter_map(|r| r.server_name().map(ToOwned::to_owned))
.collect();
for room_id in &default_rooms {
if let Err(e) = join_room_by_id_helper(
Some(&user_id),
room_id,
services().globals.config.default_rooms.join_reason.clone(),
&servers,
None,
)
.await
{
warn!("Failed to join default room: {}", e);
}
}
}
Ok(register::v3::Response {

View file

@ -518,7 +518,7 @@ pub async fn joined_members_route(
Ok(joined_members::v3::Response { joined })
}
async fn join_room_by_id_helper(
pub async fn join_room_by_id_helper(
sender_user: Option<&UserId>,
room_id: &RoomId,
reason: Option<String>,

View file

@ -61,6 +61,8 @@ pub struct Config {
pub default_room_version: RoomVersionId,
#[serde(default)]
pub well_known: WellKnownConfig,
#[serde(default)]
pub default_rooms: DefaultRoomsConfig,
#[serde(default = "false_fn")]
pub allow_jaeger: bool,
#[serde(default = "false_fn")]
@ -101,6 +103,13 @@ pub struct WellKnownConfig {
pub server: Option<OwnedServerName>,
}
#[derive(Clone, Debug, Deserialize, Default)]
pub struct DefaultRoomsConfig {
#[serde(default = "Vec::new")]
pub rooms: Vec<String>,
pub join_reason: Option<String>,
}
const DEPRECATED_KEYS: &[&str] = &["cache_capacity"];
impl Config {

View file

@ -1,11 +1,12 @@
mod data;
pub use data::{Data, SigningKeys};
use ruma::{
serde::Base64, MilliSecondsSinceUnixEpoch, OwnedDeviceId, OwnedEventId, OwnedRoomAliasId,
OwnedRoomId, OwnedServerName, OwnedUserId, RoomAliasId,
OwnedRoomId, OwnedRoomOrAliasId, OwnedServerName, OwnedUserId, RoomAliasId,
};
use crate::api::server_server::DestinationResponse;
use crate::api::{client_server::get_alias_helper, server_server::DestinationResponse};
use crate::{services, Config, Error, Result};
use futures_util::FutureExt;
@ -17,7 +18,7 @@ use ruma::{
DeviceId, RoomVersionId, ServerName, UserId,
};
use std::{
collections::{BTreeMap, HashMap},
collections::{BTreeMap, BTreeSet, HashMap},
error::Error as StdError,
fs,
future::{self, Future},
@ -33,7 +34,7 @@ use std::{
};
use tokio::sync::{broadcast, watch::Receiver, Mutex, RwLock, Semaphore};
use tower_service::Service as TowerService;
use tracing::{error, info};
use tracing::{error, info, warn};
use base64::{engine::general_purpose, Engine as _};
@ -505,6 +506,33 @@ impl Service {
self.config.well_known_client()
}
pub async fn default_rooms(&self) -> Result<BTreeSet<OwnedRoomId>> {
let server_name = &self.config.server_name;
let f = |s| async move {
match OwnedRoomOrAliasId::from_str(s).map(OwnedRoomId::try_from) {
Ok(Ok(room_id)) => room_id
.server_name()
.ok_or_else(|| Error::bad_config("Invalid room ID due to missing server name."))
.map(|_| room_id.clone()),
result => get_alias_helper(result.map(Result::unwrap_err).or_else(|_| {
format!("#{s}:{server_name}")
.parse()
.map_err(|_| Error::bad_config("Invalid opaque identifier."))
})?)
.await
.map(|response| response.room_id),
}
};
let rooms = self.config.default_rooms.rooms.iter().map(String::as_str);
futures_util::future::try_join_all(rooms.map(f))
.await
.map(Vec::into_iter)
.map(BTreeSet::from_iter)
}
pub fn shutdown(&self) {
self.shutdown.store(true, atomic::Ordering::Relaxed);
// On shutdown