2022-04-24 19:31:50 +00:00
|
|
|
use std::{fs, path::Path};
|
|
|
|
|
2022-05-01 18:34:28 +00:00
|
|
|
use crate::fs::validate_path;
|
2022-04-24 19:31:50 +00:00
|
|
|
use axum::{extract::rejection::JsonRejection, Extension, Json};
|
|
|
|
use axum_auth::AuthBearer;
|
2022-05-01 18:34:28 +00:00
|
|
|
use homedisk_database::Database;
|
2022-04-24 19:31:50 +00:00
|
|
|
use homedisk_types::{
|
|
|
|
config::types::Config,
|
2022-05-01 18:34:28 +00:00
|
|
|
errors::{FsError, ServerError},
|
2022-04-24 19:31:50 +00:00
|
|
|
fs::upload::{Request, Response},
|
|
|
|
};
|
|
|
|
|
2022-05-01 18:34:28 +00:00
|
|
|
use crate::middleware::{find_user, validate_json, validate_jwt};
|
2022-04-24 19:31:50 +00:00
|
|
|
|
|
|
|
pub async fn handle(
|
2022-05-01 18:34:28 +00:00
|
|
|
Extension(db): Extension<Database>,
|
|
|
|
Extension(config): Extension<Config>,
|
2022-04-24 19:31:50 +00:00
|
|
|
AuthBearer(token): AuthBearer,
|
|
|
|
request: Result<Json<Request>, JsonRejection>,
|
|
|
|
) -> Result<Json<Response>, ServerError> {
|
|
|
|
let Json(request) = validate_json::<Request>(request)?;
|
|
|
|
let token = validate_jwt(config.jwt.secret.as_bytes(), &token)?;
|
|
|
|
|
2022-05-01 18:34:28 +00:00
|
|
|
// validate the `path` can be used
|
|
|
|
validate_path(&request.path)?;
|
2022-04-24 19:31:50 +00:00
|
|
|
|
2022-05-01 18:34:28 +00:00
|
|
|
// search for a user by UUID from a token
|
|
|
|
let user = find_user(db, token.claims.sub).await?;
|
2022-04-24 19:31:50 +00:00
|
|
|
|
2022-05-01 18:34:28 +00:00
|
|
|
// get file content
|
|
|
|
let content = base64::decode(request.content)
|
|
|
|
.map_err(|err| ServerError::FsError(FsError::Base64(err.to_string())))?;
|
2022-04-30 20:19:53 +00:00
|
|
|
|
2022-05-01 18:34:28 +00:00
|
|
|
// directory where the file will be placed
|
|
|
|
let dir = format!(
|
|
|
|
"{user_dir}/{req_dir}",
|
|
|
|
user_dir = user.user_dir(&config.storage.path),
|
|
|
|
req_dir = request.path
|
|
|
|
);
|
|
|
|
let path = Path::new(&dir);
|
2022-04-24 19:31:50 +00:00
|
|
|
|
2022-05-01 18:34:28 +00:00
|
|
|
// check if the file currently exists to avoid overwriting it
|
|
|
|
if path.exists() {
|
|
|
|
return Err(ServerError::FsError(FsError::FileAlreadyExists));
|
|
|
|
}
|
2022-04-24 19:31:50 +00:00
|
|
|
|
2022-05-01 18:34:28 +00:00
|
|
|
// create a directory where the file will be placed
|
|
|
|
// e.g. path ==> `/secret/files/images/screenshot.png`
|
|
|
|
// directories up to `/home/homedisk/{username}/secret/files/images/` will be created
|
|
|
|
match path.parent() {
|
|
|
|
Some(prefix) => fs::create_dir_all(&prefix).unwrap(),
|
|
|
|
None => (),
|
|
|
|
}
|
2022-04-24 19:31:50 +00:00
|
|
|
|
2022-05-01 18:34:28 +00:00
|
|
|
// write file
|
|
|
|
fs::write(&path, &content)
|
|
|
|
.map_err(|err| ServerError::FsError(FsError::WriteFile(err.to_string())))?;
|
2022-04-24 19:31:50 +00:00
|
|
|
|
2022-05-01 18:34:28 +00:00
|
|
|
Ok(Json(Response { uploaded: true }))
|
2022-04-24 19:31:50 +00:00
|
|
|
}
|