Skip to content

Commit 3b6646d

Browse files
committed
feat: v0.7.0
1 parent bb5cac0 commit 3b6646d

4 files changed

Lines changed: 40 additions & 18 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "emunex-server"
33
description = "Remote Emulation & Library Management - Server"
44
repository = "https://github.com/chloecinders/emuNEX-server"
55
authors = ["chloecinders"]
6-
version = "0.6.0"
6+
version = "0.7.0"
77
edition = "2024"
88

99
[dependencies]

src/routes/api/v1/saves.rs

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::{collections::HashMap, path::PathBuf};
2-
31
use base64::{Engine as _, engine::general_purpose};
42
use rocket::{get, post, serde::json::Json};
53
use serde::Serialize;
@@ -14,9 +12,16 @@ use crate::{
1412
utils::s3::{download_object, upload_object},
1513
};
1614

15+
#[derive(serde::Deserialize)]
16+
pub struct V1SaveUploadFile {
17+
pub hash: String,
18+
pub path: String,
19+
pub content: String,
20+
}
21+
1722
#[derive(serde::Deserialize)]
1823
pub struct V1SaveUploadRequest {
19-
pub files: HashMap<String, String>,
24+
pub files: Vec<V1SaveUploadFile>,
2025
}
2126

2227
#[post("/api/v1/roms/<id>/save/<version_id>", data = "<data>")]
@@ -26,18 +31,26 @@ pub async fn upload_save(
2631
data: Json<V1SaveUploadRequest>,
2732
user: AuthenticatedUser,
2833
) -> V1ApiResponseType<()> {
29-
for (file_name, b64_content) in data.files.iter() {
30-
let buffer = general_purpose::STANDARD.decode(b64_content).map_err(|e| {
31-
error!("Failed to decode base64 for file '{}': {:?}", file_name, e);
32-
V1ApiError::BadRequest
33-
})?;
34-
35-
let save_path = format!("/saves/{}/{}/{}/{}", user.id.value(), id, version_id, file_name);
34+
for file in data.files.iter() {
35+
let buffer = general_purpose::STANDARD
36+
.decode(&file.content)
37+
.map_err(|e| {
38+
error!("Failed to decode base64 for file '{}': {:?}", file.path, e);
39+
V1ApiError::BadRequest
40+
})?;
41+
42+
let save_path = format!(
43+
"/saves/{}/{}/{}/{}",
44+
user.id.value(),
45+
id,
46+
version_id,
47+
file.hash
48+
);
3649

3750
upload_object(&save_path, &buffer).await.map_err(|e| {
3851
error!(
3952
"Failed to upload save file '{}' to '{}': {:?}",
40-
file_name, save_path, e
53+
file.path, save_path, e
4154
);
4255
V1ApiError::InternalError
4356
})?;
@@ -51,15 +64,15 @@ pub async fn upload_save(
5164
user.id.value(),
5265
id,
5366
version_id,
54-
file_name,
67+
file.path,
5568
save_path
5669
)
5770
.execute(&*SQL)
5871
.await
5972
.map_err(|e| {
6073
error!(
6174
"Database error inserting save file '{}': {:?}",
62-
file_name, e
75+
file.path, e
6376
);
6477
V1ApiError::InternalError
6578
})?;
@@ -68,14 +81,19 @@ pub async fn upload_save(
6881
Ok(V1ApiResponse(()))
6982
}
7083

71-
#[get("/api/v1/roms/<id>/save/<version_id>/<file_name>", rank = 1)]
84+
#[derive(serde::Deserialize)]
85+
pub struct V1SaveDownloadRequest {
86+
pub path: String,
87+
}
88+
89+
#[post("/api/v1/roms/<id>/save/<version_id>/download", data = "<data>")]
7290
pub async fn download_save_file(
7391
id: String,
7492
version_id: i64,
75-
file_name: PathBuf,
93+
data: Json<V1SaveDownloadRequest>,
7694
user: AuthenticatedUser,
7795
) -> Result<Vec<u8>, V1ApiError> {
78-
let file_name_str = file_name.to_str().ok_or(V1ApiError::BadRequest)?;
96+
let file_name_str = &data.path;
7997

8098
let record = sqlx::query!(
8199
"SELECT save_path FROM user_save_files

src/routes/proxy.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ pub async fn storage(file: std::path::PathBuf) -> Result<Vec<u8>, Status> {
1212
let display_path = file.display().to_string().replace("\\", "/");
1313
let key = format!("/{}", display_path);
1414

15+
if key.starts_with("/saves/") {
16+
return Err(Status::Forbidden);
17+
}
18+
1519
let is_small_cover = key.starts_with("/covers_small/");
1620
let is_large_cover = key.starts_with("/covers/");
1721
let is_icon = key.starts_with("/icons/");

0 commit comments

Comments
 (0)