Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71e7fe3086 | ||
|
|
03f2e3b1bf | ||
|
|
8bbb579d23 | ||
|
|
6448af071b | ||
|
|
c2a0ab71df | ||
|
|
7a17165c24 | ||
|
|
d7213fa409 | ||
|
|
479f0402ca | ||
|
|
b62eeef80c |
@@ -67,7 +67,7 @@ jobs:
|
||||
if: github.event_name != 'pull_request' && github.ref_name == 'main'
|
||||
uses: nev7n/wait_for_response@v1
|
||||
with:
|
||||
url: "http://localhost:8000/"
|
||||
url: "http://localhost:14702/"
|
||||
|
||||
- name: Checkout API repository
|
||||
if: github.event_name != 'pull_request' && github.ref_name == 'main'
|
||||
@@ -79,7 +79,7 @@ jobs:
|
||||
|
||||
- name: Download OpenAPI specification
|
||||
if: github.event_name != 'pull_request' && github.ref_name == 'main'
|
||||
run: curl http://localhost:8000/openapi.json -o api/OpenAPI.json
|
||||
run: curl http://localhost:14702/openapi.json -o api/OpenAPI.json
|
||||
|
||||
- name: Commit changes
|
||||
if: github.event_name != 'pull_request' && github.ref_name == 'main'
|
||||
|
||||
Generated
+13
-13
@@ -5523,7 +5523,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-autumn"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum-macros",
|
||||
@@ -5560,7 +5560,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-bonfire"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"async-channel 2.3.1",
|
||||
"async-std",
|
||||
@@ -5590,7 +5590,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-config"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"cached",
|
||||
@@ -5606,7 +5606,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-database"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"amqprs",
|
||||
"async-lock 2.8.0",
|
||||
@@ -5655,7 +5655,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-delta"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"amqprs",
|
||||
"async-channel 1.6.1",
|
||||
@@ -5702,7 +5702,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-files"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"aws-config",
|
||||
@@ -5725,7 +5725,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-january"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"async-recursion",
|
||||
"axum",
|
||||
@@ -5753,7 +5753,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-models"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"indexmap 1.9.3",
|
||||
"iso8601-timestamp 0.2.11",
|
||||
@@ -5771,7 +5771,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-nodejs-bindings"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"neon",
|
||||
@@ -5784,7 +5784,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-permissions"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"async-trait",
|
||||
@@ -5799,7 +5799,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-presence"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"log",
|
||||
@@ -5810,7 +5810,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-pushd"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"amqprs",
|
||||
"async-trait",
|
||||
@@ -5834,7 +5834,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-result"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"revolt_okapi",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-nodejs-bindings"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
description = "Node.js bindings for the Revolt software"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
license = "MIT"
|
||||
@@ -20,6 +20,6 @@ serde = { version = "1", features = ["derive"] }
|
||||
|
||||
async-std = "1.12.0"
|
||||
|
||||
revolt-config = { version = "0.8.0", path = "../../core/config" }
|
||||
revolt-result = { version = "0.8.0", path = "../../core/result" }
|
||||
revolt-database = { version = "0.8.0", path = "../../core/database" }
|
||||
revolt-config = { version = "0.8.1", path = "../../core/config" }
|
||||
revolt-result = { version = "0.8.1", path = "../../core/result" }
|
||||
revolt-database = { version = "0.8.1", path = "../../core/database" }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-bonfire"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
license = "AGPL-3.0-or-later"
|
||||
edition = "2021"
|
||||
|
||||
@@ -41,7 +41,7 @@ revolt-result = { path = "../core/result" }
|
||||
revolt-models = { path = "../core/models" }
|
||||
revolt-config = { path = "../core/config" }
|
||||
revolt-database = { path = "../core/database" }
|
||||
revolt-permissions = { version = "0.8.0", path = "../core/permissions" }
|
||||
revolt-permissions = { version = "0.8.1", path = "../core/permissions" }
|
||||
revolt-presence = { path = "../core/presence", features = ["redis-is-patched"] }
|
||||
|
||||
# redis
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-config"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
@@ -34,4 +34,4 @@ pretty_env_logger = "0.4.0"
|
||||
sentry = "0.31.5"
|
||||
|
||||
# Core
|
||||
revolt-result = { version = "0.8.0", path = "../result", optional = true }
|
||||
revolt-result = { version = "0.8.1", path = "../result", optional = true }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-database"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
@@ -24,15 +24,15 @@ default = ["mongodb", "async-std-runtime", "tasks"]
|
||||
|
||||
[dependencies]
|
||||
# Core
|
||||
revolt-config = { version = "0.8.0", path = "../config", features = [
|
||||
revolt-config = { version = "0.8.1", path = "../config", features = [
|
||||
"report-macros",
|
||||
] }
|
||||
revolt-result = { version = "0.8.0", path = "../result" }
|
||||
revolt-models = { version = "0.8.0", path = "../models", features = [
|
||||
revolt-result = { version = "0.8.1", path = "../result" }
|
||||
revolt-models = { version = "0.8.1", path = "../models", features = [
|
||||
"validator",
|
||||
] }
|
||||
revolt-presence = { version = "0.8.0", path = "../presence" }
|
||||
revolt-permissions = { version = "0.8.0", path = "../permissions", features = [
|
||||
revolt-presence = { version = "0.8.1", path = "../presence" }
|
||||
revolt-permissions = { version = "0.8.1", path = "../permissions", features = [
|
||||
"serde",
|
||||
"bson",
|
||||
] }
|
||||
|
||||
@@ -30,7 +30,7 @@ impl AbstractChannelUnreads for MongoDb {
|
||||
doc! {
|
||||
"$pull": {
|
||||
"mentions": {
|
||||
"$lt": message_id
|
||||
"$lte": message_id
|
||||
}
|
||||
},
|
||||
"$set": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-files"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
@@ -20,10 +20,10 @@ typenum = "1.17.0"
|
||||
aws-config = "1.5.5"
|
||||
aws-sdk-s3 = { version = "1.46.0", features = ["behavior-version-latest"] }
|
||||
|
||||
revolt-config = { version = "0.8.0", path = "../config", features = [
|
||||
revolt-config = { version = "0.8.1", path = "../config", features = [
|
||||
"report-macros",
|
||||
] }
|
||||
revolt-result = { version = "0.8.0", path = "../result" }
|
||||
revolt-result = { version = "0.8.1", path = "../result" }
|
||||
|
||||
# image processing
|
||||
jxl-oxide = "0.8.1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-models"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
@@ -20,8 +20,8 @@ default = ["serde", "partials", "rocket"]
|
||||
|
||||
[dependencies]
|
||||
# Core
|
||||
revolt-config = { version = "0.8.0", path = "../config" }
|
||||
revolt-permissions = { version = "0.8.0", path = "../permissions" }
|
||||
revolt-config = { version = "0.8.1", path = "../config" }
|
||||
revolt-permissions = { version = "0.8.1", path = "../permissions" }
|
||||
|
||||
# Utility
|
||||
regex = "1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-permissions"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
@@ -21,7 +21,7 @@ async-std = { version = "1.8.0", features = ["attributes"] }
|
||||
|
||||
[dependencies]
|
||||
# Core
|
||||
revolt-result = { version = "0.8.0", path = "../result" }
|
||||
revolt-result = { version = "0.8.1", path = "../result" }
|
||||
|
||||
# Utility
|
||||
auto_ops = "0.3.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-presence"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-result"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
[package]
|
||||
name = "revolt-pushd"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
revolt-config = { version = "0.8.0", path = "../../core/config" }
|
||||
revolt-database = { version = "0.8.0", path = "../../core/database" }
|
||||
revolt-models = { version = "0.8.0", path = "../../core/models", features = [
|
||||
revolt-config = { version = "0.8.1", path = "../../core/config" }
|
||||
revolt-database = { version = "0.8.1", path = "../../core/database" }
|
||||
revolt-models = { version = "0.8.1", path = "../../core/models", features = [
|
||||
"validator",
|
||||
] }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-delta"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <paulmakles@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-autumn"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@@ -42,12 +42,12 @@ tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
||||
# Core crates
|
||||
revolt-files = { version = "0.8.0", path = "../../core/files" }
|
||||
revolt-config = { version = "0.8.0", path = "../../core/config" }
|
||||
revolt-database = { version = "0.8.0", path = "../../core/database", features = [
|
||||
revolt-files = { version = "0.8.1", path = "../../core/files" }
|
||||
revolt-config = { version = "0.8.1", path = "../../core/config" }
|
||||
revolt-database = { version = "0.8.1", path = "../../core/database", features = [
|
||||
"axum-impl",
|
||||
] }
|
||||
revolt-result = { version = "0.8.0", path = "../../core/result", features = [
|
||||
revolt-result = { version = "0.8.1", path = "../../core/result", features = [
|
||||
"utoipa",
|
||||
"axum",
|
||||
] }
|
||||
|
||||
@@ -216,6 +216,27 @@ async fn upload_file(
|
||||
nanoid::nanoid!(42)
|
||||
};
|
||||
|
||||
// Determine the mime type for the file
|
||||
let mime_type = determine_mime_type(&mut file.contents, &buf, &filename);
|
||||
|
||||
// Check blocklist for mime type
|
||||
if config
|
||||
.files
|
||||
.blocked_mime_types
|
||||
.iter()
|
||||
.any(|m| m == mime_type)
|
||||
{
|
||||
return Err(create_error!(FileTypeNotAllowed));
|
||||
}
|
||||
|
||||
// Determine metadata for the file
|
||||
let metadata = generate_metadata(&file.contents, mime_type);
|
||||
|
||||
// Block non-images for non-attachment uploads
|
||||
if !matches!(tag, Tag::attachments) && !matches!(metadata, Metadata::Image { .. }) {
|
||||
return Err(create_error!(FileTypeNotAllowed));
|
||||
}
|
||||
|
||||
// Find an existing hash and use that if possible
|
||||
let file_hash_exists = if let Ok(file_hash) = db
|
||||
.fetch_attachment_hash(&format!("{original_hash:02x}"))
|
||||
@@ -239,22 +260,6 @@ async fn upload_file(
|
||||
false
|
||||
};
|
||||
|
||||
// Determine the mime type for the file
|
||||
let mime_type = determine_mime_type(&mut file.contents, &buf, &filename);
|
||||
|
||||
// Check blocklist for mime type
|
||||
if config
|
||||
.files
|
||||
.blocked_mime_types
|
||||
.iter()
|
||||
.any(|m| m == mime_type)
|
||||
{
|
||||
return Err(create_error!(FileTypeNotAllowed));
|
||||
}
|
||||
|
||||
// Determine metadata for the file
|
||||
let metadata = generate_metadata(&file.contents, mime_type);
|
||||
|
||||
// Strip metadata
|
||||
let (buf, metadata) = strip_metadata(file.contents, buf, metadata, mime_type).await?;
|
||||
|
||||
@@ -322,21 +327,23 @@ pub static CACHE_CONTROL: &str = "public, max-age=604800, must-revalidate";
|
||||
|
||||
/// Fetch preview of file
|
||||
///
|
||||
/// This route will only return image content.
|
||||
/// This route will only return image content. <br>
|
||||
/// For all other file types, please use the fetch route (you will receive a redirect if you try to use this route anyways!).
|
||||
///
|
||||
/// Depending on the given tag, the file will be re-processed to fit the criteria:
|
||||
///
|
||||
/// | Tag | Image Resolution <sup>†</sup> |
|
||||
/// | :-: | --- |
|
||||
/// | attachments | Up to 1280px on any axis |
|
||||
/// | avatars | Up to 128px on any axis |
|
||||
/// | backgrounds | Up to 1280x720px |
|
||||
/// | icons | Up to 128px on any axis |
|
||||
/// | banners | Up to 480px on any axis |
|
||||
/// | emojis | Up to 128px on any axis |
|
||||
/// | Tag | Image Resolution <sup>†</sup> | Animations stripped by preview <sup>‡</sup> |
|
||||
/// | :-: | --- | :-: |
|
||||
/// | attachments | Up to 1280px on any axis | ❌ |
|
||||
/// | avatars | Up to 128px on any axis | ✅ |
|
||||
/// | backgrounds | Up to 1280x720px | ❌ |
|
||||
/// | icons | Up to 128px on any axis | ✅ |
|
||||
/// | banners | Up to 480px on any axis | ❌ |
|
||||
/// | emojis | Up to 128px on any axis | ❌ |
|
||||
///
|
||||
/// <sup>†</sup> aspect ratio will always be preserved
|
||||
///
|
||||
/// <sup>‡</sup> to fetch animated variant, suffix `/{file_name}` or `/original` to the path
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/{tag}/{file_id}",
|
||||
@@ -352,8 +359,8 @@ async fn fetch_preview(
|
||||
State(db): State<Database>,
|
||||
Path((tag, file_id)): Path<(Tag, String)>,
|
||||
) -> Result<Response> {
|
||||
let tag: &'static str = tag.into();
|
||||
let file = db.fetch_attachment(tag, &file_id).await?;
|
||||
let tag_str: &'static str = tag.clone().into();
|
||||
let file = db.fetch_attachment(tag_str, &file_id).await?;
|
||||
|
||||
// Ignore deleted files
|
||||
if file.deleted.is_some_and(|v| v) {
|
||||
@@ -367,10 +374,14 @@ async fn fetch_preview(
|
||||
|
||||
let hash = file.as_hash(&db).await?;
|
||||
|
||||
// Only process image files and don't process GIFs
|
||||
if !matches!(hash.metadata, Metadata::Image { .. }) || hash.content_type == "image/gif" {
|
||||
let is_animated = hash.content_type == "image/gif"; // TODO: extract this data from files
|
||||
|
||||
// Only process image files and don't process GIFs if not avatar or icon
|
||||
if !matches!(hash.metadata, Metadata::Image { .. })
|
||||
|| (is_animated && !matches!(tag, Tag::avatars | Tag::icons))
|
||||
{
|
||||
return Ok(
|
||||
Redirect::permanent(&format!("/{tag}/{file_id}/{}", file.filename)).into_response(),
|
||||
Redirect::permanent(&format!("/{tag_str}/{file_id}/{}", file.filename)).into_response(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -380,7 +391,7 @@ async fn fetch_preview(
|
||||
// Read image and create thumbnail
|
||||
let data = create_thumbnail(
|
||||
decode_image(&mut Cursor::new(data), &file.content_type)?,
|
||||
tag,
|
||||
tag_str,
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -398,6 +409,8 @@ async fn fetch_preview(
|
||||
/// Fetch original file
|
||||
///
|
||||
/// Content disposition header will be set to 'attachment' to prevent browser from rendering anything.
|
||||
///
|
||||
/// Using `original` as the file name parameter will redirect you to the original file.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/{tag}/{file_id}/{file_name}",
|
||||
@@ -414,7 +427,8 @@ async fn fetch_file(
|
||||
State(db): State<Database>,
|
||||
Path((tag, file_id, file_name)): Path<(Tag, String, String)>,
|
||||
) -> Result<Response> {
|
||||
let file = db.fetch_attachment(tag.into(), &file_id).await?;
|
||||
let tag: &'static str = tag.clone().into();
|
||||
let file = db.fetch_attachment(tag, &file_id).await?;
|
||||
|
||||
// Ignore deleted files
|
||||
if file.deleted.is_some_and(|v| v) {
|
||||
@@ -428,6 +442,12 @@ async fn fetch_file(
|
||||
|
||||
// Ensure filename is correct
|
||||
if file_name != file.filename {
|
||||
if file_name == "original" {
|
||||
return Ok(
|
||||
Redirect::permanent(&format!("/{tag}/{file_id}/{}", file.filename)).into_response(),
|
||||
);
|
||||
}
|
||||
|
||||
return Err(create_error!(NotFound));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-january"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@@ -31,13 +31,13 @@ tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
||||
# Core crates
|
||||
revolt-config = { version = "0.8.0", path = "../../core/config" }
|
||||
revolt-models = { version = "0.8.0", path = "../../core/models" }
|
||||
revolt-result = { version = "0.8.0", path = "../../core/result", features = [
|
||||
revolt-config = { version = "0.8.1", path = "../../core/config" }
|
||||
revolt-models = { version = "0.8.1", path = "../../core/models" }
|
||||
revolt-result = { version = "0.8.1", path = "../../core/result", features = [
|
||||
"utoipa",
|
||||
"axum",
|
||||
] }
|
||||
revolt-files = { version = "0.8.0", path = "../../core/files" }
|
||||
revolt-files = { version = "0.8.1", path = "../../core/files" }
|
||||
|
||||
# Axum / web server
|
||||
axum = { version = "0.7.5" }
|
||||
|
||||
Reference in New Issue
Block a user