cleanup+refactor admin room alias and server account accessing to globals
Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
parent
f712c0cefb
commit
8fff7ea706
12 changed files with 77 additions and 101 deletions
|
@ -1,13 +1,12 @@
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
use ruma::{events::room::message::RoomMessageEventContent, RoomAliasId, UserId};
|
use ruma::{events::room::message::RoomMessageEventContent, RoomAliasId};
|
||||||
|
|
||||||
use super::RoomAliasCommand;
|
use super::RoomAliasCommand;
|
||||||
use crate::{escape_html, services, Result};
|
use crate::{escape_html, services, Result};
|
||||||
|
|
||||||
pub(crate) async fn process(command: RoomAliasCommand, _body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
pub(crate) async fn process(command: RoomAliasCommand, _body: Vec<&str>) -> Result<RoomMessageEventContent> {
|
||||||
let server_user = UserId::parse_with_server_name(String::from("conduit"), services().globals.server_name())
|
let server_user = &services().globals.server_user;
|
||||||
.expect("server's username is valid");
|
|
||||||
|
|
||||||
match command {
|
match command {
|
||||||
RoomAliasCommand::Set {
|
RoomAliasCommand::Set {
|
||||||
|
@ -34,7 +33,7 @@ pub(crate) async fn process(command: RoomAliasCommand, _body: Vec<&str>) -> Resu
|
||||||
(true, Ok(Some(id))) => match services()
|
(true, Ok(Some(id))) => match services()
|
||||||
.rooms
|
.rooms
|
||||||
.alias
|
.alias
|
||||||
.set_alias(&room_alias, &room_id, &server_user)
|
.set_alias(&room_alias, &room_id, server_user)
|
||||||
{
|
{
|
||||||
Ok(()) => Ok(RoomMessageEventContent::text_plain(format!(
|
Ok(()) => Ok(RoomMessageEventContent::text_plain(format!(
|
||||||
"Successfully overwrote alias (formerly {id})"
|
"Successfully overwrote alias (formerly {id})"
|
||||||
|
@ -47,7 +46,7 @@ pub(crate) async fn process(command: RoomAliasCommand, _body: Vec<&str>) -> Resu
|
||||||
(_, Ok(None)) => match services()
|
(_, Ok(None)) => match services()
|
||||||
.rooms
|
.rooms
|
||||||
.alias
|
.alias
|
||||||
.set_alias(&room_alias, &room_id, &server_user)
|
.set_alias(&room_alias, &room_id, server_user)
|
||||||
{
|
{
|
||||||
Ok(()) => Ok(RoomMessageEventContent::text_plain("Successfully set alias")),
|
Ok(()) => Ok(RoomMessageEventContent::text_plain("Successfully set alias")),
|
||||||
Err(err) => Ok(RoomMessageEventContent::text_plain(format!("Failed to remove alias: {err}"))),
|
Err(err) => Ok(RoomMessageEventContent::text_plain(format!("Failed to remove alias: {err}"))),
|
||||||
|
@ -60,7 +59,7 @@ pub(crate) async fn process(command: RoomAliasCommand, _body: Vec<&str>) -> Resu
|
||||||
Ok(Some(id)) => match services()
|
Ok(Some(id)) => match services()
|
||||||
.rooms
|
.rooms
|
||||||
.alias
|
.alias
|
||||||
.remove_alias(&room_alias, &server_user)
|
.remove_alias(&room_alias, server_user)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(()) => Ok(RoomMessageEventContent::text_plain(format!("Removed alias from {id}"))),
|
Ok(()) => Ok(RoomMessageEventContent::text_plain(format!("Removed alias from {id}"))),
|
||||||
|
|
|
@ -33,12 +33,10 @@ async fn ban_room(
|
||||||
) -> Result<RoomMessageEventContent> {
|
) -> Result<RoomMessageEventContent> {
|
||||||
debug!("Got room alias or ID: {}", room);
|
debug!("Got room alias or ID: {}", room);
|
||||||
|
|
||||||
let admin_room_alias: Box<RoomAliasId> = format!("#admins:{}", services().globals.server_name())
|
let admin_room_alias = &services().globals.admin_alias;
|
||||||
.try_into()
|
|
||||||
.expect("#admins:server_name is a valid alias name");
|
|
||||||
|
|
||||||
if let Some(admin_room_id) = Service::get_admin_room().await? {
|
if let Some(admin_room_id) = Service::get_admin_room()? {
|
||||||
if room.to_string().eq(&admin_room_id) || room.to_string().eq(&admin_room_alias) {
|
if room.to_string().eq(&admin_room_id) || room.to_string().eq(admin_room_alias) {
|
||||||
return Ok(RoomMessageEventContent::text_plain("Not allowed to ban the admin room."));
|
return Ok(RoomMessageEventContent::text_plain("Not allowed to ban the admin room."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,9 +190,7 @@ async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: boo
|
||||||
|
|
||||||
let rooms_s = body.clone().drain(1..body.len() - 1).collect::<Vec<_>>();
|
let rooms_s = body.clone().drain(1..body.len() - 1).collect::<Vec<_>>();
|
||||||
|
|
||||||
let admin_room_alias: Box<RoomAliasId> = format!("#admins:{}", services().globals.server_name())
|
let admin_room_alias = &services().globals.admin_alias;
|
||||||
.try_into()
|
|
||||||
.expect("#admins:server_name is a valid alias name");
|
|
||||||
|
|
||||||
let mut room_ban_count: usize = 0;
|
let mut room_ban_count: usize = 0;
|
||||||
let mut room_ids: Vec<OwnedRoomId> = Vec::new();
|
let mut room_ids: Vec<OwnedRoomId> = Vec::new();
|
||||||
|
@ -202,8 +198,8 @@ async fn ban_list_of_rooms(body: Vec<&str>, force: bool, disable_federation: boo
|
||||||
for &room in &rooms_s {
|
for &room in &rooms_s {
|
||||||
match <&RoomOrAliasId>::try_from(room) {
|
match <&RoomOrAliasId>::try_from(room) {
|
||||||
Ok(room_alias_or_id) => {
|
Ok(room_alias_or_id) => {
|
||||||
if let Some(admin_room_id) = Service::get_admin_room().await? {
|
if let Some(admin_room_id) = Service::get_admin_room()? {
|
||||||
if room.to_owned().eq(&admin_room_id) || room.to_owned().eq(&admin_room_alias) {
|
if room.to_owned().eq(&admin_room_id) || room.to_owned().eq(admin_room_alias) {
|
||||||
info!("User specified admin room in bulk ban list, ignoring");
|
info!("User specified admin room in bulk ban list, ignoring");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use ruma::{
|
||||||
tag::{TagEvent, TagEventContent, TagInfo},
|
tag::{TagEvent, TagEventContent, TagInfo},
|
||||||
RoomAccountDataEventType,
|
RoomAccountDataEventType,
|
||||||
},
|
},
|
||||||
OwnedRoomId, OwnedUserId, RoomId, UserId,
|
OwnedRoomId, OwnedUserId, RoomId,
|
||||||
};
|
};
|
||||||
use tracing::{error, info, warn};
|
use tracing::{error, info, warn};
|
||||||
|
|
||||||
|
@ -134,9 +134,7 @@ pub(crate) async fn deactivate(
|
||||||
let user_id = parse_local_user_id(&user_id)?;
|
let user_id = parse_local_user_id(&user_id)?;
|
||||||
|
|
||||||
// don't deactivate the server service account
|
// don't deactivate the server service account
|
||||||
if user_id
|
if user_id == services().globals.server_user {
|
||||||
== UserId::parse_with_server_name("conduit", services().globals.server_name()).expect("conduit user exists")
|
|
||||||
{
|
|
||||||
return Ok(RoomMessageEventContent::text_plain(
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
"Not allowed to deactivate the server service account.",
|
"Not allowed to deactivate the server service account.",
|
||||||
));
|
));
|
||||||
|
@ -171,9 +169,7 @@ pub(crate) async fn deactivate(
|
||||||
pub(crate) async fn reset_password(_body: Vec<&str>, username: String) -> Result<RoomMessageEventContent> {
|
pub(crate) async fn reset_password(_body: Vec<&str>, username: String) -> Result<RoomMessageEventContent> {
|
||||||
let user_id = parse_local_user_id(&username)?;
|
let user_id = parse_local_user_id(&username)?;
|
||||||
|
|
||||||
if user_id
|
if user_id == services().globals.server_user {
|
||||||
== UserId::parse_with_server_name("conduit", services().globals.server_name()).expect("conduit user exists")
|
|
||||||
{
|
|
||||||
return Ok(RoomMessageEventContent::text_plain(
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
"Not allowed to set the password for the server account. Please use the emergency password config option.",
|
"Not allowed to set the password for the server account. Please use the emergency password config option.",
|
||||||
));
|
));
|
||||||
|
@ -223,10 +219,7 @@ pub(crate) async fn deactivate_all(
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't deactivate the server service account
|
// don't deactivate the server service account
|
||||||
if user_id
|
if user_id == services().globals.server_user {
|
||||||
== UserId::parse_with_server_name("conduit", services().globals.server_name())
|
|
||||||
.expect("server user exists")
|
|
||||||
{
|
|
||||||
services()
|
services()
|
||||||
.admin
|
.admin
|
||||||
.send_message(RoomMessageEventContent::text_plain(format!(
|
.send_message(RoomMessageEventContent::text_plain(format!(
|
||||||
|
|
|
@ -347,7 +347,7 @@ pub(crate) async fn register_route(
|
||||||
// If this is the first real user, grant them admin privileges except for guest
|
// If this is the first real user, grant them admin privileges except for guest
|
||||||
// users Note: the server user, @conduit:servername, is generated first
|
// users Note: the server user, @conduit:servername, is generated first
|
||||||
if !is_guest {
|
if !is_guest {
|
||||||
if let Some(admin_room) = service::admin::Service::get_admin_room().await? {
|
if let Some(admin_room) = service::admin::Service::get_admin_room()? {
|
||||||
if services()
|
if services()
|
||||||
.rooms
|
.rooms
|
||||||
.state_cache
|
.state_cache
|
||||||
|
|
|
@ -216,7 +216,7 @@ async fn allowed_to_send_state_event(
|
||||||
},
|
},
|
||||||
// admin room is a sensitive room, it should not ever be made public
|
// admin room is a sensitive room, it should not ever be made public
|
||||||
StateEventType::RoomJoinRules => {
|
StateEventType::RoomJoinRules => {
|
||||||
if let Some(admin_room_id) = service::admin::Service::get_admin_room().await? {
|
if let Some(admin_room_id) = service::admin::Service::get_admin_room()? {
|
||||||
if admin_room_id == room_id {
|
if admin_room_id == room_id {
|
||||||
if let Ok(join_rule) = serde_json::from_str::<RoomJoinRulesEventContent>(json.json().get()) {
|
if let Ok(join_rule) = serde_json::from_str::<RoomJoinRulesEventContent>(json.json().get()) {
|
||||||
if join_rule.join_rule == JoinRule::Public {
|
if join_rule.join_rule == JoinRule::Public {
|
||||||
|
@ -231,7 +231,7 @@ async fn allowed_to_send_state_event(
|
||||||
},
|
},
|
||||||
// admin room is a sensitive room, it should not ever be made world readable
|
// admin room is a sensitive room, it should not ever be made world readable
|
||||||
StateEventType::RoomHistoryVisibility => {
|
StateEventType::RoomHistoryVisibility => {
|
||||||
if let Some(admin_room_id) = service::admin::Service::get_admin_room().await? {
|
if let Some(admin_room_id) = service::admin::Service::get_admin_room()? {
|
||||||
if admin_room_id == room_id {
|
if admin_room_id == room_id {
|
||||||
if let Ok(visibility_content) =
|
if let Ok(visibility_content) =
|
||||||
serde_json::from_str::<RoomHistoryVisibilityEventContent>(json.json().get())
|
serde_json::from_str::<RoomHistoryVisibilityEventContent>(json.json().get())
|
||||||
|
|
|
@ -19,7 +19,7 @@ use ruma::{
|
||||||
},
|
},
|
||||||
TimelineEventType,
|
TimelineEventType,
|
||||||
},
|
},
|
||||||
EventId, OwnedRoomAliasId, OwnedRoomId, OwnedUserId, RoomAliasId, RoomId, RoomVersionId, UserId,
|
EventId, OwnedRoomId, OwnedUserId, RoomId, RoomVersionId, UserId,
|
||||||
};
|
};
|
||||||
use serde_json::value::to_raw_value;
|
use serde_json::value::to_raw_value;
|
||||||
use tokio::{sync::Mutex, task::JoinHandle};
|
use tokio::{sync::Mutex, task::JoinHandle};
|
||||||
|
@ -69,18 +69,17 @@ impl Service {
|
||||||
|
|
||||||
async fn handler(self: &Arc<Self>) -> Result<()> {
|
async fn handler(self: &Arc<Self>) -> Result<()> {
|
||||||
let receiver = self.receiver.lock().await;
|
let receiver = self.receiver.lock().await;
|
||||||
let Ok(Some(admin_room)) = Self::get_admin_room().await else {
|
let Ok(Some(admin_room)) = Self::get_admin_room() else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let server_user = UserId::parse_with_server_name(String::from("conduit"), services().globals.server_name())
|
let server_user = &services().globals.server_user;
|
||||||
.expect("server's username is valid");
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
debug_assert!(!receiver.is_closed(), "channel closed");
|
debug_assert!(!receiver.is_closed(), "channel closed");
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
event = receiver.recv_async() => match event {
|
event = receiver.recv_async() => match event {
|
||||||
Ok(event) => self.receive(event, &admin_room, &server_user).await?,
|
Ok(event) => self.receive(event, &admin_room, server_user).await?,
|
||||||
Err(_e) => return Ok(()),
|
Err(_e) => return Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,15 +129,11 @@ impl Service {
|
||||||
///
|
///
|
||||||
/// Errors are propagated from the database, and will have None if there is
|
/// Errors are propagated from the database, and will have None if there is
|
||||||
/// no admin room
|
/// no admin room
|
||||||
pub async fn get_admin_room() -> Result<Option<OwnedRoomId>> {
|
pub fn get_admin_room() -> Result<Option<OwnedRoomId>> {
|
||||||
let admin_room_alias: Box<RoomAliasId> = format!("#admins:{}", services().globals.server_name())
|
|
||||||
.try_into()
|
|
||||||
.expect("#admins:server_name is a valid alias name");
|
|
||||||
|
|
||||||
services()
|
services()
|
||||||
.rooms
|
.rooms
|
||||||
.alias
|
.alias
|
||||||
.resolve_local_alias(&admin_room_alias)
|
.resolve_local_alias(&services().globals.admin_alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create the admin room.
|
/// Create the admin room.
|
||||||
|
@ -162,10 +157,9 @@ impl Service {
|
||||||
let state_lock = mutex_state.lock().await;
|
let state_lock = mutex_state.lock().await;
|
||||||
|
|
||||||
// Create a user for the server
|
// Create a user for the server
|
||||||
let server_user = UserId::parse_with_server_name("conduit", services().globals.server_name())
|
let server_user = &services().globals.server_user;
|
||||||
.expect("@conduit:server_name is valid");
|
|
||||||
|
|
||||||
services().users.create(&server_user, None)?;
|
services().users.create(server_user, None)?;
|
||||||
|
|
||||||
let room_version = services().globals.default_room_version();
|
let room_version = services().globals.default_room_version();
|
||||||
let mut content = match room_version {
|
let mut content = match room_version {
|
||||||
|
@ -205,7 +199,7 @@ impl Service {
|
||||||
state_key: Some(String::new()),
|
state_key: Some(String::new()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
&server_user,
|
server_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
|
@ -233,7 +227,7 @@ impl Service {
|
||||||
state_key: Some(server_user.to_string()),
|
state_key: Some(server_user.to_string()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
&server_user,
|
server_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
|
@ -258,7 +252,7 @@ impl Service {
|
||||||
state_key: Some(String::new()),
|
state_key: Some(String::new()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
&server_user,
|
server_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
|
@ -277,7 +271,7 @@ impl Service {
|
||||||
state_key: Some(String::new()),
|
state_key: Some(String::new()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
&server_user,
|
server_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
|
@ -296,7 +290,7 @@ impl Service {
|
||||||
state_key: Some(String::new()),
|
state_key: Some(String::new()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
&server_user,
|
server_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
|
@ -315,7 +309,7 @@ impl Service {
|
||||||
state_key: Some(String::new()),
|
state_key: Some(String::new()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
&server_user,
|
server_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
|
@ -335,7 +329,7 @@ impl Service {
|
||||||
state_key: Some(String::new()),
|
state_key: Some(String::new()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
&server_user,
|
server_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
|
@ -355,16 +349,14 @@ impl Service {
|
||||||
state_key: Some(String::new()),
|
state_key: Some(String::new()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
&server_user,
|
server_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// 6. Room alias
|
// 6. Room alias
|
||||||
let alias: OwnedRoomAliasId = format!("#admins:{}", services().globals.server_name())
|
let alias = &services().globals.admin_alias;
|
||||||
.try_into()
|
|
||||||
.expect("#admins:server_name is a valid alias name");
|
|
||||||
|
|
||||||
services()
|
services()
|
||||||
.rooms
|
.rooms
|
||||||
|
@ -381,7 +373,7 @@ impl Service {
|
||||||
state_key: Some(String::new()),
|
state_key: Some(String::new()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
&server_user,
|
server_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
|
@ -390,7 +382,7 @@ impl Service {
|
||||||
services()
|
services()
|
||||||
.rooms
|
.rooms
|
||||||
.alias
|
.alias
|
||||||
.set_alias(&alias, &room_id, &server_user)?;
|
.set_alias(alias, &room_id, server_user)?;
|
||||||
|
|
||||||
// 7. (ad-hoc) Disable room previews for everyone by default
|
// 7. (ad-hoc) Disable room previews for everyone by default
|
||||||
services()
|
services()
|
||||||
|
@ -407,7 +399,7 @@ impl Service {
|
||||||
state_key: Some(String::new()),
|
state_key: Some(String::new()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
&server_user,
|
server_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
|
@ -420,7 +412,7 @@ impl Service {
|
||||||
///
|
///
|
||||||
/// In conduit, this is equivalent to granting admin privileges.
|
/// In conduit, this is equivalent to granting admin privileges.
|
||||||
pub async fn make_user_admin(&self, user_id: &UserId, displayname: String) -> Result<()> {
|
pub async fn make_user_admin(&self, user_id: &UserId, displayname: String) -> Result<()> {
|
||||||
if let Some(room_id) = Self::get_admin_room().await? {
|
if let Some(room_id) = Self::get_admin_room()? {
|
||||||
let mutex_state = Arc::clone(
|
let mutex_state = Arc::clone(
|
||||||
services()
|
services()
|
||||||
.globals
|
.globals
|
||||||
|
@ -433,8 +425,7 @@ impl Service {
|
||||||
let state_lock = mutex_state.lock().await;
|
let state_lock = mutex_state.lock().await;
|
||||||
|
|
||||||
// Use the server user to grant the new admin's power level
|
// Use the server user to grant the new admin's power level
|
||||||
let server_user = UserId::parse_with_server_name("conduit", services().globals.server_name())
|
let server_user = &services().globals.server_user;
|
||||||
.expect("@conduit:server_name is valid");
|
|
||||||
|
|
||||||
// Invite and join the real user
|
// Invite and join the real user
|
||||||
services()
|
services()
|
||||||
|
@ -458,7 +449,7 @@ impl Service {
|
||||||
state_key: Some(user_id.to_string()),
|
state_key: Some(user_id.to_string()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
&server_user,
|
server_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
|
@ -510,7 +501,7 @@ impl Service {
|
||||||
state_key: Some(String::new()),
|
state_key: Some(String::new()),
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
&server_user,
|
server_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
|
@ -529,7 +520,7 @@ impl Service {
|
||||||
state_key: None,
|
state_key: None,
|
||||||
redacts: None,
|
redacts: None,
|
||||||
},
|
},
|
||||||
&server_user,
|
server_user,
|
||||||
&room_id,
|
&room_id,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
).await?;
|
).await?;
|
||||||
|
@ -540,7 +531,7 @@ impl Service {
|
||||||
|
|
||||||
/// Checks whether a given user is an admin of this server
|
/// Checks whether a given user is an admin of this server
|
||||||
pub async fn user_is_admin(&self, user_id: &UserId) -> Result<bool> {
|
pub async fn user_is_admin(&self, user_id: &UserId) -> Result<bool> {
|
||||||
let Ok(Some(admin_room)) = Self::get_admin_room().await else {
|
let Ok(Some(admin_room)) = Self::get_admin_room() else {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ use conduit::Result;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
events::{push_rules::PushRulesEventContent, GlobalAccountDataEvent, GlobalAccountDataEventType},
|
events::{push_rules::PushRulesEventContent, GlobalAccountDataEvent, GlobalAccountDataEventType},
|
||||||
push::Ruleset,
|
push::Ruleset,
|
||||||
UserId,
|
|
||||||
};
|
};
|
||||||
use tracing::{error, warn};
|
use tracing::{error, warn};
|
||||||
|
|
||||||
|
@ -18,21 +17,20 @@ pub(crate) fn init_emergency_access() {
|
||||||
/// Sets the emergency password and push rules for the @conduit account in case
|
/// Sets the emergency password and push rules for the @conduit account in case
|
||||||
/// emergency password is set
|
/// emergency password is set
|
||||||
fn set_emergency_access() -> Result<bool> {
|
fn set_emergency_access() -> Result<bool> {
|
||||||
let conduit_user = UserId::parse_with_server_name("conduit", services().globals.server_name())
|
let conduit_user = &services().globals.server_user;
|
||||||
.expect("@conduit:server_name is a valid UserId");
|
|
||||||
|
|
||||||
services()
|
services()
|
||||||
.users
|
.users
|
||||||
.set_password(&conduit_user, services().globals.emergency_password().as_deref())?;
|
.set_password(conduit_user, services().globals.emergency_password().as_deref())?;
|
||||||
|
|
||||||
let (ruleset, pwd_set) = match services().globals.emergency_password() {
|
let (ruleset, pwd_set) = match services().globals.emergency_password() {
|
||||||
Some(_) => (Ruleset::server_default(&conduit_user), true),
|
Some(_) => (Ruleset::server_default(conduit_user), true),
|
||||||
None => (Ruleset::new(), false),
|
None => (Ruleset::new(), false),
|
||||||
};
|
};
|
||||||
|
|
||||||
services().account_data.update(
|
services().account_data.update(
|
||||||
None,
|
None,
|
||||||
&conduit_user,
|
conduit_user,
|
||||||
GlobalAccountDataEventType::PushRules.to_string().into(),
|
GlobalAccountDataEventType::PushRules.to_string().into(),
|
||||||
&serde_json::to_value(&GlobalAccountDataEvent {
|
&serde_json::to_value(&GlobalAccountDataEvent {
|
||||||
content: PushRulesEventContent {
|
content: PushRulesEventContent {
|
||||||
|
|
|
@ -22,10 +22,9 @@ pub(crate) async fn migrations(db: &KeyValueDatabase, config: &Config) -> Result
|
||||||
// Matrix resource ownership is based on the server name; changing it
|
// Matrix resource ownership is based on the server name; changing it
|
||||||
// requires recreating the database from scratch.
|
// requires recreating the database from scratch.
|
||||||
if services().users.count()? > 0 {
|
if services().users.count()? > 0 {
|
||||||
let conduit_user =
|
let conduit_user = &services().globals.server_user;
|
||||||
UserId::parse_with_server_name("conduit", &config.server_name).expect("@conduit:server_name is valid");
|
|
||||||
|
|
||||||
if !services().users.exists(&conduit_user)? {
|
if !services().users.exists(conduit_user)? {
|
||||||
error!("The {} server user does not exist, and the database is not new.", conduit_user);
|
error!("The {} server user does not exist, and the database is not new.", conduit_user);
|
||||||
return Err(Error::bad_database(
|
return Err(Error::bad_database(
|
||||||
"Cannot reuse an existing database after changing the server name, please delete the old one first.",
|
"Cannot reuse an existing database after changing the server name, please delete the old one first.",
|
||||||
|
|
|
@ -24,8 +24,8 @@ use ruma::{
|
||||||
federation::discovery::{ServerSigningKeys, VerifyKey},
|
federation::discovery::{ServerSigningKeys, VerifyKey},
|
||||||
},
|
},
|
||||||
serde::Base64,
|
serde::Base64,
|
||||||
DeviceId, OwnedEventId, OwnedRoomId, OwnedServerName, OwnedServerSigningKeyId, OwnedUserId, RoomVersionId,
|
DeviceId, OwnedEventId, OwnedRoomAliasId, OwnedRoomId, OwnedServerName, OwnedServerSigningKeyId, OwnedUserId,
|
||||||
ServerName, UserId,
|
RoomAliasId, RoomVersionId, ServerName, UserId,
|
||||||
};
|
};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
sync::{Mutex, RwLock},
|
sync::{Mutex, RwLock},
|
||||||
|
@ -58,6 +58,8 @@ pub struct Service {
|
||||||
pub roomid_federationhandletime: RwLock<HashMap<OwnedRoomId, (OwnedEventId, Instant)>>,
|
pub roomid_federationhandletime: RwLock<HashMap<OwnedRoomId, (OwnedEventId, Instant)>>,
|
||||||
pub updates_handle: Mutex<Option<JoinHandle<()>>>,
|
pub updates_handle: Mutex<Option<JoinHandle<()>>>,
|
||||||
pub stateres_mutex: Arc<Mutex<()>>,
|
pub stateres_mutex: Arc<Mutex<()>>,
|
||||||
|
pub server_user: OwnedUserId,
|
||||||
|
pub admin_alias: OwnedRoomAliasId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Service {
|
impl Service {
|
||||||
|
@ -118,6 +120,10 @@ impl Service {
|
||||||
roomid_federationhandletime: RwLock::new(HashMap::new()),
|
roomid_federationhandletime: RwLock::new(HashMap::new()),
|
||||||
updates_handle: Mutex::new(None),
|
updates_handle: Mutex::new(None),
|
||||||
stateres_mutex: Arc::new(Mutex::new(())),
|
stateres_mutex: Arc::new(Mutex::new(())),
|
||||||
|
admin_alias: RoomAliasId::parse(format!("#admins:{}", &config.server_name))
|
||||||
|
.expect("#admins:server_name is valid alias name"),
|
||||||
|
server_user: UserId::parse_with_server_name(String::from("conduit"), &config.server_name)
|
||||||
|
.expect("@conduit:server_name is valid"),
|
||||||
};
|
};
|
||||||
|
|
||||||
fs::create_dir_all(s.get_media_folder())?;
|
fs::create_dir_all(s.get_media_folder())?;
|
||||||
|
|
|
@ -58,8 +58,7 @@ impl Service {
|
||||||
return Err(Error::BadRequest(ErrorKind::NotFound, "Alias not found."));
|
return Err(Error::BadRequest(ErrorKind::NotFound, "Alias not found."));
|
||||||
};
|
};
|
||||||
|
|
||||||
let server_user =
|
let server_user = &services().globals.server_user;
|
||||||
UserId::parse_with_server_name(String::from("conduit"), services().globals.server_name()).unwrap();
|
|
||||||
|
|
||||||
// The creator of an alias can remove it
|
// The creator of an alias can remove it
|
||||||
if self
|
if self
|
||||||
|
|
|
@ -477,24 +477,24 @@ impl Service {
|
||||||
.search
|
.search
|
||||||
.index_pdu(shortroomid, &pdu_id, &body)?;
|
.index_pdu(shortroomid, &pdu_id, &body)?;
|
||||||
|
|
||||||
let server_user = format!("@conduit:{}", services().globals.server_name());
|
let server_user = &services().globals.server_user;
|
||||||
|
|
||||||
let to_conduit = body.starts_with(&format!("{server_user}: "))
|
let to_conduit = body.starts_with(&format!("{server_user}: "))
|
||||||
|| body.starts_with(&format!("{server_user} "))
|
|| body.starts_with(&format!("{server_user} "))
|
||||||
|| body.starts_with("!admin")
|
|| body.starts_with("!admin")
|
||||||
|| body == format!("{server_user}:")
|
|| body == format!("{server_user}:")
|
||||||
|| body == server_user;
|
|| body == *server_user;
|
||||||
|
|
||||||
// This will evaluate to false if the emergency password is set up so that
|
// This will evaluate to false if the emergency password is set up so that
|
||||||
// the administrator can execute commands as conduit
|
// the administrator can execute commands as conduit
|
||||||
let from_conduit = pdu.sender == server_user && services().globals.emergency_password().is_none();
|
let from_conduit = pdu.sender == *server_user && services().globals.emergency_password().is_none();
|
||||||
if let Some(admin_room) = service::admin::Service::get_admin_room().await? {
|
if let Some(admin_room) = service::admin::Service::get_admin_room()? {
|
||||||
if to_conduit
|
if to_conduit
|
||||||
&& !from_conduit && admin_room == pdu.room_id
|
&& !from_conduit && admin_room == pdu.room_id
|
||||||
&& services()
|
&& services()
|
||||||
.rooms
|
.rooms
|
||||||
.state_cache
|
.state_cache
|
||||||
.is_joined(&UserId::parse(server_user).unwrap(), &admin_room)?
|
.is_joined(server_user, &admin_room)?
|
||||||
{
|
{
|
||||||
services()
|
services()
|
||||||
.admin
|
.admin
|
||||||
|
@ -795,7 +795,7 @@ impl Service {
|
||||||
state_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room state mutex
|
state_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room state mutex
|
||||||
) -> Result<Arc<EventId>> {
|
) -> Result<Arc<EventId>> {
|
||||||
let (pdu, pdu_json) = self.create_hash_and_sign_event(pdu_builder, sender, room_id, state_lock)?;
|
let (pdu, pdu_json) = self.create_hash_and_sign_event(pdu_builder, sender, room_id, state_lock)?;
|
||||||
if let Some(admin_room) = service::admin::Service::get_admin_room().await? {
|
if let Some(admin_room) = service::admin::Service::get_admin_room()? {
|
||||||
if admin_room == room_id {
|
if admin_room == room_id {
|
||||||
match pdu.event_type() {
|
match pdu.event_type() {
|
||||||
TimelineEventType::RoomEncryption => {
|
TimelineEventType::RoomEncryption => {
|
||||||
|
@ -810,8 +810,8 @@ impl Service {
|
||||||
.state_key()
|
.state_key()
|
||||||
.filter(|v| v.starts_with('@'))
|
.filter(|v| v.starts_with('@'))
|
||||||
.unwrap_or(sender.as_str());
|
.unwrap_or(sender.as_str());
|
||||||
let server_name = services().globals.server_name();
|
let server_user = &services().globals.server_user.to_string();
|
||||||
let server_user = format!("@conduit:{server_name}");
|
|
||||||
let content = serde_json::from_str::<RoomMemberEventContent>(pdu.content.get())
|
let content = serde_json::from_str::<RoomMemberEventContent>(pdu.content.get())
|
||||||
.map_err(|_| Error::bad_database("Invalid content in pdu."))?;
|
.map_err(|_| Error::bad_database("Invalid content in pdu."))?;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ use data::Data;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{
|
api::client::{
|
||||||
device::Device,
|
device::Device,
|
||||||
error::ErrorKind,
|
|
||||||
filter::FilterDefinition,
|
filter::FilterDefinition,
|
||||||
sync::sync_events::{
|
sync::sync_events::{
|
||||||
self,
|
self,
|
||||||
|
@ -20,10 +19,10 @@ use ruma::{
|
||||||
events::AnyToDeviceEvent,
|
events::AnyToDeviceEvent,
|
||||||
serde::Raw,
|
serde::Raw,
|
||||||
DeviceId, DeviceKeyAlgorithm, DeviceKeyId, OwnedDeviceId, OwnedDeviceKeyId, OwnedMxcUri, OwnedRoomId, OwnedUserId,
|
DeviceId, DeviceKeyAlgorithm, DeviceKeyId, OwnedDeviceId, OwnedDeviceKeyId, OwnedMxcUri, OwnedRoomId, OwnedUserId,
|
||||||
RoomAliasId, UInt, UserId,
|
UInt, UserId,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{services, Error, Result};
|
use crate::{service, services, Error, Result};
|
||||||
|
|
||||||
pub struct SlidingSyncCache {
|
pub struct SlidingSyncCache {
|
||||||
lists: BTreeMap<String, SyncRequestList>,
|
lists: BTreeMap<String, SyncRequestList>,
|
||||||
|
@ -234,18 +233,14 @@ impl Service {
|
||||||
|
|
||||||
/// Check if a user is an admin
|
/// Check if a user is an admin
|
||||||
pub fn is_admin(&self, user_id: &UserId) -> Result<bool> {
|
pub fn is_admin(&self, user_id: &UserId) -> Result<bool> {
|
||||||
let admin_room_alias_id = RoomAliasId::parse(format!("#admins:{}", services().globals.server_name()))
|
if let Some(admin_room_id) = service::admin::Service::get_admin_room()? {
|
||||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid alias."))?;
|
services()
|
||||||
let admin_room_id = services()
|
.rooms
|
||||||
.rooms
|
.state_cache
|
||||||
.alias
|
.is_joined(user_id, &admin_room_id)
|
||||||
.resolve_local_alias(&admin_room_alias_id)?
|
} else {
|
||||||
.unwrap();
|
Ok(false)
|
||||||
|
}
|
||||||
services()
|
|
||||||
.rooms
|
|
||||||
.state_cache
|
|
||||||
.is_joined(user_id, &admin_room_id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new user account on this homeserver.
|
/// Create a new user account on this homeserver.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue