fix: resolve clippy warnings and rustfmt issues for CI compliance

Fix all clippy lints (collapsible if, clone on Copy, needless borrow,
redundant bindings, unused params) and apply rustfmt across the codebase.
Update test mocks to match Uuid-based trait signatures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
zjean
2026-03-09 14:34:07 +01:00
parent cf9fe82b5f
commit 18518bedaf
34 changed files with 370 additions and 336 deletions
+5 -1
View File
@@ -73,7 +73,11 @@ async fn admin_guard(state: &AppState, headers: &HeaderMap) -> Result<(Uuid, Str
));
}
Ok((Uuid::parse_str(&claims.sub).map_err(|_| AppError::internal_error("Invalid user ID in token"))?, claims.role))
Ok((
Uuid::parse_str(&claims.sub)
.map_err(|_| AppError::internal_error("Invalid user ID in token"))?,
claims.role,
))
}
/// GET /api/admin/settings/oidc — get OIDC settings for the admin panel
@@ -75,10 +75,7 @@ async fn revoke_app_password(
let id = Uuid::parse_str(&id).map_err(|_| AppError::bad_request("Invalid UUID"))?;
let response = service
.revoke(user.id, id)
.await
.map_err(AppError::from)?;
let response = service.revoke(user.id, id).await.map_err(AppError::from)?;
Ok(Json(response))
}
@@ -299,13 +299,12 @@ async fn handle_propfind(
} else {
// Not a calendar ID — treat as user calendar home (e.g. /caldav/{username}/)
// List all calendars for this user
let calendars =
calendar_service
.list_my_calendars(user.id)
.await
.map_err(|e| {
AppError::internal_error(format!("Failed to list calendars: {}", e))
})?;
let calendars = calendar_service
.list_my_calendars(user.id)
.await
.map_err(|e| {
AppError::internal_error(format!("Failed to list calendars: {}", e))
})?;
let base_href = &format!("/caldav/{}/", first_segment);
let mut response_body = Vec::new();
@@ -190,13 +190,7 @@ impl ChunkedUploadHandler {
});
match chunked_service
.upload_chunk(
&upload_id,
auth_user.id,
params.chunk_index,
body,
checksum,
)
.upload_chunk(&upload_id, auth_user.id, params.chunk_index, body, checksum)
.await
{
Ok(response) => {
+7 -2
View File
@@ -99,7 +99,9 @@ impl DedupHandler {
}
// Only reveal whether THIS user has the blob — no global oracle
let user_has_it = dedup.user_owns_blob_reference(&hash, &auth_user.id.to_string()).await;
let user_has_it = dedup
.user_owns_blob_reference(&hash, &auth_user.id.to_string())
.await;
if user_has_it {
// Fetch size from metadata (safe — user owns a reference)
@@ -346,7 +348,10 @@ impl DedupHandler {
}
// Verify the user owns at least one file referencing this blob
if !dedup.user_owns_blob_reference(&hash, &auth_user.id.to_string()).await {
if !dedup
.user_owns_blob_reference(&hash, &auth_user.id.to_string())
.await
{
return Response::builder()
.status(StatusCode::NOT_FOUND)
.header(header::CONTENT_TYPE, "application/json")
@@ -203,7 +203,8 @@ async fn revoke_device(
) -> Result<impl IntoResponse, AppError> {
let device_service = get_device_service(&state)?;
let device_id = Uuid::parse_str(&device_id).map_err(|_| AppError::bad_request("Invalid device ID"))?;
let device_id =
Uuid::parse_str(&device_id).map_err(|_| AppError::bad_request("Invalid device ID"))?;
device_service
.revoke_device(device_id, auth_user.id)
+37 -47
View File
@@ -109,7 +109,11 @@ impl FileHandler {
if let Some(ref fid) = folder_id {
use crate::application::ports::inbound::FolderUseCase;
let folder_service = &state.applications.folder_service;
if folder_service.get_folder_owned(fid, auth_user.id).await.is_err() {
if folder_service
.get_folder_owned(fid, auth_user.id)
.await
.is_err()
{
tracing::warn!(
"⛔ UPLOAD REJECTED (IDOR): user='{}' attempted upload to folder '{}' owned by another user",
auth_user.username,
@@ -336,18 +340,17 @@ impl FileHandler {
// (file_id, size) pair. If the browser already has it, return 304
// with zero I/O or DB work.
let etag = format!("\"thumb-{}-{:?}\"", id, thumb_size);
if let Some(if_none_match) = headers.get(header::IF_NONE_MATCH) {
if let Ok(val) = if_none_match.to_str() {
if val == etag || val == "*" {
return Response::builder()
.status(StatusCode::NOT_MODIFIED)
.header(header::ETAG, &etag)
.header(header::CACHE_CONTROL, "public, max-age=31536000, immutable")
.body(Body::empty())
.unwrap()
.into_response();
}
}
if let Some(if_none_match) = headers.get(header::IF_NONE_MATCH)
&& let Ok(val) = if_none_match.to_str()
&& (val == etag || val == "*")
{
return Response::builder()
.status(StatusCode::NOT_MODIFIED)
.header(header::ETAG, &etag)
.header(header::CACHE_CONTROL, "public, max-age=31536000, immutable")
.body(Body::empty())
.unwrap()
.into_response();
}
// ── Cache-first path (Solution A) ────────────────────────────
@@ -409,21 +412,17 @@ impl FileHandler {
.get_thumbnail(&id, thumb_size.into(), &file_path)
.await
{
Ok(data) => {
Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, "image/jpeg")
.header(header::CONTENT_LENGTH, data.len())
.header(header::CACHE_CONTROL, "public, max-age=31536000, immutable")
.header(header::ETAG, &etag)
.body(Body::from(data))
.unwrap()
.into_response()
}
Err(err) => {
AppError::internal_error(format!("Thumbnail generation failed: {}", err))
.into_response()
}
Ok(data) => Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, "image/jpeg")
.header(header::CONTENT_LENGTH, data.len())
.header(header::CACHE_CONTROL, "public, max-age=31536000, immutable")
.header(header::ETAG, &etag)
.body(Body::from(data))
.unwrap()
.into_response(),
Err(err) => AppError::internal_error(format!("Thumbnail generation failed: {}", err))
.into_response(),
}
}
@@ -487,10 +486,8 @@ impl FileHandler {
.await
{
Ok(_) => StatusCode::CREATED.into_response(),
Err(err) => {
AppError::internal_error(format!("Failed to store thumbnail: {}", err))
.into_response()
}
Err(err) => AppError::internal_error(format!("Failed to store thumbnail: {}", err))
.into_response(),
}
}
@@ -663,9 +660,7 @@ impl FileHandler {
.unwrap()
.into_response(),
},
Err(err) => {
AppError::from(err).into_response()
}
Err(err) => AppError::from(err).into_response(),
}
}
@@ -715,9 +710,7 @@ impl FileHandler {
.insert(header::ETAG, header::HeaderValue::from_str(&etag).unwrap());
resp
}
Err(err) => {
AppError::from(err).into_response()
}
Err(err) => AppError::from(err).into_response(),
}
}
@@ -750,8 +743,7 @@ impl FileHandler {
tokio::spawn(async move {
tracing::info!("🖼️ Generating thumbnails for: {}", file_id);
thumbnail_service
.generate_all_sizes_background(file_id, file_path);
thumbnail_service.generate_all_sizes_background(file_id, file_path);
});
}
@@ -832,7 +824,7 @@ impl FileHandler {
match result {
Ok(_) => StatusCode::NO_CONTENT.into_response(),
Err(err) => AppError::from(err).into_response()
Err(err) => AppError::from(err).into_response(),
}
}
@@ -864,7 +856,7 @@ impl FileHandler {
let mgmt = &state.applications.file_management_service;
match mgmt.rename_file_owned(&id, auth_user.id, &new_name).await {
Ok(file_dto) => (StatusCode::OK, Json(file_dto)).into_response(),
Err(err) => AppError::from(err).into_response()
Err(err) => AppError::from(err).into_response(),
}
}
@@ -884,7 +876,7 @@ impl FileHandler {
.await
{
Ok(file) => (StatusCode::OK, Json(file)).into_response(),
Err(err) => AppError::from(err).into_response()
Err(err) => AppError::from(err).into_response(),
}
}
@@ -903,7 +895,7 @@ impl FileHandler {
let mgmt = &state.applications.file_management_service;
match mgmt.move_file_owned(&id, auth_user.id, folder_id).await {
Ok(file_dto) => (StatusCode::OK, Json(file_dto)).into_response(),
Err(err) => AppError::from(err).into_response()
Err(err) => AppError::from(err).into_response(),
}
}
@@ -962,9 +954,7 @@ impl FileHandler {
})
.collect();
format!(
"{disposition}; filename=\"{ascii_safe}\"; filename*=UTF-8''{encoded}"
)
format!("{disposition}; filename=\"{ascii_safe}\"; filename*=UTF-8''{encoded}")
}
/// Build a 201 Created JSON response.
+45 -9
View File
@@ -1251,7 +1251,11 @@ async fn handle_move(
&& let Ok(parent) =
folder_service.get_folder_by_path(dest_parent_path).await
{
assert_owner(parent.owner_id.as_deref(), &user.id.to_string(), dest_parent_path)?;
assert_owner(
parent.owner_id.as_deref(),
&user.id.to_string(),
dest_parent_path,
)?;
}
file_management_service
.move_file(&file.id, Some(dest_parent_path.to_string()))
@@ -1281,7 +1285,11 @@ async fn handle_move(
let folder_result = folder_service.get_folder_by_path(&source_path).await;
if let Ok(folder) = folder_result {
assert_owner(folder.owner_id.as_deref(), &user.id.to_string(), &source_path)?;
assert_owner(
folder.owner_id.as_deref(),
&user.id.to_string(),
&source_path,
)?;
let dest_folder_name = destination_path
.split('/')
.next_back()
@@ -1299,7 +1307,11 @@ async fn handle_move(
match folder_service.get_folder_by_path(dest_parent_path).await {
Ok(parent) => {
// SECURITY: verify destination parent belongs to caller (V-08)
assert_owner(parent.owner_id.as_deref(), &user.id.to_string(), dest_parent_path)?;
assert_owner(
parent.owner_id.as_deref(),
&user.id.to_string(),
dest_parent_path,
)?;
Some(parent.id)
}
Err(_) => None,
@@ -1352,7 +1364,11 @@ async fn handle_move(
if !dest_parent_path.is_empty()
&& let Ok(parent) = folder_service.get_folder_by_path(dest_parent_path).await
{
assert_owner(parent.owner_id.as_deref(), &user.id.to_string(), dest_parent_path)?;
assert_owner(
parent.owner_id.as_deref(),
&user.id.to_string(),
dest_parent_path,
)?;
}
file_management_service
.move_file(&file.id, Some(dest_parent_path.to_string()))
@@ -1480,7 +1496,11 @@ async fn handle_copy(
match folder_service.get_folder_by_path(dest_parent_path).await {
Ok(parent) => {
// SECURITY: verify destination parent belongs to caller (V-08)
assert_owner(parent.owner_id.as_deref(), &user.id.to_string(), dest_parent_path)?;
assert_owner(
parent.owner_id.as_deref(),
&user.id.to_string(),
dest_parent_path,
)?;
Some(parent.id)
}
Err(_) => None,
@@ -1528,7 +1548,11 @@ async fn handle_copy(
match folder_service.get_folder_by_path(dest_parent_path).await {
Ok(parent) => {
// SECURITY: verify destination parent belongs to caller (V-08)
assert_owner(parent.owner_id.as_deref(), &user.id.to_string(), dest_parent_path)?;
assert_owner(
parent.owner_id.as_deref(),
&user.id.to_string(),
dest_parent_path,
)?;
Some(parent.id)
}
Err(_) => None,
@@ -1553,7 +1577,11 @@ async fn handle_copy(
let folder_result = folder_service.get_folder_by_path(&source_path).await;
if let Ok(folder) = folder_result {
assert_owner(folder.owner_id.as_deref(), &user.id.to_string(), &source_path)?;
assert_owner(
folder.owner_id.as_deref(),
&user.id.to_string(),
&source_path,
)?;
let recursive = depth != "0";
let dest_folder_name = destination_path
@@ -1572,7 +1600,11 @@ async fn handle_copy(
match folder_service.get_folder_by_path(dest_parent_path).await {
Ok(parent) => {
// SECURITY: verify destination parent belongs to caller (V-08)
assert_owner(parent.owner_id.as_deref(), &user.id.to_string(), dest_parent_path)?;
assert_owner(
parent.owner_id.as_deref(),
&user.id.to_string(),
dest_parent_path,
)?;
Some(parent.id)
}
Err(_) => None,
@@ -1627,7 +1659,11 @@ async fn handle_copy(
match folder_service.get_folder_by_path(dest_parent_path).await {
Ok(parent) => {
// SECURITY: verify destination parent belongs to caller (V-08)
assert_owner(parent.owner_id.as_deref(), &user.id.to_string(), dest_parent_path)?;
assert_owner(
parent.owner_id.as_deref(),
&user.id.to_string(),
dest_parent_path,
)?;
Some(parent.id)
}
Err(_) => None,
+12 -11
View File
@@ -459,17 +459,18 @@ pub async fn get_editor_url(
};
// Generate WOPI access token
let (access_token, access_token_ttl) =
match state
.token_service
.generate_token(&params.file_id, &user_id.to_string(), &username, can_write)
{
Ok(t) => t,
Err(e) => {
tracing::error!("Failed to generate WOPI token: {}", e);
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}
};
let (access_token, access_token_ttl) = match state.token_service.generate_token(
&params.file_id,
&user_id.to_string(),
username,
can_write,
) {
Ok(t) => t,
Err(e) => {
tracing::error!("Failed to generate WOPI token: {}", e);
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}
};
axum::Json(EditorUrlResponse {
editor_url,
+4 -1
View File
@@ -145,7 +145,10 @@ pub fn create_api_routes(app_state: &Arc<AppState>) -> Router<Arc<AppState>> {
.route("/", get(FileHandler::list_files_query))
.route("/upload", post(FileHandler::upload_file_with_thumbnails))
.route("/{id}", get(FileHandler::download_file))
.route("/{id}/thumbnail/{size}", get(FileHandler::get_thumbnail).put(FileHandler::upload_thumbnail))
.route(
"/{id}/thumbnail/{size}",
get(FileHandler::get_thumbnail).put(FileHandler::upload_thumbnail),
)
.route("/{id}/metadata", get(FileHandler::get_file_metadata))
.layer(DefaultBodyLimit::max(10 * 1024 * 1024 * 1024)) // 10 GB for file uploads
.with_state(app_state.clone());