mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-11-12 19:56:48 +00:00
feat: Add support for MSC4322
This commit is contained in:
7 files changed
+114
-19
No files matched your search
Generated
+11
-11
@@ -4997,7 +4997,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma"
|
||||
version = "0.17.2"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=0ed7fba34213f18a628a56f527c6cc795cd7eef5#0ed7fba34213f18a628a56f527c6cc795cd7eef5"
|
||||
source = "git+https://github.com/gingershaped/ruwuma.git?rev=1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62#1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62"
|
||||
dependencies = [
|
||||
"assign",
|
||||
"js_int",
|
||||
@@ -5016,7 +5016,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-appservice-api"
|
||||
version = "0.17.1"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=0ed7fba34213f18a628a56f527c6cc795cd7eef5#0ed7fba34213f18a628a56f527c6cc795cd7eef5"
|
||||
source = "git+https://github.com/gingershaped/ruwuma.git?rev=1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62#1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62"
|
||||
dependencies = [
|
||||
"http",
|
||||
"js_int",
|
||||
@@ -5029,7 +5029,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-client-api"
|
||||
version = "0.25.2"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=0ed7fba34213f18a628a56f527c6cc795cd7eef5#0ed7fba34213f18a628a56f527c6cc795cd7eef5"
|
||||
source = "git+https://github.com/gingershaped/ruwuma.git?rev=1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62#1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"assign",
|
||||
@@ -5051,7 +5051,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-common"
|
||||
version = "0.20.2"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=0ed7fba34213f18a628a56f527c6cc795cd7eef5#0ed7fba34213f18a628a56f527c6cc795cd7eef5"
|
||||
source = "git+https://github.com/gingershaped/ruwuma.git?rev=1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62#1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"base64 0.23.1",
|
||||
@@ -5084,7 +5084,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-events"
|
||||
version = "0.35.2"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=0ed7fba34213f18a628a56f527c6cc795cd7eef5#0ed7fba34213f18a628a56f527c6cc795cd7eef5"
|
||||
source = "git+https://github.com/gingershaped/ruwuma.git?rev=1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62#1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"indexmap 2.14.2",
|
||||
@@ -5105,7 +5105,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-federation-api"
|
||||
version = "0.16.1"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=0ed7fba34213f18a628a56f527c6cc795cd7eef5#0ed7fba34213f18a628a56f527c6cc795cd7eef5"
|
||||
source = "git+https://github.com/gingershaped/ruwuma.git?rev=1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62#1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
@@ -5127,7 +5127,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-identifiers-validation"
|
||||
version = "0.14.0"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=0ed7fba34213f18a628a56f527c6cc795cd7eef5#0ed7fba34213f18a628a56f527c6cc795cd7eef5"
|
||||
source = "git+https://github.com/gingershaped/ruwuma.git?rev=1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62#1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"thiserror 2.0.21",
|
||||
@@ -5136,7 +5136,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-macros"
|
||||
version = "0.20.2"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=0ed7fba34213f18a628a56f527c6cc795cd7eef5#0ed7fba34213f18a628a56f527c6cc795cd7eef5"
|
||||
source = "git+https://github.com/gingershaped/ruwuma.git?rev=1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62#1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"cfg-if",
|
||||
@@ -5152,7 +5152,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-push-gateway-api"
|
||||
version = "0.16.0"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=0ed7fba34213f18a628a56f527c6cc795cd7eef5#0ed7fba34213f18a628a56f527c6cc795cd7eef5"
|
||||
source = "git+https://github.com/gingershaped/ruwuma.git?rev=1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62#1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
@@ -5164,7 +5164,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-signatures"
|
||||
version = "0.22.1"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=0ed7fba34213f18a628a56f527c6cc795cd7eef5#0ed7fba34213f18a628a56f527c6cc795cd7eef5"
|
||||
source = "git+https://github.com/gingershaped/ruwuma.git?rev=1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62#1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62"
|
||||
dependencies = [
|
||||
"base64 0.23.1",
|
||||
"ed25519-dalek 3.0.0",
|
||||
@@ -5181,7 +5181,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-state-res"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/ruma/ruma.git?rev=0ed7fba34213f18a628a56f527c6cc795cd7eef5#0ed7fba34213f18a628a56f527c6cc795cd7eef5"
|
||||
source = "git+https://github.com/gingershaped/ruwuma.git?rev=1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62#1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
|
||||
+3
-2
@@ -348,8 +348,8 @@ version = "1.1.1"
|
||||
|
||||
# Used for matrix spec type definitions and helpers
|
||||
[workspace.dependencies.ruma]
|
||||
git = "https://github.com/ruma/ruma.git"
|
||||
rev = "0ed7fba34213f18a628a56f527c6cc795cd7eef5"
|
||||
git = "https://github.com/gingershaped/ruwuma.git"
|
||||
rev = "1e2c07dc7b65df9a35d9e3c2cedc13857dae8a62"
|
||||
features = [
|
||||
"appservice-api-c",
|
||||
"client-api",
|
||||
@@ -381,6 +381,7 @@ features = [
|
||||
"unstable-msc4143",
|
||||
"unstable-msc4293",
|
||||
"unstable-msc4363",
|
||||
"unstable-msc4322",
|
||||
"unstable-msc4406",
|
||||
"unstable-msc4439",
|
||||
"unstable-msc4354",
|
||||
|
||||
+22
-1
@@ -18,7 +18,7 @@ use ruma::{
|
||||
get_content, get_content_as_filename, get_content_thumbnail, get_media_config,
|
||||
get_media_preview,
|
||||
},
|
||||
media::create_content,
|
||||
media::{self, create_content},
|
||||
},
|
||||
};
|
||||
use service::media::mxc::Mxc;
|
||||
@@ -238,6 +238,27 @@ pub(crate) async fn get_media_preview_route(
|
||||
})
|
||||
}
|
||||
|
||||
/// # `POST /_matrix/client/unstable/uk.timedout.msc4322/media/redact/{server_name}/{media_id}`
|
||||
pub(crate) async fn unstable_redact_media_route(
|
||||
State(services): State<crate::State>,
|
||||
body: Ruma<media::redact::unstable::Request>,
|
||||
) -> Result<media::redact::unstable::Response> {
|
||||
let user = body.identity.expect_sender_user()?;
|
||||
|
||||
let mxc = Mxc {
|
||||
server_name: &body.server_name,
|
||||
media_id: &body.media_id,
|
||||
};
|
||||
|
||||
if !(services.media.user_owns(user, &mxc).await || services.admin.user_is_admin(user).await) {
|
||||
return Err!(Request(Forbidden("You cannot redact this media.")));
|
||||
}
|
||||
|
||||
services.media.redact(&mxc).await?;
|
||||
|
||||
Ok(media::redact::unstable::Response::new())
|
||||
}
|
||||
|
||||
async fn fetch_thumbnail_meta(
|
||||
services: &Services,
|
||||
mxc: &Mxc<'_>,
|
||||
|
||||
@@ -157,6 +157,7 @@ pub fn build(router: Router<State>, state: State) -> Router<State> {
|
||||
.ruma_route(&client::get_content_as_filename_route)
|
||||
.ruma_route(&client::get_media_preview_route)
|
||||
.ruma_route(&client::get_media_config_route)
|
||||
.ruma_route(&client::unstable_redact_media_route)
|
||||
.ruma_route(&client::get_devices_route)
|
||||
.ruma_route(&client::get_device_route)
|
||||
.ruma_route(&client::update_device_route)
|
||||
|
||||
@@ -38,6 +38,10 @@ pub(crate) async fn get_content_route(
|
||||
content_disposition,
|
||||
);
|
||||
|
||||
services
|
||||
.media
|
||||
.track_remote_download(&body.identity, &body.media_id);
|
||||
|
||||
Ok(get_content::v1::Response::new(
|
||||
ContentMetadata::new(),
|
||||
FileOrLocation::File(content),
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use std::{collections::HashSet, sync::Arc, time::Duration};
|
||||
|
||||
use conduwuit::{
|
||||
Err, Result, debug, debug_info, err,
|
||||
Err, Result, at, debug, debug_info, err,
|
||||
utils::{ReadyExt, str_from_bytes, stream::TryIgnore, string_from_bytes},
|
||||
};
|
||||
use database::{Database, Interfix, Map};
|
||||
use futures::StreamExt;
|
||||
use ruma::{OwnedMxcUri, OwnedUserId, UserId, http_headers::ContentDisposition};
|
||||
use ruma::{
|
||||
OwnedMxcUri, OwnedServerName, OwnedUserId, ServerName, UserId,
|
||||
http_headers::ContentDisposition,
|
||||
};
|
||||
|
||||
use super::{preview::UrlPreviewData, thumbnail::Dim};
|
||||
use crate::media::mxc::Mxc;
|
||||
@@ -15,6 +18,8 @@ pub(crate) struct Data {
|
||||
mediaid_file: Arc<Map>,
|
||||
mediaid_user: Arc<Map>,
|
||||
url_previews: Arc<Map>,
|
||||
mediaidremote_remotedownload: Arc<Map>,
|
||||
mediaid_redacted: Arc<Map>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -30,6 +35,8 @@ impl Data {
|
||||
mediaid_file: db["mediaid_file"].clone(),
|
||||
mediaid_user: db["mediaid_user"].clone(),
|
||||
url_previews: db["url_previews"].clone(),
|
||||
mediaidremote_remotedownload: db["mediaidremote_remotedownload"].clone(),
|
||||
mediaid_redacted: db["mediaid_redacted"].clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,4 +355,22 @@ impl Data {
|
||||
audio_size,
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn track_remote_download(&self, remote: &ServerName, media_id: &str) {
|
||||
self.mediaidremote_remotedownload
|
||||
.put_raw((media_id, remote), []);
|
||||
}
|
||||
|
||||
pub(super) async fn find_remote_downloads(&self, media_id: &str) -> HashSet<OwnedServerName> {
|
||||
self.mediaidremote_remotedownload
|
||||
.keys_prefix::<(String, OwnedServerName), _>(media_id)
|
||||
.ignore_err()
|
||||
.map(at!(1))
|
||||
.collect()
|
||||
.await
|
||||
}
|
||||
|
||||
pub(super) fn mark_redacted(&self, media_id: &str) {
|
||||
self.mediaid_redacted.insert(media_id, []);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ mod preview;
|
||||
mod remote;
|
||||
mod tests;
|
||||
mod thumbnail;
|
||||
use std::{path::PathBuf, sync::Arc, time::SystemTime};
|
||||
use std::{collections::HashSet, path::PathBuf, sync::Arc, time::SystemTime};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use base64::{Engine as _, engine::general_purpose};
|
||||
@@ -19,7 +19,11 @@ use conduwuit::{
|
||||
},
|
||||
warn,
|
||||
};
|
||||
use ruma::{OwnedMxcUri, UserId, http_headers::ContentDisposition};
|
||||
use ruma::{
|
||||
OwnedMxcUri, OwnedServerName, ServerName, UserId,
|
||||
api::federation::transactions::edu::{Edu, MediaRedactionContent},
|
||||
http_headers::ContentDisposition,
|
||||
};
|
||||
use tokio::{
|
||||
fs,
|
||||
io::{AsyncReadExt, AsyncWriteExt, BufReader},
|
||||
@@ -158,6 +162,31 @@ impl Service {
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark a media file as redacted and delete it from the database.
|
||||
pub async fn redact(&self, mxc: &Mxc<'_>) -> Result<()> {
|
||||
self.db.mark_redacted(mxc.media_id);
|
||||
self.delete(mxc).await?;
|
||||
|
||||
let edu = Edu::MediaRedaction(MediaRedactionContent::new(mxc.media_id.to_owned()));
|
||||
|
||||
for server in self.find_remote_downloads(mxc.media_id).await {
|
||||
if let Err(err) = self.services.sending.send_edu_server(&server, &edu) {
|
||||
error!(?server, %mxc, ?err, "Failed to queue media redaction EDU");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check if a user uploaded a file with the given MXC.
|
||||
pub async fn user_owns(&self, user: &UserId, mxc: &Mxc<'_>) -> bool {
|
||||
// TODO: do this more efficiently when we refactor this garbage fire of
|
||||
// a service
|
||||
|
||||
let mxc = OwnedMxcUri::from(mxc.to_string());
|
||||
self.db.get_all_user_mxcs(user).await.contains(&mxc)
|
||||
}
|
||||
|
||||
/// Deletes all media by the specified user
|
||||
///
|
||||
/// currently, this is only practical for local users
|
||||
@@ -255,6 +284,20 @@ impl Service {
|
||||
Ok(mxcs)
|
||||
}
|
||||
|
||||
/// Mark a remote server as having downloaded a media file.
|
||||
pub fn track_remote_download(&self, remote: &ServerName, media_id: &str) {
|
||||
self.db.track_remote_download(remote, media_id);
|
||||
}
|
||||
|
||||
/// Find all remote servers that have downloaded the local media file with
|
||||
/// the given ID.
|
||||
pub fn find_remote_downloads(
|
||||
&self,
|
||||
media_id: &str,
|
||||
) -> impl Future<Output = HashSet<OwnedServerName>> {
|
||||
self.db.find_remote_downloads(media_id)
|
||||
}
|
||||
|
||||
/// Deletes all media files in the given time frame.
|
||||
/// Returns a usize with the amount of media files deleted.
|
||||
pub async fn delete_all_media_within_timeframe(
|
||||
|
||||
Reference in new issue
Block a user