security: fix vulnerabilities 1-7 from security audit
- Fix #1: Share handler IDOR - enforce owner check on share operations - Fix #2: list_files_query IDOR - bind folder queries to authenticated user - Fix #3: Dedup handler IDOR - restrict dedup operations to file owner - Fix #4: Trash handler OptionalAuthUser - require full AuthUser - Fix #5: Error info leakage - sanitize 500 error responses - Fix #6: Chunked upload IDOR - bind upload sessions to user_id, add verify_session_owner() check on all session operations - Fix #7: CSP unsafe-inline removal - migrate all inline scripts, styles and event handlers to external files, tighten CSP to script-src 'self'; style-src 'self' New files: - static/js/core/theme-init.js (render-blocking theme init) - static/js/core/sw-register.js (service worker registration) - static/css/views/device-verify.css (extracted inline styles) - static/js/views/device-verify/device-verify.js (extracted inline script)
This commit is contained in:
@@ -59,6 +59,7 @@ pub trait ChunkedUploadPort: Send + Sync + 'static {
|
||||
/// total number of chunks, and expiration timestamp.
|
||||
async fn create_session(
|
||||
&self,
|
||||
user_id: &str,
|
||||
filename: String,
|
||||
folder_id: Option<String>,
|
||||
content_type: String,
|
||||
@@ -72,13 +73,14 @@ pub trait ChunkedUploadPort: Send + Sync + 'static {
|
||||
async fn upload_chunk(
|
||||
&self,
|
||||
upload_id: &str,
|
||||
user_id: &str,
|
||||
chunk_index: usize,
|
||||
data: Bytes,
|
||||
checksum: Option<String>,
|
||||
) -> Result<ChunkUploadResponseDto, DomainError>;
|
||||
|
||||
/// Get the current status of an upload session.
|
||||
async fn get_status(&self, upload_id: &str) -> Result<UploadStatusResponseDto, DomainError>;
|
||||
async fn get_status(&self, upload_id: &str, user_id: &str) -> Result<UploadStatusResponseDto, DomainError>;
|
||||
|
||||
/// Assemble all chunks into the final file.
|
||||
///
|
||||
@@ -88,13 +90,14 @@ pub trait ChunkedUploadPort: Send + Sync + 'static {
|
||||
async fn complete_upload(
|
||||
&self,
|
||||
upload_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<(PathBuf, String, Option<String>, String, u64, String), DomainError>;
|
||||
|
||||
/// Finalize upload: clean up the session and temporary files.
|
||||
async fn finalize_upload(&self, upload_id: &str) -> Result<(), DomainError>;
|
||||
async fn finalize_upload(&self, upload_id: &str, user_id: &str) -> Result<(), DomainError>;
|
||||
|
||||
/// Cancel an upload and clean up all temporary data.
|
||||
async fn cancel_upload(&self, upload_id: &str) -> Result<(), DomainError>;
|
||||
async fn cancel_upload(&self, upload_id: &str, user_id: &str) -> Result<(), DomainError>;
|
||||
|
||||
/// Check if a file size qualifies for chunked upload.
|
||||
fn should_use_chunked(&self, size: u64) -> bool;
|
||||
|
||||
@@ -15,28 +15,34 @@ pub trait ShareUseCase: Send + Sync + 'static {
|
||||
dto: CreateShareDto,
|
||||
) -> Result<ShareDto, DomainError>;
|
||||
|
||||
/// Get a shared link by its ID
|
||||
async fn get_shared_link(&self, id: &str) -> Result<ShareDto, DomainError>;
|
||||
/// Get a shared link by its ID (ownership-verified)
|
||||
async fn get_shared_link(
|
||||
&self,
|
||||
id: &str,
|
||||
requester_id: &str,
|
||||
) -> Result<ShareDto, DomainError>;
|
||||
|
||||
/// Get a shared link by its token (for access by non-users)
|
||||
async fn get_shared_link_by_token(&self, token: &str) -> Result<ShareDto, DomainError>;
|
||||
|
||||
/// Get all shared links for a specific item
|
||||
/// Get all shared links for a specific item (ownership-verified)
|
||||
async fn get_shared_links_for_item(
|
||||
&self,
|
||||
item_id: &str,
|
||||
item_type: &ShareItemType,
|
||||
requester_id: &str,
|
||||
) -> Result<Vec<ShareDto>, DomainError>;
|
||||
|
||||
/// Update a shared link
|
||||
/// Update a shared link (ownership-verified)
|
||||
async fn update_shared_link(
|
||||
&self,
|
||||
id: &str,
|
||||
requester_id: &str,
|
||||
dto: UpdateShareDto,
|
||||
) -> Result<ShareDto, DomainError>;
|
||||
|
||||
/// Delete a shared link
|
||||
async fn delete_shared_link(&self, id: &str) -> Result<(), DomainError>;
|
||||
/// Delete a shared link (ownership-verified)
|
||||
async fn delete_shared_link(&self, id: &str, requester_id: &str) -> Result<(), DomainError>;
|
||||
|
||||
/// Get all shared links created by a specific user
|
||||
async fn get_user_shared_links(
|
||||
@@ -63,20 +69,29 @@ pub trait ShareStoragePort: Send + Sync + 'static {
|
||||
share: &crate::domain::entities::share::Share,
|
||||
) -> Result<crate::domain::entities::share::Share, DomainError>;
|
||||
|
||||
async fn find_share_by_id(
|
||||
&self,
|
||||
id: &str,
|
||||
) -> Result<crate::domain::entities::share::Share, DomainError>;
|
||||
|
||||
async fn find_share_by_token(
|
||||
&self,
|
||||
token: &str,
|
||||
) -> Result<crate::domain::entities::share::Share, DomainError>;
|
||||
|
||||
async fn find_shares_by_item(
|
||||
/// Find a share by ID only if it belongs to the given user.
|
||||
/// Returns `NotFound` if the share doesn't exist OR belongs to another user
|
||||
/// (prevents share-ID enumeration).
|
||||
async fn find_share_by_id_for_user(
|
||||
&self,
|
||||
id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<crate::domain::entities::share::Share, DomainError>;
|
||||
|
||||
/// Delete a share only if it belongs to the given user.
|
||||
async fn delete_share_for_user(&self, id: &str, user_id: &str) -> Result<(), DomainError>;
|
||||
|
||||
/// Find shares for a specific item that belong to the given user.
|
||||
async fn find_shares_by_item_for_user(
|
||||
&self,
|
||||
item_id: &str,
|
||||
item_type: &ShareItemType,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<crate::domain::entities::share::Share>, DomainError>;
|
||||
|
||||
async fn update_share(
|
||||
@@ -84,8 +99,6 @@ pub trait ShareStoragePort: Send + Sync + 'static {
|
||||
share: &crate::domain::entities::share::Share,
|
||||
) -> Result<crate::domain::entities::share::Share, DomainError>;
|
||||
|
||||
async fn delete_share(&self, id: &str) -> Result<(), DomainError>;
|
||||
|
||||
async fn find_shares_by_user(
|
||||
&self,
|
||||
user_id: &str,
|
||||
|
||||
Reference in New Issue
Block a user