add client IP logging to media requests

Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
strawberry 2024-07-07 14:56:18 -04:00 committed by June 🍓🦴
parent d036d8adcb
commit 93e7cf461d

View file

@ -2,6 +2,7 @@
use std::{io::Cursor, sync::Arc, time::Duration}; use std::{io::Cursor, sync::Arc, time::Duration};
use axum_client_ip::InsecureClientIp;
use conduit::{debug, error, utils::math::ruma_from_usize, warn}; use conduit::{debug, error, utils::math::ruma_from_usize, warn};
use image::io::Reader as ImgReader; use image::io::Reader as ImgReader;
use ipaddress::IPAddress; use ipaddress::IPAddress;
@ -64,18 +65,22 @@ pub(crate) async fn get_media_config_v1_route(
/// # `GET /_matrix/media/v3/preview_url` /// # `GET /_matrix/media/v3/preview_url`
/// ///
/// Returns URL preview. /// Returns URL preview.
#[tracing::instrument(skip_all, fields(%client), name = "url_preview")]
pub(crate) async fn get_media_preview_route( pub(crate) async fn get_media_preview_route(
body: Ruma<get_media_preview::v3::Request>, InsecureClientIp(client): InsecureClientIp, body: Ruma<get_media_preview::v3::Request>,
) -> Result<get_media_preview::v3::Response> { ) -> Result<get_media_preview::v3::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
let url = &body.url; let url = &body.url;
if !url_preview_allowed(url) { if !url_preview_allowed(url) {
warn!(%sender_user, "URL is not allowed to be previewed: {url}");
return Err(Error::BadRequest(ErrorKind::forbidden(), "URL is not allowed to be previewed")); return Err(Error::BadRequest(ErrorKind::forbidden(), "URL is not allowed to be previewed"));
} }
match get_url_preview(url).await { match get_url_preview(url).await {
Ok(preview) => { Ok(preview) => {
let res = serde_json::value::to_raw_value(&preview).map_err(|e| { let res = serde_json::value::to_raw_value(&preview).map_err(|e| {
error!("Failed to convert UrlPreviewData into a serde json value: {}", e); error!(%sender_user, "Failed to convert UrlPreviewData into a serde json value: {e}");
Error::BadRequest( Error::BadRequest(
ErrorKind::LimitExceeded { ErrorKind::LimitExceeded {
retry_after: Some(RetryAfter::Delay(Duration::from_secs(5))), retry_after: Some(RetryAfter::Delay(Duration::from_secs(5))),
@ -87,7 +92,7 @@ pub(crate) async fn get_media_preview_route(
Ok(get_media_preview::v3::Response::from_raw_value(res)) Ok(get_media_preview::v3::Response::from_raw_value(res))
}, },
Err(e) => { Err(e) => {
warn!("Failed to generate a URL preview: {e}"); warn!(%sender_user, "Failed to generate a URL preview: {e}");
// there doesn't seem to be an agreed-upon error code in the spec. // there doesn't seem to be an agreed-upon error code in the spec.
// the only response codes in the preview_url spec page are 200 and 429. // the only response codes in the preview_url spec page are 200 and 429.
@ -108,10 +113,13 @@ pub(crate) async fn get_media_preview_route(
/// See <https://spec.matrix.org/legacy/legacy/#id27> /// See <https://spec.matrix.org/legacy/legacy/#id27>
/// ///
/// Returns URL preview. /// Returns URL preview.
#[tracing::instrument(skip_all, fields(%client), name = "url_preview")]
pub(crate) async fn get_media_preview_v1_route( pub(crate) async fn get_media_preview_v1_route(
body: Ruma<get_media_preview::v3::Request>, InsecureClientIp(client): InsecureClientIp, body: Ruma<get_media_preview::v3::Request>,
) -> Result<RumaResponse<get_media_preview::v3::Response>> { ) -> Result<RumaResponse<get_media_preview::v3::Response>> {
get_media_preview_route(body).await.map(RumaResponse) get_media_preview_route(InsecureClientIp(client), body)
.await
.map(RumaResponse)
} }
/// # `POST /_matrix/media/v3/upload` /// # `POST /_matrix/media/v3/upload`
@ -120,8 +128,9 @@ pub(crate) async fn get_media_preview_v1_route(
/// ///
/// - Some metadata will be saved in the database /// - Some metadata will be saved in the database
/// - Media will be saved in the media/ directory /// - Media will be saved in the media/ directory
#[tracing::instrument(skip_all, fields(%client), name = "media_upload")]
pub(crate) async fn create_content_route( pub(crate) async fn create_content_route(
body: Ruma<create_content::v3::Request>, InsecureClientIp(client): InsecureClientIp, body: Ruma<create_content::v3::Request>,
) -> Result<create_content::v3::Response> { ) -> Result<create_content::v3::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let sender_user = body.sender_user.as_ref().expect("user is authenticated");
@ -167,10 +176,13 @@ pub(crate) async fn create_content_route(
/// ///
/// - Some metadata will be saved in the database /// - Some metadata will be saved in the database
/// - Media will be saved in the media/ directory /// - Media will be saved in the media/ directory
#[tracing::instrument(skip_all, fields(%client), name = "media_upload")]
pub(crate) async fn create_content_v1_route( pub(crate) async fn create_content_v1_route(
body: Ruma<create_content::v3::Request>, InsecureClientIp(client): InsecureClientIp, body: Ruma<create_content::v3::Request>,
) -> Result<RumaResponse<create_content::v3::Response>> { ) -> Result<RumaResponse<create_content::v3::Response>> {
create_content_route(body).await.map(RumaResponse) create_content_route(InsecureClientIp(client), body)
.await
.map(RumaResponse)
} }
/// # `GET /_matrix/media/v3/download/{serverName}/{mediaId}` /// # `GET /_matrix/media/v3/download/{serverName}/{mediaId}`
@ -181,7 +193,10 @@ pub(crate) async fn create_content_v1_route(
/// - Only redirects if `allow_redirect` is true /// - Only redirects if `allow_redirect` is true
/// - Uses client-provided `timeout_ms` if available, else defaults to 20 /// - Uses client-provided `timeout_ms` if available, else defaults to 20
/// seconds /// seconds
pub(crate) async fn get_content_route(body: Ruma<get_content::v3::Request>) -> Result<get_content::v3::Response> { #[tracing::instrument(skip_all, fields(%client), name = "media_get")]
pub(crate) async fn get_content_route(
InsecureClientIp(client): InsecureClientIp, body: Ruma<get_content::v3::Request>,
) -> Result<get_content::v3::Response> {
let mxc = format!("mxc://{}/{}", body.server_name, body.media_id); let mxc = format!("mxc://{}/{}", body.server_name, body.media_id);
if let Some(FileMeta { if let Some(FileMeta {
@ -243,10 +258,13 @@ pub(crate) async fn get_content_route(body: Ruma<get_content::v3::Request>) -> R
/// - Only redirects if `allow_redirect` is true /// - Only redirects if `allow_redirect` is true
/// - Uses client-provided `timeout_ms` if available, else defaults to 20 /// - Uses client-provided `timeout_ms` if available, else defaults to 20
/// seconds /// seconds
#[tracing::instrument(skip_all, fields(%client), name = "media_get")]
pub(crate) async fn get_content_v1_route( pub(crate) async fn get_content_v1_route(
body: Ruma<get_content::v3::Request>, InsecureClientIp(client): InsecureClientIp, body: Ruma<get_content::v3::Request>,
) -> Result<RumaResponse<get_content::v3::Response>> { ) -> Result<RumaResponse<get_content::v3::Response>> {
get_content_route(body).await.map(RumaResponse) get_content_route(InsecureClientIp(client), body)
.await
.map(RumaResponse)
} }
/// # `GET /_matrix/media/v3/download/{serverName}/{mediaId}/{fileName}` /// # `GET /_matrix/media/v3/download/{serverName}/{mediaId}/{fileName}`
@ -257,8 +275,9 @@ pub(crate) async fn get_content_v1_route(
/// - Only redirects if `allow_redirect` is true /// - Only redirects if `allow_redirect` is true
/// - Uses client-provided `timeout_ms` if available, else defaults to 20 /// - Uses client-provided `timeout_ms` if available, else defaults to 20
/// seconds /// seconds
#[tracing::instrument(skip_all, fields(%client), name = "media_get")]
pub(crate) async fn get_content_as_filename_route( pub(crate) async fn get_content_as_filename_route(
body: Ruma<get_content_as_filename::v3::Request>, InsecureClientIp(client): InsecureClientIp, body: Ruma<get_content_as_filename::v3::Request>,
) -> Result<get_content_as_filename::v3::Response> { ) -> Result<get_content_as_filename::v3::Response> {
let mxc = format!("mxc://{}/{}", body.server_name, body.media_id); let mxc = format!("mxc://{}/{}", body.server_name, body.media_id);
@ -328,10 +347,13 @@ pub(crate) async fn get_content_as_filename_route(
/// - Only redirects if `allow_redirect` is true /// - Only redirects if `allow_redirect` is true
/// - Uses client-provided `timeout_ms` if available, else defaults to 20 /// - Uses client-provided `timeout_ms` if available, else defaults to 20
/// seconds /// seconds
#[tracing::instrument(skip_all, fields(%client), name = "media_get")]
pub(crate) async fn get_content_as_filename_v1_route( pub(crate) async fn get_content_as_filename_v1_route(
body: Ruma<get_content_as_filename::v3::Request>, InsecureClientIp(client): InsecureClientIp, body: Ruma<get_content_as_filename::v3::Request>,
) -> Result<RumaResponse<get_content_as_filename::v3::Response>> { ) -> Result<RumaResponse<get_content_as_filename::v3::Response>> {
get_content_as_filename_route(body).await.map(RumaResponse) get_content_as_filename_route(InsecureClientIp(client), body)
.await
.map(RumaResponse)
} }
/// # `GET /_matrix/media/v3/thumbnail/{serverName}/{mediaId}` /// # `GET /_matrix/media/v3/thumbnail/{serverName}/{mediaId}`
@ -342,8 +364,9 @@ pub(crate) async fn get_content_as_filename_v1_route(
/// - Only redirects if `allow_redirect` is true /// - Only redirects if `allow_redirect` is true
/// - Uses client-provided `timeout_ms` if available, else defaults to 20 /// - Uses client-provided `timeout_ms` if available, else defaults to 20
/// seconds /// seconds
#[tracing::instrument(skip_all, fields(%client), name = "media_thumbnail_get")]
pub(crate) async fn get_content_thumbnail_route( pub(crate) async fn get_content_thumbnail_route(
body: Ruma<get_content_thumbnail::v3::Request>, InsecureClientIp(client): InsecureClientIp, body: Ruma<get_content_thumbnail::v3::Request>,
) -> Result<get_content_thumbnail::v3::Response> { ) -> Result<get_content_thumbnail::v3::Response> {
let mxc = format!("mxc://{}/{}", body.server_name, body.media_id); let mxc = format!("mxc://{}/{}", body.server_name, body.media_id);
@ -453,10 +476,13 @@ pub(crate) async fn get_content_thumbnail_route(
/// - Only redirects if `allow_redirect` is true /// - Only redirects if `allow_redirect` is true
/// - Uses client-provided `timeout_ms` if available, else defaults to 20 /// - Uses client-provided `timeout_ms` if available, else defaults to 20
/// seconds /// seconds
#[tracing::instrument(skip_all, fields(%client), name = "media_thumbnail_get")]
pub(crate) async fn get_content_thumbnail_v1_route( pub(crate) async fn get_content_thumbnail_v1_route(
body: Ruma<get_content_thumbnail::v3::Request>, InsecureClientIp(client): InsecureClientIp, body: Ruma<get_content_thumbnail::v3::Request>,
) -> Result<RumaResponse<get_content_thumbnail::v3::Response>> { ) -> Result<RumaResponse<get_content_thumbnail::v3::Response>> {
get_content_thumbnail_route(body).await.map(RumaResponse) get_content_thumbnail_route(InsecureClientIp(client), body)
.await
.map(RumaResponse)
} }
async fn get_remote_content( async fn get_remote_content(