|
|
|
@ -67,7 +67,7 @@ pub struct SendData {
|
|
|
|
|
file_length: Option<NumberOrString>,
|
|
|
|
|
|
|
|
|
|
// Used for key rotations
|
|
|
|
|
pub id: Option<String>,
|
|
|
|
|
pub id: Option<SendId>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Enforces the `Disable Send` policy. A non-owner/admin user belonging to
|
|
|
|
@ -158,8 +158,8 @@ async fn get_sends(headers: Headers, mut conn: DbConn) -> Json<Value> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[get("/sends/<uuid>")]
|
|
|
|
|
async fn get_send(uuid: &str, headers: Headers, mut conn: DbConn) -> JsonResult {
|
|
|
|
|
match Send::find_by_uuid_and_user(uuid, &headers.user.uuid, &mut conn).await {
|
|
|
|
|
async fn get_send(uuid: SendId, headers: Headers, mut conn: DbConn) -> JsonResult {
|
|
|
|
|
match Send::find_by_uuid_and_user(&uuid, &headers.user.uuid, &mut conn).await {
|
|
|
|
|
Some(send) => Ok(Json(send.to_json())),
|
|
|
|
|
None => err!("Send not found", "Invalid uuid or does not belong to user"),
|
|
|
|
|
}
|
|
|
|
@ -249,7 +249,7 @@ async fn post_send_file(data: Form<UploadData<'_>>, headers: Headers, mut conn:
|
|
|
|
|
err!("Send content is not a file");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let file_id = crate::crypto::generate_send_id();
|
|
|
|
|
let file_id = crate::crypto::generate_send_file_id();
|
|
|
|
|
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?;
|
|
|
|
@ -324,7 +324,7 @@ async fn post_send_file_v2(data: Json<SendData>, headers: Headers, mut conn: DbC
|
|
|
|
|
|
|
|
|
|
let mut send = create_send(data, headers.user.uuid)?;
|
|
|
|
|
|
|
|
|
|
let file_id = crate::crypto::generate_send_id();
|
|
|
|
|
let file_id = crate::crypto::generate_send_file_id();
|
|
|
|
|
|
|
|
|
|
let mut data_value: Value = serde_json::from_str(&send.data)?;
|
|
|
|
|
if let Some(o) = data_value.as_object_mut() {
|
|
|
|
@ -352,9 +352,9 @@ pub struct SendFileData {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// https://github.com/bitwarden/server/blob/66f95d1c443490b653e5a15d32977e2f5a3f9e32/src/Api/Tools/Controllers/SendsController.cs#L250
|
|
|
|
|
#[post("/sends/<send_uuid>/file/<file_id>", format = "multipart/form-data", data = "<data>")]
|
|
|
|
|
#[post("/sends/<uuid>/file/<file_id>", format = "multipart/form-data", data = "<data>")]
|
|
|
|
|
async fn post_send_file_v2_data(
|
|
|
|
|
send_uuid: &str,
|
|
|
|
|
uuid: SendId,
|
|
|
|
|
file_id: &str,
|
|
|
|
|
data: Form<UploadDataV2<'_>>,
|
|
|
|
|
headers: Headers,
|
|
|
|
@ -365,7 +365,7 @@ async fn post_send_file_v2_data(
|
|
|
|
|
|
|
|
|
|
let mut data = data.into_inner();
|
|
|
|
|
|
|
|
|
|
let Some(send) = Send::find_by_uuid_and_user(send_uuid, &headers.user.uuid, &mut conn).await else {
|
|
|
|
|
let Some(send) = Send::find_by_uuid_and_user(&uuid, &headers.user.uuid, &mut conn).await else {
|
|
|
|
|
err!("Send not found. Unable to save the file.", "Invalid uuid or does not belong to user.")
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -402,7 +402,7 @@ async fn post_send_file_v2_data(
|
|
|
|
|
err!("Send file size does not match.", format!("Expected a file size of {} got {size}", send_data.size));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let folder_path = tokio::fs::canonicalize(&CONFIG.sends_folder()).await?.join(send_uuid);
|
|
|
|
|
let folder_path = tokio::fs::canonicalize(&CONFIG.sends_folder()).await?.join(uuid);
|
|
|
|
|
let file_path = folder_path.join(file_id);
|
|
|
|
|
|
|
|
|
|
// Check if the file already exists, if that is the case do not overwrite it
|
|
|
|
@ -493,16 +493,16 @@ async fn post_access(
|
|
|
|
|
Ok(Json(send.to_json_access(&mut conn).await))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[post("/sends/<send_id>/access/file/<file_id>", data = "<data>")]
|
|
|
|
|
#[post("/sends/<uuid>/access/file/<file_id>", data = "<data>")]
|
|
|
|
|
async fn post_access_file(
|
|
|
|
|
send_id: &str,
|
|
|
|
|
uuid: SendId,
|
|
|
|
|
file_id: &str,
|
|
|
|
|
data: Json<SendAccessData>,
|
|
|
|
|
host: Host,
|
|
|
|
|
mut conn: DbConn,
|
|
|
|
|
nt: Notify<'_>,
|
|
|
|
|
) -> JsonResult {
|
|
|
|
|
let Some(mut send) = Send::find_by_uuid(send_id, &mut conn).await else {
|
|
|
|
|
let Some(mut send) = Send::find_by_uuid(&uuid, &mut conn).await else {
|
|
|
|
|
err_code!(SEND_INACCESSIBLE_MSG, 404)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -547,33 +547,39 @@ async fn post_access_file(
|
|
|
|
|
)
|
|
|
|
|
.await;
|
|
|
|
|
|
|
|
|
|
let token_claims = crate::auth::generate_send_claims(send_id, file_id);
|
|
|
|
|
let token_claims = crate::auth::generate_send_claims(&uuid, file_id);
|
|
|
|
|
let token = crate::auth::encode_jwt(&token_claims);
|
|
|
|
|
Ok(Json(json!({
|
|
|
|
|
"object": "send-fileDownload",
|
|
|
|
|
"id": file_id,
|
|
|
|
|
"url": format!("{}/api/sends/{}/{}?t={}", &host.host, send_id, file_id, token)
|
|
|
|
|
"url": format!("{}/api/sends/{}/{}?t={}", &host.host, uuid, file_id, token)
|
|
|
|
|
})))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[get("/sends/<send_id>/<file_id>?<t>")]
|
|
|
|
|
async fn download_send(send_id: SafeString, file_id: SafeString, t: &str) -> Option<NamedFile> {
|
|
|
|
|
#[get("/sends/<uuid>/<file_id>?<t>")]
|
|
|
|
|
async fn download_send(uuid: SendId, file_id: SafeString, t: &str) -> Option<NamedFile> {
|
|
|
|
|
if let Ok(claims) = crate::auth::decode_send(t) {
|
|
|
|
|
if claims.sub == format!("{send_id}/{file_id}") {
|
|
|
|
|
return NamedFile::open(Path::new(&CONFIG.sends_folder()).join(send_id).join(file_id)).await.ok();
|
|
|
|
|
if claims.sub == format!("{uuid}/{file_id}") {
|
|
|
|
|
return NamedFile::open(Path::new(&CONFIG.sends_folder()).join(uuid).join(file_id)).await.ok();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[put("/sends/<uuid>", data = "<data>")]
|
|
|
|
|
async fn put_send(uuid: &str, data: Json<SendData>, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult {
|
|
|
|
|
async fn put_send(
|
|
|
|
|
uuid: SendId,
|
|
|
|
|
data: Json<SendData>,
|
|
|
|
|
headers: Headers,
|
|
|
|
|
mut conn: DbConn,
|
|
|
|
|
nt: Notify<'_>,
|
|
|
|
|
) -> JsonResult {
|
|
|
|
|
enforce_disable_send_policy(&headers, &mut conn).await?;
|
|
|
|
|
|
|
|
|
|
let data: SendData = data.into_inner();
|
|
|
|
|
enforce_disable_hide_email_policy(&data, &headers, &mut conn).await?;
|
|
|
|
|
|
|
|
|
|
let Some(mut send) = Send::find_by_uuid_and_user(uuid, &headers.user.uuid, &mut conn).await else {
|
|
|
|
|
let Some(mut send) = Send::find_by_uuid_and_user(&uuid, &headers.user.uuid, &mut conn).await else {
|
|
|
|
|
err!("Send not found", "Send uuid is invalid or does not belong to user")
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -641,8 +647,8 @@ pub async fn update_send_from_data(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[delete("/sends/<uuid>")]
|
|
|
|
|
async fn delete_send(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
|
|
|
|
|
let Some(send) = Send::find_by_uuid_and_user(uuid, &headers.user.uuid, &mut conn).await else {
|
|
|
|
|
async fn delete_send(uuid: SendId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
|
|
|
|
|
let Some(send) = Send::find_by_uuid_and_user(&uuid, &headers.user.uuid, &mut conn).await else {
|
|
|
|
|
err!("Send not found", "Invalid send uuid, or does not belong to user")
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -660,10 +666,10 @@ async fn delete_send(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[put("/sends/<uuid>/remove-password")]
|
|
|
|
|
async fn put_remove_password(uuid: &str, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult {
|
|
|
|
|
async fn put_remove_password(uuid: SendId, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> JsonResult {
|
|
|
|
|
enforce_disable_send_policy(&headers, &mut conn).await?;
|
|
|
|
|
|
|
|
|
|
let Some(mut send) = Send::find_by_uuid_and_user(uuid, &headers.user.uuid, &mut conn).await else {
|
|
|
|
|
let Some(mut send) = Send::find_by_uuid_and_user(&uuid, &headers.user.uuid, &mut conn).await else {
|
|
|
|
|
err!("Send not found", "Invalid send uuid, or does not belong to user")
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|