security upgrade
This commit is contained in:
+24
-56
@@ -16,6 +16,7 @@ pub async fn upload_pad_file(
|
||||
Path(slug): Path<String>,
|
||||
mut multipart: Multipart,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
require_upload_permission(&state, &headers).await?;
|
||||
let mut password: Option<String> = None;
|
||||
let mut access_token: Option<String> = None;
|
||||
let mut file: Option<(String, Vec<u8>)> = None;
|
||||
@@ -60,14 +61,6 @@ pub async fn upload_pad_file(
|
||||
&headers,
|
||||
)
|
||||
.await?;
|
||||
require_upload_permission(
|
||||
&state,
|
||||
&headers,
|
||||
"pad",
|
||||
&slug,
|
||||
resource_request_token(&headers, "pad", &slug, access_token.as_deref()),
|
||||
)
|
||||
.await?;
|
||||
let level = if db::verify_pad_password(&pad, password.as_deref())
|
||||
|| (pad.is_private == 0 && pad.password_hash.is_none())
|
||||
{
|
||||
@@ -190,10 +183,18 @@ pub async fn delete_pad_file(
|
||||
&headers,
|
||||
)
|
||||
.await?;
|
||||
if !crate::auth::is_resource_owner(&state, "pad", &pad.slug, bearer_token(&headers))
|
||||
.await
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let account_owner = crate::auth::is_resource_owner(
|
||||
&state,
|
||||
"pad",
|
||||
&pad.slug,
|
||||
bearer_token(&headers),
|
||||
)
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
let guest_owner = pad_creator_is_requester(&headers, &pad);
|
||||
let password_write_access =
|
||||
has_password_write_access(&state, &headers, "pad", &pad.slug).await?;
|
||||
if !account_owner && !guest_owner && !password_write_access {
|
||||
return Err(ApiError::forbidden("Only the note owner can delete files"));
|
||||
}
|
||||
let file = db::find_pad_file(&state.db, pad.id, file_id)
|
||||
@@ -212,6 +213,7 @@ pub async fn upload_note_file(
|
||||
Path((workspace_slug, note_slug)): Path<(String, String)>,
|
||||
mut multipart: Multipart,
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
require_upload_permission(&state, &headers).await?;
|
||||
let mut password: Option<String> = None;
|
||||
let mut access_token: Option<String> = None;
|
||||
let mut file: Option<(String, Vec<u8>)> = None;
|
||||
@@ -258,20 +260,6 @@ pub async fn upload_note_file(
|
||||
)
|
||||
.await?;
|
||||
|
||||
require_upload_permission(
|
||||
&state,
|
||||
&headers,
|
||||
"workspace",
|
||||
&workspace_slug,
|
||||
resource_request_token(
|
||||
&headers,
|
||||
"workspace",
|
||||
&workspace_slug,
|
||||
access_token.as_deref(),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let level = if db::verify_workspace_password(&workspace, password.as_deref())
|
||||
|| (workspace.is_private == 0 && workspace.password_hash.is_none())
|
||||
{
|
||||
@@ -433,19 +421,12 @@ pub async fn delete_note_file(
|
||||
)
|
||||
.await
|
||||
.unwrap_or(false);
|
||||
let note_owner = crate::auth::optional_user(&state, &headers)
|
||||
.await
|
||||
.ok()
|
||||
.flatten()
|
||||
.and_then(|user| {
|
||||
note.created_by
|
||||
.as_deref()
|
||||
.map(|creator| creator == user.nickname)
|
||||
})
|
||||
.unwrap_or(false);
|
||||
if !workspace_owner && !note_owner {
|
||||
let note_owner = note_creator_is_requester(&state, &headers, ¬e).await?;
|
||||
let password_write_access =
|
||||
has_password_write_access(&state, &headers, "workspace", &workspace.slug).await?;
|
||||
if !workspace_owner && !note_owner && !password_write_access {
|
||||
return Err(ApiError::forbidden(
|
||||
"Only the note owner or workspace owner can delete files",
|
||||
"Only the note owner, workspace owner, or password holder can delete files",
|
||||
));
|
||||
}
|
||||
let file = db::find_note_file(&state.db, note.id, file_id)
|
||||
@@ -461,29 +442,16 @@ pub async fn delete_note_file(
|
||||
async fn require_upload_permission(
|
||||
state: &SharedState,
|
||||
headers: &HeaderMap,
|
||||
kind: &str,
|
||||
slug: &str,
|
||||
resource_token: Option<&str>,
|
||||
) -> Result<(), ApiError> {
|
||||
let permission = crate::auth::share_link_permission(state, kind, slug, resource_token)
|
||||
.await
|
||||
.map_err(|error| ApiError::forbidden(&error.message))?;
|
||||
if permission.as_deref() == Some("rw") {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let user = crate::auth::optional_user(state, headers)
|
||||
.await
|
||||
.map_err(|error| ApiError::forbidden(&error.message))?;
|
||||
if user.is_some() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
match permission.as_deref() {
|
||||
Some("ro") => Err(ApiError::forbidden("Read-only access.")),
|
||||
_ => Err(ApiError::forbidden(
|
||||
"Log in or use a read-write share link to upload files.",
|
||||
)),
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ApiError::forbidden(
|
||||
"Log in with read-write access to upload files.",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user