diff --git a/mnemo_cards_backend/lib/api/v2/admin_cards_api_v2.dart b/mnemo_cards_backend/lib/api/v2/admin_cards_api_v2.dart index 00165dc..bdc3b60 100644 --- a/mnemo_cards_backend/lib/api/v2/admin_cards_api_v2.dart +++ b/mnemo_cards_backend/lib/api/v2/admin_cards_api_v2.dart @@ -674,11 +674,24 @@ class AdminCardsApiV2 { return _json(SuccessResponse(success: true).toJson()); } catch (e, s) { print('Error in updateCard: $e\n$s'); + + // Check for common database errors + final errorMessage = e.toString().toLowerCase(); + String details = 'An unexpected error occurred while updating the card.'; + + if (errorMessage.contains('constraint') || errorMessage.contains('unique')) { + details = 'A card with similar data may already exist. Please check for duplicates.'; + } else if (errorMessage.contains('foreign key') || errorMessage.contains('pack')) { + details = 'The specified pack ID may be invalid. Please verify that the pack exists.'; + } else if (errorMessage.contains('null') || errorMessage.contains('required')) { + details = 'Required fields are missing or invalid. Please check all required fields are provided.'; + } + return _json( ErrorResponse( error: 'Internal server error', message: 'Failed to update card', - details: 'An unexpected error occurred while updating the card. Please try again later.', + details: details, ).toJson(), statusCode: 500, ); diff --git a/mnemo_cards_backend/lib/api/v2/packs_api_v2.dart b/mnemo_cards_backend/lib/api/v2/packs_api_v2.dart index 80ea829..55bfca8 100644 --- a/mnemo_cards_backend/lib/api/v2/packs_api_v2.dart +++ b/mnemo_cards_backend/lib/api/v2/packs_api_v2.dart @@ -156,12 +156,18 @@ class PacksApiV2 { if (!_isValidUuid(value)) return null; try { - return await _minioService.getPresignedUrl( + final url = await _minioService.getPresignedUrl( bucket: bucket, objectId: value, ); - } catch (e) { - print('Error generating presigned URL for $bucket/$value: $e'); + if (url == null) { + print('⚠️ Warning: Failed to generate presigned URL for $bucket/$value - object may not exist in MinIO'); + } else { + print('✅ Generated presigned URL for $bucket/$value (expires in ${MinioConfig.presignedUrlExpirySeconds}s)'); + } + return url; + } catch (e, s) { + print('❌ Error generating presigned URL for $bucket/$value: $e\n$s'); return null; } } diff --git a/mnemo_cards_backend/lib/storage/minio_service.dart b/mnemo_cards_backend/lib/storage/minio_service.dart index 3f87d0b..bf29a34 100644 --- a/mnemo_cards_backend/lib/storage/minio_service.dart +++ b/mnemo_cards_backend/lib/storage/minio_service.dart @@ -93,7 +93,7 @@ class MinioService { /// /// [bucket] - The bucket name /// [objectId] - The object ID (UUID) - /// [expirySeconds] - Optional expiry time in seconds (default: 4 hours) + /// [expirySeconds] - Optional expiry time in seconds (default: 7 days) /// /// Returns the presigned URL, or null if the object doesn't exist Future getPresignedUrl({ @@ -101,6 +101,7 @@ class MinioService { required String objectId, int? expirySeconds, }) async { + final expiry = expirySeconds ?? MinioConfig.presignedUrlExpirySeconds; try { // Check if object exists await _client.statObject(bucket, objectId); @@ -109,13 +110,19 @@ class MinioService { final url = await _client.presignedGetObject( bucket, objectId, - expires: expirySeconds ?? MinioConfig.presignedUrlExpirySeconds, + expires: expiry, ); + print('✅ Generated presigned URL for $bucket/$objectId (expires in ${expiry}s)'); return url; - } catch (e) { + } on MinioException catch (e) { print( - '⚠️ Warning: Failed to generate presigned URL for $bucket/$objectId: $e', + '❌ MinIO error generating presigned URL for $bucket/$objectId: ${e.code} - ${e.message}', + ); + return null; + } catch (e, s) { + print( + '❌ Unexpected error generating presigned URL for $bucket/$objectId: $e\n$s', ); return null; }