1
0
Fork 0
forked from mirror/grapevine

cargo update ruma httparse

This adds authenticated media APIs.
This commit is contained in:
Lambda 2024-07-21 13:22:42 +00:00
parent 556f2157a2
commit 5a5bea3217
5 changed files with 78 additions and 47 deletions

56
Cargo.lock generated
View file

@ -1045,6 +1045,15 @@ dependencies = [
"itoa", "itoa",
] ]
[[package]]
name = "http-auth"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "643c9bbf6a4ea8a656d6b4cd53d34f79e3f841ad5203c1a55fb7d761923bc255"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "http-body" name = "http-body"
version = "0.4.6" version = "0.4.6"
@ -1081,9 +1090,9 @@ dependencies = [
[[package]] [[package]]
name = "httparse" name = "httparse"
version = "1.8.0" version = "1.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9"
[[package]] [[package]]
name = "httpdate" name = "httpdate"
@ -2111,7 +2120,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma" name = "ruma"
version = "0.10.1" version = "0.10.1"
source = "git+https://github.com/ruma/ruma?branch=main#ba9a492fdee6ad89b179e2b3ab689c3114107012" source = "git+https://github.com/ruma/ruma?branch=main#14d7415f0d80aadf425c2384c0f348d1c03527c8"
dependencies = [ dependencies = [
"assign", "assign",
"js_int", "js_int",
@ -2132,7 +2141,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-appservice-api" name = "ruma-appservice-api"
version = "0.10.0" version = "0.10.0"
source = "git+https://github.com/ruma/ruma?branch=main#ba9a492fdee6ad89b179e2b3ab689c3114107012" source = "git+https://github.com/ruma/ruma?branch=main#14d7415f0d80aadf425c2384c0f348d1c03527c8"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@ -2144,7 +2153,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-client-api" name = "ruma-client-api"
version = "0.18.0" version = "0.18.0"
source = "git+https://github.com/ruma/ruma?branch=main#ba9a492fdee6ad89b179e2b3ab689c3114107012" source = "git+https://github.com/ruma/ruma?branch=main#14d7415f0d80aadf425c2384c0f348d1c03527c8"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"assign", "assign",
@ -2167,7 +2176,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-common" name = "ruma-common"
version = "0.13.0" version = "0.13.0"
source = "git+https://github.com/ruma/ruma?branch=main#ba9a492fdee6ad89b179e2b3ab689c3114107012" source = "git+https://github.com/ruma/ruma?branch=main#14d7415f0d80aadf425c2384c0f348d1c03527c8"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"base64 0.22.1", "base64 0.22.1",
@ -2197,7 +2206,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-events" name = "ruma-events"
version = "0.28.1" version = "0.28.1"
source = "git+https://github.com/ruma/ruma?branch=main#ba9a492fdee6ad89b179e2b3ab689c3114107012" source = "git+https://github.com/ruma/ruma?branch=main#14d7415f0d80aadf425c2384c0f348d1c03527c8"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"indexmap 2.2.6", "indexmap 2.2.6",
@ -2213,15 +2222,22 @@ dependencies = [
"thiserror", "thiserror",
"tracing", "tracing",
"url", "url",
"web-time",
"wildmatch", "wildmatch",
] ]
[[package]] [[package]]
name = "ruma-federation-api" name = "ruma-federation-api"
version = "0.9.0" version = "0.9.0"
source = "git+https://github.com/ruma/ruma?branch=main#ba9a492fdee6ad89b179e2b3ab689c3114107012" source = "git+https://github.com/ruma/ruma?branch=main#14d7415f0d80aadf425c2384c0f348d1c03527c8"
dependencies = [ dependencies = [
"bytes",
"http 1.1.0",
"httparse",
"js_int", "js_int",
"memchr",
"mime",
"rand",
"ruma-common", "ruma-common",
"ruma-events", "ruma-events",
"serde", "serde",
@ -2231,7 +2247,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-identifiers-validation" name = "ruma-identifiers-validation"
version = "0.9.5" version = "0.9.5"
source = "git+https://github.com/ruma/ruma?branch=main#ba9a492fdee6ad89b179e2b3ab689c3114107012" source = "git+https://github.com/ruma/ruma?branch=main#14d7415f0d80aadf425c2384c0f348d1c03527c8"
dependencies = [ dependencies = [
"js_int", "js_int",
"thiserror", "thiserror",
@ -2240,7 +2256,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-identity-service-api" name = "ruma-identity-service-api"
version = "0.9.0" version = "0.9.0"
source = "git+https://github.com/ruma/ruma?branch=main#ba9a492fdee6ad89b179e2b3ab689c3114107012" source = "git+https://github.com/ruma/ruma?branch=main#14d7415f0d80aadf425c2384c0f348d1c03527c8"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@ -2250,7 +2266,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-macros" name = "ruma-macros"
version = "0.13.0" version = "0.13.0"
source = "git+https://github.com/ruma/ruma?branch=main#ba9a492fdee6ad89b179e2b3ab689c3114107012" source = "git+https://github.com/ruma/ruma?branch=main#14d7415f0d80aadf425c2384c0f348d1c03527c8"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"proc-macro-crate", "proc-macro-crate",
@ -2265,7 +2281,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-push-gateway-api" name = "ruma-push-gateway-api"
version = "0.9.0" version = "0.9.0"
source = "git+https://github.com/ruma/ruma?branch=main#ba9a492fdee6ad89b179e2b3ab689c3114107012" source = "git+https://github.com/ruma/ruma?branch=main#14d7415f0d80aadf425c2384c0f348d1c03527c8"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@ -2277,18 +2293,20 @@ dependencies = [
[[package]] [[package]]
name = "ruma-server-util" name = "ruma-server-util"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/ruma/ruma?branch=main#ba9a492fdee6ad89b179e2b3ab689c3114107012" source = "git+https://github.com/ruma/ruma?branch=main#14d7415f0d80aadf425c2384c0f348d1c03527c8"
dependencies = [ dependencies = [
"headers", "headers",
"http 1.1.0",
"http-auth",
"ruma-common", "ruma-common",
"thiserror",
"tracing", "tracing",
"yap",
] ]
[[package]] [[package]]
name = "ruma-signatures" name = "ruma-signatures"
version = "0.15.0" version = "0.15.0"
source = "git+https://github.com/ruma/ruma?branch=main#ba9a492fdee6ad89b179e2b3ab689c3114107012" source = "git+https://github.com/ruma/ruma?branch=main#14d7415f0d80aadf425c2384c0f348d1c03527c8"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"ed25519-dalek", "ed25519-dalek",
@ -2304,7 +2322,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-state-res" name = "ruma-state-res"
version = "0.11.0" version = "0.11.0"
source = "git+https://github.com/ruma/ruma?branch=main#ba9a492fdee6ad89b179e2b3ab689c3114107012" source = "git+https://github.com/ruma/ruma?branch=main#14d7415f0d80aadf425c2384c0f348d1c03527c8"
dependencies = [ dependencies = [
"itertools", "itertools",
"js_int", "js_int",
@ -3720,12 +3738,6 @@ version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546"
[[package]]
name = "yap"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfe269e7b803a5e8e20cbd97860e136529cd83bf2c9c6d37b142467e7e1f051f"
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.7.34" version = "0.7.34"

View file

@ -6,12 +6,15 @@ use http::{
HeaderName, HeaderValue, HeaderName, HeaderValue,
}; };
use phf::{phf_set, Set}; use phf::{phf_set, Set};
use ruma::api::client::{ use ruma::{
error::ErrorKind, api::client::{
media::{ error::ErrorKind,
create_content, get_content, get_content_as_filename, media::{
get_content_thumbnail, get_media_config, create_content, get_content, get_content_as_filename,
get_content_thumbnail, get_media_config,
},
}, },
http_headers::{ContentDisposition, ContentDispositionType},
}; };
use tracing::error; use tracing::error;
@ -77,16 +80,17 @@ fn content_security_policy() -> HeaderValue {
// Doing this correctly is tricky, so I'm skipping it for now. // Doing this correctly is tricky, so I'm skipping it for now.
fn content_disposition_for( fn content_disposition_for(
content_type: Option<&str>, content_type: Option<&str>,
filename: Option<&str>, filename: Option<String>,
) -> String { ) -> ContentDisposition {
match ( let disposition_type = match content_type {
content_type.is_some_and(|x| INLINE_CONTENT_TYPES.contains(x)), Some(x) if INLINE_CONTENT_TYPES.contains(x) => {
ContentDispositionType::Inline
}
_ => ContentDispositionType::Attachment,
};
ContentDisposition {
disposition_type,
filename, filename,
) {
(true, None) => "inline".to_owned(),
(true, Some(x)) => format!("inline; filename={x}"),
(false, None) => "attachment".to_owned(),
(false, Some(x)) => format!("attachment; filename={x}"),
} }
} }
@ -114,6 +118,7 @@ fn set_header_or_panic(
/// # `GET /_matrix/media/r0/config` /// # `GET /_matrix/media/r0/config`
/// ///
/// Returns max upload size. /// Returns max upload size.
#[allow(deprecated)] // unauthenticated media
pub(crate) async fn get_media_config_route( pub(crate) async fn get_media_config_route(
_body: Ar<get_media_config::v3::Request>, _body: Ar<get_media_config::v3::Request>,
) -> Result<Ra<get_media_config::v3::Response>> { ) -> Result<Ra<get_media_config::v3::Response>> {
@ -142,9 +147,12 @@ pub(crate) async fn create_content_route(
.create( .create(
mxc.clone(), mxc.clone(),
body.filename body.filename
.as_ref() .clone()
.map(|filename| format!("inline; filename={filename}")) .map(|filename| ContentDisposition {
.as_deref(), disposition_type: ContentDispositionType::Inline,
filename: Some(filename),
})
.as_ref(),
body.content_type.as_deref(), body.content_type.as_deref(),
&body.file, &body.file,
) )
@ -156,6 +164,7 @@ pub(crate) async fn create_content_route(
})) }))
} }
#[allow(deprecated)] // unauthenticated media
pub(crate) async fn get_remote_content( pub(crate) async fn get_remote_content(
mxc: &str, mxc: &str,
server_name: &ruma::ServerName, server_name: &ruma::ServerName,
@ -179,7 +188,7 @@ pub(crate) async fn get_remote_content(
.media .media
.create( .create(
mxc.to_owned(), mxc.to_owned(),
content_response.content_disposition.as_deref(), content_response.content_disposition.as_ref(),
content_response.content_type.as_deref(), content_response.content_type.as_deref(),
&content_response.file, &content_response.file,
) )
@ -198,6 +207,7 @@ pub(crate) async fn get_remote_content(
/// Load media from our server or over federation. /// Load media from our server or over federation.
/// ///
/// - Only allows federation if `allow_remote` is true /// - Only allows federation if `allow_remote` is true
#[allow(deprecated)] // unauthenticated media
pub(crate) async fn get_content_route( pub(crate) async fn get_content_route(
body: Ar<get_content::v3::Request>, body: Ar<get_content::v3::Request>,
) -> Result<axum::response::Response> { ) -> Result<axum::response::Response> {
@ -214,6 +224,7 @@ pub(crate) async fn get_content_route(
}) })
} }
#[allow(deprecated)] // unauthenticated media
async fn get_content_route_ruma( async fn get_content_route_ruma(
body: Ar<get_content::v3::Request>, body: Ar<get_content::v3::Request>,
) -> Result<get_content::v3::Response> { ) -> Result<get_content::v3::Response> {
@ -259,6 +270,7 @@ async fn get_content_route_ruma(
/// Load media from our server or over federation, permitting desired filename. /// Load media from our server or over federation, permitting desired filename.
/// ///
/// - Only allows federation if `allow_remote` is true /// - Only allows federation if `allow_remote` is true
#[allow(deprecated)] // unauthenticated media
pub(crate) async fn get_content_as_filename_route( pub(crate) async fn get_content_as_filename_route(
body: Ar<get_content_as_filename::v3::Request>, body: Ar<get_content_as_filename::v3::Request>,
) -> Result<axum::response::Response> { ) -> Result<axum::response::Response> {
@ -275,6 +287,7 @@ pub(crate) async fn get_content_as_filename_route(
}) })
} }
#[allow(deprecated)] // unauthenticated media
pub(crate) async fn get_content_as_filename_route_ruma( pub(crate) async fn get_content_as_filename_route_ruma(
body: Ar<get_content_as_filename::v3::Request>, body: Ar<get_content_as_filename::v3::Request>,
) -> Result<get_content_as_filename::v3::Response> { ) -> Result<get_content_as_filename::v3::Response> {
@ -290,7 +303,7 @@ pub(crate) async fn get_content_as_filename_route_ruma(
file, file,
content_disposition: Some(content_disposition_for( content_disposition: Some(content_disposition_for(
content_type.as_deref(), content_type.as_deref(),
Some(body.filename.as_str()), Some(body.filename.clone()),
)), )),
content_type, content_type,
cross_origin_resource_policy: Some("cross-origin".to_owned()), cross_origin_resource_policy: Some("cross-origin".to_owned()),
@ -305,7 +318,7 @@ pub(crate) async fn get_content_as_filename_route_ruma(
Ok(get_content_as_filename::v3::Response { Ok(get_content_as_filename::v3::Response {
content_disposition: Some(content_disposition_for( content_disposition: Some(content_disposition_for(
remote_content_response.content_type.as_deref(), remote_content_response.content_type.as_deref(),
Some(body.filename.as_str()), Some(body.filename.clone()),
)), )),
content_type: remote_content_response.content_type, content_type: remote_content_response.content_type,
file: remote_content_response.file, file: remote_content_response.file,
@ -321,6 +334,7 @@ pub(crate) async fn get_content_as_filename_route_ruma(
/// Load media thumbnail from our server or over federation. /// Load media thumbnail from our server or over federation.
/// ///
/// - Only allows federation if `allow_remote` is true /// - Only allows federation if `allow_remote` is true
#[allow(deprecated)] // unauthenticated media
pub(crate) async fn get_content_thumbnail_route( pub(crate) async fn get_content_thumbnail_route(
body: Ar<get_content_thumbnail::v3::Request>, body: Ar<get_content_thumbnail::v3::Request>,
) -> Result<axum::response::Response> { ) -> Result<axum::response::Response> {
@ -342,6 +356,7 @@ pub(crate) async fn get_content_thumbnail_route(
&mut r, &mut r,
CONTENT_DISPOSITION, CONTENT_DISPOSITION,
content_disposition_for(content_type.as_deref(), None) content_disposition_for(content_type.as_deref(), None)
.to_string()
.try_into() .try_into()
.expect("generated header value should be valid"), .expect("generated header value should be valid"),
); );
@ -350,6 +365,7 @@ pub(crate) async fn get_content_thumbnail_route(
}) })
} }
#[allow(deprecated)] // unauthenticated media
async fn get_content_thumbnail_route_ruma( async fn get_content_thumbnail_route_ruma(
body: Ar<get_content_thumbnail::v3::Request>, body: Ar<get_content_thumbnail::v3::Request>,
) -> Result<get_content_thumbnail::v3::Response> { ) -> Result<get_content_thumbnail::v3::Response> {
@ -393,6 +409,7 @@ async fn get_content_thumbnail_route_ruma(
media_id: body.media_id.clone(), media_id: body.media_id.clone(),
timeout_ms: Duration::from_secs(20), timeout_ms: Duration::from_secs(20),
allow_redirect: false, allow_redirect: false,
animated: Some(false),
}, },
) )
.await?; .await?;

View file

@ -212,7 +212,7 @@ async fn ar_from_request_inner(
let origin_signatures = BTreeMap::from_iter([( let origin_signatures = BTreeMap::from_iter([(
x_matrix.key.to_string(), x_matrix.key.to_string(),
CanonicalJsonValue::String(x_matrix.sig), CanonicalJsonValue::String(x_matrix.sig.to_string()),
)]); )]);
let signatures = BTreeMap::from_iter([( let signatures = BTreeMap::from_iter([(

View file

@ -244,11 +244,12 @@ where
.unwrap(); .unwrap();
let key_id = OwnedSigningKeyId::try_from(key_id.clone()).unwrap(); let key_id = OwnedSigningKeyId::try_from(key_id.clone()).unwrap();
let signature = signature.as_str().unwrap().to_owned(); let signature = Base64::parse(signature.as_str().unwrap())
.expect("generated signature should be valid base64");
http_request.headers_mut().typed_insert(Authorization(XMatrix::new( http_request.headers_mut().typed_insert(Authorization(XMatrix::new(
services().globals.server_name().to_owned(), services().globals.server_name().to_owned(),
Some(destination.to_owned()), destination.to_owned(),
key_id, key_id,
signature, signature,
))); )));

View file

@ -1,6 +1,7 @@
use std::io::Cursor; use std::io::Cursor;
use image::imageops::FilterType; use image::imageops::FilterType;
use ruma::http_headers::ContentDisposition;
use tokio::{ use tokio::{
fs::File, fs::File,
io::{AsyncReadExt, AsyncWriteExt}, io::{AsyncReadExt, AsyncWriteExt},
@ -35,7 +36,7 @@ impl Service {
pub(crate) async fn create( pub(crate) async fn create(
&self, &self,
mxc: String, mxc: String,
content_disposition: Option<&str>, content_disposition: Option<&ContentDisposition>,
content_type: Option<&str>, content_type: Option<&str>,
file: &[u8], file: &[u8],
) -> Result<()> { ) -> Result<()> {
@ -44,7 +45,7 @@ impl Service {
mxc, mxc,
0, 0,
0, 0,
content_disposition, content_disposition.map(ContentDisposition::to_string).as_deref(),
content_type, content_type,
)?; )?;