From 7f2029c454e14d818b85b6755b13dbc40f0df74f Mon Sep 17 00:00:00 2001 From: Pumpkin-Nguyen Date: Sun, 31 May 2026 11:26:18 +0700 Subject: [PATCH 1/4] fix(client): age validate logic --- .../main/java/com/bigbid/client/controller/LoginController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bigbid-client/src/main/java/com/bigbid/client/controller/LoginController.java b/bigbid-client/src/main/java/com/bigbid/client/controller/LoginController.java index 9834777..1589a23 100644 --- a/bigbid-client/src/main/java/com/bigbid/client/controller/LoginController.java +++ b/bigbid-client/src/main/java/com/bigbid/client/controller/LoginController.java @@ -170,7 +170,7 @@ private void handleRegister() { return; } - if (LocalDate.now().minusYears(16).isAfter(dob)) { + if (dob.minusYears(16).isAfter(LocalDate.now())) { AlertHelper.showWarning( "Age Requirement", "You must be at least 16 years old to register."); return; From 79c849c5ce9448c4a6c8dbb3fad82610dd8f858c Mon Sep 17 00:00:00 2001 From: Pumpkin-Nguyen Date: Sun, 31 May 2026 12:50:55 +0700 Subject: [PATCH 2/4] fix(server): add handler for file size limit --- .../controller/AuctionDetailController.java | 6 +-- .../bigbid/server/exception/ErrorCode.java | 1 + .../exception/GlobalExceptionHandler.java | 41 ++++++++++++------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/bigbid-client/src/main/java/com/bigbid/client/controller/AuctionDetailController.java b/bigbid-client/src/main/java/com/bigbid/client/controller/AuctionDetailController.java index c2f97c4..55bb054 100644 --- a/bigbid-client/src/main/java/com/bigbid/client/controller/AuctionDetailController.java +++ b/bigbid-client/src/main/java/com/bigbid/client/controller/AuctionDetailController.java @@ -68,7 +68,6 @@ public class AuctionDetailController { private final AuctionService auctionService; private final AuthGuard authGuard; private final WebSocketClient webSocketClient; - private final ObjectMapper objectMapper; private final XYChart.Series bidHistorySeries = new XYChart.Series<>(); @@ -250,7 +249,7 @@ private void loadAuctionBidHistory() { } private void applyBidHistory( - List bidHistory) { + List bidHistory) { if (bidHistory == null || bidHistory.isEmpty()) { return; } @@ -265,8 +264,7 @@ private void applyBidHistory( .forEach(this::appendBidPoint); } - private void appendBidPoint( - com.bigbid.client.model.response.BidTransactionResponse bidTransaction) { + private void appendBidPoint(BidTransactionResponse bidTransaction) { LocalDateTime timestamp = bidTransaction.getTimestamp(); long xValue = toEpochMillis(timestamp != null ? timestamp : LocalDateTime.now()); long yValue = bidTransaction.getAmount(); diff --git a/bigbid-server/src/main/java/com/bigbid/server/exception/ErrorCode.java b/bigbid-server/src/main/java/com/bigbid/server/exception/ErrorCode.java index 1ed1a38..b072ea5 100644 --- a/bigbid-server/src/main/java/com/bigbid/server/exception/ErrorCode.java +++ b/bigbid-server/src/main/java/com/bigbid/server/exception/ErrorCode.java @@ -12,6 +12,7 @@ public enum ErrorCode { DATA_INTEGRITY_VIOLATION(9997, "Data error", HttpStatus.BAD_REQUEST), INVALID_KEY(9998, "Uncategorized error", HttpStatus.BAD_REQUEST), UNCATEGORIZED_EXCEPTION(9999, "Uncategorized error", HttpStatus.INTERNAL_SERVER_ERROR), + FILE_SIZE_LIMIT(9998, "File size limit exceeded", HttpStatus.BAD_REQUEST), // USER EXCEPTION (1000-1099) USER_EXISTED(1002, "User existed", HttpStatus.BAD_REQUEST), diff --git a/bigbid-server/src/main/java/com/bigbid/server/exception/GlobalExceptionHandler.java b/bigbid-server/src/main/java/com/bigbid/server/exception/GlobalExceptionHandler.java index 6e458a4..0d7d211 100644 --- a/bigbid-server/src/main/java/com/bigbid/server/exception/GlobalExceptionHandler.java +++ b/bigbid-server/src/main/java/com/bigbid/server/exception/GlobalExceptionHandler.java @@ -5,6 +5,7 @@ import jakarta.validation.ConstraintViolation; +import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; @@ -25,9 +26,9 @@ public class GlobalExceptionHandler { public static final String MIN_ATTRIBUTE = "min"; @ExceptionHandler(value = RuntimeException.class) - ResponseEntity handleRuntimeException(RuntimeException exception) { + ResponseEntity> handleRuntimeException(RuntimeException exception) { log.error("Exception: ", exception); - ApiResponse apiResponse = new ApiResponse(); + ApiResponse apiResponse = new ApiResponse<>(); apiResponse.setCode(ErrorCode.UNCATEGORIZED_EXCEPTION.getCode()); apiResponse.setMessage(ErrorCode.UNCATEGORIZED_EXCEPTION.getMessage()); @@ -35,10 +36,20 @@ ResponseEntity handleRuntimeException(RuntimeException exception) { return ResponseEntity.badRequest().body(apiResponse); } + @ExceptionHandler(value = FileSizeLimitExceededException.class) + ResponseEntity> handleFileSizeLimitExceededException(FileSizeLimitExceededException exception) { + ApiResponse apiResponse = new ApiResponse<>(); + + apiResponse.setCode(ErrorCode.FILE_SIZE_LIMIT.getCode()); + apiResponse.setMessage(ErrorCode.FILE_SIZE_LIMIT.getMessage()); + + return ResponseEntity.badRequest().body(apiResponse); + } + @ExceptionHandler(value = AppException.class) - ResponseEntity handleAppException(AppException exception) { + ResponseEntity> handleAppException(AppException exception) { ErrorCode errorCode = exception.getErrorCode(); - ApiResponse apiResponse = new ApiResponse(); + ApiResponse apiResponse = new ApiResponse<>(); apiResponse.setCode(errorCode.getCode()); apiResponse.setMessage(errorCode.getMessage()); @@ -46,56 +57,56 @@ ResponseEntity handleAppException(AppException exception) { } @ExceptionHandler(value = AccessDeniedException.class) - ResponseEntity handlingAccessDeniedException(AccessDeniedException exception) { + ResponseEntity> handlingAccessDeniedException(AccessDeniedException exception) { ErrorCode errorCode = ErrorCode.UNAUTHORIZED; return ResponseEntity.status(errorCode.getStatusCode()) .body( - ApiResponse.builder() + ApiResponse.builder() .code(errorCode.getCode()) .message(errorCode.getMessage()) .build()); } @ExceptionHandler(value = HttpMessageNotReadableException.class) - ResponseEntity handleHttpMessageNotReadableException( + ResponseEntity> handleHttpMessageNotReadableException( HttpMessageNotReadableException exception) { ErrorCode errorCode = ErrorCode.INVALID_REQUEST_BODY; log.error("Exception: ", exception); return ResponseEntity.status(errorCode.getStatusCode()) .body( - ApiResponse.builder() + ApiResponse.builder() .code(errorCode.getCode()) .message(errorCode.getMessage()) .build()); } @ExceptionHandler(value = DataIntegrityViolationException.class) - ResponseEntity handleDataIntegrityViolationException( + ResponseEntity> handleDataIntegrityViolationException( DataIntegrityViolationException exception) { ErrorCode errorCode = ErrorCode.DATA_INTEGRITY_VIOLATION; return ResponseEntity.status(errorCode.getStatusCode()) .body( - ApiResponse.builder() + ApiResponse.builder() .code(errorCode.getCode()) .message(errorCode.getMessage()) .build()); } @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class) - ResponseEntity handleHttpRequestMethodNotSupportedException( + ResponseEntity> handleHttpRequestMethodNotSupportedException( HttpRequestMethodNotSupportedException exception) { ErrorCode errorCode = ErrorCode.NOT_FOUND; return ResponseEntity.status(errorCode.getStatusCode()) .body( - ApiResponse.builder() + ApiResponse.builder() .code(errorCode.getCode()) .message(errorCode.getMessage()) .build()); } @ExceptionHandler(value = MethodArgumentNotValidException.class) - ResponseEntity handleValidation(MethodArgumentNotValidException exception) { + ResponseEntity> handleValidation(MethodArgumentNotValidException exception) { String enumKey = exception.getFieldError().getDefaultMessage(); ErrorCode errorCode = ErrorCode.INVALID_KEY; @@ -116,7 +127,7 @@ ResponseEntity handleValidation(MethodArgumentNotValidException exc } catch (IllegalArgumentException e) { } - ApiResponse apiResponse = new ApiResponse(); + ApiResponse apiResponse = new ApiResponse<>(); apiResponse.setCode(errorCode.getCode()); apiResponse.setMessage( Objects.nonNull(attributes) @@ -131,4 +142,4 @@ private String mapAttributes(String message, Map attributes) { return message.replace("{" + MIN_ATTRIBUTE + "}", minValue); } -} +} \ No newline at end of file From 89a683dd175c08b392f391e703e2005e24f5fefe Mon Sep 17 00:00:00 2001 From: Pumpkin-Nguyen Date: Sun, 31 May 2026 17:03:16 +0700 Subject: [PATCH 3/4] chore(server): change the active profile to default --- README.md | 53 ++++++++++++------- bigbid-client/pom.xml | 27 +++++++++- .../controller/AuctionDetailController.java | 4 +- .../exception/GlobalExceptionHandler.java | 5 +- ....yaml.example => application.yaml.example} | 0 5 files changed, 64 insertions(+), 25 deletions(-) rename bigbid-server/src/main/resources/{application-prod.yaml.example => application.yaml.example} (100%) diff --git a/README.md b/README.md index f81c3e8..a4da475 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,6 @@ - [Giới thiệu](#gioi-thieu) - [Công nghệ sử dụng](#cong-nghe) -- [Yêu cầu môi trường](#-yêu-cầu-môi-trường) - [Cấu trúc dự án](#-cấu-trúc-dự-án) - [🚀 Release](#-release) - [🔨 Build từ mã nguồn](#-build-từ-mã-nguồn) @@ -83,17 +82,6 @@ --- -## 💻 Yêu cầu môi trường - -| Công cụ | Phiên bản tối thiểu | -|---|---| -| Java (JDK) | **25** | -| Maven | 3.9+ | -| Docker | 24+ | -| Docker Compose | 2.x | - ---- - ## 📁 Cấu trúc dự án ``` @@ -143,20 +131,39 @@ bigbid/ ## 🚀 Release +### Yêu cầu môi trường +| Công cụ | Phiên bản tối thiểu | +|---|---| +| Java (JDK) | **25** | +| Docker | 24+ | + ### Bước 1 — Tải bản Release [![Release](https://img.shields.io/badge/Download-Release-blue?style=for-the-badge&logo=github)](https://github.com/Pumpkin-Nguyen/bigbid/releases) ### Bước 2 — Khởi động MySQL bằng Docker +## MacOS / Linux ```bash docker volume create db_data && docker run -d --name bigbid-db -p 3306:3306 -e MYSQL_ROOT_PASSWORD=anhemf36 -e MYSQL_DATABASE=bigbid -v db_data:/var/lib/mysql --restart always mysql:8.4 ``` +## Window +```bash +docker volume create db_data; ` +docker run -d --name bigbid-db ` + -p 3306:3306 ` + -e MYSQL_ROOT_PASSWORD=anhemf36 ` + -e MYSQL_DATABASE=bigbid ` + -v db_data:/var/lib/mysql ` + --restart always ` + mysql:8.4 +``` + ### Bước 3: Khởi động server và client ```bash -java -jar bigbid-server-1.0.0.jar --spring.profiles.active=prod +java -jar bigbid-server-1.0.0.jar ``` --- @@ -168,6 +175,14 @@ java -jar bigbid-client-1.0.0.jar ## 🔨 Build từ mã nguồn +### Yêu cầu môi trường +| Công cụ | Phiên bản tối thiểu | +|---|---| +| Java (JDK) | **25** | +| Maven | 3.9+ | +| Docker | 24+ | +| Docker Compose | 2.x | + ### Clone repository ```bash @@ -191,19 +206,19 @@ cd bigbid-server #### macOS / Linux ```bash -cp src/main/resources/application-prod.yaml.example \ -src/main/resources/application-prod.yaml +cp src/main/resources/application.yaml.example \ +src/main/resources/application.yaml ``` #### Windows ```bash -copy src/main/resources/application-prod.yaml.example ` -src/main/resources/application-prod.yaml +copy src/main/resources/application.yaml.example ` +src/main/resources/application.yaml ``` --- -### Bước 3 — Điền các config tại file `application-prod.yaml` +### Bước 3 — Điền các config tại file `application.yaml` --- @@ -219,7 +234,7 @@ src/main/resources/application-prod.yaml ``` #### Run ```bash -java -jar target/bigbid-server-1.0.0.jar --spring.profiles.active=prod +java -jar target/bigbid-server-1.0.0.jar ``` --- diff --git a/bigbid-client/pom.xml b/bigbid-client/pom.xml index f33d35e..53b9caf 100644 --- a/bigbid-client/pom.xml +++ b/bigbid-client/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 @@ -36,6 +36,31 @@ 25 + + org.openjfx + javafx-graphics + 21.0.2 + win + + + org.openjfx + javafx-graphics + 21.0.2 + linux + + + org.openjfx + javafx-graphics + 21.0.2 + mac + + + org.openjfx + javafx-graphics + 21.0.2 + mac-aarch64 + + org.projectlombok lombok diff --git a/bigbid-client/src/main/java/com/bigbid/client/controller/AuctionDetailController.java b/bigbid-client/src/main/java/com/bigbid/client/controller/AuctionDetailController.java index 55bb054..1c766e9 100644 --- a/bigbid-client/src/main/java/com/bigbid/client/controller/AuctionDetailController.java +++ b/bigbid-client/src/main/java/com/bigbid/client/controller/AuctionDetailController.java @@ -41,7 +41,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import tools.jackson.databind.ObjectMapper; @Slf4j @Component @@ -248,8 +247,7 @@ private void loadAuctionBidHistory() { }); } - private void applyBidHistory( - List bidHistory) { + private void applyBidHistory(List bidHistory) { if (bidHistory == null || bidHistory.isEmpty()) { return; } diff --git a/bigbid-server/src/main/java/com/bigbid/server/exception/GlobalExceptionHandler.java b/bigbid-server/src/main/java/com/bigbid/server/exception/GlobalExceptionHandler.java index 0d7d211..70469ac 100644 --- a/bigbid-server/src/main/java/com/bigbid/server/exception/GlobalExceptionHandler.java +++ b/bigbid-server/src/main/java/com/bigbid/server/exception/GlobalExceptionHandler.java @@ -37,7 +37,8 @@ ResponseEntity> handleRuntimeException(RuntimeException exception } @ExceptionHandler(value = FileSizeLimitExceededException.class) - ResponseEntity> handleFileSizeLimitExceededException(FileSizeLimitExceededException exception) { + ResponseEntity> handleFileSizeLimitExceededException( + FileSizeLimitExceededException exception) { ApiResponse apiResponse = new ApiResponse<>(); apiResponse.setCode(ErrorCode.FILE_SIZE_LIMIT.getCode()); @@ -142,4 +143,4 @@ private String mapAttributes(String message, Map attributes) { return message.replace("{" + MIN_ATTRIBUTE + "}", minValue); } -} \ No newline at end of file +} diff --git a/bigbid-server/src/main/resources/application-prod.yaml.example b/bigbid-server/src/main/resources/application.yaml.example similarity index 100% rename from bigbid-server/src/main/resources/application-prod.yaml.example rename to bigbid-server/src/main/resources/application.yaml.example From bcebfdf167622c8981703a575865612d0db9029b Mon Sep 17 00:00:00 2001 From: Pumpkin-Nguyen Date: Sun, 31 May 2026 18:43:08 +0700 Subject: [PATCH 4/4] fix(server): file limit exception --- README.md | 9 +-------- bigbid-client/pom.xml | 8 ++++---- .../bigbid/server/exception/GlobalExceptionHandler.java | 8 ++++---- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index a4da475..8fc6839 100644 --- a/README.md +++ b/README.md @@ -299,13 +299,6 @@ java -jar target/bigbid-client-1.0.0.jar - [x] Thông báo kết quả phiên qua WebSocket --- - ## 📎 Báo cáo và Demo - -| Tài liệu | Đường dẫn | -|--------------------------|-----------| -| 📄 **Báo cáo PDF** | | -| 🎥 **Video Demo** | | -| 💻 **GitHub Repository** | | - +- https://drive.google.com/drive/folders/1IBAXfG7eJSammKFNKEgccJiwrgA384K_ --- \ No newline at end of file diff --git a/bigbid-client/pom.xml b/bigbid-client/pom.xml index 53b9caf..ef8fee2 100644 --- a/bigbid-client/pom.xml +++ b/bigbid-client/pom.xml @@ -39,25 +39,25 @@ org.openjfx javafx-graphics - 21.0.2 + 25 win org.openjfx javafx-graphics - 21.0.2 + 25 linux org.openjfx javafx-graphics - 21.0.2 + 25 mac org.openjfx javafx-graphics - 21.0.2 + 25 mac-aarch64 diff --git a/bigbid-server/src/main/java/com/bigbid/server/exception/GlobalExceptionHandler.java b/bigbid-server/src/main/java/com/bigbid/server/exception/GlobalExceptionHandler.java index 70469ac..76e5632 100644 --- a/bigbid-server/src/main/java/com/bigbid/server/exception/GlobalExceptionHandler.java +++ b/bigbid-server/src/main/java/com/bigbid/server/exception/GlobalExceptionHandler.java @@ -5,7 +5,6 @@ import jakarta.validation.ConstraintViolation; -import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; @@ -14,6 +13,7 @@ import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.multipart.MaxUploadSizeExceededException; import com.bigbid.server.dto.ApiResponse; @@ -36,9 +36,9 @@ ResponseEntity> handleRuntimeException(RuntimeException exception return ResponseEntity.badRequest().body(apiResponse); } - @ExceptionHandler(value = FileSizeLimitExceededException.class) - ResponseEntity> handleFileSizeLimitExceededException( - FileSizeLimitExceededException exception) { + @ExceptionHandler(value = MaxUploadSizeExceededException.class) + ResponseEntity> handleMaxUploadSizeExceededException( + MaxUploadSizeExceededException exception) { ApiResponse apiResponse = new ApiResponse<>(); apiResponse.setCode(ErrorCode.FILE_SIZE_LIMIT.getCode());