mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2025-07-10 12:26:42 +02:00
Merge branch 'girlbossceo:main' into main
This commit is contained in:
commit
ba3446e4ec
15 changed files with 139 additions and 20 deletions
|
@ -209,7 +209,7 @@ explicit_outlives_requirements = "warn"
|
||||||
# unreachable_pub = "warn"
|
# unreachable_pub = "warn"
|
||||||
unused_extern_crates = "warn"
|
unused_extern_crates = "warn"
|
||||||
unused_import_braces = "warn"
|
unused_import_braces = "warn"
|
||||||
# unused_lifetimes = "warn"
|
unused_lifetimes = "warn"
|
||||||
unused_qualifications = "warn"
|
unused_qualifications = "warn"
|
||||||
dead_code = "warn"
|
dead_code = "warn"
|
||||||
|
|
||||||
|
|
|
@ -248,7 +248,7 @@ server {
|
||||||
|
|
||||||
location /_matrix/ {
|
location /_matrix/ {
|
||||||
# TCP
|
# TCP
|
||||||
proxy_pass http://127.0.0.1:6167$request_uri;
|
proxy_pass http://127.0.0.1:6167;
|
||||||
|
|
||||||
# UNIX socket
|
# UNIX socket
|
||||||
#proxy_pass http://backend;
|
#proxy_pass http://backend;
|
||||||
|
|
|
@ -73,3 +73,4 @@
|
||||||
- Add admin command to delete both the thumbnail and media MXC URLs from an event ID (e.g. from an abuse report)
|
- Add admin command to delete both the thumbnail and media MXC URLs from an event ID (e.g. from an abuse report)
|
||||||
- Add `!admin` as a way to call the Conduit admin bot
|
- Add `!admin` as a way to call the Conduit admin bot
|
||||||
- Add support for listening on multiple TCP ports
|
- Add support for listening on multiple TCP ports
|
||||||
|
- Add admin command to list all the rooms a local user is joined in
|
|
@ -70,7 +70,7 @@ docker run -d -p 8448:6167 \
|
||||||
|
|
||||||
or you can use [docker-compose](#docker-compose).
|
or you can use [docker-compose](#docker-compose).
|
||||||
|
|
||||||
The `-d` flag lets the container run in detached mode. You now need to supply a `conduit.toml` config file, an example can be found [here](../conduit-example.toml).
|
The `-d` flag lets the container run in detached mode. You now need to supply a `conduit.toml` config file, an example can be found [here](../conduwuit-example.toml).
|
||||||
You can pass in different env vars to change config values on the fly. You can even configure Conduit completely by using env vars, but for that you need
|
You can pass in different env vars to change config values on the fly. You can even configure Conduit completely by using env vars, but for that you need
|
||||||
to pass `-e CONDUIT_CONFIG=""` into your container. For an overview of possible values, please take a look at the `docker-compose.yml` file.
|
to pass `-e CONDUIT_CONFIG=""` into your container. For an overview of possible values, please take a look at the `docker-compose.yml` file.
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ So...step by step:
|
||||||
1. Copy [`docker-compose.for-traefik.yml`](docker-compose.for-traefik.yml) (or
|
1. Copy [`docker-compose.for-traefik.yml`](docker-compose.for-traefik.yml) (or
|
||||||
[`docker-compose.with-traefik.yml`](docker-compose.with-traefik.yml)) and [`docker-compose.override.yml`](docker-compose.override.yml) from the repository and remove `.for-traefik` (or `.with-traefik`) from the filename.
|
[`docker-compose.with-traefik.yml`](docker-compose.with-traefik.yml)) and [`docker-compose.override.yml`](docker-compose.override.yml) from the repository and remove `.for-traefik` (or `.with-traefik`) from the filename.
|
||||||
2. Open both files and modify/adjust them to your needs. Meaning, change the `CONDUIT_SERVER_NAME` and the volume host mappings according to your needs.
|
2. Open both files and modify/adjust them to your needs. Meaning, change the `CONDUIT_SERVER_NAME` and the volume host mappings according to your needs.
|
||||||
3. Create the `conduit.toml` config file, an example can be found [here](../conduit-example.toml), or set `CONDUIT_CONFIG=""` and configure Conduit per env vars.
|
3. Create the `conduit.toml` config file, an example can be found [here](../conduwuit-example.toml), or set `CONDUIT_CONFIG=""` and configure Conduit per env vars.
|
||||||
4. Uncomment the `element-web` service if you want to host your own Element Web Client and create a `element_config.json`.
|
4. Uncomment the `element-web` service if you want to host your own Element Web Client and create a `element_config.json`.
|
||||||
5. Create the files needed by the `well-known` service.
|
5. Create the files needed by the `well-known` service.
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@ https://attic.kennel.juneis.dog/conduwuit
|
||||||
conduwuit:lYPVh7o1hLu1idH4Xt2QHaRa49WRGSAqzcfFd94aOTw=
|
conduwuit:lYPVh7o1hLu1idH4Xt2QHaRa49WRGSAqzcfFd94aOTw=
|
||||||
```
|
```
|
||||||
|
|
||||||
You can now use the usual Nix commands to interact with Conduit's flake. For
|
You can now use the usual Nix commands to interact with conduwuit's flake. For
|
||||||
example, `nix run gitlab:famedly/conduit` will run Conduit (though you'll need
|
example, `nix run github:girlbossceo/conduwuit` will run conduwuit (though you'll need
|
||||||
to provide configuration and such manually as usual).
|
to provide configuration and such manually as usual).
|
||||||
|
|
||||||
If your NixOS configuration is defined as a flake, you can depend on this flake
|
If your NixOS configuration is defined as a flake, you can depend on this flake
|
||||||
|
@ -25,7 +25,7 @@ add the following to your `inputs`:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
conduit = {
|
conduit = {
|
||||||
url = "gitlab:famedly/conduit";
|
url = "github:girlbossceo/conduwuit";
|
||||||
|
|
||||||
# Assuming you have an input for nixpkgs called `nixpkgs`. If you experience
|
# Assuming you have an input for nixpkgs called `nixpkgs`. If you experience
|
||||||
# build failures while using this, try commenting/deleting this line. This
|
# build failures while using this, try commenting/deleting this line. This
|
||||||
|
@ -38,7 +38,7 @@ Next, make sure you're passing your flake inputs to the `specialArgs` argument
|
||||||
of `nixpkgs.lib.nixosSystem` [as explained here][specialargs]. This guide will
|
of `nixpkgs.lib.nixosSystem` [as explained here][specialargs]. This guide will
|
||||||
assume you've named the group `flake-inputs`.
|
assume you've named the group `flake-inputs`.
|
||||||
|
|
||||||
Now you can configure Conduit and a reverse proxy for it. Add the following to
|
Now you can configure conduwuit and a reverse proxy for it. Add the following to
|
||||||
a new Nix file and include it in your configuration:
|
a new Nix file and include it in your configuration:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
|
@ -144,7 +144,7 @@ in
|
||||||
];
|
];
|
||||||
|
|
||||||
locations."/_matrix/" = {
|
locations."/_matrix/" = {
|
||||||
proxyPass = "http://backend_conduit$request_uri";
|
proxyPass = "http://backend_conduit";
|
||||||
proxyWebsockets = true;
|
proxyWebsockets = true;
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
|
|
|
@ -1492,6 +1492,9 @@ pub async fn sync_events_v4_route(
|
||||||
|
|
||||||
let mut known_subscription_rooms = BTreeSet::new();
|
let mut known_subscription_rooms = BTreeSet::new();
|
||||||
for (room_id, room) in &body.room_subscriptions {
|
for (room_id, room) in &body.room_subscriptions {
|
||||||
|
if !services().rooms.metadata.exists(room_id)? {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let todo_room = todo_rooms
|
let todo_room = todo_rooms
|
||||||
.entry(room_id.clone())
|
.entry(room_id.clone())
|
||||||
.or_insert((BTreeSet::new(), 0, u64::MAX));
|
.or_insert((BTreeSet::new(), 0, u64::MAX));
|
||||||
|
|
|
@ -1963,6 +1963,13 @@ pub async fn get_devices_route(
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if body.user_id.server_name() != services().globals.server_name() {
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::InvalidParam,
|
||||||
|
"Tried to access user from other server.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let sender_servername = body
|
let sender_servername = body
|
||||||
.sender_servername
|
.sender_servername
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -2044,7 +2051,7 @@ pub async fn get_profile_information_route(
|
||||||
|
|
||||||
if body.user_id.server_name() != services().globals.server_name() {
|
if body.user_id.server_name() != services().globals.server_name() {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::InvalidParam,
|
||||||
"User does not belong to this server",
|
"User does not belong to this server",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -2085,6 +2092,17 @@ pub async fn get_keys_route(body: Ruma<get_keys::v1::Request>) -> Result<get_key
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if body
|
||||||
|
.device_keys
|
||||||
|
.iter()
|
||||||
|
.any(|(u, _)| u.server_name() != services().globals.server_name())
|
||||||
|
{
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::InvalidParam,
|
||||||
|
"User does not belong to this server.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let result = get_keys_helper(
|
let result = get_keys_helper(
|
||||||
None,
|
None,
|
||||||
&body.device_keys,
|
&body.device_keys,
|
||||||
|
@ -2110,6 +2128,17 @@ pub async fn claim_keys_route(
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if body
|
||||||
|
.one_time_keys
|
||||||
|
.iter()
|
||||||
|
.any(|(u, _)| u.server_name() != services().globals.server_name())
|
||||||
|
{
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::InvalidParam,
|
||||||
|
"Tried to access user from other server.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let result = claim_keys_helper(&body.one_time_keys).await?;
|
let result = claim_keys_helper(&body.one_time_keys).await?;
|
||||||
|
|
||||||
Ok(claim_keys::v1::Response {
|
Ok(claim_keys::v1::Response {
|
||||||
|
|
|
@ -190,7 +190,7 @@ impl KvTree for RocksDbEngineTree<'_> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_batch<'a>(&self, iter: &mut dyn Iterator<Item = (Vec<u8>, Vec<u8>)>) -> Result<()> {
|
fn insert_batch(&self, iter: &mut dyn Iterator<Item = (Vec<u8>, Vec<u8>)>) -> Result<()> {
|
||||||
for (key, value) in iter {
|
for (key, value) in iter {
|
||||||
self.db.rocks.put_cf(&self.cf(), key, value)?;
|
self.db.rocks.put_cf(&self.cf(), key, value)?;
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ impl KvTree for RocksDbEngineTree<'_> {
|
||||||
Ok(new)
|
Ok(new)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increment_batch<'a>(&self, iter: &mut dyn Iterator<Item = Vec<u8>>) -> Result<()> {
|
fn increment_batch(&self, iter: &mut dyn Iterator<Item = Vec<u8>>) -> Result<()> {
|
||||||
let lock = self.write_lock.write().unwrap();
|
let lock = self.write_lock.write().unwrap();
|
||||||
|
|
||||||
for key in iter {
|
for key in iter {
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{database::KeyValueDatabase, service, services, utils, Result};
|
||||||
type SearchPdusResult<'a> = Result<Option<(Box<dyn Iterator<Item = Vec<u8>> + 'a>, Vec<String>)>>;
|
type SearchPdusResult<'a> = Result<Option<(Box<dyn Iterator<Item = Vec<u8>> + 'a>, Vec<String>)>>;
|
||||||
|
|
||||||
impl service::rooms::search::Data for KeyValueDatabase {
|
impl service::rooms::search::Data for KeyValueDatabase {
|
||||||
fn index_pdu<'a>(&self, shortroomid: u64, pdu_id: &[u8], message_body: &str) -> Result<()> {
|
fn index_pdu(&self, shortroomid: u64, pdu_id: &[u8], message_body: &str) -> Result<()> {
|
||||||
let mut batch = message_body
|
let mut batch = message_body
|
||||||
.split_terminator(|c: char| !c.is_alphanumeric())
|
.split_terminator(|c: char| !c.is_alphanumeric())
|
||||||
.filter(|s| !s.is_empty())
|
.filter(|s| !s.is_empty())
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl service::rooms::state::Data for KeyValueDatabase {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_forward_extremities<'a>(
|
fn set_forward_extremities(
|
||||||
&self,
|
&self,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
event_ids: Vec<OwnedEventId>,
|
event_ids: Vec<OwnedEventId>,
|
||||||
|
|
|
@ -330,7 +330,7 @@ fn count_to_id(
|
||||||
.rooms
|
.rooms
|
||||||
.short
|
.short
|
||||||
.get_shortroomid(room_id)?
|
.get_shortroomid(room_id)?
|
||||||
.expect("room exists")
|
.ok_or_else(|| Error::bad_database("Looked for bad shortroomid in timeline"))?
|
||||||
.to_be_bytes()
|
.to_be_bytes()
|
||||||
.to_vec();
|
.to_vec();
|
||||||
let mut pdu_id = prefix.clone();
|
let mut pdu_id = prefix.clone();
|
||||||
|
|
|
@ -179,6 +179,9 @@ enum UserCommand {
|
||||||
|
|
||||||
/// - List local users in the database
|
/// - List local users in the database
|
||||||
List,
|
List,
|
||||||
|
|
||||||
|
/// - Lists all the rooms (local and remote) that the specified user is joined in
|
||||||
|
ListJoinedRooms { user_id: Box<UserId> },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(test, derive(Debug))]
|
#[cfg_attr(test, derive(Debug))]
|
||||||
|
@ -1005,6 +1008,52 @@ impl Service {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UserCommand::ListJoinedRooms { user_id } => {
|
||||||
|
if user_id.server_name() != services().globals.server_name() {
|
||||||
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
|
"User does not belong to our server.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut rooms: Vec<(OwnedRoomId, u64, String)> = vec![]; // room ID, members joined, room name
|
||||||
|
|
||||||
|
for room_id in services().rooms.state_cache.rooms_joined(&user_id) {
|
||||||
|
let room_id = room_id?;
|
||||||
|
rooms.push(Self::get_room_info(room_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if rooms.is_empty() {
|
||||||
|
return Ok(RoomMessageEventContent::text_plain(
|
||||||
|
"User is not in any rooms.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
rooms.sort_by_key(|r| r.1);
|
||||||
|
rooms.reverse();
|
||||||
|
|
||||||
|
let output_plain = format!(
|
||||||
|
"Rooms {user_id} Joined:\n{}",
|
||||||
|
rooms
|
||||||
|
.iter()
|
||||||
|
.map(|(id, members, name)| format!(
|
||||||
|
"{id}\tMembers: {members}\tName: {name}"
|
||||||
|
))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
);
|
||||||
|
let output_html = format!(
|
||||||
|
"<table><caption>Rooms {user_id} Joined</caption>\n<tr><th>id</th>\t<th>members</th>\t<th>name</th></tr>\n{}</table>",
|
||||||
|
rooms
|
||||||
|
.iter()
|
||||||
|
.fold(String::new(), |mut output, (id, members, name)| {
|
||||||
|
writeln!(output, "<tr><td>{}</td>\t<td>{}</td>\t<td>{}</td></tr>", escape_html(id.as_ref()),
|
||||||
|
members,
|
||||||
|
escape_html(name)).unwrap();
|
||||||
|
output
|
||||||
|
})
|
||||||
|
);
|
||||||
|
RoomMessageEventContent::text_html(output_plain, output_html)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
AdminCommand::Rooms(command) => match command {
|
AdminCommand::Rooms(command) => match command {
|
||||||
RoomCommand::Moderation(command) => match command {
|
RoomCommand::Moderation(command) => match command {
|
||||||
|
|
|
@ -190,7 +190,22 @@ impl Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors >= 5 {
|
if errors >= 5 {
|
||||||
break;
|
// Timeout other events
|
||||||
|
match services()
|
||||||
|
.globals
|
||||||
|
.bad_event_ratelimiter
|
||||||
|
.write()
|
||||||
|
.unwrap()
|
||||||
|
.entry((*prev_id).to_owned())
|
||||||
|
{
|
||||||
|
hash_map::Entry::Vacant(e) => {
|
||||||
|
e.insert((Instant::now(), 1));
|
||||||
|
}
|
||||||
|
hash_map::Entry::Occupied(mut e) => {
|
||||||
|
*e.get_mut() = (Instant::now(), e.get().1 + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((pdu, json)) = eventid_info.remove(&*prev_id) {
|
if let Some((pdu, json)) = eventid_info.remove(&*prev_id) {
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub struct Service {
|
||||||
|
|
||||||
impl Service {
|
impl Service {
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn index_pdu<'a>(&self, shortroomid: u64, pdu_id: &[u8], message_body: &str) -> Result<()> {
|
pub fn index_pdu(&self, shortroomid: u64, pdu_id: &[u8], message_body: &str) -> Result<()> {
|
||||||
self.db.index_pdu(shortroomid, pdu_id, message_body)
|
self.db.index_pdu(shortroomid, pdu_id, message_body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -224,7 +224,7 @@ impl Service {
|
||||||
///
|
///
|
||||||
/// Returns pdu id
|
/// Returns pdu id
|
||||||
#[tracing::instrument(skip(self, pdu, pdu_json, leaves))]
|
#[tracing::instrument(skip(self, pdu, pdu_json, leaves))]
|
||||||
pub async fn append_pdu<'a>(
|
pub async fn append_pdu(
|
||||||
&self,
|
&self,
|
||||||
pdu: &PduEvent,
|
pdu: &PduEvent,
|
||||||
mut pdu_json: CanonicalJsonObject,
|
mut pdu_json: CanonicalJsonObject,
|
||||||
|
@ -318,6 +318,28 @@ impl Service {
|
||||||
let mut pdu_id = shortroomid.to_be_bytes().to_vec();
|
let mut pdu_id = shortroomid.to_be_bytes().to_vec();
|
||||||
pdu_id.extend_from_slice(&count2.to_be_bytes());
|
pdu_id.extend_from_slice(&count2.to_be_bytes());
|
||||||
|
|
||||||
|
// https://spec.matrix.org/v1.9/rooms/v11/#moving-the-redacts-property-of-mroomredaction-events-to-a-content-property
|
||||||
|
// For backwards-compatibility with older clients,
|
||||||
|
// servers should add a redacts property to the top level of m.room.redaction events in when serving such events over the Client-Server API.
|
||||||
|
if pdu.kind == TimelineEventType::RoomRedaction
|
||||||
|
&& services().rooms.state.get_room_version(&pdu.room_id)? == RoomVersionId::V11
|
||||||
|
{
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Redaction {
|
||||||
|
redacts: Option<OwnedEventId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = serde_json::from_str::<Redaction>(pdu.content.get())
|
||||||
|
.map_err(|_| Error::bad_database("Invalid content in redaction pdu."))?;
|
||||||
|
|
||||||
|
if let Some(redact_id) = &content.redacts {
|
||||||
|
pdu_json.insert(
|
||||||
|
"redacts".to_owned(),
|
||||||
|
CanonicalJsonValue::String(redact_id.to_string()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Insert pdu
|
// Insert pdu
|
||||||
self.db.append_pdu(&pdu_id, pdu, &pdu_json, count2)?;
|
self.db.append_pdu(&pdu_id, pdu, &pdu_json, count2)?;
|
||||||
|
|
||||||
|
@ -1019,7 +1041,7 @@ impl Service {
|
||||||
/// Append the incoming event setting the state snapshot to the state from the
|
/// Append the incoming event setting the state snapshot to the state from the
|
||||||
/// server that sent the event.
|
/// server that sent the event.
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub async fn append_incoming_pdu<'a>(
|
pub async fn append_incoming_pdu(
|
||||||
&self,
|
&self,
|
||||||
pdu: &PduEvent,
|
pdu: &PduEvent,
|
||||||
pdu_json: CanonicalJsonObject,
|
pdu_json: CanonicalJsonObject,
|
||||||
|
|
Loading…
Add table
Reference in a new issue