Skip to content

Commit

Permalink
WIP: Send API v2
Browse files Browse the repository at this point in the history
  • Loading branch information
BlackDex committed Sep 20, 2022
1 parent 9c891ba commit 7c3a51e
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 9 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ tracing = { version = "0.1.36", features = ["log"] } # Needed to have lettre and
backtrace = "0.3.66" # Logging panics to logfile instead stderr only

# A `dotenv` implementation for Rust
dotenvy = { version = "=0.15.1", default-features = false }
dotenvy = { version = "0.15.5", default-features = false }

# Lazy initialization
once_cell = "1.14.0"
Expand Down
106 changes: 101 additions & 5 deletions src/api/core/sends.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ pub fn routes() -> Vec<rocket::Route> {
put_send,
delete_send,
put_remove_password,
download_send
download_send,
post_send_file_v2,
post_send_file_v2_data
]
}

Expand All @@ -41,7 +43,7 @@ pub async fn purge_sends(pool: DbPool) {
}
}

#[derive(Deserialize)]
#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
struct SendData {
Type: i32,
Expand All @@ -58,6 +60,7 @@ struct SendData {
Notes: Option<String>,
Text: Option<Value>,
File: Option<Value>,
FileLength: Option<NumberOrString>,
}

/// Enforces the `Disable Send` policy. A non-owner/admin user belonging to
Expand Down Expand Up @@ -185,6 +188,14 @@ struct UploadData<'f> {
data: TempFile<'f>,
}

#[derive(FromForm, Debug)]
struct UploadDataV2<'f> {
data: TempFile<'f>,
}

// Get the file length and add an extra 5% to avoid issues
const SIZE_525_MB: u64 = 550_502_400;

#[post("/sends/file", format = "multipart/form-data", data = "<data>")]
async fn post_send_file(data: Form<UploadData<'_>>, headers: Headers, conn: DbConn, nt: Notify<'_>) -> JsonResult {
enforce_disable_send_policy(&headers, &conn).await?;
Expand All @@ -197,9 +208,6 @@ async fn post_send_file(data: Form<UploadData<'_>>, headers: Headers, conn: DbCo

enforce_disable_hide_email_policy(&model, &headers, &conn).await?;

// Get the file length and add an extra 5% to avoid issues
const SIZE_525_MB: u64 = 550_502_400;

let size_limit = match CONFIG.user_attachment_limit() {
Some(0) => err!("File uploads are disabled"),
Some(limit_kb) => {
Expand Down Expand Up @@ -257,6 +265,94 @@ async fn post_send_file(data: Form<UploadData<'_>>, headers: Headers, conn: DbCo
Ok(Json(send.to_json()))
}

#[post("/sends/file/v2", data = "<data>")]
async fn post_send_file_v2(data: JsonUpcase<SendData>, headers: Headers, conn: DbConn, _nt: Notify<'_>) -> JsonResult {
enforce_disable_send_policy(&headers, &conn).await?;

let data = data.into_inner().data;

if data.Type != SendType::File as i32 {
err!("Send content is not a file");
}

let file_length = match &data.FileLength {
Some(m) => Some(m.into_i32()?),
_ => None,
};

let size_limit = match CONFIG.user_attachment_limit() {
Some(0) => err!("File uploads are disabled"),
Some(limit_kb) => {
let left = (limit_kb * 1024) - Attachment::size_by_user(&headers.user.uuid, &conn).await;
if left <= 0 {
err!("Attachment storage limit reached! Delete some attachments to free up space")
}
std::cmp::Ord::max(left as u64, SIZE_525_MB)
}
None => SIZE_525_MB,
};

if file_length.is_some() && file_length.unwrap() as u64 > size_limit {
err!("Attachment storage limit exceeded with this file");
}

let mut send = create_send(data, headers.user.uuid)?;

let file_id = crate::crypto::generate_send_id();

let mut data_value: Value = serde_json::from_str(&send.data)?;
if let Some(o) = data_value.as_object_mut() {
o.insert(String::from("Id"), Value::String(file_id.clone()));
o.insert(String::from("Size"), Value::Number(file_length.unwrap().into()));
o.insert(String::from("SizeName"), Value::String(crate::util::get_display_size(file_length.unwrap())));
}
send.data = serde_json::to_string(&data_value)?;
send.save(&conn).await?;

Ok(Json(json!({
"fileUploadType": 0, // 0 == Direct | 1 == Azure
"object": "send-fileUpload",
"url": format!("/sends/{}/file/{}", send.uuid, file_id),
"sendResponse": send.to_json()
})))
}

#[post("/sends/<send_uuid>/file/<file_id>", format = "multipart/form-data", data = "<data>")]
async fn post_send_file_v2_data(
send_uuid: String,
file_id: String,
data: Form<UploadDataV2<'_>>,
headers: Headers,
conn: DbConn,
_nt: Notify<'_>,
) -> JsonResult {
enforce_disable_send_policy(&headers, &conn).await?;

let mut data = data.into_inner();

// There seems to be a bug somewhere regarding uploading attachments using the Android Client (Maybe iOS too?)
// See: https://github.com/dani-garcia/vaultwarden/issues/2644
// Since all other clients seem to match TempFile::File and not TempFile::Buffered lets catch this and return an error for now.
// We need to figure out how to solve this, but for now it's better to not accept these attachments since they will be broken.
if let TempFile::Buffered {
content: _,
} = &data.data
{
err!("Error reading attachment data. Please try an other client.");
}

let folder_path = tokio::fs::canonicalize(&CONFIG.sends_folder()).await?.join(&send_uuid);
let file_path = folder_path.join(&file_id);
tokio::fs::create_dir_all(&folder_path).await?;

if let Err(_err) = data.data.persist_to(&file_path).await {
data.data.move_copy_to(file_path).await?
}
// nt.send_send_update(UpdateType::SyncSendUpdate, &send, &send.update_users_revision(&conn).await).await;

Ok(Json(json!({})))
}

#[derive(Deserialize)]
#[allow(non_snake_case)]
pub struct SendAccessData {
Expand Down
2 changes: 1 addition & 1 deletion src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ use serde_json::{self, Value};

pub type JsonMap = serde_json::Map<String, Value>;

#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Debug)]
pub struct UpCase<T: DeserializeOwned> {
#[serde(deserialize_with = "upcase_deserialize")]
#[serde(flatten)]
Expand Down

0 comments on commit 7c3a51e

Please sign in to comment.