refactor+fix various issues with regs/logins and admin user commands
Signed-off-by: June Clementine Strawberry <june@3.dog>
This commit is contained in:
parent
00cc23b649
commit
af714d5778
11 changed files with 309 additions and 220 deletions
|
@ -21,11 +21,11 @@ use crate::Services;
|
|||
|
||||
/// Create the admin room.
|
||||
///
|
||||
/// Users in this room are considered admins by conduit, and the room can be
|
||||
/// Users in this room are considered admins by conduwuit, and the room can be
|
||||
/// used to issue admin commands by talking to the server user inside it.
|
||||
pub async fn create_admin_room(services: &Services) -> Result<()> {
|
||||
pub async fn create_admin_room(services: &Services) -> Result {
|
||||
let room_id = RoomId::new(services.globals.server_name());
|
||||
let room_version = &services.server.config.default_room_version;
|
||||
let room_version = &services.config.default_room_version;
|
||||
|
||||
let _short_id = services
|
||||
.rooms
|
||||
|
@ -36,14 +36,14 @@ pub async fn create_admin_room(services: &Services) -> Result<()> {
|
|||
let state_lock = services.rooms.state.mutex.lock(&room_id).await;
|
||||
|
||||
// Create a user for the server
|
||||
let server_user = &services.globals.server_user;
|
||||
let server_user = services.globals.server_user.as_ref();
|
||||
services.users.create(server_user, None)?;
|
||||
|
||||
let create_content = {
|
||||
use RoomVersionId::*;
|
||||
match room_version {
|
||||
| V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 =>
|
||||
RoomCreateEventContent::new_v1(server_user.clone()),
|
||||
RoomCreateEventContent::new_v1(server_user.into()),
|
||||
| _ => RoomCreateEventContent::new_v11(),
|
||||
}
|
||||
};
|
||||
|
@ -71,7 +71,7 @@ pub async fn create_admin_room(services: &Services) -> Result<()> {
|
|||
.timeline
|
||||
.build_and_append_pdu(
|
||||
PduBuilder::state(
|
||||
server_user.to_string(),
|
||||
String::from(server_user),
|
||||
&RoomMemberEventContent::new(MembershipState::Join),
|
||||
),
|
||||
server_user,
|
||||
|
@ -81,7 +81,7 @@ pub async fn create_admin_room(services: &Services) -> Result<()> {
|
|||
.await?;
|
||||
|
||||
// 3. Power levels
|
||||
let users = BTreeMap::from_iter([(server_user.clone(), 100.into())]);
|
||||
let users = BTreeMap::from_iter([(server_user.into(), 69420.into())]);
|
||||
|
||||
services
|
||||
.rooms
|
||||
|
@ -140,7 +140,7 @@ pub async fn create_admin_room(services: &Services) -> Result<()> {
|
|||
.await?;
|
||||
|
||||
// 5. Events implied by name and topic
|
||||
let room_name = format!("{} Admin Room", services.globals.server_name());
|
||||
let room_name = format!("{} Admin Room", services.config.server_name);
|
||||
services
|
||||
.rooms
|
||||
.timeline
|
||||
|
@ -157,7 +157,7 @@ pub async fn create_admin_room(services: &Services) -> Result<()> {
|
|||
.timeline
|
||||
.build_and_append_pdu(
|
||||
PduBuilder::state(String::new(), &RoomTopicEventContent {
|
||||
topic: format!("Manage {}", services.globals.server_name()),
|
||||
topic: format!("Manage {} | Run commands prefixed with `!admin` | Run `!admin -h` for help | Documentation: https://conduwuit.puppyirl.gay/", services.config.server_name),
|
||||
}),
|
||||
server_user,
|
||||
&room_id,
|
||||
|
@ -187,7 +187,7 @@ pub async fn create_admin_room(services: &Services) -> Result<()> {
|
|||
.alias
|
||||
.set_alias(alias, &room_id, server_user)?;
|
||||
|
||||
// 7. (ad-hoc) Disable room previews for everyone by default
|
||||
// 7. (ad-hoc) Disable room URL previews for everyone by default
|
||||
services
|
||||
.rooms
|
||||
.timeline
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use conduwuit::{Result, error, implement};
|
||||
use conduwuit::{Err, Result, debug_info, debug_warn, error, implement};
|
||||
use ruma::{
|
||||
RoomId, UserId,
|
||||
events::{
|
||||
RoomAccountDataEventType,
|
||||
RoomAccountDataEventType, StateEventType,
|
||||
room::{
|
||||
member::{MembershipState, RoomMemberEventContent},
|
||||
message::RoomMessageEventContent,
|
||||
|
@ -20,55 +20,98 @@ use crate::pdu::PduBuilder;
|
|||
///
|
||||
/// This is equivalent to granting server admin privileges.
|
||||
#[implement(super::Service)]
|
||||
pub async fn make_user_admin(&self, user_id: &UserId) -> Result<()> {
|
||||
pub async fn make_user_admin(&self, user_id: &UserId) -> Result {
|
||||
let Ok(room_id) = self.get_admin_room().await else {
|
||||
debug_warn!(
|
||||
"make_user_admin was called without an admin room being available or created"
|
||||
);
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let state_lock = self.services.state.mutex.lock(&room_id).await;
|
||||
|
||||
if self.services.state_cache.is_joined(user_id, &room_id).await {
|
||||
return Err!(debug_warn!("User is already joined in the admin room"));
|
||||
}
|
||||
if self
|
||||
.services
|
||||
.state_cache
|
||||
.is_invited(user_id, &room_id)
|
||||
.await
|
||||
{
|
||||
return Err!(debug_warn!("User is already pending an invitation to the admin room"));
|
||||
}
|
||||
|
||||
// Use the server user to grant the new admin's power level
|
||||
let server_user = &self.services.globals.server_user;
|
||||
let server_user = self.services.globals.server_user.as_ref();
|
||||
|
||||
// Invite and join the real user
|
||||
self.services
|
||||
.timeline
|
||||
.build_and_append_pdu(
|
||||
PduBuilder::state(
|
||||
user_id.to_string(),
|
||||
&RoomMemberEventContent::new(MembershipState::Invite),
|
||||
),
|
||||
server_user,
|
||||
// if this is our local user, just forcefully join them in the room. otherwise,
|
||||
// invite the remote user.
|
||||
if self.services.globals.user_is_local(user_id) {
|
||||
debug_info!("Inviting local user {user_id} to admin room {room_id}");
|
||||
self.services
|
||||
.timeline
|
||||
.build_and_append_pdu(
|
||||
PduBuilder::state(
|
||||
String::from(user_id),
|
||||
&RoomMemberEventContent::new(MembershipState::Invite),
|
||||
),
|
||||
server_user,
|
||||
&room_id,
|
||||
&state_lock,
|
||||
)
|
||||
.await?;
|
||||
|
||||
debug_info!("Force joining local user {user_id} to admin room {room_id}");
|
||||
self.services
|
||||
.timeline
|
||||
.build_and_append_pdu(
|
||||
PduBuilder::state(
|
||||
String::from(user_id),
|
||||
&RoomMemberEventContent::new(MembershipState::Join),
|
||||
),
|
||||
user_id,
|
||||
&room_id,
|
||||
&state_lock,
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
debug_info!("Inviting remote user {user_id} to admin room {room_id}");
|
||||
self.services
|
||||
.timeline
|
||||
.build_and_append_pdu(
|
||||
PduBuilder::state(
|
||||
user_id.to_string(),
|
||||
&RoomMemberEventContent::new(MembershipState::Invite),
|
||||
),
|
||||
server_user,
|
||||
&room_id,
|
||||
&state_lock,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// Set power levels
|
||||
let mut room_power_levels = self
|
||||
.services
|
||||
.state_accessor
|
||||
.room_state_get_content::<RoomPowerLevelsEventContent>(
|
||||
&room_id,
|
||||
&state_lock,
|
||||
&StateEventType::RoomPowerLevels,
|
||||
"",
|
||||
)
|
||||
.await?;
|
||||
self.services
|
||||
.timeline
|
||||
.build_and_append_pdu(
|
||||
PduBuilder::state(
|
||||
user_id.to_string(),
|
||||
&RoomMemberEventContent::new(MembershipState::Join),
|
||||
),
|
||||
user_id,
|
||||
&room_id,
|
||||
&state_lock,
|
||||
)
|
||||
.await?;
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
// Set power level
|
||||
let users = BTreeMap::from_iter([
|
||||
(server_user.clone(), 100.into()),
|
||||
(user_id.to_owned(), 100.into()),
|
||||
]);
|
||||
room_power_levels
|
||||
.users
|
||||
.insert(server_user.into(), 69420.into());
|
||||
room_power_levels.users.insert(user_id.into(), 100.into());
|
||||
|
||||
self.services
|
||||
.timeline
|
||||
.build_and_append_pdu(
|
||||
PduBuilder::state(String::new(), &RoomPowerLevelsEventContent {
|
||||
users,
|
||||
..Default::default()
|
||||
}),
|
||||
PduBuilder::state(String::new(), &room_power_levels),
|
||||
server_user,
|
||||
&room_id,
|
||||
&state_lock,
|
||||
|
@ -76,15 +119,17 @@ pub async fn make_user_admin(&self, user_id: &UserId) -> Result<()> {
|
|||
.await?;
|
||||
|
||||
// Set room tag
|
||||
let room_tag = &self.services.server.config.admin_room_tag;
|
||||
let room_tag = self.services.server.config.admin_room_tag.as_str();
|
||||
if !room_tag.is_empty() {
|
||||
if let Err(e) = self.set_room_tag(&room_id, user_id, room_tag).await {
|
||||
error!(?room_id, ?user_id, ?room_tag, ?e, "Failed to set tag for admin grant");
|
||||
error!(?room_id, ?user_id, ?room_tag, "Failed to set tag for admin grant: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
if self.services.server.config.admin_room_notices {
|
||||
let welcome_message = String::from("## Thank you for trying out conduwuit!\n\nconduwuit is technically a hard fork of Conduit, which is in Beta. The Beta status initially was inherited from Conduit, however overtime this Beta status is rapidly becoming less and less relevant as our codebase significantly diverges more and more. conduwuit is quite stable and very usable as a daily driver and for a low-medium sized homeserver. There is still a lot of more work to be done, but it is in a far better place than the project was in early 2024.\n\nHelpful links:\n> GitHub Repo: https://github.com/girlbossceo/conduwuit\n> Documentation: https://conduwuit.puppyirl.gay/\n> Report issues: https://github.com/girlbossceo/conduwuit/issues\n\nFor a list of available commands, send the following message in this room: `!admin --help`\n\nHere are some rooms you can join (by typing the command into your client) -\n\nconduwuit space: `/join #conduwuit-space:puppygock.gay`\nconduwuit main room (Ask questions and get notified on updates): `/join #conduwuit:puppygock.gay`\nconduwuit offtopic room: `/join #conduwuit-offtopic:puppygock.gay`");
|
||||
let welcome_message = String::from(
|
||||
"## Thank you for trying out conduwuit!\n\nconduwuit is technically a hard fork of Conduit, which is in Beta. The Beta status initially was inherited from Conduit, however overtime this Beta status is rapidly becoming less and less relevant as our codebase significantly diverges more and more. conduwuit is quite stable and very usable as a daily driver and for a low-medium sized homeserver. There is still a lot of more work to be done, but it is in a far better place than the project was in early 2024.\n\nHelpful links:\n> GitHub Repo: https://github.com/girlbossceo/conduwuit\n> Documentation: https://conduwuit.puppyirl.gay/\n> Report issues: https://github.com/girlbossceo/conduwuit/issues\n\nFor a list of available commands, send the following message in this room: `!admin --help`\n\nHere are some rooms you can join (by typing the command into your client) -\n\nconduwuit space: `/join #conduwuit-space:puppygock.gay`\nconduwuit main room (Ask questions and get notified on updates): `/join #conduwuit:puppygock.gay`\nconduwuit offtopic room: `/join #conduwuit-offtopic:puppygock.gay`",
|
||||
);
|
||||
|
||||
// Send welcome message
|
||||
self.services
|
||||
|
@ -102,7 +147,7 @@ pub async fn make_user_admin(&self, user_id: &UserId) -> Result<()> {
|
|||
}
|
||||
|
||||
#[implement(super::Service)]
|
||||
async fn set_room_tag(&self, room_id: &RoomId, user_id: &UserId, tag: &str) -> Result<()> {
|
||||
async fn set_room_tag(&self, room_id: &RoomId, user_id: &UserId, tag: &str) -> Result {
|
||||
let mut event = self
|
||||
.services
|
||||
.account_data
|
||||
|
@ -125,7 +170,5 @@ async fn set_room_tag(&self, room_id: &RoomId, user_id: &UserId, tag: &str) -> R
|
|||
RoomAccountDataEventType::Tag,
|
||||
&serde_json::to_value(event)?,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
.await
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ struct Services {
|
|||
timeline: Dep<rooms::timeline::Service>,
|
||||
state: Dep<rooms::state::Service>,
|
||||
state_cache: Dep<rooms::state_cache::Service>,
|
||||
state_accessor: Dep<rooms::state_accessor::Service>,
|
||||
account_data: Dep<account_data::Service>,
|
||||
services: StdRwLock<Option<Weak<crate::Services>>>,
|
||||
}
|
||||
|
@ -85,6 +86,8 @@ impl crate::Service for Service {
|
|||
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
|
||||
state: args.depend::<rooms::state::Service>("rooms::state"),
|
||||
state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"),
|
||||
state_accessor: args
|
||||
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
|
||||
account_data: args.depend::<account_data::Service>("account_data"),
|
||||
services: None.into(),
|
||||
},
|
||||
|
@ -357,8 +360,8 @@ impl Service {
|
|||
}
|
||||
|
||||
// This will evaluate to false if the emergency password is set up so that
|
||||
// the administrator can execute commands as conduit
|
||||
let emergency_password_set = self.services.globals.emergency_password().is_some();
|
||||
// the administrator can execute commands as the server user
|
||||
let emergency_password_set = self.services.server.config.emergency_password.is_some();
|
||||
let from_server = pdu.sender == *server_user && !emergency_password_set;
|
||||
if from_server && self.is_admin_room(&pdu.room_id).await {
|
||||
return false;
|
||||
|
|
|
@ -90,7 +90,7 @@ impl Service {
|
|||
.write()
|
||||
.await
|
||||
.remove(appservice_id)
|
||||
.ok_or(err!("Appservice not found"))?;
|
||||
.ok_or_else(|| err!("Appservice not found"))?;
|
||||
|
||||
// remove the appservice from the database
|
||||
self.db.id_appserviceregistrations.del(appservice_id);
|
||||
|
|
|
@ -9,7 +9,7 @@ use ruma::{
|
|||
push::Ruleset,
|
||||
};
|
||||
|
||||
use crate::{Dep, account_data, globals, users};
|
||||
use crate::{Dep, account_data, config, globals, users};
|
||||
|
||||
pub struct Service {
|
||||
services: Services,
|
||||
|
@ -17,6 +17,7 @@ pub struct Service {
|
|||
|
||||
struct Services {
|
||||
account_data: Dep<account_data::Service>,
|
||||
config: Dep<config::Service>,
|
||||
globals: Dep<globals::Service>,
|
||||
users: Dep<users::Service>,
|
||||
}
|
||||
|
@ -27,6 +28,8 @@ impl crate::Service for Service {
|
|||
Ok(Arc::new(Self {
|
||||
services: Services {
|
||||
account_data: args.depend::<account_data::Service>("account_data"),
|
||||
config: args.depend::<config::Service>("config"),
|
||||
|
||||
globals: args.depend::<globals::Service>("globals"),
|
||||
users: args.depend::<users::Service>("users"),
|
||||
},
|
||||
|
@ -54,9 +57,9 @@ impl Service {
|
|||
|
||||
self.services
|
||||
.users
|
||||
.set_password(server_user, self.services.globals.emergency_password().as_deref())?;
|
||||
.set_password(server_user, self.services.config.emergency_password.as_deref())?;
|
||||
|
||||
let (ruleset, pwd_set) = match self.services.globals.emergency_password() {
|
||||
let (ruleset, pwd_set) = match self.services.config.emergency_password {
|
||||
| Some(_) => (Ruleset::server_default(server_user), true),
|
||||
| None => (Ruleset::new(), false),
|
||||
};
|
||||
|
|
|
@ -153,8 +153,6 @@ impl Service {
|
|||
|
||||
pub fn notification_push_path(&self) -> &String { &self.server.config.notification_push_path }
|
||||
|
||||
pub fn emergency_password(&self) -> &Option<String> { &self.server.config.emergency_password }
|
||||
|
||||
pub fn url_preview_domain_contains_allowlist(&self) -> &Vec<String> {
|
||||
&self.server.config.url_preview_domain_contains_allowlist
|
||||
}
|
||||
|
|
|
@ -363,7 +363,7 @@ impl super::Service {
|
|||
let hostname = hostname.trim_end_matches('.');
|
||||
match self.resolver.resolver.srv_lookup(hostname).await {
|
||||
| Err(e) => Self::handle_resolve_error(&e, hostname)?,
|
||||
| Ok(result) =>
|
||||
| Ok(result) => {
|
||||
return Ok(result.iter().next().map(|result| {
|
||||
FedDest::Named(
|
||||
result.target().to_string().trim_end_matches('.').to_owned(),
|
||||
|
@ -372,7 +372,8 @@ impl super::Service {
|
|||
.try_into()
|
||||
.unwrap_or_else(|_| FedDest::default_port()),
|
||||
)
|
||||
})),
|
||||
}));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue