From 96171d3ec254f35d4cf8d11ccab53f8922c94412 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Sat, 18 Apr 2026 10:22:18 +0000 Subject: [PATCH 01/51] fix: missing required parameters (#27) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/27 --- build.dev.sh | 5 +++++ .../java/com/drinkool/controller/CustomerController.java | 8 ++++---- .../main/java/com/drinkool/services/CustomerService.java | 6 +++--- 3 files changed, 12 insertions(+), 7 deletions(-) create mode 100755 build.dev.sh diff --git a/build.dev.sh b/build.dev.sh new file mode 100755 index 0000000..3ed6693 --- /dev/null +++ b/build.dev.sh @@ -0,0 +1,5 @@ +mvn package -DskipTests -Dquarkus.container-image.push=false \ + -Dquarkus.container-image.registry=git.demonkernel.io.vn \ + -Dquarkus.log.category."org.jboss.resteasy.reactive.client.logging".level=DEBUG \ + -Dquarkus.rest-client.logging.scope=full \ + -Dquarkus.rest-client.logging.body-limit=1024 diff --git a/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java b/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java index f56fad2..e064799 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java @@ -1,13 +1,13 @@ package com.drinkool.controller; -import com.drinkool.Role; -import com.drinkool.Url; +import com.drinkool.*; import com.drinkool.dtos.*; import com.drinkool.services.CustomerService; import io.smallrye.mutiny.Uni; import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; +import java.util.*; import org.eclipse.microprofile.rest.client.inject.RestClient; @Path("/api/" + Role.Customer) @@ -30,7 +30,7 @@ public class CustomerController { } @GET - public Uni me() { - return accountService.me(); + public Uni me(@HeaderParam(InternalValue.userId) UUID id) { + return accountService.me(id); } } diff --git a/gateway-service/src/main/java/com/drinkool/services/CustomerService.java b/gateway-service/src/main/java/com/drinkool/services/CustomerService.java index a870c64..28d09f6 100644 --- a/gateway-service/src/main/java/com/drinkool/services/CustomerService.java +++ b/gateway-service/src/main/java/com/drinkool/services/CustomerService.java @@ -1,11 +1,11 @@ package com.drinkool.services; -import com.drinkool.Role; -import com.drinkool.Url; +import com.drinkool.*; import com.drinkool.dtos.*; import io.smallrye.mutiny.Uni; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; +import java.util.*; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; @RegisterRestClient(configKey = "account") @@ -29,5 +29,5 @@ public interface CustomerService { @GET @Path(Url.Me) - Uni me(); + Uni me(@HeaderParam(InternalValue.userId) UUID id); } From 74acb68bbf7fca4acf5ec710c5b487985c436fa9 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sat, 18 Apr 2026 10:38:36 +0000 Subject: [PATCH 02/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s.yaml | 6 +++--- lib/pom.xml | 2 +- pom.xml | 2 +- 7 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0c7195..04b7d75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.5](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.4...v1.5.5) (2026-04-18) + + +### Bug Fixes + +* missing required parameters ([#27](https://git.demonkernel.io.vn/FoodSurf/backend/issues/27)) ([96171d3](https://git.demonkernel.io.vn/FoodSurf/backend/commit/96171d3ec254f35d4cf8d11ccab53f8922c94412)) + ## [1.5.4](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.3...v1.5.4) (2026-04-17) diff --git a/account-service/pom.xml b/account-service/pom.xml index 9c68f0b..74fe9d3 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.4 + 1.5.5 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 8478c74..f841069 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.4 + 1.5.5 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 9fa057c..08400da 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.4 + 1.5.5 ../pom.xml diff --git a/k8s.yaml b/k8s.yaml index 0aa324b..7ce39f5 100644 --- a/k8s.yaml +++ b/k8s.yaml @@ -15,7 +15,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.4 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.5 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -73,7 +73,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.4 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.5 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -129,7 +129,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.4 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.5 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index 6627e87..d0520e8 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.4 + 1.5.5 ../pom.xml diff --git a/pom.xml b/pom.xml index 8cc9e64..7a8588a 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.4 + 1.5.5 pom 25 From 24df313c0f7effeacd89e537896d7ac9452ec526 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Sun, 19 Apr 2026 02:06:19 +0000 Subject: [PATCH 03/51] fix: response exceptions from sub services (#28) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/28 --- .../mappers/RestClientExceptionMapper.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 gateway-service/src/main/java/com/drinkool/mappers/RestClientExceptionMapper.java diff --git a/gateway-service/src/main/java/com/drinkool/mappers/RestClientExceptionMapper.java b/gateway-service/src/main/java/com/drinkool/mappers/RestClientExceptionMapper.java new file mode 100644 index 0000000..da072ca --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/mappers/RestClientExceptionMapper.java @@ -0,0 +1,21 @@ +package com.drinkool.mappers; + +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import jakarta.ws.rs.ext.Provider; +import org.jboss.resteasy.reactive.ClientWebApplicationException; + +@Provider +public class RestClientExceptionMapper + implements ExceptionMapper +{ + + @Override + public Response toResponse(ClientWebApplicationException exception) { + Response originalResponse = exception.getResponse(); + + return Response.status(originalResponse.getStatus()) + .entity(originalResponse.readEntity(String.class)) + .build(); + } +} From d94117576baf5badef418c7b6c1aa1e85b4ff01f Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 19 Apr 2026 02:20:48 +0000 Subject: [PATCH 04/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s.yaml | 6 +++--- lib/pom.xml | 2 +- pom.xml | 2 +- 7 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04b7d75..be9e1f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.6](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.5...v1.5.6) (2026-04-19) + + +### Bug Fixes + +* response exceptions from sub services ([#28](https://git.demonkernel.io.vn/FoodSurf/backend/issues/28)) ([24df313](https://git.demonkernel.io.vn/FoodSurf/backend/commit/24df313c0f7effeacd89e537896d7ac9452ec526)) + ## [1.5.5](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.4...v1.5.5) (2026-04-18) diff --git a/account-service/pom.xml b/account-service/pom.xml index 74fe9d3..688d404 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.5 + 1.5.6 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index f841069..4d293e7 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.5 + 1.5.6 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 08400da..1294947 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.5 + 1.5.6 ../pom.xml diff --git a/k8s.yaml b/k8s.yaml index 7ce39f5..59b02a0 100644 --- a/k8s.yaml +++ b/k8s.yaml @@ -15,7 +15,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.5 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.6 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -73,7 +73,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.5 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.6 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -129,7 +129,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.5 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.6 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index d0520e8..5138643 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.5 + 1.5.6 ../pom.xml diff --git a/pom.xml b/pom.xml index 7a8588a..174800c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.5 + 1.5.6 pom 25 From 4811934b84f7684410297a8f7d1f7ff14611a25a Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Sun, 19 Apr 2026 09:16:26 +0000 Subject: [PATCH 05/51] fix: add logout, quick signup and quick login (#29) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/29 --- .devcontainer/Dockerfile | 8 ++++++ .devcontainer/devcontainer.json | 1 + .gitea/workflows/test.yaml | 2 +- .gitignore | 1 + .releaserc.yaml | 2 +- account-service/pom.xml | 20 +++++++++++--- .../mapper/ExceptionHandlersMapper.java | 16 ++++++++++++ .../drinkool/services/CustomerService.java | 3 --- .../drinkool/services/BaseServiceTest.java | 6 +++-- .../services/CustomerServiceTest.java | 2 -- build.dev.sh | 5 ---- eatery-service/pom.xml | 19 +++++++++++--- gateway-service/pom.xml | 18 ++++++++++--- .../drinkool/controller/BaseController.java | 26 +++++++++++++++++++ .../controller/CustomerController.java | 14 +++++++++- .../drinkool/services/CustomerService.java | 2 +- .../controller/BaseControllerTest.java | 24 +++++++++++++++++ .../src/test/resources/application.properties | 5 +++- lib/src/main/java/com/drinkool/Url.java | 1 + scripts/build.sh | 3 +++ scripts/install.sh | 3 +++ scripts/publish.sh | 11 ++++++++ scripts/test.sh | 1 + 23 files changed, 167 insertions(+), 26 deletions(-) create mode 100644 account-service/src/main/java/com/drinkool/mapper/ExceptionHandlersMapper.java delete mode 100755 build.dev.sh create mode 100644 gateway-service/src/main/java/com/drinkool/controller/BaseController.java create mode 100644 gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java create mode 100755 scripts/build.sh create mode 100755 scripts/install.sh create mode 100755 scripts/publish.sh create mode 100755 scripts/test.sh diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 492af3c..12d0c67 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -20,11 +20,19 @@ RUN apt-get update && apt-get install -y ca-certificates && apt-get clean RUN apt-get update --fix-missing && apt-get install --no-install-recommends --no-install-suggests -y \ git \ docker-buildx \ + locales \ docker-cli \ docker.io \ kubectl \ openjdk-25-jdk-headless \ + redis-server \ maven RUN jbang trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/ RUN jbang app install --fresh --force quarkus@quarkusio + +# Fix Locale +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ + locale-gen +ENV LANG=en_US.UTF-8 +ENV LC_ALL=en_US.UTF-8 \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 8c894ad..e44a899 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -32,6 +32,7 @@ "QUARKUS_DEBUG_HOST": "0.0.0.0", "http_proxy": "http://host.docker.internal:3142" }, + "postStartCommand": "redis-server --daemonize yes", "postCreateCommand": "git config --global --add safe.directory '*'", "forwardPorts": [5005, 8080] } diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index 9423c75..639cf30 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -49,7 +49,7 @@ jobs: - name: Build and Test all modules run: | ./mvnw -B install \ - -Dquarkus.container-image.push=false + -Dquarkus.container-image.push=false -Pnative - name: Publish Test Report uses: dorny/test-reporter@v3 diff --git a/.gitignore b/.gitignore index 9851e15..68c9671 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ nb-configuration.xml # Visual Studio Code .vscode .factorypath +*.rdb # OSX .DS_Store diff --git a/.releaserc.yaml b/.releaserc.yaml index 190d4eb..88e101a 100644 --- a/.releaserc.yaml +++ b/.releaserc.yaml @@ -13,7 +13,7 @@ plugins: ./mvnw versions:set -DnewVersion=${nextRelease.version} && sed -i "/-service:/ s|:[^:]*$|:${nextRelease.version}|" k8s.yaml && if [ "${branch.name}" = "main" ]; then - ./mvnw package -B -Dquarkus.container-image.tag=${nextRelease.version} -DskipTests + ./mvnw package -B -Pnative -Dquarkus.container-image.tag=${nextRelease.version} -DskipTests fi - - "@saithodev/semantic-release-gitea" - giteaUrl: "https://git.demonkernel.io.vn/" diff --git a/account-service/pom.xml b/account-service/pom.xml index 688d404..f717c1d 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -17,9 +17,7 @@ quarkus - false - false - true + 3.15.0 25 UTF-8 @@ -164,4 +162,20 @@ + + + + native + + + native + + + + false + false + true + + + diff --git a/account-service/src/main/java/com/drinkool/mapper/ExceptionHandlersMapper.java b/account-service/src/main/java/com/drinkool/mapper/ExceptionHandlersMapper.java new file mode 100644 index 0000000..4372d2a --- /dev/null +++ b/account-service/src/main/java/com/drinkool/mapper/ExceptionHandlersMapper.java @@ -0,0 +1,16 @@ +package com.drinkool.mapper; + +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.BadRequestException; +import org.jboss.resteasy.reactive.server.ServerExceptionMapper; + +public class ExceptionHandlersMapper { + + @ServerExceptionMapper + public Response mapBadRequestException(BadRequestException x) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(x.getMessage()) + .type("text/plain") + .build(); + } +} diff --git a/account-service/src/main/java/com/drinkool/services/CustomerService.java b/account-service/src/main/java/com/drinkool/services/CustomerService.java index 7b2db10..87e09eb 100644 --- a/account-service/src/main/java/com/drinkool/services/CustomerService.java +++ b/account-service/src/main/java/com/drinkool/services/CustomerService.java @@ -42,9 +42,6 @@ public class CustomerService extends BaseService { newCustomer.signup(input.phone); return Response.status(Response.Status.CREATED) - .header(InternalValue.userId, newCustomer.id.toString()) - .header(InternalValue.role, Role.Customer) - .entity(newCustomer) .build(); } diff --git a/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java b/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java index 497b8bd..2838545 100644 --- a/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java @@ -15,14 +15,16 @@ public class BaseServiceTest { @Test public void testMeEndpointWithHeader() { String phone = Utils.generateRandomPhone(); - QuickSignup input = new QuickSignup(); + Signup input = new Signup(); + input.name = "Test User"; input.phone = phone; + input.password = "password123"; String testUserId = given() .contentType(ContentType.JSON) .body(input) .when() - .post(Role.Customer + Url.QuickSignup) + .post(Role.Customer + Url.Signup) .then() .extract() .header(InternalValue.userId); diff --git a/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java b/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java index 5bede45..a823961 100644 --- a/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java @@ -50,8 +50,6 @@ public class CustomerServiceTest { .when() .post(Role.Customer + Url.QuickSignup) .then() - .header(InternalValue.userId, notNullValue()) - .header(InternalValue.role, is(Role.Customer)) .statusCode(201); assertEquals(1, CustomerEntity.find("phone", phone).count()); diff --git a/build.dev.sh b/build.dev.sh deleted file mode 100755 index 3ed6693..0000000 --- a/build.dev.sh +++ /dev/null @@ -1,5 +0,0 @@ -mvn package -DskipTests -Dquarkus.container-image.push=false \ - -Dquarkus.container-image.registry=git.demonkernel.io.vn \ - -Dquarkus.log.category."org.jboss.resteasy.reactive.client.logging".level=DEBUG \ - -Dquarkus.rest-client.logging.scope=full \ - -Dquarkus.rest-client.logging.body-limit=1024 diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 4d293e7..8ae5b17 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -17,9 +17,6 @@ quarkus - false - false - true 3.15.0 25 UTF-8 @@ -150,4 +147,20 @@ + + + + native + + + native + + + + false + false + true + + + diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 1294947..74f1078 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -17,9 +17,6 @@ quarkus - false - false - true 3.15.0 25 UTF-8 @@ -142,4 +139,19 @@ + + + native + + + native + + + + false + false + true + + + diff --git a/gateway-service/src/main/java/com/drinkool/controller/BaseController.java b/gateway-service/src/main/java/com/drinkool/controller/BaseController.java new file mode 100644 index 0000000..c87ecb6 --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/controller/BaseController.java @@ -0,0 +1,26 @@ +package com.drinkool.controller; + +import com.drinkool.InternalValue; +import com.drinkool.Url; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.NewCookie; +import org.jboss.resteasy.reactive.RestResponse; + +public abstract class BaseController { + + @POST + @Path(Url.Logout) + public RestResponse logout() { + NewCookie cookie = new NewCookie.Builder(InternalValue.cookieName) + .secure(true) + .maxAge(0) + .path("/") + .httpOnly(true) + .build(); + + return RestResponse.ResponseBuilder.noContent() + .cookie(cookie) + .build(); + } +} diff --git a/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java b/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java index e064799..ee38f53 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java @@ -11,7 +11,7 @@ import java.util.*; import org.eclipse.microprofile.rest.client.inject.RestClient; @Path("/api/" + Role.Customer) -public class CustomerController { +public class CustomerController extends BaseController { @Inject @RestClient @@ -29,6 +29,18 @@ public class CustomerController { return accountService.login(input); } + @POST + @Path(Url.QuickSignup) + public Uni proxyQuickSignup(QuickSignup input) { + return accountService.quickSignup(input); + } + + @POST() + @Path(Url.QuickLogin) + public Uni proxyQuickLogin(QuickLogin input) { + return accountService.quickLogin(input); + } + @GET public Uni me(@HeaderParam(InternalValue.userId) UUID id) { return accountService.me(id); diff --git a/gateway-service/src/main/java/com/drinkool/services/CustomerService.java b/gateway-service/src/main/java/com/drinkool/services/CustomerService.java index 28d09f6..123d3f8 100644 --- a/gateway-service/src/main/java/com/drinkool/services/CustomerService.java +++ b/gateway-service/src/main/java/com/drinkool/services/CustomerService.java @@ -25,7 +25,7 @@ public interface CustomerService { @POST @Path(Url.QuickLogin) - Uni quickLogin(QuickSignup input); + Uni quickLogin(QuickLogin input); @GET @Path(Url.Me) diff --git a/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java b/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java new file mode 100644 index 0000000..91c0680 --- /dev/null +++ b/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java @@ -0,0 +1,24 @@ +package com.drinkool.controller; + +import static io.restassured.RestAssured.*; +import static org.hamcrest.CoreMatchers.*; + +import com.drinkool.*; +import io.quarkus.test.junit.QuarkusTest; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class BaseControllerTest { + + @Test + public void testLogoutShouldClearCookie() { + given() + .when() + .post("/api/" + Role.Customer + Url.Logout) + .then() + .statusCode(204) + .header("Set-Cookie", containsString(InternalValue.cookieName)) + .header("Set-Cookie", containsString("Max-Age=0")) + .header("Set-Cookie", containsString("HttpOnly")); + } +} diff --git a/gateway-service/src/test/resources/application.properties b/gateway-service/src/test/resources/application.properties index bf4225d..9f91177 100644 --- a/gateway-service/src/test/resources/application.properties +++ b/gateway-service/src/test/resources/application.properties @@ -2,4 +2,7 @@ quarkus.http.host=0.0.0.0 # JWT -gateway.jwt.secret=1uZk07Hqu1316z9YqrcSGPTTJDhMWU1ZhFSLBrDQvmU= \ No newline at end of file +gateway.jwt.secret=1uZk07Hqu1316z9YqrcSGPTTJDhMWU1ZhFSLBrDQvmU= + +# App configuration +quarkus.rest-client.account.url=http://account-service:8080 \ No newline at end of file diff --git a/lib/src/main/java/com/drinkool/Url.java b/lib/src/main/java/com/drinkool/Url.java index 8aa4a01..e547d3c 100644 --- a/lib/src/main/java/com/drinkool/Url.java +++ b/lib/src/main/java/com/drinkool/Url.java @@ -8,4 +8,5 @@ public class Url { public static final String QuickLogin = "/quick_login"; public static final String SmsOtp = "/sms_otp"; public static final String Me = "/me"; + public static final String Logout = "/logout"; } diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..17b5426 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,3 @@ +mvn clean package -DskipTests -Pnative \ + -Dquarkus.container-image.push=false \ + -Dquarkus.container-image.registry=git.demonkernel.io.vn diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100755 index 0000000..cfcde0e --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,3 @@ +mvn clean install -DskipTests \ + -Dquarkus.container-image.build=false \ + -Dquarkus.container-image.push=false \ No newline at end of file diff --git a/scripts/publish.sh b/scripts/publish.sh new file mode 100755 index 0000000..1becc04 --- /dev/null +++ b/scripts/publish.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +CURRENT_DIR=$(pwd) +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) + +cd "$SCRIPT_DIR/.." + +kubectl delete all --all -n drinkool-backend +kubectl apply -f k8s.yaml -n drinkool-backend + +cd "$CURRENT_DIR" \ No newline at end of file diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 0000000..3b7a38f --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1 @@ +mvn clean package -Dquarkus.container-image.push=false -Dquarkus.container-image.build=false \ No newline at end of file From 95ca1266706e4af6642ce48dbb1f75e9b450ec8b Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 19 Apr 2026 09:28:51 +0000 Subject: [PATCH 06/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- .../java/com/drinkool/mapper/ExceptionHandlersMapper.java | 2 +- .../main/java/com/drinkool/services/CustomerService.java | 3 +-- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- .../java/com/drinkool/controller/CustomerController.java | 2 +- k8s.yaml | 6 +++--- lib/pom.xml | 2 +- pom.xml | 2 +- 10 files changed, 18 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be9e1f5..5fd3730 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.7](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.6...v1.5.7) (2026-04-19) + + +### Bug Fixes + +* add logout, quick signup and quick login ([#29](https://git.demonkernel.io.vn/FoodSurf/backend/issues/29)) ([4811934](https://git.demonkernel.io.vn/FoodSurf/backend/commit/4811934b84f7684410297a8f7d1f7ff14611a25a)) + ## [1.5.6](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.5...v1.5.6) (2026-04-19) diff --git a/account-service/pom.xml b/account-service/pom.xml index f717c1d..2a3da27 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.6 + 1.5.7 ../pom.xml diff --git a/account-service/src/main/java/com/drinkool/mapper/ExceptionHandlersMapper.java b/account-service/src/main/java/com/drinkool/mapper/ExceptionHandlersMapper.java index 4372d2a..f38e9da 100644 --- a/account-service/src/main/java/com/drinkool/mapper/ExceptionHandlersMapper.java +++ b/account-service/src/main/java/com/drinkool/mapper/ExceptionHandlersMapper.java @@ -1,7 +1,7 @@ package com.drinkool.mapper; -import jakarta.ws.rs.core.Response; import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.core.Response; import org.jboss.resteasy.reactive.server.ServerExceptionMapper; public class ExceptionHandlersMapper { diff --git a/account-service/src/main/java/com/drinkool/services/CustomerService.java b/account-service/src/main/java/com/drinkool/services/CustomerService.java index 87e09eb..ea00033 100644 --- a/account-service/src/main/java/com/drinkool/services/CustomerService.java +++ b/account-service/src/main/java/com/drinkool/services/CustomerService.java @@ -41,8 +41,7 @@ public class CustomerService extends BaseService { newCustomer.signup(input.phone); - return Response.status(Response.Status.CREATED) - .build(); + return Response.status(Response.Status.CREATED).build(); } @POST diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 8ae5b17..5cd1114 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.6 + 1.5.7 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 74f1078..9e15b21 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.6 + 1.5.7 ../pom.xml diff --git a/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java b/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java index ee38f53..ccaac42 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java @@ -35,7 +35,7 @@ public class CustomerController extends BaseController { return accountService.quickSignup(input); } - @POST() + @POST @Path(Url.QuickLogin) public Uni proxyQuickLogin(QuickLogin input) { return accountService.quickLogin(input); diff --git a/k8s.yaml b/k8s.yaml index 59b02a0..25dbdb6 100644 --- a/k8s.yaml +++ b/k8s.yaml @@ -15,7 +15,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.6 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.7 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -73,7 +73,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.6 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.7 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -129,7 +129,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.6 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.7 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index 5138643..6d62186 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.6 + 1.5.7 ../pom.xml diff --git a/pom.xml b/pom.xml index 174800c..a2b8aae 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.6 + 1.5.7 pom 25 From a5359db271fc020dfc579fb62c2aa468852070a8 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Sun, 19 Apr 2026 11:00:45 +0000 Subject: [PATCH 07/51] fix: add sms otp protocol (#30) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/30 --- .../drinkool/controller/IndexController.java | 25 +++++++++++++++++++ .../com/drinkool/services/BaseService.java | 17 +++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 gateway-service/src/main/java/com/drinkool/controller/IndexController.java create mode 100644 gateway-service/src/main/java/com/drinkool/services/BaseService.java diff --git a/gateway-service/src/main/java/com/drinkool/controller/IndexController.java b/gateway-service/src/main/java/com/drinkool/controller/IndexController.java new file mode 100644 index 0000000..a212dfd --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/controller/IndexController.java @@ -0,0 +1,25 @@ +package com.drinkool.controller; + +import com.drinkool.Url; +import com.drinkool.dtos.SmsOtp; +import com.drinkool.services.BaseService; +import io.smallrye.mutiny.Uni; +import jakarta.inject.Inject; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Response; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +@Path("/api") +public class IndexController { + + @Inject + @RestClient + BaseService baseService; + + @POST + @Path(Url.SmsOtp) + public Uni smsOtp(SmsOtp input) { + return baseService.smsOtp(input); + } +} diff --git a/gateway-service/src/main/java/com/drinkool/services/BaseService.java b/gateway-service/src/main/java/com/drinkool/services/BaseService.java new file mode 100644 index 0000000..48a87a5 --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/services/BaseService.java @@ -0,0 +1,17 @@ +package com.drinkool.services; + +import com.drinkool.Url; +import com.drinkool.dtos.SmsOtp; +import io.smallrye.mutiny.Uni; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Response; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@RegisterRestClient(configKey = "account") +@Path("") +public interface BaseService { + @POST + @Path(Url.SmsOtp) + Uni smsOtp(SmsOtp input); +} From 715fbaf202388cc3e7389d80067aea1575eae759 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 19 Apr 2026 11:14:18 +0000 Subject: [PATCH 08/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s.yaml | 6 +++--- lib/pom.xml | 2 +- pom.xml | 2 +- 7 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fd3730..8e64827 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.8](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.7...v1.5.8) (2026-04-19) + + +### Bug Fixes + +* add sms otp protocol ([#30](https://git.demonkernel.io.vn/FoodSurf/backend/issues/30)) ([a5359db](https://git.demonkernel.io.vn/FoodSurf/backend/commit/a5359db271fc020dfc579fb62c2aa468852070a8)) + ## [1.5.7](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.6...v1.5.7) (2026-04-19) diff --git a/account-service/pom.xml b/account-service/pom.xml index 2a3da27..984fc1b 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.7 + 1.5.8 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 5cd1114..6bcd503 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.7 + 1.5.8 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 9e15b21..09e9d98 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.7 + 1.5.8 ../pom.xml diff --git a/k8s.yaml b/k8s.yaml index 25dbdb6..a309332 100644 --- a/k8s.yaml +++ b/k8s.yaml @@ -15,7 +15,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.7 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.8 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -73,7 +73,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.7 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.8 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -129,7 +129,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.7 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.8 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index 6d62186..3c0fe31 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.7 + 1.5.8 ../pom.xml diff --git a/pom.xml b/pom.xml index a2b8aae..ce94197 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.7 + 1.5.8 pom 25 From b7bf0164e6a4a7f37324c4cdab5c8e6158e81615 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Mon, 20 Apr 2026 07:42:22 +0000 Subject: [PATCH 09/51] fix: better redis connection (#31) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/31 --- account-service/src/main/resources/application.properties | 4 ++-- k8s.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/account-service/src/main/resources/application.properties b/account-service/src/main/resources/application.properties index 42df8b3..af3a9a5 100644 --- a/account-service/src/main/resources/application.properties +++ b/account-service/src/main/resources/application.properties @@ -2,7 +2,7 @@ quarkus.datasource.db-kind=postgresql quarkus.datasource.username=postgres quarkus.datasource.password=password -quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/postgres +quarkus.datasource.jdbc.url=jdbc:postgresql://host.docker.internal:5432/postgres quarkus.hibernate-orm.database.generation=update @@ -16,7 +16,7 @@ quarkus.container-image.builder=docker quarkus.container-image.additional-tags=latest # Redis -quarkus.redis.hosts=redis://localhost:6379 +quarkus.redis.hosts=redis://${REDIS_SERVICE_SERVICE_HOST:localhost}:${REDIS_SERVICE_SERVICE_PORT:6379} # Dependency diff --git a/k8s.yaml b/k8s.yaml index a309332..919c421 100644 --- a/k8s.yaml +++ b/k8s.yaml @@ -20,7 +20,7 @@ spec: ports: - containerPort: 8080 env: - - name: QUARKUS_REDIS_HOST + - name: REDIS_SERVICE value: "redis-service" - name: QUARKUS_DATASOURCE_PASSWORD valueFrom: From 4ab284e96698248b8a6e513b9ac729ae36997542 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Mon, 20 Apr 2026 07:58:34 +0000 Subject: [PATCH 10/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s.yaml | 6 +++--- lib/pom.xml | 2 +- pom.xml | 2 +- 7 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e64827..4647f2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.9](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.8...v1.5.9) (2026-04-20) + + +### Bug Fixes + +* better redis connection ([#31](https://git.demonkernel.io.vn/FoodSurf/backend/issues/31)) ([b7bf016](https://git.demonkernel.io.vn/FoodSurf/backend/commit/b7bf0164e6a4a7f37324c4cdab5c8e6158e81615)) + ## [1.5.8](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.7...v1.5.8) (2026-04-19) diff --git a/account-service/pom.xml b/account-service/pom.xml index 984fc1b..ef35183 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.8 + 1.5.9 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 6bcd503..4635f15 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.8 + 1.5.9 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 09e9d98..602b637 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.8 + 1.5.9 ../pom.xml diff --git a/k8s.yaml b/k8s.yaml index 919c421..c1cc58d 100644 --- a/k8s.yaml +++ b/k8s.yaml @@ -15,7 +15,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.8 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.9 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -73,7 +73,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.8 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.9 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -129,7 +129,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.8 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.9 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index 3c0fe31..c47f1c0 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.8 + 1.5.9 ../pom.xml diff --git a/pom.xml b/pom.xml index ce94197..7c8f999 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.8 + 1.5.9 pom 25 From 6eb075c4b51a345aa5a5438a5d3ef9dec27dcc2c Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Mon, 20 Apr 2026 08:39:50 +0000 Subject: [PATCH 11/51] fix: add field role for user model (#32) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/32 --- .../main/java/com/drinkool/entities/CustomerEntity.java | 4 ++++ .../main/java/com/drinkool/entities/ManagerEntity.java | 4 ++++ .../src/main/java/com/drinkool/models/UserModel.java | 9 +++++++++ .../src/test/java/com/drinkool/models/UserModelTest.java | 6 +++++- 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/account-service/src/main/java/com/drinkool/entities/CustomerEntity.java b/account-service/src/main/java/com/drinkool/entities/CustomerEntity.java index 3f75fd7..1c5deae 100644 --- a/account-service/src/main/java/com/drinkool/entities/CustomerEntity.java +++ b/account-service/src/main/java/com/drinkool/entities/CustomerEntity.java @@ -10,6 +10,10 @@ import java.util.UUID; @Table(name = Role.Customer) public class CustomerEntity extends UserModel { + public CustomerEntity() { + super(Role.Customer); + } + @Transactional public void signup(String phone) { this.signup(phone, phone, UUID.randomUUID().toString().substring(0, 32)); diff --git a/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java b/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java index 582a489..1f7e2ea 100644 --- a/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java +++ b/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java @@ -12,6 +12,10 @@ public class ManagerEntity extends UserModel { public boolean isVerified; + public ManagerEntity() { + super(Role.Manager); + } + public void signup( String name, String phone, diff --git a/account-service/src/main/java/com/drinkool/models/UserModel.java b/account-service/src/main/java/com/drinkool/models/UserModel.java index 7145ea3..fcdb2d2 100644 --- a/account-service/src/main/java/com/drinkool/models/UserModel.java +++ b/account-service/src/main/java/com/drinkool/models/UserModel.java @@ -23,6 +23,15 @@ public abstract class UserModel extends BaseEntity { @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) public String hashedPassword; + @Transient + public String role; + + protected UserModel(String role) { + this.role = role; + } + + public UserModel() {} + @Transactional public void signup(String name, String phone, String rawPassword) { UserModel existedUser = UserModel.find("phone", phone).firstResult(); diff --git a/account-service/src/test/java/com/drinkool/models/UserModelTest.java b/account-service/src/test/java/com/drinkool/models/UserModelTest.java index 28f42db..d7fa859 100644 --- a/account-service/src/test/java/com/drinkool/models/UserModelTest.java +++ b/account-service/src/test/java/com/drinkool/models/UserModelTest.java @@ -12,7 +12,11 @@ import org.junit.jupiter.api.Test; @Entity @Table(name = "test_users") -class TestUserEntity extends UserModel {} +class TestUserEntity extends UserModel { + public TestUserEntity() { + super("TestRole"); + } +} @QuarkusTest public class UserModelTest { From aaa7cebd3299a2563059f3336e351715f73f43eb Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Mon, 20 Apr 2026 08:53:43 +0000 Subject: [PATCH 12/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- .../src/test/java/com/drinkool/models/UserModelTest.java | 1 + eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s.yaml | 6 +++--- lib/pom.xml | 2 +- pom.xml | 2 +- 8 files changed, 16 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4647f2c..f585448 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.10](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.9...v1.5.10) (2026-04-20) + + +### Bug Fixes + +* add field role for user model ([#32](https://git.demonkernel.io.vn/FoodSurf/backend/issues/32)) ([6eb075c](https://git.demonkernel.io.vn/FoodSurf/backend/commit/6eb075c4b51a345aa5a5438a5d3ef9dec27dcc2c)) + ## [1.5.9](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.8...v1.5.9) (2026-04-20) diff --git a/account-service/pom.xml b/account-service/pom.xml index ef35183..1b44ac7 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.9 + 1.5.10 ../pom.xml diff --git a/account-service/src/test/java/com/drinkool/models/UserModelTest.java b/account-service/src/test/java/com/drinkool/models/UserModelTest.java index d7fa859..6995059 100644 --- a/account-service/src/test/java/com/drinkool/models/UserModelTest.java +++ b/account-service/src/test/java/com/drinkool/models/UserModelTest.java @@ -13,6 +13,7 @@ import org.junit.jupiter.api.Test; @Entity @Table(name = "test_users") class TestUserEntity extends UserModel { + public TestUserEntity() { super("TestRole"); } diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 4635f15..60415e3 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.9 + 1.5.10 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 602b637..1743d61 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.9 + 1.5.10 ../pom.xml diff --git a/k8s.yaml b/k8s.yaml index c1cc58d..006c114 100644 --- a/k8s.yaml +++ b/k8s.yaml @@ -15,7 +15,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.9 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.10 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -73,7 +73,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.9 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.10 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -129,7 +129,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.9 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.10 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index c47f1c0..5446ca6 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.9 + 1.5.10 ../pom.xml diff --git a/pom.xml b/pom.xml index 7c8f999..675690a 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.9 + 1.5.10 pom 25 From 1775192c52b8412d16377796da0f3e6674236b74 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Wed, 22 Apr 2026 04:08:46 +0000 Subject: [PATCH 13/51] fix: create eatery when manager signup (#33) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/33 --- .gitea/workflows/publish.yaml | 5 +- .gitea/workflows/test.yaml | 14 +- account-service/pom.xml | 14 ++ .../src/main/docker/Dockerfile.jvm | 2 +- .../src/main/docker/Dockerfile.legacy-jar | 2 +- .../com/drinkool/entities/ManagerEntity.java | 17 -- .../java/com/drinkool/models/UserModel.java | 2 +- .../com/drinkool/services/AccountService.java | 2 +- .../drinkool/services/CustomerService.java | 1 + .../com/drinkool/services/ManagerService.java | 26 ++- .../src/main/resources/application.properties | 11 +- .../drinkool/services/AccountServiceTest.java | 1 + .../drinkool/services/BaseServiceTest.java | 1 + .../services/CustomerServiceTest.java | 2 +- .../drinkool/services/ManagerServiceTest.java | 122 ++++++++++ eatery-service/pom.xml | 37 ++-- eatery-service/src/main/docker/Dockerfile.jvm | 2 +- .../src/main/docker/Dockerfile.legacy-jar | 2 +- .../com/drinkool/entities/EateryEntity.java | 37 ++++ .../entities/EateryInventoryItemEntity.java | 1 + .../entities/InventoryItemEntity.java | 1 + .../com/drinkool/entities/MenuItemEntity.java | 1 + .../entities/MenuItemIngredientEntity.java | 1 + .../com/drinkool/entities/ReviewEntity.java | 2 +- .../com/drinkool/services/EateryService.java | 20 ++ .../src/main/resources/application.properties | 13 +- .../drinkool/entities/ReviewEntityTest.java | 2 +- .../drinkool/services/EateryServiceTest.java | 43 ++++ .../drinkool/services/ReviewServiceTest.java | 2 +- .../src/test/resources/application.properties | 5 +- .../src/main/docker/Dockerfile.jvm | 2 +- .../src/main/docker/Dockerfile.legacy-jar | 2 +- .../drinkool/controller/BaseController.java | 5 +- .../controller/ManagerController.java | 36 +++ .../filters/InternalHeaderGatewayFilter.java | 3 +- .../com/drinkool/services/BaseService.java | 1 + .../drinkool/services/CustomerService.java | 5 +- .../com/drinkool/services/ManagerService.java | 28 +++ .../controller/BaseControllerTest.java | 1 + .../InternalHeaderGatewayFilterTest.java | 3 +- k8s.yaml | 208 ------------------ k8s/account.yaml | 58 +++++ k8s/eatery.yaml | 57 +++++ k8s/gateway.yaml | 48 ++++ k8s/kafdrop.yaml | 35 +++ k8s/kafka.yaml | 52 +++++ k8s/redis.yaml | 43 ++++ lib/pom.xml | 10 + .../java/com/drinkool/dtos/SendReview.java | 2 +- .../drinkool/dtos/event/ManagerCreate.java | 17 ++ .../{ => lib}/entities/BaseEntity.java | 2 +- .../{ => lib}/models/ReviewModel.java | 4 +- scripts/build.sh | 4 +- scripts/publish.sh | 2 +- 54 files changed, 738 insertions(+), 281 deletions(-) create mode 100644 account-service/src/test/java/com/drinkool/services/ManagerServiceTest.java create mode 100644 eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java create mode 100644 eatery-service/src/main/java/com/drinkool/services/EateryService.java create mode 100644 eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java create mode 100644 gateway-service/src/main/java/com/drinkool/controller/ManagerController.java create mode 100644 gateway-service/src/main/java/com/drinkool/services/ManagerService.java delete mode 100644 k8s.yaml create mode 100644 k8s/account.yaml create mode 100644 k8s/eatery.yaml create mode 100644 k8s/gateway.yaml create mode 100644 k8s/kafdrop.yaml create mode 100644 k8s/kafka.yaml create mode 100644 k8s/redis.yaml create mode 100644 lib/src/main/java/com/drinkool/dtos/event/ManagerCreate.java rename lib/src/main/java/com/drinkool/{ => lib}/entities/BaseEntity.java (88%) rename lib/src/main/java/com/drinkool/{ => lib}/models/ReviewModel.java (87%) diff --git a/.gitea/workflows/publish.yaml b/.gitea/workflows/publish.yaml index ec7bdc4..5bf62e3 100644 --- a/.gitea/workflows/publish.yaml +++ b/.gitea/workflows/publish.yaml @@ -38,7 +38,10 @@ jobs: - name: Cache Maven packages uses: actions/cache@v4 with: - path: ~/.m2/repository + path: | + ~/.m2/repository + **/target/native-image-cache + **/target/reports key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index 639cf30..c7e167f 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -30,7 +30,10 @@ jobs: - name: Cache Maven packages uses: actions/cache@v4 with: - path: ~/.m2/repository + path: | + ~/.m2/repository + **/target/native-image-cache + **/target/reports key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- @@ -46,10 +49,13 @@ jobs: apt-get install -y --no-install-recommends --no-install-suggests \ openjdk-25-jdk-headless docker-cli docker-buildx - - name: Build and Test all modules + - name: Build and Test all module + env: + TESTCONTAINERS_RYUK_DISABLED: true run: | - ./mvnw -B install \ - -Dquarkus.container-image.push=false -Pnative + ./mvnw -B clean install -Pnative \ + -Dquarkus.container-image.push=false \ + -Dquarkus.container-image.registry=git.demonkernel.io.vn - name: Publish Test Report uses: dorny/test-reporter@v3 diff --git a/account-service/pom.xml b/account-service/pom.xml index 1b44ac7..5f1e025 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -49,6 +49,20 @@ lib ${project.version} + + org.bitbucket.b_c + jose4j + 0.9.3 + + + io.quarkus + quarkus-messaging-kafka + + + io.quarkus + quarkus-test-kafka-companion + test + io.quarkus quarkus-jdbc-h2 diff --git a/account-service/src/main/docker/Dockerfile.jvm b/account-service/src/main/docker/Dockerfile.jvm index 6a6f0e5..49bfabc 100644 --- a/account-service/src/main/docker/Dockerfile.jvm +++ b/account-service/src/main/docker/Dockerfile.jvm @@ -80,7 +80,7 @@ # You can find more information about the UBI base runtime images and their configuration here: # https://rh-openjdk.github.io/redhat-openjdk-containers/ ### -FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:1.24 +FROM registry.access.redhat.com/ubi9/openjdk-25-runtime:1.24 ENV LANGUAGE='en_US:en' diff --git a/account-service/src/main/docker/Dockerfile.legacy-jar b/account-service/src/main/docker/Dockerfile.legacy-jar index 53dfe67..192280b 100644 --- a/account-service/src/main/docker/Dockerfile.legacy-jar +++ b/account-service/src/main/docker/Dockerfile.legacy-jar @@ -80,7 +80,7 @@ # You can find more information about the UBI base runtime images and their configuration here: # https://rh-openjdk.github.io/redhat-openjdk-containers/ ### -FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:1.24 +FROM registry.access.redhat.com/ubi9/openjdk-25-runtime:1.24 ENV LANGUAGE='en_US:en' diff --git a/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java b/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java index 1f7e2ea..6d4691d 100644 --- a/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java +++ b/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java @@ -8,24 +8,7 @@ import jakarta.persistence.*; @Table(name = Role.Manager) public class ManagerEntity extends UserModel { - public String eateryName; - - public boolean isVerified; - public ManagerEntity() { super(Role.Manager); } - - public void signup( - String name, - String phone, - String rawPassword, - String eateryName - ) { - this.eateryName = eateryName; - - this.isVerified = false; - - this.signup(name, phone, rawPassword); - } } diff --git a/account-service/src/main/java/com/drinkool/models/UserModel.java b/account-service/src/main/java/com/drinkool/models/UserModel.java index fcdb2d2..e3a1346 100644 --- a/account-service/src/main/java/com/drinkool/models/UserModel.java +++ b/account-service/src/main/java/com/drinkool/models/UserModel.java @@ -1,6 +1,6 @@ package com.drinkool.models; -import com.drinkool.entities.BaseEntity; +import com.drinkool.lib.entities.BaseEntity; import com.drinkool.utils.PhoneValidator; import com.fasterxml.jackson.annotation.JsonProperty; import com.password4j.Password; diff --git a/account-service/src/main/java/com/drinkool/services/AccountService.java b/account-service/src/main/java/com/drinkool/services/AccountService.java index 5c7cb22..a6c3002 100644 --- a/account-service/src/main/java/com/drinkool/services/AccountService.java +++ b/account-service/src/main/java/com/drinkool/services/AccountService.java @@ -7,7 +7,7 @@ import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; -@Path("") +@Path("/") public class AccountService { @Inject diff --git a/account-service/src/main/java/com/drinkool/services/CustomerService.java b/account-service/src/main/java/com/drinkool/services/CustomerService.java index ea00033..c03301d 100644 --- a/account-service/src/main/java/com/drinkool/services/CustomerService.java +++ b/account-service/src/main/java/com/drinkool/services/CustomerService.java @@ -3,6 +3,7 @@ package com.drinkool.services; import com.drinkool.*; import com.drinkool.dtos.*; import com.drinkool.entities.CustomerEntity; + import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.*; diff --git a/account-service/src/main/java/com/drinkool/services/ManagerService.java b/account-service/src/main/java/com/drinkool/services/ManagerService.java index f69f601..cffc147 100644 --- a/account-service/src/main/java/com/drinkool/services/ManagerService.java +++ b/account-service/src/main/java/com/drinkool/services/ManagerService.java @@ -2,13 +2,24 @@ package com.drinkool.services; import com.drinkool.*; import com.drinkool.dtos.*; +import com.drinkool.dtos.event.ManagerCreate; import com.drinkool.entities.ManagerEntity; +import jakarta.enterprise.context.ApplicationScoped; import jakarta.transaction.Transactional; import jakarta.ws.rs.*; import jakarta.ws.rs.core.*; +import org.eclipse.microprofile.reactive.messaging.*; @Path(Role.Manager) -public class ManagerService { +@ApplicationScoped +public class ManagerService extends BaseService { + + public ManagerService() { + super(ManagerEntity.class); + } + + @Channel("manager-out") + Emitter managerEmitter; @POST @Path(Url.Signup) @@ -16,12 +27,13 @@ public class ManagerService { public Response signup(ManagerSignup input) { ManagerEntity newManager = new ManagerEntity(); - newManager.signup( - input.name, - input.phone, - input.password, - input.eateryName - ); + newManager.signup(input.name, input.phone, input.password); + + ManagerCreate message = new ManagerCreate(); + message.id = newManager.id; + message.eateryName = input.eateryName; + + managerEmitter.send(message); return Response.status(Response.Status.CREATED) .header(InternalValue.userId, newManager.id.toString()) diff --git a/account-service/src/main/resources/application.properties b/account-service/src/main/resources/application.properties index af3a9a5..e26a74b 100644 --- a/account-service/src/main/resources/application.properties +++ b/account-service/src/main/resources/application.properties @@ -27,4 +27,13 @@ quarkus.index-dependency.lib.artifact-id=lib quarkus.native.container-build=true quarkus.native.remote-container-build=true quarkus.native.additional-build-args=--initialize-at-run-time=com.password4j.AlgorithmFinder,--future-defaults=all -quarkus.native.resources.includes=com/google/i18n/phonenumbers/data/**/* \ No newline at end of file +quarkus.native.resources.includes=com/google/i18n/phonenumbers/data/**/* + +# Kafka +%prod.mp.messaging.connector.smallrye-kafka.bootstrap.servers=${KAFKA_SERVICE_SERVICE_HOST:host.docker.internal}:9092 + +## Create restaurant topic +mp.messaging.outgoing.manager-out.connector=smallrye-kafka +mp.messaging.outgoing.manager-out.topic=create-restaurant +mp.messaging.outgoing.manager-out.value.serializer=io.quarkus.kafka.client.serialization.ObjectMapperSerializer +quarkus.messaging.kafka.serializer-generation.enabled=true \ No newline at end of file diff --git a/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java b/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java index c8880af..cf06231 100644 --- a/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java @@ -4,6 +4,7 @@ import static io.restassured.RestAssured.*; import com.drinkool.*; import com.drinkool.dtos.*; + import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import org.junit.jupiter.api.Test; diff --git a/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java b/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java index 2838545..4737e7e 100644 --- a/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java @@ -5,6 +5,7 @@ import static org.hamcrest.CoreMatchers.*; import com.drinkool.*; import com.drinkool.dtos.*; + import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import org.junit.jupiter.api.Test; diff --git a/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java b/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java index a823961..50d8459 100644 --- a/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java @@ -1,12 +1,12 @@ package com.drinkool.services; import static io.restassured.RestAssured.*; -import static org.hamcrest.CoreMatchers.*; import static org.junit.jupiter.api.Assertions.*; import com.drinkool.*; import com.drinkool.dtos.*; import com.drinkool.entities.CustomerEntity; + import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import jakarta.inject.Inject; diff --git a/account-service/src/test/java/com/drinkool/services/ManagerServiceTest.java b/account-service/src/test/java/com/drinkool/services/ManagerServiceTest.java new file mode 100644 index 0000000..c2343a0 --- /dev/null +++ b/account-service/src/test/java/com/drinkool/services/ManagerServiceTest.java @@ -0,0 +1,122 @@ +package com.drinkool.services; + +import static io.restassured.RestAssured.*; +import static org.junit.jupiter.api.Assertions.*; + +import com.drinkool.*; +import com.drinkool.dtos.*; +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.kafka.*; +import io.restassured.http.ContentType; +import io.smallrye.reactive.messaging.kafka.companion.ConsumerTask; +import io.smallrye.reactive.messaging.kafka.companion.KafkaCompanion; +import java.time.Duration; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.junit.jupiter.api.Test; + +@QuarkusTest +@QuarkusTestResource(KafkaCompanionResource.class) +public class ManagerServiceTest { + + @InjectKafkaCompanion + KafkaCompanion companion; + + @ConfigProperty(name = "mp.messaging.outgoing.manager-out.topic") + String topicName; + + @Test + void testSignupSuccessAndKafkaMessageSent() { + ManagerSignup input = new ManagerSignup(); + input.name = "Ho Van Quan"; + input.phone = Utils.generateRandomPhone(); + input.password = "strong_password"; + input.eateryName = "Quan Com Ngon"; + + ConsumerTask consumer = companion + .consumeStrings() + .fromTopics(topicName, 1); + + // 2. Gọi API POST /signup + var response = given() + .contentType("application/json") + .body(input) + .when() + .post(Role.Manager + Url.Signup) + .then() + .statusCode(201) + .header(InternalValue.userId, org.hamcrest.Matchers.notNullValue()) + .header(InternalValue.role, Role.Manager) + .extract(); + + String userId = response.header(InternalValue.userId); + + var records = consumer.awaitCompletion(Duration.ofSeconds(15)).getRecords(); + + assertEquals(1, records.size()); + String kafkaPayload = records.get(0).value(); + + assertTrue(kafkaPayload.contains(userId)); + assertTrue(kafkaPayload.contains("Quan Com Ngon")); + } + + @Test + void testLoginSuccess() { + // BƯỚC 1: Tạo user trước bằng signup + String phone = Utils.generateRandomPhone(); + ManagerSignup signupData = new ManagerSignup(); + signupData.name = "Login User"; + signupData.phone = phone; + signupData.password = "secure_pass"; + signupData.eateryName = "Test Eatery"; + + given() + .contentType(ContentType.JSON) + .body(signupData) + .post(Role.Manager + Url.Signup) + .then() + .statusCode(201); + + // BƯỚC 2: Thử đăng nhập + Login loginInput = new Login(); + loginInput.phone = phone; + loginInput.password = "secure_pass"; + + given() + .contentType(ContentType.JSON) + .body(loginInput) + .when() + .post(Role.Manager + Url.Login) + .then() + .statusCode(202); + } + + @Test + void testLoginFailWrongPassword() { + String phone = Utils.generateRandomPhone(); + ManagerSignup signupData = new ManagerSignup(); + signupData.name = "Wrong Pass User"; + signupData.phone = phone; + signupData.password = "correct_password"; + signupData.eateryName = "Test Eatery"; + + given() + .contentType(ContentType.JSON) + .body(signupData) + .post(Role.Manager + Url.Signup) + .then() + .statusCode(201); + + Login loginInput = new Login(); + loginInput.phone = phone; + loginInput.password = "wrong_password"; + + given() + .contentType(ContentType.JSON) + .body(loginInput) + .when() + .post(Role.Manager + Url.Login) + .then() + .statusCode(400); // BadRequestException + } +} diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 60415e3..9f926e5 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -1,9 +1,5 @@ - - + + 4.0.0 @@ -20,11 +16,9 @@ 3.15.0 25 UTF-8 - UTF-8 + UTF-8 quarkus-bom - io.quarkus.platform + io.quarkus.platform 3.32.4 true 3.5.4 @@ -48,6 +42,20 @@ lib ${project.version} + + io.quarkus + quarkus-messaging-kafka + + + io.smallrye.reactive + smallrye-reactive-messaging-in-memory + test + + + org.bitbucket.b_c + jose4j + 0.9.3 + io.quarkus quarkus-jdbc-h2 @@ -114,8 +122,7 @@ @{argLine} - org.jboss.logmanager.LogManager + org.jboss.logmanager.LogManager ${maven.home} 1 @@ -137,10 +144,8 @@ @{argLine} - - ${project.build.directory}/${project.build.finalName}-runner - org.jboss.logmanager.LogManager + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager ${maven.home} diff --git a/eatery-service/src/main/docker/Dockerfile.jvm b/eatery-service/src/main/docker/Dockerfile.jvm index 23c1893..2431b4b 100644 --- a/eatery-service/src/main/docker/Dockerfile.jvm +++ b/eatery-service/src/main/docker/Dockerfile.jvm @@ -80,7 +80,7 @@ # You can find more information about the UBI base runtime images and their configuration here: # https://rh-openjdk.github.io/redhat-openjdk-containers/ ### -FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:1.24 +FROM registry.access.redhat.com/ubi9/openjdk-25-runtime:1.24 ENV LANGUAGE='en_US:en' diff --git a/eatery-service/src/main/docker/Dockerfile.legacy-jar b/eatery-service/src/main/docker/Dockerfile.legacy-jar index 5059b5c..735c308 100644 --- a/eatery-service/src/main/docker/Dockerfile.legacy-jar +++ b/eatery-service/src/main/docker/Dockerfile.legacy-jar @@ -80,7 +80,7 @@ # You can find more information about the UBI base runtime images and their configuration here: # https://rh-openjdk.github.io/redhat-openjdk-containers/ ### -FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:1.24 +FROM registry.access.redhat.com/ubi9/openjdk-25-runtime:1.24 ENV LANGUAGE='en_US:en' diff --git a/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java b/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java new file mode 100644 index 0000000..ae47d29 --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java @@ -0,0 +1,37 @@ +package com.drinkool.entities; + +import com.drinkool.lib.entities.BaseEntity; +import jakarta.persistence.*; +import jakarta.transaction.Transactional; +import java.util.UUID; + +@Entity +@Table +public class EateryEntity extends BaseEntity { + + @Column(unique = true, nullable = false) + public UUID ownerId; + + @Column(unique = true, nullable = false) + public String name; + + @Column(nullable = false) + public boolean isVerified = false; + + public EateryEntity() {} + + @Transactional + public void create(UUID ownerId, String name) { + EateryEntity existedEatery = EateryEntity.find( + "ownerId", + ownerId + ).firstResult(); + + if (existedEatery != null) throw new RuntimeException("ExistedEatery"); + + this.ownerId = ownerId; + this.name = name; + + this.persist(); + } +} diff --git a/eatery-service/src/main/java/com/drinkool/entities/EateryInventoryItemEntity.java b/eatery-service/src/main/java/com/drinkool/entities/EateryInventoryItemEntity.java index 334655b..e428384 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/EateryInventoryItemEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/EateryInventoryItemEntity.java @@ -1,5 +1,6 @@ package com.drinkool.entities; +import com.drinkool.lib.entities.BaseEntity; import jakarta.persistence.*; import jakarta.transaction.Transactional; diff --git a/eatery-service/src/main/java/com/drinkool/entities/InventoryItemEntity.java b/eatery-service/src/main/java/com/drinkool/entities/InventoryItemEntity.java index d83d1d0..e85a8e1 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/InventoryItemEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/InventoryItemEntity.java @@ -1,5 +1,6 @@ package com.drinkool.entities; +import com.drinkool.lib.entities.BaseEntity; import jakarta.persistence.Entity; import jakarta.persistence.Table; import jakarta.transaction.Transactional; diff --git a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java index 81da14b..efbd32a 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java @@ -1,5 +1,6 @@ package com.drinkool.entities; +import com.drinkool.lib.entities.BaseEntity; import jakarta.persistence.*; import jakarta.transaction.Transactional; import java.util.*; diff --git a/eatery-service/src/main/java/com/drinkool/entities/MenuItemIngredientEntity.java b/eatery-service/src/main/java/com/drinkool/entities/MenuItemIngredientEntity.java index 2c01f3c..17f7cd8 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/MenuItemIngredientEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/MenuItemIngredientEntity.java @@ -1,5 +1,6 @@ package com.drinkool.entities; +import com.drinkool.lib.entities.BaseEntity; import jakarta.persistence.*; @Entity diff --git a/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java b/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java index efd5e77..4477958 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java @@ -1,6 +1,6 @@ package com.drinkool.entities; -import com.drinkool.models.ReviewModel; +import com.drinkool.lib.models.ReviewModel; import jakarta.persistence.*; import jakarta.transaction.Transactional; import java.util.UUID; diff --git a/eatery-service/src/main/java/com/drinkool/services/EateryService.java b/eatery-service/src/main/java/com/drinkool/services/EateryService.java new file mode 100644 index 0000000..68844ef --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/services/EateryService.java @@ -0,0 +1,20 @@ +package com.drinkool.services; + +import com.drinkool.dtos.event.ManagerCreate; +import com.drinkool.entities.EateryEntity; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.transaction.Transactional; +import org.eclipse.microprofile.reactive.messaging.Incoming; + +@ApplicationScoped +public class EateryService { + + @Incoming("manager-in") + @Transactional + public void consumeManagerSignup(ManagerCreate input) { + EateryEntity eatery = new EateryEntity(); + + eatery.create(input.id, input.eateryName); + } +} diff --git a/eatery-service/src/main/resources/application.properties b/eatery-service/src/main/resources/application.properties index ff3d981..6652b84 100644 --- a/eatery-service/src/main/resources/application.properties +++ b/eatery-service/src/main/resources/application.properties @@ -3,7 +3,7 @@ quarkus.datasource.db-kind=postgresql quarkus.datasource.username=postgres quarkus.datasource.password=password -quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/eatery +quarkus.datasource.jdbc.url=jdbc:postgresql://host.docker.internal:5432/postgres ## Tự động tạo bảng từ Entity (chỉ dùng cho môi trường dev) quarkus.hibernate-orm.database.generation=update @@ -24,4 +24,13 @@ quarkus.index-dependency.lib.artifact-id=lib # Build quarkus.native.container-build=true quarkus.native.remote-container-build=true -quarkus.native.additional-build-args=--future-defaults=all \ No newline at end of file +quarkus.native.additional-build-args=--future-defaults=all + +# Kafka +mp.messaging.connector.smallrye-kafka.bootstrap.servers=${KAFKA_SERVICE_SERVICE_HOST:host.docker.internal}:9092 + +## Create restaurant topic +mp.messaging.incoming.manager-in.connector=smallrye-kafka +mp.messaging.incoming.manager-in.topic=create-restaurant +mp.messaging.incoming.manager-in.auto.offset.reset=earliest +quarkus.messaging.kafka.serializer-generation.enabled=true \ No newline at end of file diff --git a/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java index 956b795..9dedee1 100644 --- a/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java +++ b/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java @@ -1,6 +1,6 @@ package com.drinkool.entities; -import com.drinkool.models.ReviewModel; +import com.drinkool.lib.models.ReviewModel; import io.quarkus.test.junit.QuarkusTest; import jakarta.transaction.Transactional; import java.util.UUID; diff --git a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java new file mode 100644 index 0000000..897be96 --- /dev/null +++ b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java @@ -0,0 +1,43 @@ +package com.drinkool.services; + +import com.drinkool.dtos.event.ManagerCreate; +import com.drinkool.entities.EateryEntity; +import io.quarkus.test.junit.QuarkusTest; +import io.smallrye.reactive.messaging.memory.InMemoryConnector; +import jakarta.enterprise.context.control.ActivateRequestContext; +import jakarta.enterprise.inject.Any; +import jakarta.inject.Inject; +import java.util.UUID; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class EateryServiceTest { + + @Inject + @Any + InMemoryConnector connector; + + @Test + @ActivateRequestContext + void testConsumeManagerSignup() throws InterruptedException { + // 1. Chuẩn bị dữ liệu giả lập + ManagerCreate input = new ManagerCreate(); + input.id = UUID.randomUUID(); // Giả sử manager ID là 99 + input.eateryName = "Quan Bun Cha Test"; + + // 2. Đẩy tin nhắn vào channel "manager-in" bằng InMemoryConnector + connector.source("manager-in").send(input); + + Thread.sleep(1000); + + // 3. Kiểm tra kết quả trong Database + // Lưu ý: Vì xử lý Kafka là bất đồng bộ, đôi khi cần đợi vài miligiây + // nhưng với InMemoryConnector thì thường là tức thì. + + EateryEntity eatery = EateryEntity.find("ownerId", input.id).firstResult(); + + Assertions.assertNotNull(eatery, "Eatery should be created in DB"); + Assertions.assertEquals("Quan Bun Cha Test", eatery.name); + } +} diff --git a/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java index 69c5c34..5ed751e 100644 --- a/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java @@ -5,7 +5,7 @@ import static org.junit.jupiter.api.Assertions.*; import com.drinkool.dtos.SendReview; import com.drinkool.entities.ReviewEntity; -import com.drinkool.models.ReviewModel; +import com.drinkool.lib.models.ReviewModel; import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import java.util.Random; diff --git a/eatery-service/src/test/resources/application.properties b/eatery-service/src/test/resources/application.properties index 42128a9..f69780f 100644 --- a/eatery-service/src/test/resources/application.properties +++ b/eatery-service/src/test/resources/application.properties @@ -7,4 +7,7 @@ quarkus.http.host=0.0.0.0 %test.quarkus.datasource.jdbc.url=jdbc:h2:mem:test_db;DB_CLOSE_DELAY=-1 ## Orm -%test.quarkus.hibernate-orm.database.generation=drop-and-create \ No newline at end of file +%test.quarkus.hibernate-orm.database.generation=drop-and-create + +# Kafka +mp.messaging.incoming.manager-in.connector=smallrye-in-memory \ No newline at end of file diff --git a/gateway-service/src/main/docker/Dockerfile.jvm b/gateway-service/src/main/docker/Dockerfile.jvm index 5d81f84..fe587ea 100644 --- a/gateway-service/src/main/docker/Dockerfile.jvm +++ b/gateway-service/src/main/docker/Dockerfile.jvm @@ -80,7 +80,7 @@ # You can find more information about the UBI base runtime images and their configuration here: # https://rh-openjdk.github.io/redhat-openjdk-containers/ ### -FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:1.24 +FROM registry.access.redhat.com/ubi9/openjdk-25-runtime:1.24 ENV LANGUAGE='en_US:en' diff --git a/gateway-service/src/main/docker/Dockerfile.legacy-jar b/gateway-service/src/main/docker/Dockerfile.legacy-jar index 604f97d..15bc9a6 100644 --- a/gateway-service/src/main/docker/Dockerfile.legacy-jar +++ b/gateway-service/src/main/docker/Dockerfile.legacy-jar @@ -80,7 +80,7 @@ # You can find more information about the UBI base runtime images and their configuration here: # https://rh-openjdk.github.io/redhat-openjdk-containers/ ### -FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:1.24 +FROM registry.access.redhat.com/ubi9/openjdk-25-runtime:1.24 ENV LANGUAGE='en_US:en' diff --git a/gateway-service/src/main/java/com/drinkool/controller/BaseController.java b/gateway-service/src/main/java/com/drinkool/controller/BaseController.java index c87ecb6..7937ab4 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/BaseController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/BaseController.java @@ -1,12 +1,13 @@ package com.drinkool.controller; -import com.drinkool.InternalValue; -import com.drinkool.Url; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.core.NewCookie; import org.jboss.resteasy.reactive.RestResponse; +import com.drinkool.InternalValue; +import com.drinkool.Url; + public abstract class BaseController { @POST diff --git a/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java b/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java new file mode 100644 index 0000000..6e3667f --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java @@ -0,0 +1,36 @@ +package com.drinkool.controller; + +import com.drinkool.*; +import com.drinkool.dtos.*; +import com.drinkool.services.ManagerService; +import io.smallrye.mutiny.Uni; +import jakarta.inject.Inject; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.Response; +import java.util.*; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +@Path("/api/" + Role.Manager) +public class ManagerController extends BaseController { + + @Inject + @RestClient + ManagerService managerService; + + @POST + @Path(Url.Signup) + public Uni proxySignup(ManagerSignup input) { + return managerService.signup(input); + } + + @POST + @Path(Url.Login) + public Uni proxyLogin(Login input) { + return managerService.login(input); + } + + @GET + public Uni me(@HeaderParam(InternalValue.userId) UUID id) { + return managerService.me(id); + } +} diff --git a/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java b/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java index 99afa06..0cef877 100644 --- a/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java +++ b/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java @@ -1,6 +1,5 @@ package com.drinkool.filters; -import com.drinkool.InternalValue; import io.smallrye.mutiny.Uni; import jakarta.ws.rs.Priorities; import jakarta.ws.rs.container.*; @@ -16,6 +15,8 @@ import org.jose4j.jwt.consumer.JwtConsumer; import org.jose4j.jwt.consumer.JwtConsumerBuilder; import org.jose4j.keys.HmacKey; +import com.drinkool.InternalValue; + public class InternalHeaderGatewayFilter { @ConfigProperty(name = "gateway.jwt.secret") diff --git a/gateway-service/src/main/java/com/drinkool/services/BaseService.java b/gateway-service/src/main/java/com/drinkool/services/BaseService.java index 48a87a5..9b0828c 100644 --- a/gateway-service/src/main/java/com/drinkool/services/BaseService.java +++ b/gateway-service/src/main/java/com/drinkool/services/BaseService.java @@ -2,6 +2,7 @@ package com.drinkool.services; import com.drinkool.Url; import com.drinkool.dtos.SmsOtp; + import io.smallrye.mutiny.Uni; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; diff --git a/gateway-service/src/main/java/com/drinkool/services/CustomerService.java b/gateway-service/src/main/java/com/drinkool/services/CustomerService.java index 123d3f8..42147a6 100644 --- a/gateway-service/src/main/java/com/drinkool/services/CustomerService.java +++ b/gateway-service/src/main/java/com/drinkool/services/CustomerService.java @@ -1,7 +1,10 @@ package com.drinkool.services; -import com.drinkool.*; +import com.drinkool.InternalValue; +import com.drinkool.Role; +import com.drinkool.Url; import com.drinkool.dtos.*; + import io.smallrye.mutiny.Uni; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; diff --git a/gateway-service/src/main/java/com/drinkool/services/ManagerService.java b/gateway-service/src/main/java/com/drinkool/services/ManagerService.java new file mode 100644 index 0000000..aeb0c3d --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/services/ManagerService.java @@ -0,0 +1,28 @@ +package com.drinkool.services; + +import com.drinkool.InternalValue; +import com.drinkool.Role; +import com.drinkool.Url; +import com.drinkool.dtos.*; + +import io.smallrye.mutiny.Uni; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.Response; +import java.util.*; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@RegisterRestClient(configKey = "account") +@Path(Role.Manager) +public interface ManagerService { + @POST + @Path(Url.Signup) + Uni signup(ManagerSignup input); + + @POST + @Path(Url.Login) + Uni login(Login input); + + @GET + @Path(Url.Me) + Uni me(@HeaderParam(InternalValue.userId) UUID id); +} diff --git a/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java b/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java index 91c0680..3b04780 100644 --- a/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java +++ b/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java @@ -4,6 +4,7 @@ import static io.restassured.RestAssured.*; import static org.hamcrest.CoreMatchers.*; import com.drinkool.*; + import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Test; diff --git a/gateway-service/src/test/java/com/drinkool/filters/InternalHeaderGatewayFilterTest.java b/gateway-service/src/test/java/com/drinkool/filters/InternalHeaderGatewayFilterTest.java index 205c5b8..a53e7a2 100644 --- a/gateway-service/src/test/java/com/drinkool/filters/InternalHeaderGatewayFilterTest.java +++ b/gateway-service/src/test/java/com/drinkool/filters/InternalHeaderGatewayFilterTest.java @@ -4,7 +4,6 @@ import static io.restassured.RestAssured.*; import static org.hamcrest.CoreMatchers.*; import static org.junit.jupiter.api.Assertions.*; -import com.drinkool.InternalValue; import io.quarkus.test.junit.QuarkusTest; import io.restassured.response.Response; import org.eclipse.microprofile.config.inject.ConfigProperty; @@ -15,6 +14,8 @@ import org.jose4j.keys.HmacKey; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import com.drinkool.InternalValue; + @QuarkusTest public class InternalHeaderGatewayFilterTest { diff --git a/k8s.yaml b/k8s.yaml deleted file mode 100644 index 006c114..0000000 --- a/k8s.yaml +++ /dev/null @@ -1,208 +0,0 @@ -# 1. ACCOUNT SERVICE -apiVersion: apps/v1 -kind: Deployment -metadata: - name: account-deploy -spec: - replicas: 1 - selector: - matchLabels: - app: account - template: - metadata: - labels: - app: account - spec: - containers: - - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.10 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 8080 - env: - - name: REDIS_SERVICE - value: "redis-service" - - name: QUARKUS_DATASOURCE_PASSWORD - valueFrom: - secretKeyRef: - name: postgres-credentials - key: password - - name: QUARKUS_DATASOURCE_USERNAME - valueFrom: - secretKeyRef: - name: postgres-credentials - key: username - - name: QUARKUS_DATASOURCE_JDBC_URL - valueFrom: - secretKeyRef: - name: postgres-credentials - key: url - resources: - requests: - memory: "32Mi" - cpu: "50m" - limits: - memory: "64Mi" - cpu: "250m" ---- -apiVersion: v1 -kind: Service -metadata: - name: account-service -spec: - selector: - app: account - ports: - - port: 80 - targetPort: 8080 ---- -# 2. EATERY SERVICE -apiVersion: apps/v1 -kind: Deployment -metadata: - name: eatery-deploy -spec: - replicas: 1 - selector: - matchLabels: - app: eatery - template: - metadata: - labels: - app: eatery - spec: - containers: - - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.10 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 8080 - env: - - name: QUARKUS_DATASOURCE_PASSWORD - valueFrom: - secretKeyRef: - name: postgres-credentials - key: password - - name: QUARKUS_DATASOURCE_USERNAME - valueFrom: - secretKeyRef: - name: postgres-credentials - key: username - - name: QUARKUS_DATASOURCE_JDBC_URL - valueFrom: - secretKeyRef: - name: postgres-credentials - key: url - resources: - requests: - memory: "32Mi" - cpu: "50m" - limits: - memory: "64Mi" - cpu: "250m" ---- -apiVersion: v1 -kind: Service -metadata: - name: eatery-service -spec: - selector: - app: eatery - ports: - - port: 80 - targetPort: 8080 ---- -# 3. GATEWAY SERVICE -apiVersion: apps/v1 -kind: Deployment -metadata: - name: gateway-deploy -spec: - replicas: 1 - selector: - matchLabels: - app: gateway - template: - metadata: - labels: - app: gateway - spec: - containers: - - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.10 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 8080 - env: - - name: QUARKUS_REST_CLIENT_ACCOUNT_URL - value: "http://account-service" - - name: GATEWAY_JWT_SECRET - valueFrom: - secretKeyRef: - name: jwt-secret - key: secret - resources: - requests: - memory: "32Mi" - cpu: "50m" - limits: - memory: "64Mi" - cpu: "250m" ---- -apiVersion: v1 -kind: Service -metadata: - name: gateway-service -spec: - type: NodePort - selector: - app: gateway - ports: - - port: 80 - targetPort: 8080 - nodePort: 32080 ---- -# 4. REDIS -apiVersion: apps/v1 -kind: Deployment -metadata: - name: redis-deploy -spec: - selector: - matchLabels: - app: redis - template: - metadata: - labels: - app: redis - spec: - containers: - - name: redis-pod - image: redis:alpine - ports: - - containerPort: 6379 - resources: - limits: - cpu: "100m" - memory: "128Mi" - requests: - cpu: "20m" - memory: "64Mi" - command: - [ - "redis-server", - "--maxmemory", - "96mb", - "--maxmemory-policy", - "allkeys-lru", - ] ---- -apiVersion: v1 -kind: Service -metadata: - name: redis-service -spec: - selector: - app: redis - ports: - - port: 6379 diff --git a/k8s/account.yaml b/k8s/account.yaml new file mode 100644 index 0000000..67bf1c5 --- /dev/null +++ b/k8s/account.yaml @@ -0,0 +1,58 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: account-deploy +spec: + replicas: 1 + selector: + matchLabels: + app: account + template: + metadata: + labels: + app: account + spec: + containers: + - name: account-pod + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.10 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8080 + env: + - name: REDIS_SERVICE + value: "redis-service" + - name: KAFKA_SERVICE + value: "kafka-service" + - name: QUARKUS_DATASOURCE_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-credentials + key: password + - name: QUARKUS_DATASOURCE_USERNAME + valueFrom: + secretKeyRef: + name: postgres-credentials + key: username + - name: QUARKUS_DATASOURCE_JDBC_URL + valueFrom: + secretKeyRef: + name: postgres-credentials + key: url + resources: + requests: + memory: "32Mi" + cpu: "50m" + limits: + memory: "64Mi" + cpu: "250m" +--- +apiVersion: v1 +kind: Service +metadata: + name: account-service +spec: + selector: + app: account + ports: + - port: 80 + targetPort: 8080 \ No newline at end of file diff --git a/k8s/eatery.yaml b/k8s/eatery.yaml new file mode 100644 index 0000000..62523f9 --- /dev/null +++ b/k8s/eatery.yaml @@ -0,0 +1,57 @@ + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: eatery-deploy +spec: + replicas: 1 + selector: + matchLabels: + app: eatery + template: + metadata: + labels: + app: eatery + spec: + containers: + - name: eatery-pod + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.10 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8080 + env: + - name: KAFKA_SERVICE + value: "kafka-service" + - name: QUARKUS_DATASOURCE_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-credentials + key: password + - name: QUARKUS_DATASOURCE_USERNAME + valueFrom: + secretKeyRef: + name: postgres-credentials + key: username + - name: QUARKUS_DATASOURCE_JDBC_URL + valueFrom: + secretKeyRef: + name: postgres-credentials + key: url + resources: + requests: + memory: "32Mi" + cpu: "50m" + limits: + memory: "64Mi" + cpu: "250m" +--- +apiVersion: v1 +kind: Service +metadata: + name: eatery-service +spec: + selector: + app: eatery + ports: + - port: 80 + targetPort: 8080 \ No newline at end of file diff --git a/k8s/gateway.yaml b/k8s/gateway.yaml new file mode 100644 index 0000000..d4bc419 --- /dev/null +++ b/k8s/gateway.yaml @@ -0,0 +1,48 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gateway-deploy +spec: + replicas: 1 + selector: + matchLabels: + app: gateway + template: + metadata: + labels: + app: gateway + spec: + containers: + - name: gateway-pod + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.10 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8080 + env: + - name: QUARKUS_REST_CLIENT_ACCOUNT_URL + value: "http://account-service" + - name: GATEWAY_JWT_SECRET + valueFrom: + secretKeyRef: + name: jwt-secret + key: secret + resources: + requests: + memory: "32Mi" + cpu: "50m" + limits: + memory: "64Mi" + cpu: "250m" +--- +apiVersion: v1 +kind: Service +metadata: + name: gateway-service +spec: + type: NodePort + selector: + app: gateway + ports: + - port: 80 + targetPort: 8080 + nodePort: 32080 \ No newline at end of file diff --git a/k8s/kafdrop.yaml b/k8s/kafdrop.yaml new file mode 100644 index 0000000..9e0a2ed --- /dev/null +++ b/k8s/kafdrop.yaml @@ -0,0 +1,35 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kafdrop +spec: + replicas: 1 + selector: + matchLabels: + app: kafdrop + template: + metadata: + labels: + app: kafdrop + spec: + containers: + - name: kafdrop + image: obsidiandynamics/kafdrop + ports: + - containerPort: 9000 + env: + - name: KAFKA_BROKERCONNECT + value: "kafka-service:9092" # Trỏ vào service Kafka của bạn +--- +apiVersion: v1 +kind: Service +metadata: + name: kafdrop-svc +spec: + type: NodePort + selector: + app: kafdrop + ports: + - protocol: TCP + port: 9000 + nodePort: 30900 \ No newline at end of file diff --git a/k8s/kafka.yaml b/k8s/kafka.yaml new file mode 100644 index 0000000..951ba58 --- /dev/null +++ b/k8s/kafka.yaml @@ -0,0 +1,52 @@ +apiVersion: v1 +kind: Service +metadata: + name: kafka-service +spec: + ports: + - port: 9092 + selector: + app: kafka +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kafka-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: kafka + template: + metadata: + labels: + app: kafka + spec: + containers: + - name: kafka + image: apache/kafka:latest + ports: + - containerPort: 9092 + env: + - name: KAFKA_NODE_ID + value: "1" + - name: KAFKA_PROCESS_ROLES + value: "broker,controller" + - name: KAFKA_LISTENERS + value: "PLAINTEXT://:9092,CONTROLLER://:9093" + - name: KAFKA_ADVERTISED_LISTENERS + value: "PLAINTEXT://kafka-service:9092" + - name: KAFKA_CONTROLLER_QUORUM_VOTERS + value: "1@127.0.0.1:9093" + - name: KAFKA_CONTROLLER_LISTENER_NAMES + value: "CONTROLLER" + - name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP + value: "CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT" + - name: KAFKA_AUTO_CREATE_TOPICS_ENABLE + value: "true" + - name: KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR + value: "1" + - name: KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR + value: "1" + - name: KAFKA_TRANSACTION_STATE_LOG_MIN_ISR + value: "1" \ No newline at end of file diff --git a/k8s/redis.yaml b/k8s/redis.yaml new file mode 100644 index 0000000..1f11a6b --- /dev/null +++ b/k8s/redis.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-deploy +spec: + selector: + matchLabels: + app: redis + template: + metadata: + labels: + app: redis + spec: + containers: + - name: redis-pod + image: redis:alpine + ports: + - containerPort: 6379 + resources: + limits: + cpu: "100m" + memory: "128Mi" + requests: + cpu: "20m" + memory: "64Mi" + command: + [ + "redis-server", + "--maxmemory", + "96mb", + "--maxmemory-policy", + "allkeys-lru", + ] +--- +apiVersion: v1 +kind: Service +metadata: + name: redis-service +spec: + selector: + app: redis + ports: + - port: 6379 \ No newline at end of file diff --git a/lib/pom.xml b/lib/pom.xml index 5446ca6..56ee628 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -26,6 +26,16 @@ jackson-annotations 2.15.2 + + io.quarkus + quarkus-kafka-client + + + org.projectlombok + lombok + 1.18.30 + provided + jakarta.persistence jakarta.persistence-api diff --git a/lib/src/main/java/com/drinkool/dtos/SendReview.java b/lib/src/main/java/com/drinkool/dtos/SendReview.java index 637f40b..c0fb899 100644 --- a/lib/src/main/java/com/drinkool/dtos/SendReview.java +++ b/lib/src/main/java/com/drinkool/dtos/SendReview.java @@ -1,6 +1,6 @@ package com.drinkool.dtos; -import com.drinkool.models.ReviewModel; +import com.drinkool.lib.models.ReviewModel; import java.util.UUID; public class SendReview { diff --git a/lib/src/main/java/com/drinkool/dtos/event/ManagerCreate.java b/lib/src/main/java/com/drinkool/dtos/event/ManagerCreate.java new file mode 100644 index 0000000..e337a6f --- /dev/null +++ b/lib/src/main/java/com/drinkool/dtos/event/ManagerCreate.java @@ -0,0 +1,17 @@ +package com.drinkool.dtos.event; + +import io.quarkus.runtime.annotations.RegisterForReflection; +import java.util.UUID; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@RegisterForReflection +@Getter +@Setter +@NoArgsConstructor +public class ManagerCreate { + + public UUID id; + public String eateryName; +} diff --git a/lib/src/main/java/com/drinkool/entities/BaseEntity.java b/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java similarity index 88% rename from lib/src/main/java/com/drinkool/entities/BaseEntity.java rename to lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java index 984cab9..0ee8e50 100644 --- a/lib/src/main/java/com/drinkool/entities/BaseEntity.java +++ b/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java @@ -1,4 +1,4 @@ -package com.drinkool.entities; +package com.drinkool.lib.entities; import io.quarkus.hibernate.orm.panache.PanacheEntityBase; import jakarta.persistence.*; diff --git a/lib/src/main/java/com/drinkool/models/ReviewModel.java b/lib/src/main/java/com/drinkool/lib/models/ReviewModel.java similarity index 87% rename from lib/src/main/java/com/drinkool/models/ReviewModel.java rename to lib/src/main/java/com/drinkool/lib/models/ReviewModel.java index 58c4279..6412d6f 100644 --- a/lib/src/main/java/com/drinkool/models/ReviewModel.java +++ b/lib/src/main/java/com/drinkool/lib/models/ReviewModel.java @@ -1,6 +1,6 @@ -package com.drinkool.models; +package com.drinkool.lib.models; -import com.drinkool.entities.BaseEntity; +import com.drinkool.lib.entities.BaseEntity; import jakarta.persistence.*; import java.time.LocalDateTime; diff --git a/scripts/build.sh b/scripts/build.sh index 17b5426..8f96807 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,3 +1,3 @@ -mvn clean package -DskipTests -Pnative \ +mvn clean package -DskipTests \ -Dquarkus.container-image.push=false \ - -Dquarkus.container-image.registry=git.demonkernel.io.vn + -Dquarkus.container-image.registry=git.demonkernel.io.vn diff --git a/scripts/publish.sh b/scripts/publish.sh index 1becc04..e15d5d6 100755 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -6,6 +6,6 @@ SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) cd "$SCRIPT_DIR/.." kubectl delete all --all -n drinkool-backend -kubectl apply -f k8s.yaml -n drinkool-backend +kubectl apply -f k8s -n drinkool-backend cd "$CURRENT_DIR" \ No newline at end of file From 667e803a63de3162e5e20cfc8d39234730dde45d Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Wed, 22 Apr 2026 05:14:49 +0000 Subject: [PATCH 14/51] fix: better release script (#34) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/34 --- .releaserc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.releaserc.yaml b/.releaserc.yaml index 88e101a..e4eeddc 100644 --- a/.releaserc.yaml +++ b/.releaserc.yaml @@ -11,7 +11,7 @@ plugins: - - "@semantic-release/exec" - prepareCmd: | ./mvnw versions:set -DnewVersion=${nextRelease.version} && - sed -i "/-service:/ s|:[^:]*$|:${nextRelease.version}|" k8s.yaml && + sed -i "/-service:/ s|:[^:]*$|:${nextRelease.version}|" k8s/*.yaml && if [ "${branch.name}" = "main" ]; then ./mvnw package -B -Pnative -Dquarkus.container-image.tag=${nextRelease.version} -DskipTests fi From a20720541bf17a3ec6996965d6dcaa2082d8b4b2 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Wed, 22 Apr 2026 08:32:41 +0000 Subject: [PATCH 15/51] fix: add eatery query (#35) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/35 --- eatery-service/pom.xml | 19 +++++- .../com/drinkool/entities/EateryEntity.java | 13 +++- .../com/drinkool/entities/MenuItemEntity.java | 7 ++ .../com/drinkool/services/EateryService.java | 17 ++++- .../drinkool/services/EateryServiceTest.java | 66 +++++++++++++++++++ gateway-service/pom.xml | 4 ++ .../drinkool/controller/EateryController.java | 34 ++++++++++ .../controller/BaseControllerTest.java | 5 +- k8s/gateway.yaml | 2 + k8s/kafdrop.yaml | 20 +++--- 10 files changed, 170 insertions(+), 17 deletions(-) create mode 100644 gateway-service/src/main/java/com/drinkool/controller/EateryController.java diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 9f926e5..c3be3c3 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -1,5 +1,7 @@ - + 4.0.0 @@ -42,6 +44,16 @@ lib ${project.version} + + net.datafaker + datafaker + 2.0.2 + test + + + io.quarkus + quarkus-smallrye-graphql + io.quarkus quarkus-messaging-kafka @@ -144,7 +156,8 @@ @{argLine} - ${project.build.directory}/${project.build.finalName}-runner + + ${project.build.directory}/${project.build.finalName}-runner org.jboss.logmanager.LogManager ${maven.home} @@ -168,4 +181,4 @@ - + \ No newline at end of file diff --git a/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java b/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java index ae47d29..d8e16d9 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java @@ -3,6 +3,8 @@ package com.drinkool.entities; import com.drinkool.lib.entities.BaseEntity; import jakarta.persistence.*; import jakarta.transaction.Transactional; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; @Entity @@ -18,10 +20,17 @@ public class EateryEntity extends BaseEntity { @Column(nullable = false) public boolean isVerified = false; + @OneToMany( + mappedBy = "eatery", + cascade = CascadeType.ALL, + orphanRemoval = true + ) + public List menus = new ArrayList<>(); + public EateryEntity() {} @Transactional - public void create(UUID ownerId, String name) { + public EateryEntity create(UUID ownerId, String name) { EateryEntity existedEatery = EateryEntity.find( "ownerId", ownerId @@ -33,5 +42,7 @@ public class EateryEntity extends BaseEntity { this.name = name; this.persist(); + + return this; } } diff --git a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java index efbd32a..39ddb09 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java @@ -9,9 +9,16 @@ import java.util.*; @Table public class MenuItemEntity extends BaseEntity { + @Column(nullable = false) public String name; + + @Column(nullable = false) public double price; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "eatery_id") + public EateryEntity eatery; + // Danh sách các nguyên liệu cấu thành món ăn này @OneToMany( mappedBy = "menuItem", diff --git a/eatery-service/src/main/java/com/drinkool/services/EateryService.java b/eatery-service/src/main/java/com/drinkool/services/EateryService.java index 68844ef..50a26af 100644 --- a/eatery-service/src/main/java/com/drinkool/services/EateryService.java +++ b/eatery-service/src/main/java/com/drinkool/services/EateryService.java @@ -2,12 +2,17 @@ package com.drinkool.services; import com.drinkool.dtos.event.ManagerCreate; import com.drinkool.entities.EateryEntity; - import jakarta.enterprise.context.ApplicationScoped; import jakarta.transaction.Transactional; +import java.util.List; +import java.util.UUID; +import org.eclipse.microprofile.graphql.GraphQLApi; +import org.eclipse.microprofile.graphql.Name; +import org.eclipse.microprofile.graphql.Query; import org.eclipse.microprofile.reactive.messaging.Incoming; @ApplicationScoped +@GraphQLApi public class EateryService { @Incoming("manager-in") @@ -17,4 +22,14 @@ public class EateryService { eatery.create(input.id, input.eateryName); } + + @Query("allEateries") + public List getAll() { + return EateryEntity.listAll(); + } + + @Query("eateryById") + public EateryEntity getEatery(@Name("id") UUID id) { + return EateryEntity.findById(id); + } } diff --git a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java index 897be96..16bde3e 100644 --- a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java @@ -1,19 +1,30 @@ package com.drinkool.services; +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.Matchers.hasItems; + import com.drinkool.dtos.event.ManagerCreate; import com.drinkool.entities.EateryEntity; import io.quarkus.test.junit.QuarkusTest; +import io.restassured.http.ContentType; import io.smallrye.reactive.messaging.memory.InMemoryConnector; import jakarta.enterprise.context.control.ActivateRequestContext; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; +import jakarta.transaction.Transactional; import java.util.UUID; +import net.datafaker.Faker; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @QuarkusTest public class EateryServiceTest { + private final Faker faker = new Faker(); + @Inject @Any InMemoryConnector connector; @@ -40,4 +51,59 @@ public class EateryServiceTest { Assertions.assertNotNull(eatery, "Eatery should be created in DB"); Assertions.assertEquals("Quan Bun Cha Test", eatery.name); } + + private UUID lastSavedId; + private String lastSavedName; + + @BeforeEach + @Transactional + void setup() { + EateryEntity.deleteAll(); + + lastSavedName = faker.restaurant().name(); + + EateryEntity eatery = new EateryEntity(); + lastSavedId = eatery.create(UUID.randomUUID(), lastSavedName).id; + + for (int i = 0; i < 2; i++) { + EateryEntity e = new EateryEntity(); + e.create(UUID.randomUUID(), faker.restaurant().name()); + } + } + + @Test + void testGetAllEateries() { + // Cấu trúc query GraphQL + String query = "{ \"query\": \"{ allEateries { ownerId name } }\" }"; + + given() + .contentType(ContentType.JSON) + .body(query) + .when() + .post("/graphql") + .then() + .statusCode(200) + // GraphQL trả về dữ liệu bọc trong object "data" + .body("data.allEateries", notNullValue()) + .body("data.allEateries.name", hasItems(lastSavedName)); + } + + @Test + void testGetEateryById() { + // Sử dụng biến id đã lưu ở setup + // Lưu ý: Trong GraphQL, String/UUID phải nằm trong dấu ngoặc kép + String query = String.format( + "{ \"query\": \"{ eateryById(id: \\\"%s\\\") { ownerId name } }\" }", + lastSavedId + ); + + given() + .contentType(ContentType.JSON) + .body(query) + .when() + .post("/graphql") + .then() + .statusCode(200) + .body("data.eateryById.name", is(lastSavedName)); + } } diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 1743d61..ecbdb89 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -48,6 +48,10 @@ jose4j 0.9.6 + + io.quarkus + quarkus-smallrye-graphql-client + com.drinkool lib diff --git a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java new file mode 100644 index 0000000..3e98288 --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java @@ -0,0 +1,34 @@ +package com.drinkool.controller; + +import io.smallrye.graphql.client.GraphQLClient; +import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Response; +import java.util.concurrent.ExecutionException; + +@Path("/api/eatery") +public class EateryController { + + @GraphQLClient("eatery") + DynamicGraphQLClient dynamicClient; + + @POST + @Path("/graphql") + public Response forward(String query) + throws ExecutionException, InterruptedException { + io.smallrye.graphql.client.Response response = dynamicClient.executeSync( + query + ); + + if (response.hasError()) { + return jakarta.ws.rs.core.Response.status(500) + .entity(response.getErrors()) + .build(); + } + + return jakarta.ws.rs.core.Response.ok( + response.getData().toString() + ).build(); + } +} diff --git a/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java b/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java index 3b04780..2382510 100644 --- a/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java +++ b/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java @@ -3,8 +3,9 @@ package com.drinkool.controller; import static io.restassured.RestAssured.*; import static org.hamcrest.CoreMatchers.*; -import com.drinkool.*; - +import com.drinkool.InternalValue; +import com.drinkool.Role; +import com.drinkool.Url; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Test; diff --git a/k8s/gateway.yaml b/k8s/gateway.yaml index d4bc419..47f2316 100644 --- a/k8s/gateway.yaml +++ b/k8s/gateway.yaml @@ -21,6 +21,8 @@ spec: env: - name: QUARKUS_REST_CLIENT_ACCOUNT_URL value: "http://account-service" + - name: QUARKUS_SMALLRYE_GRAPHQL_CLIENT_EATERY_URL + value: "http://eatery-service/graphql" - name: GATEWAY_JWT_SECRET valueFrom: secretKeyRef: diff --git a/k8s/kafdrop.yaml b/k8s/kafdrop.yaml index 9e0a2ed..129d0ea 100644 --- a/k8s/kafdrop.yaml +++ b/k8s/kafdrop.yaml @@ -13,13 +13,13 @@ spec: app: kafdrop spec: containers: - - name: kafdrop - image: obsidiandynamics/kafdrop - ports: - - containerPort: 9000 - env: - - name: KAFKA_BROKERCONNECT - value: "kafka-service:9092" # Trỏ vào service Kafka của bạn + - name: kafdrop + image: obsidiandynamics/kafdrop + ports: + - containerPort: 9000 + env: + - name: KAFKA_BROKERCONNECT + value: "kafka-service:9092" --- apiVersion: v1 kind: Service @@ -30,6 +30,6 @@ spec: selector: app: kafdrop ports: - - protocol: TCP - port: 9000 - nodePort: 30900 \ No newline at end of file + - protocol: TCP + port: 9000 + nodePort: 30900 From 0170bab3de49d8ffd544b3b87f5d5dc7b644b1c3 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Thu, 23 Apr 2026 01:05:11 +0000 Subject: [PATCH 16/51] fix: better release script (#36) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/36 --- .releaserc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.releaserc.yaml b/.releaserc.yaml index e4eeddc..7e9ed03 100644 --- a/.releaserc.yaml +++ b/.releaserc.yaml @@ -11,7 +11,7 @@ plugins: - - "@semantic-release/exec" - prepareCmd: | ./mvnw versions:set -DnewVersion=${nextRelease.version} && - sed -i "/-service:/ s|:[^:]*$|:${nextRelease.version}|" k8s/*.yaml && + sed -i "/image:.*-service:/ s|:[^:]*$|:${nextRelease.version}|" k8s/*.yaml && if [ "${branch.name}" = "main" ]; then ./mvnw package -B -Pnative -Dquarkus.container-image.tag=${nextRelease.version} -DskipTests fi From 4c0eaeaa8ba2f9d2be702d3e89c3112b638b3f38 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Thu, 23 Apr 2026 02:08:45 +0000 Subject: [PATCH 17/51] chore: release [ci skip] --- .gitea/workflows/test.yaml | 2 +- CHANGELOG.md | 7 +++++ account-service/pom.xml | 2 +- .../drinkool/services/CustomerService.java | 1 - .../drinkool/services/AccountServiceTest.java | 1 - .../drinkool/services/BaseServiceTest.java | 1 - .../services/CustomerServiceTest.java | 1 - eatery-service/pom.xml | 26 ++++++++++++------- gateway-service/pom.xml | 2 +- .../drinkool/controller/BaseController.java | 5 ++-- .../filters/InternalHeaderGatewayFilter.java | 3 +-- .../com/drinkool/services/BaseService.java | 1 - .../drinkool/services/CustomerService.java | 1 - .../com/drinkool/services/ManagerService.java | 1 - .../InternalHeaderGatewayFilterTest.java | 3 +-- k8s/account.yaml | 4 +-- k8s/eatery.yaml | 5 ++-- k8s/gateway.yaml | 4 +-- k8s/kafka.yaml | 2 +- k8s/redis.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 22 files changed, 40 insertions(+), 38 deletions(-) diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index c7e167f..4397345 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -55,7 +55,7 @@ jobs: run: | ./mvnw -B clean install -Pnative \ -Dquarkus.container-image.push=false \ - -Dquarkus.container-image.registry=git.demonkernel.io.vn + -Dquarkus.container-image.registry=git.demonkernel.io.vn - name: Publish Test Report uses: dorny/test-reporter@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index f585448..d38aa8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.13](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.12...v1.5.13) (2026-04-23) + + +### Bug Fixes + +* better release script ([#36](https://git.demonkernel.io.vn/FoodSurf/backend/issues/36)) ([0170bab](https://git.demonkernel.io.vn/FoodSurf/backend/commit/0170bab3de49d8ffd544b3b87f5d5dc7b644b1c3)) + ## [1.5.10](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.9...v1.5.10) (2026-04-20) diff --git a/account-service/pom.xml b/account-service/pom.xml index 5f1e025..53ea2ad 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.10 + 1.5.13 ../pom.xml diff --git a/account-service/src/main/java/com/drinkool/services/CustomerService.java b/account-service/src/main/java/com/drinkool/services/CustomerService.java index c03301d..ea00033 100644 --- a/account-service/src/main/java/com/drinkool/services/CustomerService.java +++ b/account-service/src/main/java/com/drinkool/services/CustomerService.java @@ -3,7 +3,6 @@ package com.drinkool.services; import com.drinkool.*; import com.drinkool.dtos.*; import com.drinkool.entities.CustomerEntity; - import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.*; diff --git a/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java b/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java index cf06231..c8880af 100644 --- a/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java @@ -4,7 +4,6 @@ import static io.restassured.RestAssured.*; import com.drinkool.*; import com.drinkool.dtos.*; - import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import org.junit.jupiter.api.Test; diff --git a/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java b/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java index 4737e7e..2838545 100644 --- a/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java @@ -5,7 +5,6 @@ import static org.hamcrest.CoreMatchers.*; import com.drinkool.*; import com.drinkool.dtos.*; - import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import org.junit.jupiter.api.Test; diff --git a/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java b/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java index 50d8459..359bff5 100644 --- a/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java @@ -6,7 +6,6 @@ import static org.junit.jupiter.api.Assertions.*; import com.drinkool.*; import com.drinkool.dtos.*; import com.drinkool.entities.CustomerEntity; - import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import jakarta.inject.Inject; diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index c3be3c3..8625282 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -1,13 +1,15 @@ - - + + 4.0.0 com.drinkool drinkool - 1.5.10 + 1.5.13 ../pom.xml @@ -18,9 +20,11 @@ 3.15.0 25 UTF-8 - UTF-8 + UTF-8 quarkus-bom - io.quarkus.platform + io.quarkus.platform 3.32.4 true 3.5.4 @@ -134,7 +138,8 @@ @{argLine} - org.jboss.logmanager.LogManager + org.jboss.logmanager.LogManager ${maven.home} 1 @@ -158,7 +163,8 @@ ${project.build.directory}/${project.build.finalName}-runner - org.jboss.logmanager.LogManager + org.jboss.logmanager.LogManager ${maven.home} @@ -181,4 +187,4 @@ - \ No newline at end of file + diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index ecbdb89..8013320 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.10 + 1.5.13 ../pom.xml diff --git a/gateway-service/src/main/java/com/drinkool/controller/BaseController.java b/gateway-service/src/main/java/com/drinkool/controller/BaseController.java index 7937ab4..c87ecb6 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/BaseController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/BaseController.java @@ -1,13 +1,12 @@ package com.drinkool.controller; +import com.drinkool.InternalValue; +import com.drinkool.Url; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.core.NewCookie; import org.jboss.resteasy.reactive.RestResponse; -import com.drinkool.InternalValue; -import com.drinkool.Url; - public abstract class BaseController { @POST diff --git a/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java b/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java index 0cef877..99afa06 100644 --- a/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java +++ b/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java @@ -1,5 +1,6 @@ package com.drinkool.filters; +import com.drinkool.InternalValue; import io.smallrye.mutiny.Uni; import jakarta.ws.rs.Priorities; import jakarta.ws.rs.container.*; @@ -15,8 +16,6 @@ import org.jose4j.jwt.consumer.JwtConsumer; import org.jose4j.jwt.consumer.JwtConsumerBuilder; import org.jose4j.keys.HmacKey; -import com.drinkool.InternalValue; - public class InternalHeaderGatewayFilter { @ConfigProperty(name = "gateway.jwt.secret") diff --git a/gateway-service/src/main/java/com/drinkool/services/BaseService.java b/gateway-service/src/main/java/com/drinkool/services/BaseService.java index 9b0828c..48a87a5 100644 --- a/gateway-service/src/main/java/com/drinkool/services/BaseService.java +++ b/gateway-service/src/main/java/com/drinkool/services/BaseService.java @@ -2,7 +2,6 @@ package com.drinkool.services; import com.drinkool.Url; import com.drinkool.dtos.SmsOtp; - import io.smallrye.mutiny.Uni; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; diff --git a/gateway-service/src/main/java/com/drinkool/services/CustomerService.java b/gateway-service/src/main/java/com/drinkool/services/CustomerService.java index 42147a6..5660e19 100644 --- a/gateway-service/src/main/java/com/drinkool/services/CustomerService.java +++ b/gateway-service/src/main/java/com/drinkool/services/CustomerService.java @@ -4,7 +4,6 @@ import com.drinkool.InternalValue; import com.drinkool.Role; import com.drinkool.Url; import com.drinkool.dtos.*; - import io.smallrye.mutiny.Uni; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; diff --git a/gateway-service/src/main/java/com/drinkool/services/ManagerService.java b/gateway-service/src/main/java/com/drinkool/services/ManagerService.java index aeb0c3d..bae3afd 100644 --- a/gateway-service/src/main/java/com/drinkool/services/ManagerService.java +++ b/gateway-service/src/main/java/com/drinkool/services/ManagerService.java @@ -4,7 +4,6 @@ import com.drinkool.InternalValue; import com.drinkool.Role; import com.drinkool.Url; import com.drinkool.dtos.*; - import io.smallrye.mutiny.Uni; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; diff --git a/gateway-service/src/test/java/com/drinkool/filters/InternalHeaderGatewayFilterTest.java b/gateway-service/src/test/java/com/drinkool/filters/InternalHeaderGatewayFilterTest.java index a53e7a2..205c5b8 100644 --- a/gateway-service/src/test/java/com/drinkool/filters/InternalHeaderGatewayFilterTest.java +++ b/gateway-service/src/test/java/com/drinkool/filters/InternalHeaderGatewayFilterTest.java @@ -4,6 +4,7 @@ import static io.restassured.RestAssured.*; import static org.hamcrest.CoreMatchers.*; import static org.junit.jupiter.api.Assertions.*; +import com.drinkool.InternalValue; import io.quarkus.test.junit.QuarkusTest; import io.restassured.response.Response; import org.eclipse.microprofile.config.inject.ConfigProperty; @@ -14,8 +15,6 @@ import org.jose4j.keys.HmacKey; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import com.drinkool.InternalValue; - @QuarkusTest public class InternalHeaderGatewayFilterTest { diff --git a/k8s/account.yaml b/k8s/account.yaml index 67bf1c5..5fcf9f2 100644 --- a/k8s/account.yaml +++ b/k8s/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.10 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.13 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -55,4 +55,4 @@ spec: app: account ports: - port: 80 - targetPort: 8080 \ No newline at end of file + targetPort: 8080 diff --git a/k8s/eatery.yaml b/k8s/eatery.yaml index 62523f9..ec5a06a 100644 --- a/k8s/eatery.yaml +++ b/k8s/eatery.yaml @@ -1,4 +1,3 @@ - apiVersion: apps/v1 kind: Deployment metadata: @@ -15,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.10 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.13 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -54,4 +53,4 @@ spec: app: eatery ports: - port: 80 - targetPort: 8080 \ No newline at end of file + targetPort: 8080 diff --git a/k8s/gateway.yaml b/k8s/gateway.yaml index 47f2316..5348987 100644 --- a/k8s/gateway.yaml +++ b/k8s/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.10 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.13 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 @@ -47,4 +47,4 @@ spec: ports: - port: 80 targetPort: 8080 - nodePort: 32080 \ No newline at end of file + nodePort: 32080 diff --git a/k8s/kafka.yaml b/k8s/kafka.yaml index 951ba58..26a2a6d 100644 --- a/k8s/kafka.yaml +++ b/k8s/kafka.yaml @@ -49,4 +49,4 @@ spec: - name: KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR value: "1" - name: KAFKA_TRANSACTION_STATE_LOG_MIN_ISR - value: "1" \ No newline at end of file + value: "1" diff --git a/k8s/redis.yaml b/k8s/redis.yaml index 1f11a6b..a49a355 100644 --- a/k8s/redis.yaml +++ b/k8s/redis.yaml @@ -40,4 +40,4 @@ spec: selector: app: redis ports: - - port: 6379 \ No newline at end of file + - port: 6379 diff --git a/lib/pom.xml b/lib/pom.xml index 56ee628..05bf8ce 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.10 + 1.5.13 ../pom.xml diff --git a/pom.xml b/pom.xml index 675690a..6edf4b2 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.10 + 1.5.13 pom 25 From c9d6439cf8839bd20190d4ae3f410763052781e9 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Sun, 26 Apr 2026 06:28:26 +0000 Subject: [PATCH 18/51] fix: add menu creation and query (#37) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/37 --- .../com/drinkool/entities/EateryEntity.java | 12 ++ .../entities/EateryInventoryItemEntity.java | 51 ------ .../entities/InventoryItemEntity.java | 34 ---- .../com/drinkool/entities/MenuItemEntity.java | 41 +---- .../entities/MenuItemIngredientEntity.java | 37 ---- .../com/drinkool/services/EateryService.java | 38 +++++ .../drinkool/services/InventoryService.java | 20 --- .../EateryInventoryItemEntityTest.java | 52 ------ .../entities/InventoryItemEntityTest.java | 50 ------ .../drinkool/entities/MenuItemEntityTest.java | 90 ---------- .../MenuItemIngredientEntityTest.java | 60 ------- .../drinkool/services/EateryServiceTest.java | 158 +++++++++++++++++- .../services/InventoryServiceTest.java | 32 ---- .../drinkool/controller/EateryController.java | 6 +- lib/pom.xml | 27 +-- .../java/com/drinkool/dtos/GraphqlDto.java | 7 + .../lib/utils/HeaderIdentityProvider.java | 38 +++++ 17 files changed, 279 insertions(+), 474 deletions(-) delete mode 100644 eatery-service/src/main/java/com/drinkool/entities/EateryInventoryItemEntity.java delete mode 100644 eatery-service/src/main/java/com/drinkool/entities/InventoryItemEntity.java delete mode 100644 eatery-service/src/main/java/com/drinkool/entities/MenuItemIngredientEntity.java delete mode 100644 eatery-service/src/main/java/com/drinkool/services/InventoryService.java delete mode 100644 eatery-service/src/test/java/com/drinkool/entities/EateryInventoryItemEntityTest.java delete mode 100644 eatery-service/src/test/java/com/drinkool/entities/InventoryItemEntityTest.java delete mode 100644 eatery-service/src/test/java/com/drinkool/entities/MenuItemEntityTest.java delete mode 100644 eatery-service/src/test/java/com/drinkool/entities/MenuItemIngredientEntityTest.java delete mode 100644 eatery-service/src/test/java/com/drinkool/services/InventoryServiceTest.java create mode 100644 lib/src/main/java/com/drinkool/dtos/GraphqlDto.java create mode 100644 lib/src/main/java/com/drinkool/lib/utils/HeaderIdentityProvider.java diff --git a/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java b/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java index d8e16d9..1a1426c 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java @@ -45,4 +45,16 @@ public class EateryEntity extends BaseEntity { return this; } + + @Transactional + public static EateryEntity findByOwnerId(String ownerId) { + UUID ownerUUID = UUID.fromString(ownerId); + + return EateryEntity.find("ownerId", ownerUUID).firstResult(); + } + + @Transactional + public static EateryEntity findByOwnerId(UUID ownerId) { + return EateryEntity.find("ownerId", ownerId).firstResult(); + } } diff --git a/eatery-service/src/main/java/com/drinkool/entities/EateryInventoryItemEntity.java b/eatery-service/src/main/java/com/drinkool/entities/EateryInventoryItemEntity.java deleted file mode 100644 index e428384..0000000 --- a/eatery-service/src/main/java/com/drinkool/entities/EateryInventoryItemEntity.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.drinkool.entities; - -import com.drinkool.lib.entities.BaseEntity; -import jakarta.persistence.*; -import jakarta.transaction.Transactional; - -@Entity -@Table -public class EateryInventoryItemEntity extends BaseEntity { - - public double quantity; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "inventory_item_id") - public InventoryItemEntity inventoryItem; - - private EateryInventoryItemEntity() {} - - // Create - @Transactional - public static EateryInventoryItemEntity create( - String name, - double quantity, - String unit - ) { - String itemName = name.toLowerCase(); - - InventoryItemEntity item = InventoryItemEntity.find( - "name", - itemName - ).firstResult(); - - if (item == null || item.unit != unit) { - if (unit != null || unit == "") { - item = InventoryItemEntity.create(itemName, unit); - } else { - item = InventoryItemEntity.create(itemName); - } - } - - EateryInventoryItemEntity eateryInventoryItem = - new EateryInventoryItemEntity(); - - eateryInventoryItem.quantity = quantity; - eateryInventoryItem.inventoryItem = item; - - eateryInventoryItem.persist(); - - return eateryInventoryItem; - } -} diff --git a/eatery-service/src/main/java/com/drinkool/entities/InventoryItemEntity.java b/eatery-service/src/main/java/com/drinkool/entities/InventoryItemEntity.java deleted file mode 100644 index e85a8e1..0000000 --- a/eatery-service/src/main/java/com/drinkool/entities/InventoryItemEntity.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.drinkool.entities; - -import com.drinkool.lib.entities.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.Table; -import jakarta.transaction.Transactional; - -@Entity -@Table(name = "inventory_items") -public class InventoryItemEntity extends BaseEntity { - - public String name; - public String unit; - - private InventoryItemEntity() {} - - // Create - @Transactional - public static InventoryItemEntity create(String name, String unit) { - InventoryItemEntity item = new InventoryItemEntity(); - - item.name = name; - item.unit = unit; - - item.persist(); - - return item; - } - - @Transactional - public static InventoryItemEntity create(String name) { - return InventoryItemEntity.create(name, "unit"); - } -} diff --git a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java index 39ddb09..8254931 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java @@ -3,7 +3,6 @@ package com.drinkool.entities; import com.drinkool.lib.entities.BaseEntity; import jakarta.persistence.*; import jakarta.transaction.Transactional; -import java.util.*; @Entity @Table @@ -19,45 +18,19 @@ public class MenuItemEntity extends BaseEntity { @JoinColumn(name = "eatery_id") public EateryEntity eatery; - // Danh sách các nguyên liệu cấu thành món ăn này - @OneToMany( - mappedBy = "menuItem", - cascade = CascadeType.ALL, - orphanRemoval = true - ) - public List ingredients = new ArrayList<>(); - - /** - * Thêm nguyên liệu vào món ăn với định lượng cụ thể - */ - @Transactional - public void addIngredient( - EateryInventoryItemEntity inventoryItem, - double requiredQty - ) { - MenuItemIngredientEntity ingredient = MenuItemIngredientEntity.create( - this, - inventoryItem, - requiredQty - ); - - this.ingredients.add(ingredient); - - this.persist(); - } - /** * Phương thức tiện ích để tạo nhanh Menu Item từ tên */ @Transactional - public static MenuItemEntity create(String name, double price) { - MenuItemEntity menu = new MenuItemEntity(); + public static MenuItemEntity create(EateryEntity eatery, String name, double price) { + MenuItemEntity menuItem = new MenuItemEntity(); - menu.name = name; - menu.price = price; + menuItem.name = name; + menuItem.price = price; + menuItem.eatery = eatery; - menu.persist(); + menuItem.persist(); - return menu; + return menuItem; } } diff --git a/eatery-service/src/main/java/com/drinkool/entities/MenuItemIngredientEntity.java b/eatery-service/src/main/java/com/drinkool/entities/MenuItemIngredientEntity.java deleted file mode 100644 index 17f7cd8..0000000 --- a/eatery-service/src/main/java/com/drinkool/entities/MenuItemIngredientEntity.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.drinkool.entities; - -import com.drinkool.lib.entities.BaseEntity; -import jakarta.persistence.*; - -@Entity -@Table(name = "menu_item_ingredients") -public class MenuItemIngredientEntity extends BaseEntity { - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "menu_item_id") - public MenuItemEntity menuItem; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "inventory_item_id") - public EateryInventoryItemEntity inventoryItem; - - public double requiredQuantity; - - private MenuItemIngredientEntity() {} - - public static MenuItemIngredientEntity create( - MenuItemEntity menuItem, - EateryInventoryItemEntity inventoryItem, - double requiredQuantity - ) { - MenuItemIngredientEntity ingredient = new MenuItemIngredientEntity(); - - ingredient.menuItem = menuItem; - ingredient.inventoryItem = inventoryItem; - ingredient.requiredQuantity = requiredQuantity; - - ingredient.persist(); - - return ingredient; - } -} diff --git a/eatery-service/src/main/java/com/drinkool/services/EateryService.java b/eatery-service/src/main/java/com/drinkool/services/EateryService.java index 50a26af..15fb483 100644 --- a/eatery-service/src/main/java/com/drinkool/services/EateryService.java +++ b/eatery-service/src/main/java/com/drinkool/services/EateryService.java @@ -1,12 +1,19 @@ package com.drinkool.services; +import com.drinkool.InternalValue; +import com.drinkool.Role; import com.drinkool.dtos.event.ManagerCreate; import com.drinkool.entities.EateryEntity; +import com.drinkool.entities.MenuItemEntity; +import io.vertx.core.http.HttpServerRequest; +import jakarta.annotation.security.RolesAllowed; import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import jakarta.transaction.Transactional; import java.util.List; import java.util.UUID; import org.eclipse.microprofile.graphql.GraphQLApi; +import org.eclipse.microprofile.graphql.Mutation; import org.eclipse.microprofile.graphql.Name; import org.eclipse.microprofile.graphql.Query; import org.eclipse.microprofile.reactive.messaging.Incoming; @@ -15,6 +22,9 @@ import org.eclipse.microprofile.reactive.messaging.Incoming; @GraphQLApi public class EateryService { + @Inject + HttpServerRequest request; + @Incoming("manager-in") @Transactional public void consumeManagerSignup(ManagerCreate input) { @@ -32,4 +42,32 @@ public class EateryService { public EateryEntity getEatery(@Name("id") UUID id) { return EateryEntity.findById(id); } + + @Mutation("addMenuItem") + @RolesAllowed(Role.Manager) + @Transactional + public MenuItemEntity addMenuItem( + @Name("name") String name, + @Name("price") double price + ) { + String ownerId = request.getHeader(InternalValue.userId); + + EateryEntity eatery = EateryEntity.findByOwnerId(ownerId); + if (eatery == null) return null; + + MenuItemEntity item = MenuItemEntity.create(eatery, name, price); + + return item; + } + + @Query("menuItemsByEatery") + public List getMenuItemsByEatery( + @Name("eateryId") UUID eateryId + ) { + EateryEntity eatery = EateryEntity.findById(eateryId); + + if (eatery == null) return List.of(); + + return MenuItemEntity.list("eatery", eatery); + } } diff --git a/eatery-service/src/main/java/com/drinkool/services/InventoryService.java b/eatery-service/src/main/java/com/drinkool/services/InventoryService.java deleted file mode 100644 index c051aa4..0000000 --- a/eatery-service/src/main/java/com/drinkool/services/InventoryService.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.drinkool.services; - -import com.drinkool.dtos.AddInventory; -import com.drinkool.entities.InventoryItemEntity; -import jakarta.transaction.Transactional; -import jakarta.ws.rs.*; -import jakarta.ws.rs.core.Response; - -@Path("/api/inventory") -public class InventoryService { - - @POST - @Path("/create") - @Transactional - public Response create(AddInventory input) { - InventoryItemEntity.create(input.name, input.unit); - - return Response.ok().build(); - } -} diff --git a/eatery-service/src/test/java/com/drinkool/entities/EateryInventoryItemEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/EateryInventoryItemEntityTest.java deleted file mode 100644 index ca2717c..0000000 --- a/eatery-service/src/test/java/com/drinkool/entities/EateryInventoryItemEntityTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.drinkool.entities; - -import static org.junit.jupiter.api.Assertions.*; - -import io.quarkus.test.junit.QuarkusTest; -import jakarta.transaction.Transactional; -import org.junit.jupiter.api.Test; - -@QuarkusTest -public class EateryInventoryItemEntityTest { - - @Test - @Transactional - void testAdd_WhenItemExists_ShouldUseExistingItem() { - String itemName = "Coca Cola"; - int quantity = 10; - - InventoryItemEntity.create(itemName); - - EateryInventoryItemEntity eateryItem = EateryInventoryItemEntity.create( - itemName, - quantity, - "" - ); - - EateryInventoryItemEntity savedEntity = EateryInventoryItemEntity.find( - "id", - eateryItem.id - ).firstResult(); - assertNotNull(savedEntity); - } - - @Test - @Transactional - void testAdd_WhenItemDoesNotExist_ShouldCreateNewItem() { - String itemName = "Pepsi"; - int quantity = 5; - String unit = "Bottle"; - - EateryInventoryItemEntity eateryItem = EateryInventoryItemEntity.create( - itemName, - quantity, - unit - ); - - EateryInventoryItemEntity savedEntity = EateryInventoryItemEntity.find( - "id", - eateryItem.id - ).firstResult(); - assertNotNull(savedEntity); - } -} diff --git a/eatery-service/src/test/java/com/drinkool/entities/InventoryItemEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/InventoryItemEntityTest.java deleted file mode 100644 index 4aecfc0..0000000 --- a/eatery-service/src/test/java/com/drinkool/entities/InventoryItemEntityTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.drinkool.entities; - -import io.quarkus.test.junit.QuarkusTest; -import jakarta.transaction.Transactional; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -@QuarkusTest -public class InventoryItemEntityTest { - - @Test - @Transactional - public void testCreateInventoryItem() { - // 1. Chuẩn bị dữ liệu (Lưu ý: Không còn biến quantity nữa) - String name = "Trà sữa truyền thống"; - String unit = "Ly"; - - // 2. Gọi hàm static create (Không dùng new hay hàm add nữa) - // Hàm này vừa tạo object, vừa gán data, vừa gọi persist() luôn - InventoryItemEntity item = InventoryItemEntity.create(name, unit); - - // 3. Kiểm chứng - Assertions.assertNotNull(item, "Entity tạo ra không được null"); - Assertions.assertEquals(name, item.name, "Tên không khớp"); - Assertions.assertEquals(unit, item.unit, "Đơn vị không khớp"); - Assertions.assertNotNull( - item.id, - "ID phải được sinh ra tự động sau khi persist" - ); - } - - @Test - @Transactional - public void testCreateWithDefaultUnit() { - // 1. Chuẩn bị dữ liệu - String name = "Trân châu đen"; - - // 2. Gọi hàm static create rút gọn (chỉ truyền name, unit sẽ tự là "unit") - InventoryItemEntity item = InventoryItemEntity.create(name); - - // 3. Kiểm chứng - Assertions.assertNotNull(item, "Entity tạo ra không được null"); - Assertions.assertEquals(name, item.name, "Tên không khớp"); - Assertions.assertEquals("unit", item.unit, "Unit mặc định phải là 'unit'"); - Assertions.assertNotNull( - item.id, - "ID phải được sinh ra tự động sau khi persist" - ); - } -} diff --git a/eatery-service/src/test/java/com/drinkool/entities/MenuItemEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/MenuItemEntityTest.java deleted file mode 100644 index e6b62ac..0000000 --- a/eatery-service/src/test/java/com/drinkool/entities/MenuItemEntityTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.drinkool.entities; - -import static org.junit.jupiter.api.Assertions.*; - -import io.quarkus.test.junit.QuarkusTest; -import jakarta.transaction.Transactional; -import org.junit.jupiter.api.Test; - -@QuarkusTest -public class MenuItemEntityTest { - - @Test - @Transactional - public void testCreateMenuItemSuccessfully() { - // 1. Chuẩn bị dữ liệu (Arrange) - String name = "Cà phê sữa đá"; - double price = 29000.0; - - // 2. Thực thi (Act) - Gọi hàm tĩnh create - MenuItemEntity menuItem = MenuItemEntity.create(name, price); - - // 3. Kiểm chứng (Assert) - assertNotNull(menuItem, "Thực thể MenuItem không được null"); - assertEquals(name, menuItem.name, "Tên món ăn không khớp"); - assertEquals(price, menuItem.price, "Giá món ăn không khớp"); - assertNotNull(menuItem.id, "ID phải được tự động sinh ra sau khi persist"); - assertTrue( - menuItem.ingredients.isEmpty(), - "Danh sách nguyên liệu ban đầu phải rỗng" - ); - } - - @Test - @Transactional - public void testAddIngredientSuccessfully() { - // 1. Chuẩn bị dữ liệu (Arrange) - // Tạo món ăn - MenuItemEntity menuItem = MenuItemEntity.create( - "Trà sữa trân châu", - 45000.0 - ); - - // Tạo nguyên liệu trong kho (Dùng đúng hàm add() của EateryInventoryItemEntity như đã fix) - EateryInventoryItemEntity inventoryItem = EateryInventoryItemEntity.create( - "Trân châu đen", - 50, - "kg" - ); - - double requiredQty = 0.2; // Cần 0.2 kg trân châu cho 1 ly - - // 2. Thực thi (Act) - Thêm nguyên liệu vào món ăn - menuItem.addIngredient(inventoryItem, requiredQty); - - // 3. Kiểm chứng (Assert) - // Kiểm tra danh sách nguyên liệu của món ăn - assertFalse( - menuItem.ingredients.isEmpty(), - "Danh sách nguyên liệu không được rỗng sau khi thêm" - ); - assertEquals( - 1, - menuItem.ingredients.size(), - "Phải có đúng 1 nguyên liệu trong danh sách" - ); - - // Lấy phần tử nguyên liệu đầu tiên ra để kiểm tra chi tiết các liên kết - MenuItemIngredientEntity addedIngredient = menuItem.ingredients.get(0); - - assertNotNull( - addedIngredient.id, - "ID của Entity trung gian phải được sinh ra" - ); - assertEquals( - menuItem.id, - addedIngredient.menuItem.id, - "Khóa ngoại MenuItem bị sai" - ); - assertEquals( - inventoryItem.id, - addedIngredient.inventoryItem.id, - "Khóa ngoại InventoryItem bị sai" - ); - assertEquals( - requiredQty, - addedIngredient.requiredQuantity, - "Định lượng (requiredQty) không khớp" - ); - } -} diff --git a/eatery-service/src/test/java/com/drinkool/entities/MenuItemIngredientEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/MenuItemIngredientEntityTest.java deleted file mode 100644 index f9f84f8..0000000 --- a/eatery-service/src/test/java/com/drinkool/entities/MenuItemIngredientEntityTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.drinkool.entities; - -import static org.junit.jupiter.api.Assertions.*; - -import io.quarkus.test.junit.QuarkusTest; -import jakarta.transaction.Transactional; -import org.junit.jupiter.api.Test; - -@QuarkusTest -public class MenuItemIngredientEntityTest { - - @Test - @Transactional - void testCreate_ShouldPersistIngredientSuccessfully() { - // 1. Chuẩn bị dữ liệu giả định - - String menuItemName = "Milk Tea"; - double menuItemPrice = 40; - - MenuItemEntity menuItem = MenuItemEntity.create( - menuItemName, - menuItemPrice - ); - - String inventoryItemName = "Water"; - int inventoryItemQuantity = 10; // Đổi thành int cho khớp với kiểu của EateryInventoryItemEntity - String inventoryItemUnit = "l"; - - // SỬA Ở ĐÂY: Khởi tạo bằng new và dùng hàm add() đúng như cấu trúc class của bạn - EateryInventoryItemEntity inventoryItem = EateryInventoryItemEntity.create( - inventoryItemName, - inventoryItemQuantity, - inventoryItemUnit - ); - // Lưu ý: Hàm add() của bạn đã có sẵn lệnh this.persist() bên trong nên không cần gọi lại nữa! - - double requiredQuantity = 0.5; - - // 2. Gọi hàm static create cần test - MenuItemIngredientEntity createdIngredient = - MenuItemIngredientEntity.create( - menuItem, - inventoryItem, - requiredQuantity - ); - - // 3. Kiểm tra kết quả - assertNotNull(createdIngredient.id, "ID không được null sau khi persist"); - - // Truy vấn lại từ Database để đảm bảo dữ liệu đã được lưu đúng - MenuItemIngredientEntity savedEntity = MenuItemIngredientEntity.findById( - createdIngredient.id - ); - - assertNotNull(savedEntity); - assertEquals(menuItem.id, savedEntity.menuItem.id); - assertEquals(inventoryItem.id, savedEntity.inventoryItem.id); - assertEquals(requiredQuantity, savedEntity.requiredQuantity); - } -} diff --git a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java index 16bde3e..b28fd3f 100644 --- a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java @@ -2,11 +2,16 @@ package com.drinkool.services; import static io.restassured.RestAssured.given; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.hasSize; +import com.drinkool.InternalValue; +import com.drinkool.Role; import com.drinkool.dtos.event.ManagerCreate; import com.drinkool.entities.EateryEntity; +import com.drinkool.entities.MenuItemEntity; import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import io.smallrye.reactive.messaging.memory.InMemoryConnector; @@ -54,21 +59,32 @@ public class EateryServiceTest { private UUID lastSavedId; private String lastSavedName; + private UUID lastOwnerId = UUID.randomUUID(); @BeforeEach @Transactional void setup() { + MenuItemEntity.deleteAll(); EateryEntity.deleteAll(); lastSavedName = faker.restaurant().name(); EateryEntity eatery = new EateryEntity(); - lastSavedId = eatery.create(UUID.randomUUID(), lastSavedName).id; + eatery = eatery.create(lastOwnerId, lastSavedName); + lastSavedId = eatery.id; for (int i = 0; i < 2; i++) { EateryEntity e = new EateryEntity(); e.create(UUID.randomUUID(), faker.restaurant().name()); } + + for (int i = 0; i < 3; i++) { + MenuItemEntity.create( + eatery, + faker.food().dish(), + faker.number().randomDouble(2, 10, 100) + ); + } } @Test @@ -106,4 +122,144 @@ public class EateryServiceTest { .statusCode(200) .body("data.eateryById.name", is(lastSavedName)); } + + @Test + public void testAddMenuItemSuccess() { + String mutation = + "mutation addMenuItem($name: String!, $price: Float!) {" + + " addMenuItem(name: $name, price: $price) {" + + " id" + + " name" + + " price" + + " }" + + "}"; + + java.util.Map variables = new java.util.HashMap<>(); + variables.put("name", "Trà Sữa"); + variables.put("price", 30000.0); + + java.util.Map requestBody = new java.util.HashMap<>(); + requestBody.put("query", mutation); + requestBody.put("variables", variables); + + given() + .contentType(ContentType.JSON) + .header(InternalValue.role, Role.Manager) + .header(InternalValue.userId, lastOwnerId) // Thay "x-user-id" bằng InternalValue.userId của bạn + .body(requestBody) + .when() + .post("/graphql") + .then() + .statusCode(200) + .body("data.addMenuItem.name", is("Trà Sữa")) + .body("data.addMenuItem.id", notNullValue()); + } + + @Test + public void testAddMenuItemFailInvalidRole() { + String mutation = + "mutation addMenuItem($name: String!, $price: Float!) {" + + " addMenuItem(name: $name, price: $price) {" + + " id" + + " name" + + " price" + + " }" + + "}"; + + java.util.Map variables = new java.util.HashMap<>(); + variables.put("name", "Trà Sữa"); + variables.put("price", 30000.0); + + java.util.Map requestBody = new java.util.HashMap<>(); + requestBody.put("query", mutation); + requestBody.put("variables", variables); + + given() + .contentType(ContentType.JSON) + .header(InternalValue.role, Role.Customer) + .header(InternalValue.userId, lastOwnerId) + .body(requestBody) + .when() + .post("/graphql") + .then() + .statusCode(200) + .body("data.addMenuItem.name", is("Trà Sữa")) + .body("data.addMenuItem.id", notNullValue()); + } + + @Test + public void testAddMenuItemFailInvalidOwner() { + String mutation = + "mutation { addMenuItem(name: \"Coffee\", price: 20000.0) { id } }"; + + java.util.Map requestBody = new java.util.HashMap<>(); + requestBody.put("query", mutation); + + given() + .contentType(ContentType.JSON) + .header(InternalValue.role, Role.Manager) + .header(InternalValue.userId, UUID.randomUUID()) + .body(requestBody) + .when() + .post("/graphql") + .then() + .statusCode(200) + .body("data.addMenuItem", is((Object) null)); + } + + @Test + public void testGetMenuItemsByEatery_Success() { + String query = + "query getItems($id: String!) {" + + " menuItemsByEatery(eateryId: $id) {" + + " id" + + " name" + + " price" + + " }" + + "}"; + + java.util.Map variables = new java.util.HashMap<>(); + variables.put("id", lastSavedId.toString()); + + java.util.Map requestBody = new java.util.HashMap<>(); + requestBody.put("query", query); + requestBody.put("variables", variables); + + given() + .contentType(ContentType.JSON) + .body(requestBody) + .when() + .post("/graphql") + .then() + .statusCode(200) + .body("data.menuItemsByEatery", hasSize(not(0))); + } + + @Test + public void testGetMenuItemsByEatery_NotFound() { + String randomId = UUID.randomUUID().toString(); + + String query = + "query getItems($id: String!) {" + + " menuItemsByEatery(eateryId: $id) {" + + " id" + + " }" + + "}"; + + java.util.Map variables = new java.util.HashMap<>(); + variables.put("id", randomId); + + java.util.Map requestBody = new java.util.HashMap<>(); + requestBody.put("query", query); + requestBody.put("variables", variables); + + given() + .contentType(ContentType.JSON) + .body(requestBody) + .when() + .post("/graphql") + .then() + .statusCode(200) + .body("data.menuItemsByEatery", hasSize(0)); // Phải trả về List rỗng như code bạn viết + } } diff --git a/eatery-service/src/test/java/com/drinkool/services/InventoryServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/InventoryServiceTest.java deleted file mode 100644 index e6e2ca8..0000000 --- a/eatery-service/src/test/java/com/drinkool/services/InventoryServiceTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.drinkool.services; - -import static io.restassured.RestAssured.given; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.drinkool.dtos.AddInventory; -import com.drinkool.entities.InventoryItemEntity; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.http.ContentType; -import java.util.UUID; -import org.junit.jupiter.api.Test; - -@QuarkusTest -public class InventoryServiceTest { - - @Test - void add() { - String name = UUID.randomUUID().toString(); - - AddInventory input = new AddInventory(); - input.name = name; - - given() - .contentType(ContentType.JSON) - .body(input) - .when() - .post("/api/inventory/create") - .then(); - - assertEquals(1, InventoryItemEntity.find("name", name).count()); - } -} diff --git a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java index 3e98288..6073717 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java @@ -1,5 +1,6 @@ package com.drinkool.controller; +import com.drinkool.dtos.GraphqlDto; import io.smallrye.graphql.client.GraphQLClient; import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient; import jakarta.ws.rs.POST; @@ -15,10 +16,11 @@ public class EateryController { @POST @Path("/graphql") - public Response forward(String query) + public Response forward(GraphqlDto gqlRequest) throws ExecutionException, InterruptedException { io.smallrye.graphql.client.Response response = dynamicClient.executeSync( - query + gqlRequest.query, + gqlRequest.variables ); if (response.hasError()) { diff --git a/lib/pom.xml b/lib/pom.xml index 05bf8ce..6c2c7ef 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -1,8 +1,8 @@ - + 4.0.0 @@ -21,20 +21,25 @@ + + io.quarkus + quarkus-security + provided + com.fasterxml.jackson.core jackson-annotations 2.15.2 - io.quarkus - quarkus-kafka-client + io.quarkus + quarkus-kafka-client - org.projectlombok - lombok - 1.18.30 - provided + org.projectlombok + lombok + 1.18.30 + provided jakarta.persistence @@ -55,4 +60,4 @@ test - + \ No newline at end of file diff --git a/lib/src/main/java/com/drinkool/dtos/GraphqlDto.java b/lib/src/main/java/com/drinkool/dtos/GraphqlDto.java new file mode 100644 index 0000000..a358ed0 --- /dev/null +++ b/lib/src/main/java/com/drinkool/dtos/GraphqlDto.java @@ -0,0 +1,7 @@ +package com.drinkool.dtos; + +public class GraphqlDto { + + public String query; + public java.util.Map variables; +} diff --git a/lib/src/main/java/com/drinkool/lib/utils/HeaderIdentityProvider.java b/lib/src/main/java/com/drinkool/lib/utils/HeaderIdentityProvider.java new file mode 100644 index 0000000..aee7b63 --- /dev/null +++ b/lib/src/main/java/com/drinkool/lib/utils/HeaderIdentityProvider.java @@ -0,0 +1,38 @@ +package com.drinkool.lib.utils; + +import com.drinkool.InternalValue; +import io.quarkus.security.identity.AuthenticationRequestContext; +import io.quarkus.security.identity.IdentityProvider; +import io.quarkus.security.identity.SecurityIdentity; +import io.quarkus.security.identity.request.TrustedAuthenticationRequest; +import io.quarkus.security.runtime.QuarkusSecurityIdentity; +import io.smallrye.mutiny.Uni; +import io.vertx.core.http.HttpServerRequest; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class HeaderIdentityProvider + implements IdentityProvider +{ + + @Inject + HttpServerRequest httpServerRequest; + + @Override + public Class getRequestType() { + return TrustedAuthenticationRequest.class; + } + + @Override + public Uni authenticate( + TrustedAuthenticationRequest request, + AuthenticationRequestContext context + ) { + String role = httpServerRequest.getHeader(InternalValue.role); + + return Uni.createFrom().item( + QuarkusSecurityIdentity.builder().addRole(role).build() + ); + } +} From 08e7242382be0f21dbb1cf9ac507d740b3780e75 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 26 Apr 2026 09:44:30 +0000 Subject: [PATCH 19/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- .../java/com/drinkool/entities/MenuItemEntity.java | 6 +++++- gateway-service/pom.xml | 2 +- k8s/account.yaml | 2 +- k8s/eatery.yaml | 2 +- k8s/gateway.yaml | 2 +- lib/pom.xml | 12 ++++++------ pom.xml | 2 +- 10 files changed, 25 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d38aa8f..46a8d51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.14](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.13...v1.5.14) (2026-04-26) + + +### Bug Fixes + +* add menu creation and query ([#37](https://git.demonkernel.io.vn/FoodSurf/backend/issues/37)) ([c9d6439](https://git.demonkernel.io.vn/FoodSurf/backend/commit/c9d6439cf8839bd20190d4ae3f410763052781e9)) + ## [1.5.13](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.12...v1.5.13) (2026-04-23) diff --git a/account-service/pom.xml b/account-service/pom.xml index 53ea2ad..4964dd2 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.13 + 1.5.14 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 8625282..fa0cdb7 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.13 + 1.5.14 ../pom.xml diff --git a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java index 8254931..fbf8e74 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java @@ -22,7 +22,11 @@ public class MenuItemEntity extends BaseEntity { * Phương thức tiện ích để tạo nhanh Menu Item từ tên */ @Transactional - public static MenuItemEntity create(EateryEntity eatery, String name, double price) { + public static MenuItemEntity create( + EateryEntity eatery, + String name, + double price + ) { MenuItemEntity menuItem = new MenuItemEntity(); menuItem.name = name; diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 8013320..f04c9f6 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.13 + 1.5.14 ../pom.xml diff --git a/k8s/account.yaml b/k8s/account.yaml index 5fcf9f2..ba758c6 100644 --- a/k8s/account.yaml +++ b/k8s/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.13 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.14 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/eatery.yaml b/k8s/eatery.yaml index ec5a06a..9ced4f6 100644 --- a/k8s/eatery.yaml +++ b/k8s/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.13 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.14 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/gateway.yaml b/k8s/gateway.yaml index 5348987..bf6c790 100644 --- a/k8s/gateway.yaml +++ b/k8s/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.13 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.14 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index 6c2c7ef..e47f729 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -1,15 +1,15 @@ - + 4.0.0 com.drinkool drinkool - 1.5.13 + 1.5.14 ../pom.xml @@ -60,4 +60,4 @@ test - \ No newline at end of file + diff --git a/pom.xml b/pom.xml index 6edf4b2..d023200 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.13 + 1.5.14 pom 25 From e60c0b89b924c913d1827ebdcfae536cd9e1cde9 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Sun, 26 Apr 2026 16:45:42 +0000 Subject: [PATCH 20/51] fix: merge customer and manager login (#38) Co-authored-by: Copilot Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/38 --- .../controller/CustomerController.java | 8 +---- .../drinkool/controller/MainController.java | 35 +++++++++++++++++++ .../controller/ManagerController.java | 8 +---- .../controller/BaseControllerTest.java | 2 +- 4 files changed, 38 insertions(+), 15 deletions(-) create mode 100644 gateway-service/src/main/java/com/drinkool/controller/MainController.java diff --git a/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java b/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java index ccaac42..36efce8 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java @@ -11,7 +11,7 @@ import java.util.*; import org.eclipse.microprofile.rest.client.inject.RestClient; @Path("/api/" + Role.Customer) -public class CustomerController extends BaseController { +public class CustomerController { @Inject @RestClient @@ -23,12 +23,6 @@ public class CustomerController extends BaseController { return accountService.signup(input); } - @POST - @Path(Url.Login) - public Uni proxyLogin(Login input) { - return accountService.login(input); - } - @POST @Path(Url.QuickSignup) public Uni proxyQuickSignup(QuickSignup input) { diff --git a/gateway-service/src/main/java/com/drinkool/controller/MainController.java b/gateway-service/src/main/java/com/drinkool/controller/MainController.java new file mode 100644 index 0000000..f739339 --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/controller/MainController.java @@ -0,0 +1,35 @@ +package com.drinkool.controller; + +import com.drinkool.Url; +import com.drinkool.dtos.Login; +import com.drinkool.services.CustomerService; +import com.drinkool.services.ManagerService; +import io.smallrye.mutiny.Uni; +import jakarta.inject.Inject; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Response; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +@Path("/api") +public class MainController extends BaseController { + + @Inject + @RestClient + ManagerService managerService; + + @Inject + @RestClient + CustomerService customerService; + + @POST + @Path(Url.Login) + public Uni proxyLogin(Login input) { + return managerService + .login(input) + .onFailure() + .recoverWithUni(() -> { + return customerService.login(input); + }); + } +} diff --git a/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java b/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java index 6e3667f..81ed01e 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java @@ -11,7 +11,7 @@ import java.util.*; import org.eclipse.microprofile.rest.client.inject.RestClient; @Path("/api/" + Role.Manager) -public class ManagerController extends BaseController { +public class ManagerController { @Inject @RestClient @@ -23,12 +23,6 @@ public class ManagerController extends BaseController { return managerService.signup(input); } - @POST - @Path(Url.Login) - public Uni proxyLogin(Login input) { - return managerService.login(input); - } - @GET public Uni me(@HeaderParam(InternalValue.userId) UUID id) { return managerService.me(id); diff --git a/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java b/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java index 2382510..34642af 100644 --- a/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java +++ b/gateway-service/src/test/java/com/drinkool/controller/BaseControllerTest.java @@ -16,7 +16,7 @@ public class BaseControllerTest { public void testLogoutShouldClearCookie() { given() .when() - .post("/api/" + Role.Customer + Url.Logout) + .post("/api" + Url.Logout) .then() .statusCode(204) .header("Set-Cookie", containsString(InternalValue.cookieName)) From dd2e53e24d917a44fcfcf18ed131530464c136a4 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 26 Apr 2026 16:59:12 +0000 Subject: [PATCH 21/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- .../java/com/drinkool/controller/ManagerController.java | 2 +- k8s/account.yaml | 2 +- k8s/eatery.yaml | 2 +- k8s/gateway.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 10 files changed, 16 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46a8d51..e909739 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.15](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.14...v1.5.15) (2026-04-26) + + +### Bug Fixes + +* merge customer and manager login ([#38](https://git.demonkernel.io.vn/FoodSurf/backend/issues/38)) ([e60c0b8](https://git.demonkernel.io.vn/FoodSurf/backend/commit/e60c0b89b924c913d1827ebdcfae536cd9e1cde9)) + ## [1.5.14](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.13...v1.5.14) (2026-04-26) diff --git a/account-service/pom.xml b/account-service/pom.xml index 4964dd2..f76a1eb 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.14 + 1.5.15 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index fa0cdb7..de865fe 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.14 + 1.5.15 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index f04c9f6..3ba3a0d 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.14 + 1.5.15 ../pom.xml diff --git a/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java b/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java index 81ed01e..8b126f2 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java @@ -11,7 +11,7 @@ import java.util.*; import org.eclipse.microprofile.rest.client.inject.RestClient; @Path("/api/" + Role.Manager) -public class ManagerController { +public class ManagerController { @Inject @RestClient diff --git a/k8s/account.yaml b/k8s/account.yaml index ba758c6..ebf9eba 100644 --- a/k8s/account.yaml +++ b/k8s/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.14 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.15 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/eatery.yaml b/k8s/eatery.yaml index 9ced4f6..f48a2c6 100644 --- a/k8s/eatery.yaml +++ b/k8s/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.14 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.15 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/gateway.yaml b/k8s/gateway.yaml index bf6c790..d5ab67c 100644 --- a/k8s/gateway.yaml +++ b/k8s/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.14 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.15 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index e47f729..c944af5 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.14 + 1.5.15 ../pom.xml diff --git a/pom.xml b/pom.xml index d023200..be08d26 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.14 + 1.5.15 pom 25 From 5434445a4c8be08c990e84d4162479ffacd34147 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Tue, 28 Apr 2026 07:23:30 +0000 Subject: [PATCH 22/51] fix: better manager response (#39) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/39 --- .../main/java/com/drinkool/services/AccountService.java | 9 +++++++-- .../main/java/com/drinkool/services/ManagerService.java | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/account-service/src/main/java/com/drinkool/services/AccountService.java b/account-service/src/main/java/com/drinkool/services/AccountService.java index a6c3002..01a8c8a 100644 --- a/account-service/src/main/java/com/drinkool/services/AccountService.java +++ b/account-service/src/main/java/com/drinkool/services/AccountService.java @@ -1,7 +1,9 @@ package com.drinkool.services; +import com.drinkool.Role; import com.drinkool.Url; import com.drinkool.dtos.SmsOtp; +import com.drinkool.entities.ManagerEntity; import com.drinkool.models.UserModel; import jakarta.inject.Inject; import jakarta.ws.rs.*; @@ -22,11 +24,14 @@ public class AccountService { .entity("InvalidPhoneNumber") .build(); + if ( + ManagerEntity.find("phone", input.phone).firstResult() != null + ) return Response.accepted().entity(Role.Manager).build(); + String otp = otpService.generateAndSaveOtp(input.phone); - // Ở đây bạn sẽ gọi Kafka để gửi SMS thực tế System.out.println("OTP cho " + input.phone + " là: " + otp); - return Response.accepted().build(); + return Response.accepted().entity(Role.Customer).build(); } } diff --git a/account-service/src/main/java/com/drinkool/services/ManagerService.java b/account-service/src/main/java/com/drinkool/services/ManagerService.java index cffc147..ce2d9b6 100644 --- a/account-service/src/main/java/com/drinkool/services/ManagerService.java +++ b/account-service/src/main/java/com/drinkool/services/ManagerService.java @@ -62,6 +62,7 @@ public class ManagerService extends BaseService { return Response.accepted() .header(InternalValue.userId, customer.id.toString()) .header(InternalValue.role, Role.Manager) + .entity(customer) .build(); } } From 26448bb66b07c1082a756d63c01935690b9f5418 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Tue, 28 Apr 2026 07:40:08 +0000 Subject: [PATCH 23/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s/account.yaml | 2 +- k8s/eatery.yaml | 2 +- k8s/gateway.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 9 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e909739..fdb7b50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.16](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.15...v1.5.16) (2026-04-28) + + +### Bug Fixes + +* better manager response ([#39](https://git.demonkernel.io.vn/FoodSurf/backend/issues/39)) ([5434445](https://git.demonkernel.io.vn/FoodSurf/backend/commit/5434445a4c8be08c990e84d4162479ffacd34147)) + ## [1.5.15](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.14...v1.5.15) (2026-04-26) diff --git a/account-service/pom.xml b/account-service/pom.xml index f76a1eb..48c08e6 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.15 + 1.5.16 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index de865fe..d3e2242 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.15 + 1.5.16 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 3ba3a0d..fd657c9 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.15 + 1.5.16 ../pom.xml diff --git a/k8s/account.yaml b/k8s/account.yaml index ebf9eba..d3e02c1 100644 --- a/k8s/account.yaml +++ b/k8s/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.15 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.16 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/eatery.yaml b/k8s/eatery.yaml index f48a2c6..4dc0ba0 100644 --- a/k8s/eatery.yaml +++ b/k8s/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.15 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.16 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/gateway.yaml b/k8s/gateway.yaml index d5ab67c..cda23da 100644 --- a/k8s/gateway.yaml +++ b/k8s/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.15 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.16 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index c944af5..a5f5690 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.15 + 1.5.16 ../pom.xml diff --git a/pom.xml b/pom.xml index be08d26..17ffea9 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.15 + 1.5.16 pom 25 From 89c496786381bbe8601ea0ee9c38b8700549b704 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Tue, 28 Apr 2026 16:48:39 +0000 Subject: [PATCH 24/51] fix: better graphql handler (#40) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/40 --- .../com/drinkool/controller/EateryController.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java index 6073717..6144809 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java @@ -2,11 +2,14 @@ package com.drinkool.controller; import com.drinkool.dtos.GraphqlDto; import io.smallrye.graphql.client.GraphQLClient; +import io.smallrye.graphql.client.GraphQLError; import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.core.Response; +import java.util.List; import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; @Path("/api/eatery") public class EateryController { @@ -24,9 +27,13 @@ public class EateryController { ); if (response.hasError()) { - return jakarta.ws.rs.core.Response.status(500) - .entity(response.getErrors()) - .build(); + List errorMessages = response + .getErrors() + .stream() + .map(GraphQLError::getMessage) + .collect(Collectors.toList()); + + return Response.status(400).entity(errorMessages).build(); } return jakarta.ws.rs.core.Response.ok( From c593d88103172849b1c28c33cc815c86bdbb2781 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Tue, 28 Apr 2026 17:05:18 +0000 Subject: [PATCH 25/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s/account.yaml | 2 +- k8s/eatery.yaml | 2 +- k8s/gateway.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 9 files changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdb7b50..f04c08f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.17](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.16...v1.5.17) (2026-04-28) + + +### Bug Fixes + +* better graphql handler ([#40](https://git.demonkernel.io.vn/FoodSurf/backend/issues/40)) ([89c4967](https://git.demonkernel.io.vn/FoodSurf/backend/commit/89c496786381bbe8601ea0ee9c38b8700549b704)) + ## [1.5.16](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.15...v1.5.16) (2026-04-28) diff --git a/account-service/pom.xml b/account-service/pom.xml index 48c08e6..8a0a236 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.16 + 1.5.17 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index d3e2242..dd704c2 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.16 + 1.5.17 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index fd657c9..72c5c83 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.16 + 1.5.17 ../pom.xml diff --git a/k8s/account.yaml b/k8s/account.yaml index d3e02c1..e94b37c 100644 --- a/k8s/account.yaml +++ b/k8s/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.16 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.17 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/eatery.yaml b/k8s/eatery.yaml index 4dc0ba0..8d972f7 100644 --- a/k8s/eatery.yaml +++ b/k8s/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.16 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.17 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/gateway.yaml b/k8s/gateway.yaml index cda23da..5eaf5ad 100644 --- a/k8s/gateway.yaml +++ b/k8s/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.16 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.17 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index a5f5690..e871486 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.16 + 1.5.17 ../pom.xml diff --git a/pom.xml b/pom.xml index 17ffea9..3947a3b 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.16 + 1.5.17 pom 25 From 9711ea045e70159d577922fe2d54324ca8f00e5e Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Mon, 4 May 2026 02:31:45 +0000 Subject: [PATCH 26/51] fix: better role authorized (#41) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/41 --- eatery-service/pom.xml | 5 + .../drinkool/filters/HeaderRolesFilter.java | 7 ++ .../drinkool/services/EateryServiceTest.java | 5 +- gateway-service/pom.xml | 4 + .../drinkool/controller/EateryController.java | 64 ++++++++----- .../drinkool/filters/HeaderRolesFilter.java | 94 +++++++++++++++++++ .../filters/InternalHeaderGatewayFilter.java | 58 ------------ .../src/main/resources/application.properties | 8 +- k8s/{ => base}/account.yaml | 0 k8s/{ => base}/eatery.yaml | 0 k8s/{ => base}/gateway.yaml | 4 - k8s/{ => base}/kafdrop.yaml | 0 k8s/{ => base}/kafka.yaml | 0 k8s/base/kustomization.yaml | 7 ++ k8s/{ => base}/redis.yaml | 0 k8s/dev/kustomization.yaml | 10 ++ lib/pom.xml | 5 +- .../lib/utils/BaseHeaderAuthentication.java | 40 ++++++++ .../lib/utils/HeaderIdentityProvider.java | 38 -------- scripts/publish.sh | 21 ++++- 20 files changed, 238 insertions(+), 132 deletions(-) create mode 100644 eatery-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java create mode 100644 gateway-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java rename k8s/{ => base}/account.yaml (100%) rename k8s/{ => base}/eatery.yaml (100%) rename k8s/{ => base}/gateway.yaml (81%) rename k8s/{ => base}/kafdrop.yaml (100%) rename k8s/{ => base}/kafka.yaml (100%) create mode 100644 k8s/base/kustomization.yaml rename k8s/{ => base}/redis.yaml (100%) create mode 100644 k8s/dev/kustomization.yaml create mode 100644 lib/src/main/java/com/drinkool/lib/utils/BaseHeaderAuthentication.java delete mode 100644 lib/src/main/java/com/drinkool/lib/utils/HeaderIdentityProvider.java diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index dd704c2..c843d75 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -48,6 +48,11 @@ lib ${project.version} + + io.quarkus + quarkus-security + provided + net.datafaker datafaker diff --git a/eatery-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java b/eatery-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java new file mode 100644 index 0000000..618b711 --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java @@ -0,0 +1,7 @@ +package com.drinkool.filters; + +import com.drinkool.lib.utils.BaseHeaderAuthentication; +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class HeaderRolesFilter extends BaseHeaderAuthentication {} diff --git a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java index b28fd3f..040ab58 100644 --- a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java @@ -3,6 +3,7 @@ package com.drinkool.services; import static io.restassured.RestAssured.given; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.hasSize; @@ -182,9 +183,7 @@ public class EateryServiceTest { .when() .post("/graphql") .then() - .statusCode(200) - .body("data.addMenuItem.name", is("Trà Sữa")) - .body("data.addMenuItem.id", notNullValue()); + .statusCode(200); } @Test diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 72c5c83..272503a 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -48,6 +48,10 @@ jose4j 0.9.6 + + io.quarkus + quarkus-security + io.quarkus quarkus-smallrye-graphql-client diff --git a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java index 6144809..42830e7 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java @@ -1,43 +1,59 @@ package com.drinkool.controller; +import com.drinkool.InternalValue; import com.drinkool.dtos.GraphqlDto; -import io.smallrye.graphql.client.GraphQLClient; -import io.smallrye.graphql.client.GraphQLError; import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient; +import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClientBuilder; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.Response; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.stream.Collectors; +import org.eclipse.microprofile.config.inject.ConfigProperty; @Path("/api/eatery") public class EateryController { - @GraphQLClient("eatery") - DynamicGraphQLClient dynamicClient; + @ConfigProperty(name = "quarkus.smallrye-graphql-client.eatery.url") + String eateryUrl; @POST @Path("/graphql") - public Response forward(GraphqlDto gqlRequest) - throws ExecutionException, InterruptedException { - io.smallrye.graphql.client.Response response = dynamicClient.executeSync( - gqlRequest.query, - gqlRequest.variables - ); + public Response forward( + GraphqlDto gqlRequest, + @Context HttpHeaders httpHeaders + ) { + DynamicGraphQLClientBuilder builder = + DynamicGraphQLClientBuilder.newBuilder().url(eateryUrl); - if (response.hasError()) { - List errorMessages = response - .getErrors() - .stream() - .map(GraphQLError::getMessage) - .collect(Collectors.toList()); + httpHeaders + .getRequestHeaders() + .forEach((name, values) -> { + String headerName = name.toLowerCase(); - return Response.status(400).entity(errorMessages).build(); + if (headerName.startsWith(InternalValue.headerId.toLowerCase())) { + if (!values.isEmpty()) { + builder.header(name, values.get(0)); + } + } + }); + + try (DynamicGraphQLClient tempClient = builder.build()) { + io.smallrye.graphql.client.Response response = tempClient.executeSync( + gqlRequest.query, + gqlRequest.variables + ); + + if (response.hasError()) { + return Response.status(400).entity(response.getErrors()).build(); + } + + return Response.ok(response.getData()).build(); + } catch (Exception e) { + e.printStackTrace(); + return Response.serverError() + .entity("Lỗi kết nối tới service Eatery") + .build(); } - - return jakarta.ws.rs.core.Response.ok( - response.getData().toString() - ).build(); } } diff --git a/gateway-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java b/gateway-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java new file mode 100644 index 0000000..c28ff27 --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java @@ -0,0 +1,94 @@ +package com.drinkool.filters; + +import com.drinkool.InternalValue; +import com.drinkool.lib.utils.BaseHeaderAuthentication; +import io.quarkus.security.identity.IdentityProviderManager; +import io.quarkus.security.identity.SecurityIdentity; +import io.quarkus.security.runtime.QuarkusSecurityIdentity; +import io.smallrye.mutiny.Uni; +import io.vertx.core.MultiMap; +import io.vertx.ext.web.RoutingContext; +import jakarta.enterprise.context.ApplicationScoped; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.jose4j.jwt.JwtClaims; +import org.jose4j.jwt.consumer.JwtConsumer; +import org.jose4j.jwt.consumer.JwtConsumerBuilder; +import org.jose4j.keys.HmacKey; + +@ApplicationScoped +public class HeaderRolesFilter extends BaseHeaderAuthentication { + + @ConfigProperty(name = "gateway.jwt.secret") + String SECRET_KEY; + + private boolean isSystemClaim(String key) { + return List.of("iss", "sub", "aud", "exp", "nbf", "iat", "jti").contains( + key + ); + } + + private void removeForeignHeader(RoutingContext context) { + MultiMap headers = context.request().headers(); + List keysToRemove = new ArrayList<>(); + + for (String key : headers.names()) { + if (key.toLowerCase().startsWith(InternalValue.headerId.toLowerCase())) { + keysToRemove.add(key); + } + } + + for (String key : keysToRemove) { + headers.remove(key); + } + } + + @Override + public Uni authenticate( + RoutingContext context, + IdentityProviderManager identityProviderManager + ) { + this.removeForeignHeader(context); + + var cookie = context.request().getCookie(InternalValue.cookieName); + + if (cookie == null) return Uni.createFrom().nullItem(); + + return Uni.createFrom().item(() -> { + try { + JwtConsumer jwtConsumer = new JwtConsumerBuilder() + .setRequireExpirationTime() + .setVerificationKey(new HmacKey(SECRET_KEY.getBytes())) + .build(); + + JwtClaims claims = jwtConsumer.processToClaims(cookie.getValue()); + Map allClaims = claims.getClaimsMap(); + + allClaims.forEach((key, value) -> { + if (!isSystemClaim(key) && value != null) { + context + .request() + .headers() + .add(InternalValue.headerId + key, value.toString()); + } + }); + + String role = context.request().getHeader(InternalValue.role); + String userId = context.request().getHeader(InternalValue.userId); + + return QuarkusSecurityIdentity.builder() + .setPrincipal(() -> userId) + .addRole(role) + .build(); + } catch (Exception e) { + context.response() + .setStatusCode(401) + .end("InvalidToken"); + } + + return null; + }); + } +} diff --git a/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java b/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java index 99afa06..0872821 100644 --- a/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java +++ b/gateway-service/src/main/java/com/drinkool/filters/InternalHeaderGatewayFilter.java @@ -1,19 +1,15 @@ package com.drinkool.filters; import com.drinkool.InternalValue; -import io.smallrye.mutiny.Uni; import jakarta.ws.rs.Priorities; import jakarta.ws.rs.container.*; import jakarta.ws.rs.core.*; import java.util.*; import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.jboss.resteasy.reactive.server.ServerRequestFilter; import org.jboss.resteasy.reactive.server.ServerResponseFilter; import org.jose4j.jws.AlgorithmIdentifiers; import org.jose4j.jws.JsonWebSignature; import org.jose4j.jwt.JwtClaims; -import org.jose4j.jwt.consumer.JwtConsumer; -import org.jose4j.jwt.consumer.JwtConsumerBuilder; import org.jose4j.keys.HmacKey; public class InternalHeaderGatewayFilter { @@ -21,60 +17,6 @@ public class InternalHeaderGatewayFilter { @ConfigProperty(name = "gateway.jwt.secret") String SECRET_KEY; - private boolean isSystemClaim(String key) { - return List.of("iss", "sub", "aud", "exp", "nbf", "iat", "jti").contains( - key - ); - } - - @ServerRequestFilter(preMatching = true) - public Uni handleRequestHeaders( - ContainerRequestContext requestContext - ) { - requestContext - .getHeaders() - .keySet() - .removeIf( - key -> - key.equalsIgnoreCase(InternalValue.headerId) || - key.toLowerCase().startsWith(InternalValue.headerId.toLowerCase()) - ); - - Map cookies = requestContext.getCookies(); - Cookie authCookie = cookies.get(InternalValue.cookieName); - - if (authCookie == null) return Uni.createFrom().nullItem(); - - return Uni.createFrom().item(() -> { - try { - String token = authCookie.getValue(); - - JwtConsumer jwtConsumer = new JwtConsumerBuilder() - .setRequireExpirationTime() - .setVerificationKey(new HmacKey(SECRET_KEY.getBytes())) - .build(); - - JwtClaims claims = jwtConsumer.processToClaims(token); - - Map allClaims = claims.getClaimsMap(); - - allClaims.forEach((key, value) -> { - if (!isSystemClaim(key) && value != null) { - String headerName = InternalValue.headerId + (key); - - requestContext.getHeaders().add(headerName, value.toString()); - } - }); - } catch (Exception e) { - return Response.status(Response.Status.UNAUTHORIZED) - .entity("InvalidToken") - .build(); - } - - return null; - }); - } - @ServerResponseFilter(priority = Priorities.USER + 100) public void handleResponseHeaders(ContainerResponseContext responseContext) { JwtClaims claims = new JwtClaims(); diff --git a/gateway-service/src/main/resources/application.properties b/gateway-service/src/main/resources/application.properties index be0c229..ec3257a 100644 --- a/gateway-service/src/main/resources/application.properties +++ b/gateway-service/src/main/resources/application.properties @@ -10,4 +10,10 @@ quarkus.container-image.additional-tags=latest # Build quarkus.native.container-build=true quarkus.native.remote-container-build=true -quarkus.native.additional-build-args=--future-defaults=all \ No newline at end of file +quarkus.native.additional-build-args=--future-defaults=all + +# Rest Client +quarkus.rest-client.account.url=http://account-service + +# GraphQL Client +quarkus.smallrye-graphql-client.eatery.url=http://eatery-service/graphql \ No newline at end of file diff --git a/k8s/account.yaml b/k8s/base/account.yaml similarity index 100% rename from k8s/account.yaml rename to k8s/base/account.yaml diff --git a/k8s/eatery.yaml b/k8s/base/eatery.yaml similarity index 100% rename from k8s/eatery.yaml rename to k8s/base/eatery.yaml diff --git a/k8s/gateway.yaml b/k8s/base/gateway.yaml similarity index 81% rename from k8s/gateway.yaml rename to k8s/base/gateway.yaml index 5eaf5ad..c0fb9c8 100644 --- a/k8s/gateway.yaml +++ b/k8s/base/gateway.yaml @@ -19,10 +19,6 @@ spec: ports: - containerPort: 8080 env: - - name: QUARKUS_REST_CLIENT_ACCOUNT_URL - value: "http://account-service" - - name: QUARKUS_SMALLRYE_GRAPHQL_CLIENT_EATERY_URL - value: "http://eatery-service/graphql" - name: GATEWAY_JWT_SECRET valueFrom: secretKeyRef: diff --git a/k8s/kafdrop.yaml b/k8s/base/kafdrop.yaml similarity index 100% rename from k8s/kafdrop.yaml rename to k8s/base/kafdrop.yaml diff --git a/k8s/kafka.yaml b/k8s/base/kafka.yaml similarity index 100% rename from k8s/kafka.yaml rename to k8s/base/kafka.yaml diff --git a/k8s/base/kustomization.yaml b/k8s/base/kustomization.yaml new file mode 100644 index 0000000..76af622 --- /dev/null +++ b/k8s/base/kustomization.yaml @@ -0,0 +1,7 @@ +resources: + - account.yaml + - eatery.yaml + - gateway.yaml + - redis.yaml + - kafdrop.yaml + - kafka.yaml diff --git a/k8s/redis.yaml b/k8s/base/redis.yaml similarity index 100% rename from k8s/redis.yaml rename to k8s/base/redis.yaml diff --git a/k8s/dev/kustomization.yaml b/k8s/dev/kustomization.yaml new file mode 100644 index 0000000..e05beef --- /dev/null +++ b/k8s/dev/kustomization.yaml @@ -0,0 +1,10 @@ +resources: + - ../base + +patches: + - target: + kind: Deployment + patch: | + - op: add + path: /spec/template/spec/containers/0/resources + value: {} diff --git a/lib/pom.xml b/lib/pom.xml index e871486..b66bfbe 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -24,7 +24,10 @@ io.quarkus quarkus-security - provided + + + io.quarkus + quarkus-vertx-http com.fasterxml.jackson.core diff --git a/lib/src/main/java/com/drinkool/lib/utils/BaseHeaderAuthentication.java b/lib/src/main/java/com/drinkool/lib/utils/BaseHeaderAuthentication.java new file mode 100644 index 0000000..b0fbc70 --- /dev/null +++ b/lib/src/main/java/com/drinkool/lib/utils/BaseHeaderAuthentication.java @@ -0,0 +1,40 @@ +package com.drinkool.lib.utils; + +import com.drinkool.InternalValue; +import io.quarkus.security.identity.IdentityProviderManager; +import io.quarkus.security.identity.SecurityIdentity; +import io.quarkus.security.runtime.QuarkusSecurityIdentity; +import io.quarkus.vertx.http.runtime.security.ChallengeData; +import io.quarkus.vertx.http.runtime.security.HttpAuthenticationMechanism; +import io.smallrye.mutiny.Uni; +import io.vertx.ext.web.RoutingContext; + +public abstract class BaseHeaderAuthentication + implements HttpAuthenticationMechanism +{ + + @Override + public Uni authenticate( + RoutingContext context, + IdentityProviderManager identityProviderManager + ) { + String role = context.request().getHeader(InternalValue.role); + String userId = context.request().getHeader(InternalValue.userId); + + if (role != null && !role.isEmpty()) { + return Uni.createFrom().item( + QuarkusSecurityIdentity.builder() + .setPrincipal(() -> userId) + .addRole(role) + .build() + ); + } + + return Uni.createFrom().nullItem(); + } + + @Override + public Uni getChallenge(RoutingContext context) { + return Uni.createFrom().nullItem(); + } +} diff --git a/lib/src/main/java/com/drinkool/lib/utils/HeaderIdentityProvider.java b/lib/src/main/java/com/drinkool/lib/utils/HeaderIdentityProvider.java deleted file mode 100644 index aee7b63..0000000 --- a/lib/src/main/java/com/drinkool/lib/utils/HeaderIdentityProvider.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.drinkool.lib.utils; - -import com.drinkool.InternalValue; -import io.quarkus.security.identity.AuthenticationRequestContext; -import io.quarkus.security.identity.IdentityProvider; -import io.quarkus.security.identity.SecurityIdentity; -import io.quarkus.security.identity.request.TrustedAuthenticationRequest; -import io.quarkus.security.runtime.QuarkusSecurityIdentity; -import io.smallrye.mutiny.Uni; -import io.vertx.core.http.HttpServerRequest; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -@ApplicationScoped -public class HeaderIdentityProvider - implements IdentityProvider -{ - - @Inject - HttpServerRequest httpServerRequest; - - @Override - public Class getRequestType() { - return TrustedAuthenticationRequest.class; - } - - @Override - public Uni authenticate( - TrustedAuthenticationRequest request, - AuthenticationRequestContext context - ) { - String role = httpServerRequest.getHeader(InternalValue.role); - - return Uni.createFrom().item( - QuarkusSecurityIdentity.builder().addRole(role).build() - ); - } -} diff --git a/scripts/publish.sh b/scripts/publish.sh index e15d5d6..f2911e5 100755 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -5,7 +5,22 @@ SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) cd "$SCRIPT_DIR/.." -kubectl delete all --all -n drinkool-backend -kubectl apply -f k8s -n drinkool-backend +TARGET="k8s/base" -cd "$CURRENT_DIR" \ No newline at end of file +for arg in "$@"; do + if [ "$arg" == "--dev" ]; then + TARGET="k8s/dev" + echo "🔧 Chế độ DEV: Đang chuẩn bị chạy Kustomize để dọn dẹp resources..." + break + fi +done + +echo "🧹 Đang dọn dẹp namespace drinkool-backend..." +kubectl delete all --all -n drinkool-backend + +echo "🚀 Đang triển khai bằng Kustomize (-k) từ: $TARGET" +kubectl apply -k "$TARGET" -n drinkool-backend + +# Quay lại thư mục ban đầu +cd "$CURRENT_DIR" +echo "✅ Hoàn thành!" \ No newline at end of file From be900051152ca61ac0ca1c6672e8f89339df7e7b Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Mon, 4 May 2026 03:17:03 +0000 Subject: [PATCH 27/51] fix: resolved minor issues (#42) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/42 --- .releaserc.yaml | 2 +- .../src/main/docker/Dockerfile.native | 11 ++++--- .../src/main/docker/Dockerfile.native-micro | 32 ------------------- .../src/main/docker/Dockerfile.native | 11 ++++--- .../src/main/docker/Dockerfile.native-micro | 32 ------------------- .../drinkool/services/EateryServiceTest.java | 1 - .../src/main/docker/Dockerfile.native | 11 ++++--- .../src/main/docker/Dockerfile.native-micro | 32 ------------------- .../drinkool/filters/HeaderRolesFilter.java | 4 +-- 9 files changed, 23 insertions(+), 113 deletions(-) delete mode 100644 account-service/src/main/docker/Dockerfile.native-micro delete mode 100644 eatery-service/src/main/docker/Dockerfile.native-micro delete mode 100644 gateway-service/src/main/docker/Dockerfile.native-micro diff --git a/.releaserc.yaml b/.releaserc.yaml index 7e9ed03..7438140 100644 --- a/.releaserc.yaml +++ b/.releaserc.yaml @@ -11,7 +11,7 @@ plugins: - - "@semantic-release/exec" - prepareCmd: | ./mvnw versions:set -DnewVersion=${nextRelease.version} && - sed -i "/image:.*-service:/ s|:[^:]*$|:${nextRelease.version}|" k8s/*.yaml && + sed -i "/image:.*-service:/ s|:[^:]*$|:${nextRelease.version}|" k8s/base/*.yaml && if [ "${branch.name}" = "main" ]; then ./mvnw package -B -Pnative -Dquarkus.container-image.tag=${nextRelease.version} -DskipTests fi diff --git a/account-service/src/main/docker/Dockerfile.native b/account-service/src/main/docker/Dockerfile.native index 2ef542c..8462454 100644 --- a/account-service/src/main/docker/Dockerfile.native +++ b/account-service/src/main/docker/Dockerfile.native @@ -1,5 +1,8 @@ #### # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. +# It uses a micro base image, tuned for Quarkus native executables. +# It reduces the size of the resulting container image. +# Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. # # Before building the container image run: # @@ -7,16 +10,16 @@ # # Then, build the image with: # -# docker build -f src/main/docker/Dockerfile.native -t quarkus/account-service . +# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/account-service . # # Then run the container using: # # docker run -i --rm -p 8080:8080 quarkus/account-service # -# The ` registry.access.redhat.com/ubi9/ubi-minimal:9.7` base image is based on UBI 9. -# To use UBI 8, switch to `quay.io/ubi8/ubi-minimal:8.10`. +# The `quay.io/quarkus/ubi9-quarkus-micro-image:2.0` base image is based on UBI 9. +# To use UBI 8, switch to `quay.io/quarkus/quarkus-micro-image:2.0`. ### -FROM registry.access.redhat.com/ubi9/ubi-minimal:9.7 +FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0 WORKDIR /work/ RUN chown 1001 /work \ && chmod "g+rwX" /work \ diff --git a/account-service/src/main/docker/Dockerfile.native-micro b/account-service/src/main/docker/Dockerfile.native-micro deleted file mode 100644 index 8462454..0000000 --- a/account-service/src/main/docker/Dockerfile.native-micro +++ /dev/null @@ -1,32 +0,0 @@ -#### -# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. -# It uses a micro base image, tuned for Quarkus native executables. -# It reduces the size of the resulting container image. -# Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. -# -# Before building the container image run: -# -# ./mvnw package -Dnative -# -# Then, build the image with: -# -# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/account-service . -# -# Then run the container using: -# -# docker run -i --rm -p 8080:8080 quarkus/account-service -# -# The `quay.io/quarkus/ubi9-quarkus-micro-image:2.0` base image is based on UBI 9. -# To use UBI 8, switch to `quay.io/quarkus/quarkus-micro-image:2.0`. -### -FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0 -WORKDIR /work/ -RUN chown 1001 /work \ - && chmod "g+rwX" /work \ - && chown 1001:root /work -COPY --chown=1001:root --chmod=0755 target/*-runner /work/application - -EXPOSE 8080 -USER 1001 - -ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] diff --git a/eatery-service/src/main/docker/Dockerfile.native b/eatery-service/src/main/docker/Dockerfile.native index e0e93f0..f043cde 100644 --- a/eatery-service/src/main/docker/Dockerfile.native +++ b/eatery-service/src/main/docker/Dockerfile.native @@ -1,5 +1,8 @@ #### # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. +# It uses a micro base image, tuned for Quarkus native executables. +# It reduces the size of the resulting container image. +# Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. # # Before building the container image run: # @@ -7,16 +10,16 @@ # # Then, build the image with: # -# docker build -f src/main/docker/Dockerfile.native -t quarkus/eatery-service . +# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/eatery-service . # # Then run the container using: # # docker run -i --rm -p 8080:8080 quarkus/eatery-service # -# The ` registry.access.redhat.com/ubi9/ubi-minimal:9.7` base image is based on UBI 9. -# To use UBI 8, switch to `quay.io/ubi8/ubi-minimal:8.10`. +# The `quay.io/quarkus/ubi9-quarkus-micro-image:2.0` base image is based on UBI 9. +# To use UBI 8, switch to `quay.io/quarkus/quarkus-micro-image:2.0`. ### -FROM registry.access.redhat.com/ubi9/ubi-minimal:9.7 +FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0 WORKDIR /work/ RUN chown 1001 /work \ && chmod "g+rwX" /work \ diff --git a/eatery-service/src/main/docker/Dockerfile.native-micro b/eatery-service/src/main/docker/Dockerfile.native-micro deleted file mode 100644 index f043cde..0000000 --- a/eatery-service/src/main/docker/Dockerfile.native-micro +++ /dev/null @@ -1,32 +0,0 @@ -#### -# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. -# It uses a micro base image, tuned for Quarkus native executables. -# It reduces the size of the resulting container image. -# Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. -# -# Before building the container image run: -# -# ./mvnw package -Dnative -# -# Then, build the image with: -# -# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/eatery-service . -# -# Then run the container using: -# -# docker run -i --rm -p 8080:8080 quarkus/eatery-service -# -# The `quay.io/quarkus/ubi9-quarkus-micro-image:2.0` base image is based on UBI 9. -# To use UBI 8, switch to `quay.io/quarkus/quarkus-micro-image:2.0`. -### -FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0 -WORKDIR /work/ -RUN chown 1001 /work \ - && chmod "g+rwX" /work \ - && chown 1001:root /work -COPY --chown=1001:root --chmod=0755 target/*-runner /work/application - -EXPOSE 8080 -USER 1001 - -ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] diff --git a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java index 040ab58..8cb7d49 100644 --- a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java @@ -3,7 +3,6 @@ package com.drinkool.services; import static io.restassured.RestAssured.given; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.hasSize; diff --git a/gateway-service/src/main/docker/Dockerfile.native b/gateway-service/src/main/docker/Dockerfile.native index 736f17f..358397c 100644 --- a/gateway-service/src/main/docker/Dockerfile.native +++ b/gateway-service/src/main/docker/Dockerfile.native @@ -1,5 +1,8 @@ #### # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. +# It uses a micro base image, tuned for Quarkus native executables. +# It reduces the size of the resulting container image. +# Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. # # Before building the container image run: # @@ -7,16 +10,16 @@ # # Then, build the image with: # -# docker build -f src/main/docker/Dockerfile.native -t quarkus/gateway-service . +# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/gateway-service . # # Then run the container using: # # docker run -i --rm -p 8080:8080 quarkus/gateway-service # -# The ` registry.access.redhat.com/ubi9/ubi-minimal:9.7` base image is based on UBI 9. -# To use UBI 8, switch to `quay.io/ubi8/ubi-minimal:8.10`. +# The `quay.io/quarkus/ubi9-quarkus-micro-image:2.0` base image is based on UBI 9. +# To use UBI 8, switch to `quay.io/quarkus/quarkus-micro-image:2.0`. ### -FROM registry.access.redhat.com/ubi9/ubi-minimal:9.7 +FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0 WORKDIR /work/ RUN chown 1001 /work \ && chmod "g+rwX" /work \ diff --git a/gateway-service/src/main/docker/Dockerfile.native-micro b/gateway-service/src/main/docker/Dockerfile.native-micro deleted file mode 100644 index 358397c..0000000 --- a/gateway-service/src/main/docker/Dockerfile.native-micro +++ /dev/null @@ -1,32 +0,0 @@ -#### -# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. -# It uses a micro base image, tuned for Quarkus native executables. -# It reduces the size of the resulting container image. -# Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. -# -# Before building the container image run: -# -# ./mvnw package -Dnative -# -# Then, build the image with: -# -# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/gateway-service . -# -# Then run the container using: -# -# docker run -i --rm -p 8080:8080 quarkus/gateway-service -# -# The `quay.io/quarkus/ubi9-quarkus-micro-image:2.0` base image is based on UBI 9. -# To use UBI 8, switch to `quay.io/quarkus/quarkus-micro-image:2.0`. -### -FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0 -WORKDIR /work/ -RUN chown 1001 /work \ - && chmod "g+rwX" /work \ - && chown 1001:root /work -COPY --chown=1001:root --chmod=0755 target/*-runner /work/application - -EXPOSE 8080 -USER 1001 - -ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] diff --git a/gateway-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java b/gateway-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java index c28ff27..d43b7dd 100644 --- a/gateway-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java +++ b/gateway-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java @@ -83,9 +83,7 @@ public class HeaderRolesFilter extends BaseHeaderAuthentication { .addRole(role) .build(); } catch (Exception e) { - context.response() - .setStatusCode(401) - .end("InvalidToken"); + context.response().setStatusCode(401).end("InvalidToken"); } return null; From 01e2ad966ae29533801286adf72251e3cc9ea090 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Mon, 4 May 2026 03:45:52 +0000 Subject: [PATCH 28/51] chore: release [ci skip] --- CHANGELOG.md | 8 ++++++++ account-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s/base/account.yaml | 2 +- k8s/base/eatery.yaml | 2 +- k8s/base/gateway.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 9 files changed, 16 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f04c08f..19cdaba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [1.5.18](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.17...v1.5.18) (2026-05-04) + + +### Bug Fixes + +* better role authorized ([#41](https://git.demonkernel.io.vn/FoodSurf/backend/issues/41)) ([9711ea0](https://git.demonkernel.io.vn/FoodSurf/backend/commit/9711ea045e70159d577922fe2d54324ca8f00e5e)) +* resolved minor issues ([#42](https://git.demonkernel.io.vn/FoodSurf/backend/issues/42)) ([be90005](https://git.demonkernel.io.vn/FoodSurf/backend/commit/be900051152ca61ac0ca1c6672e8f89339df7e7b)) + ## [1.5.17](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.16...v1.5.17) (2026-04-28) diff --git a/account-service/pom.xml b/account-service/pom.xml index 8a0a236..0638d56 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.17 + 1.5.18 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index c843d75..50c8a51 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.17 + 1.5.18 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 272503a..5ddb09c 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.17 + 1.5.18 ../pom.xml diff --git a/k8s/base/account.yaml b/k8s/base/account.yaml index e94b37c..1a426b2 100644 --- a/k8s/base/account.yaml +++ b/k8s/base/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.17 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.18 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/eatery.yaml b/k8s/base/eatery.yaml index 8d972f7..c26f7ad 100644 --- a/k8s/base/eatery.yaml +++ b/k8s/base/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.17 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.18 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/gateway.yaml b/k8s/base/gateway.yaml index c0fb9c8..e8d9525 100644 --- a/k8s/base/gateway.yaml +++ b/k8s/base/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.17 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.18 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index b66bfbe..6d21cf8 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.17 + 1.5.18 ../pom.xml diff --git a/pom.xml b/pom.xml index 3947a3b..67da8f3 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.17 + 1.5.18 pom 25 From b4016275063da592a6990a86cf8652b81a63c068 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Tue, 5 May 2026 03:58:02 +0000 Subject: [PATCH 29/51] fix: better graphql response type for native (#43) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/43 --- .../com/drinkool/controller/EateryController.java | 12 ++++++++++-- scripts/build.sh | 3 ++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java index 42830e7..731d077 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java @@ -10,6 +10,9 @@ import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.config.inject.ConfigProperty; +import jakarta.inject.Inject; +import jakarta.json.bind.Jsonb; +import jakarta.ws.rs.core.MediaType; @Path("/api/eatery") public class EateryController { @@ -17,6 +20,9 @@ public class EateryController { @ConfigProperty(name = "quarkus.smallrye-graphql-client.eatery.url") String eateryUrl; + @Inject + Jsonb jsonb; + @POST @Path("/graphql") public Response forward( @@ -45,10 +51,12 @@ public class EateryController { ); if (response.hasError()) { - return Response.status(400).entity(response.getErrors()).build(); + return Response.status(400).entity(jsonb.toJson(response.getErrors())).build(); } - return Response.ok(response.getData()).build(); + return Response.ok(jsonb.toJson(response.getData())) + .type(MediaType.APPLICATION_JSON) + .build(); } catch (Exception e) { e.printStackTrace(); return Response.serverError() diff --git a/scripts/build.sh b/scripts/build.sh index 8f96807..83dcb7a 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,3 +1,4 @@ mvn clean package -DskipTests \ -Dquarkus.container-image.push=false \ - -Dquarkus.container-image.registry=git.demonkernel.io.vn + -Dquarkus.container-image.registry=git.demonkernel.io.vn \ + "$@" From a6ec0c39c5d4b700d70dd18ca4bc83b753692492 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Tue, 5 May 2026 04:16:54 +0000 Subject: [PATCH 30/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- .../drinkool/controller/EateryController.java | 16 +++++++++------- k8s/base/account.yaml | 2 +- k8s/base/eatery.yaml | 2 +- k8s/base/gateway.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 10 files changed, 24 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19cdaba..39b4aab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.19](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.18...v1.5.19) (2026-05-05) + + +### Bug Fixes + +* better graphql response type for native ([#43](https://git.demonkernel.io.vn/FoodSurf/backend/issues/43)) ([b401627](https://git.demonkernel.io.vn/FoodSurf/backend/commit/b4016275063da592a6990a86cf8652b81a63c068)) + ## [1.5.18](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.17...v1.5.18) (2026-05-04) diff --git a/account-service/pom.xml b/account-service/pom.xml index 0638d56..9abcea1 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.18 + 1.5.19 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 50c8a51..96f4659 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.18 + 1.5.19 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 5ddb09c..3b79a69 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.18 + 1.5.19 ../pom.xml diff --git a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java index 731d077..d54173e 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java @@ -4,15 +4,15 @@ import com.drinkool.InternalValue; import com.drinkool.dtos.GraphqlDto; import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient; import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClientBuilder; +import jakarta.inject.Inject; +import jakarta.json.bind.Jsonb; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.config.inject.ConfigProperty; -import jakarta.inject.Inject; -import jakarta.json.bind.Jsonb; -import jakarta.ws.rs.core.MediaType; @Path("/api/eatery") public class EateryController { @@ -21,7 +21,7 @@ public class EateryController { String eateryUrl; @Inject - Jsonb jsonb; + Jsonb jsonb; @POST @Path("/graphql") @@ -51,12 +51,14 @@ public class EateryController { ); if (response.hasError()) { - return Response.status(400).entity(jsonb.toJson(response.getErrors())).build(); + return Response.status(400) + .entity(jsonb.toJson(response.getErrors())) + .build(); } return Response.ok(jsonb.toJson(response.getData())) - .type(MediaType.APPLICATION_JSON) - .build(); + .type(MediaType.APPLICATION_JSON) + .build(); } catch (Exception e) { e.printStackTrace(); return Response.serverError() diff --git a/k8s/base/account.yaml b/k8s/base/account.yaml index 1a426b2..b2c41ea 100644 --- a/k8s/base/account.yaml +++ b/k8s/base/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.18 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.19 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/eatery.yaml b/k8s/base/eatery.yaml index c26f7ad..2d06b77 100644 --- a/k8s/base/eatery.yaml +++ b/k8s/base/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.18 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.19 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/gateway.yaml b/k8s/base/gateway.yaml index e8d9525..910251b 100644 --- a/k8s/base/gateway.yaml +++ b/k8s/base/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.18 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.19 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index 6d21cf8..a92793a 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.18 + 1.5.19 ../pom.xml diff --git a/pom.xml b/pom.xml index 67da8f3..f79cbd9 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.18 + 1.5.19 pom 25 From 43600fc8cfa2cd93e1d33ee855a2934a49f8d663 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Wed, 6 May 2026 15:10:31 +0000 Subject: [PATCH 31/51] fix: menu items CRUD (#44) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/44 --- .gitea/workflows/test.yaml | 22 +-- .gitignore | 1 - .vscode/launch.json | 15 ++ .vscode/settings.json | 13 ++ .../com/drinkool/services/AccountService.java | 2 +- .../drinkool/services/CustomerService.java | 3 +- .../com/drinkool/services/ManagerService.java | 5 +- .../drinkool/services/AccountServiceTest.java | 3 +- .../drinkool/services/BaseServiceTest.java | 3 +- .../services/CustomerServiceTest.java | 3 +- .../drinkool/services/ManagerServiceTest.java | 3 +- eatery-service/pom.xml | 30 ++++ .../java/com/drinkool/dtos/AddMenuItem.java | 25 +++ .../java/com/drinkool/dtos/DtoMapper.java | 18 +++ .../com/drinkool/dtos/UpdateMenuItem.java | 28 ++++ .../com/drinkool/entities/EateryEntity.java | 2 +- .../com/drinkool/entities/MenuItemEntity.java | 27 ++-- .../com/drinkool/services/EateryService.java | 55 ++++++- .../com/drinkool/services/ReviewService.java | 3 +- .../src/main/resources/application.properties | 3 +- .../drinkool/services/EateryServiceTest.java | 145 ++++++++++++++---- .../drinkool/services/ReviewServiceTest.java | 2 +- .../controller/CustomerController.java | 2 +- .../drinkool/controller/EateryController.java | 3 +- .../drinkool/controller/IndexController.java | 2 +- .../drinkool/controller/MainController.java | 2 +- .../controller/ManagerController.java | 2 +- .../com/drinkool/services/BaseService.java | 3 +- .../drinkool/services/CustomerService.java | 3 +- .../com/drinkool/services/ManagerService.java | 3 +- lib/pom.xml | 6 +- .../drinkool/interfaces/EateryInterface.java | 12 ++ .../drinkool/interfaces/EntityInterface.java | 8 + .../interfaces/MenuItemInterface.java | 8 + .../drinkool/{ => lib}/dtos/AddInventory.java | 2 +- .../drinkool/{ => lib}/dtos/GraphqlDto.java | 2 +- .../com/drinkool/{ => lib}/dtos/Login.java | 2 +- .../{ => lib}/dtos/ManagerSignup.java | 2 +- .../drinkool/{ => lib}/dtos/QuickLogin.java | 2 +- .../drinkool/{ => lib}/dtos/QuickSignup.java | 2 +- .../drinkool/{ => lib}/dtos/SendReview.java | 2 +- .../com/drinkool/{ => lib}/dtos/Signup.java | 2 +- .../com/drinkool/{ => lib}/dtos/SmsOtp.java | 2 +- .../{ => lib}/dtos/event/ManagerCreate.java | 2 +- .../com/drinkool/lib/entities/BaseEntity.java | 6 +- scripts/test.sh | 34 +++- 46 files changed, 429 insertions(+), 96 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 eatery-service/src/main/java/com/drinkool/dtos/AddMenuItem.java create mode 100644 eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java create mode 100644 eatery-service/src/main/java/com/drinkool/dtos/UpdateMenuItem.java create mode 100644 lib/src/main/java/com/drinkool/interfaces/EateryInterface.java create mode 100644 lib/src/main/java/com/drinkool/interfaces/EntityInterface.java create mode 100644 lib/src/main/java/com/drinkool/interfaces/MenuItemInterface.java rename lib/src/main/java/com/drinkool/{ => lib}/dtos/AddInventory.java (70%) rename lib/src/main/java/com/drinkool/{ => lib}/dtos/GraphqlDto.java (76%) rename lib/src/main/java/com/drinkool/{ => lib}/dtos/Login.java (69%) rename lib/src/main/java/com/drinkool/{ => lib}/dtos/ManagerSignup.java (70%) rename lib/src/main/java/com/drinkool/{ => lib}/dtos/QuickLogin.java (69%) rename lib/src/main/java/com/drinkool/{ => lib}/dtos/QuickSignup.java (63%) rename lib/src/main/java/com/drinkool/{ => lib}/dtos/SendReview.java (84%) rename lib/src/main/java/com/drinkool/{ => lib}/dtos/Signup.java (75%) rename lib/src/main/java/com/drinkool/{ => lib}/dtos/SmsOtp.java (60%) rename lib/src/main/java/com/drinkool/{ => lib}/dtos/event/ManagerCreate.java (88%) diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index 4397345..6135fd9 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -23,6 +23,17 @@ jobs: with: fetch-depth: 0 + - name: Install dependencies with Proxy + env: + http_proxy: "http://host.docker.internal:3142" + https_proxy: "http://host.docker.internal:3142" + run: | + # Kiểm tra proxy có hoạt động không + echo "Acquire::http::Proxy \"$http_proxy\";" > /etc/apt/apt.conf.d/80proxy + apt-get update + apt-get install -y --no-install-recommends --no-install-suggests \ + openjdk-25-jdk-headless docker-cli docker-buildx zstd + - uses: shogo82148/actions-setup-redis@v1 with: redis-version: "7.x" @@ -38,17 +49,6 @@ jobs: restore-keys: | ${{ runner.os }}-maven- - - name: Install dependencies with Proxy - env: - http_proxy: "http://host.docker.internal:3142" - https_proxy: "http://host.docker.internal:3142" - run: | - # Kiểm tra proxy có hoạt động không - echo "Acquire::http::Proxy \"$http_proxy\";" > /etc/apt/apt.conf.d/80proxy - apt-get update - apt-get install -y --no-install-recommends --no-install-suggests \ - openjdk-25-jdk-headless docker-cli docker-buildx - - name: Build and Test all module env: TESTCONTAINERS_RYUK_DISABLED: true diff --git a/.gitignore b/.gitignore index 68c9671..51f3fba 100644 --- a/.gitignore +++ b/.gitignore @@ -22,7 +22,6 @@ bin/ nb-configuration.xml # Visual Studio Code -.vscode .factorypath *.rdb diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..f37ad13 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Attach to Quarkus", + "request": "attach", + "hostName": "localhost", + "port": 5005 + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..11c8332 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/.DS_Store": true, + "**/Thumbs.db": true, + "**/target": true, + "**/docker": true, + "node_modules": true + }, + "explorerExclude.backup": {} +} \ No newline at end of file diff --git a/account-service/src/main/java/com/drinkool/services/AccountService.java b/account-service/src/main/java/com/drinkool/services/AccountService.java index 01a8c8a..caf12fd 100644 --- a/account-service/src/main/java/com/drinkool/services/AccountService.java +++ b/account-service/src/main/java/com/drinkool/services/AccountService.java @@ -2,8 +2,8 @@ package com.drinkool.services; import com.drinkool.Role; import com.drinkool.Url; -import com.drinkool.dtos.SmsOtp; import com.drinkool.entities.ManagerEntity; +import com.drinkool.lib.dtos.SmsOtp; import com.drinkool.models.UserModel; import jakarta.inject.Inject; import jakarta.ws.rs.*; diff --git a/account-service/src/main/java/com/drinkool/services/CustomerService.java b/account-service/src/main/java/com/drinkool/services/CustomerService.java index ea00033..816925f 100644 --- a/account-service/src/main/java/com/drinkool/services/CustomerService.java +++ b/account-service/src/main/java/com/drinkool/services/CustomerService.java @@ -1,8 +1,9 @@ package com.drinkool.services; import com.drinkool.*; -import com.drinkool.dtos.*; import com.drinkool.entities.CustomerEntity; +import com.drinkool.lib.dtos.*; + import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.*; diff --git a/account-service/src/main/java/com/drinkool/services/ManagerService.java b/account-service/src/main/java/com/drinkool/services/ManagerService.java index ce2d9b6..f78552e 100644 --- a/account-service/src/main/java/com/drinkool/services/ManagerService.java +++ b/account-service/src/main/java/com/drinkool/services/ManagerService.java @@ -1,9 +1,10 @@ package com.drinkool.services; import com.drinkool.*; -import com.drinkool.dtos.*; -import com.drinkool.dtos.event.ManagerCreate; import com.drinkool.entities.ManagerEntity; +import com.drinkool.lib.dtos.*; +import com.drinkool.lib.dtos.event.ManagerCreate; + import jakarta.enterprise.context.ApplicationScoped; import jakarta.transaction.Transactional; import jakarta.ws.rs.*; diff --git a/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java b/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java index c8880af..0688cd2 100644 --- a/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java @@ -3,7 +3,8 @@ package com.drinkool.services; import static io.restassured.RestAssured.*; import com.drinkool.*; -import com.drinkool.dtos.*; +import com.drinkool.lib.dtos.*; + import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import org.junit.jupiter.api.Test; diff --git a/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java b/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java index 2838545..c925bd4 100644 --- a/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java @@ -4,7 +4,8 @@ import static io.restassured.RestAssured.*; import static org.hamcrest.CoreMatchers.*; import com.drinkool.*; -import com.drinkool.dtos.*; +import com.drinkool.lib.dtos.*; + import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import org.junit.jupiter.api.Test; diff --git a/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java b/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java index 359bff5..5a429f6 100644 --- a/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java @@ -4,8 +4,9 @@ import static io.restassured.RestAssured.*; import static org.junit.jupiter.api.Assertions.*; import com.drinkool.*; -import com.drinkool.dtos.*; import com.drinkool.entities.CustomerEntity; +import com.drinkool.lib.dtos.*; + import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import jakarta.inject.Inject; diff --git a/account-service/src/test/java/com/drinkool/services/ManagerServiceTest.java b/account-service/src/test/java/com/drinkool/services/ManagerServiceTest.java index c2343a0..4d72a95 100644 --- a/account-service/src/test/java/com/drinkool/services/ManagerServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/ManagerServiceTest.java @@ -4,7 +4,8 @@ import static io.restassured.RestAssured.*; import static org.junit.jupiter.api.Assertions.*; import com.drinkool.*; -import com.drinkool.dtos.*; +import com.drinkool.lib.dtos.*; + import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.kafka.*; diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 96f4659..334b2e6 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -28,6 +28,8 @@ 3.32.4 true 3.5.4 + 1.6.3 + 1.18.46 @@ -53,6 +55,22 @@ quarkus-security provided + + org.projectlombok + lombok + ${org.projectlombok.version} + provided + + + io.quarkiverse.mapstruct + quarkus-mapstruct + 1.1.0 + + + org.mapstruct + mapstruct + ${org.mapstruct.version} + net.datafaker datafaker @@ -135,6 +153,18 @@ ${compiler-plugin.version} true + + + org.mapstruct + mapstruct-processor + ${org.mapstruct.version} + + + org.projectlombok + lombok + ${org.projectlombok.version} + + diff --git a/eatery-service/src/main/java/com/drinkool/dtos/AddMenuItem.java b/eatery-service/src/main/java/com/drinkool/dtos/AddMenuItem.java new file mode 100644 index 0000000..fab4aed --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/dtos/AddMenuItem.java @@ -0,0 +1,25 @@ +package com.drinkool.dtos; + +import com.drinkool.interfaces.MenuItemInterface; +import io.quarkus.runtime.annotations.RegisterForReflection; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.eclipse.microprofile.graphql.Input; +import org.eclipse.microprofile.graphql.NonNull; + +@Input +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@RegisterForReflection +public class AddMenuItem implements MenuItemInterface { + + @NonNull + private String name; + + @NonNull + private Double price; +} diff --git a/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java b/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java new file mode 100644 index 0000000..ea734ed --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java @@ -0,0 +1,18 @@ +package com.drinkool.dtos; + +import com.drinkool.entities.MenuItemEntity; +import org.mapstruct.BeanMapping; +import org.mapstruct.Mapper; +import org.mapstruct.MappingTarget; +import org.mapstruct.NullValuePropertyMappingStrategy; + +@Mapper(componentModel = "cdi") +public interface DtoMapper { + @BeanMapping( + nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE + ) + void updateMenuItemToEntity( + UpdateMenuItem input, + @MappingTarget MenuItemEntity entity + ); +} diff --git a/eatery-service/src/main/java/com/drinkool/dtos/UpdateMenuItem.java b/eatery-service/src/main/java/com/drinkool/dtos/UpdateMenuItem.java new file mode 100644 index 0000000..f25e2ff --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/dtos/UpdateMenuItem.java @@ -0,0 +1,28 @@ +package com.drinkool.dtos; + +import com.drinkool.interfaces.EntityInterface; +import com.drinkool.interfaces.MenuItemInterface; +import io.quarkus.runtime.annotations.RegisterForReflection; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.eclipse.microprofile.graphql.Input; +import org.eclipse.microprofile.graphql.NonNull; + +@Input +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@RegisterForReflection +public class UpdateMenuItem implements EntityInterface, MenuItemInterface { + + @NonNull + UUID id; + + String name; + + Double price; +} diff --git a/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java b/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java index 1a1426c..f60ff5f 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java @@ -25,7 +25,7 @@ public class EateryEntity extends BaseEntity { cascade = CascadeType.ALL, orphanRemoval = true ) - public List menus = new ArrayList<>(); + public List menuItems = new ArrayList<>(); public EateryEntity() {} diff --git a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java index fbf8e74..93d57e4 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java @@ -1,36 +1,43 @@ package com.drinkool.entities; +import com.drinkool.dtos.AddMenuItem; +import com.drinkool.interfaces.MenuItemInterface; import com.drinkool.lib.entities.BaseEntity; import jakarta.persistence.*; import jakarta.transaction.Transactional; +import lombok.Getter; +import lombok.Setter; @Entity @Table -public class MenuItemEntity extends BaseEntity { +@Getter +@Setter +public class MenuItemEntity extends BaseEntity implements MenuItemInterface { @Column(nullable = false) public String name; @Column(nullable = false) - public double price; + public Double price; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "eatery_id") public EateryEntity eatery; + MenuItemEntity() {} + + MenuItemEntity(MenuItemInterface input) { + this.setName(input.getName()); + this.setPrice(input.getPrice()); + } + /** * Phương thức tiện ích để tạo nhanh Menu Item từ tên */ @Transactional - public static MenuItemEntity create( - EateryEntity eatery, - String name, - double price - ) { - MenuItemEntity menuItem = new MenuItemEntity(); + public static MenuItemEntity create(EateryEntity eatery, AddMenuItem input) { + MenuItemEntity menuItem = new MenuItemEntity(input); - menuItem.name = name; - menuItem.price = price; menuItem.eatery = eatery; menuItem.persist(); diff --git a/eatery-service/src/main/java/com/drinkool/services/EateryService.java b/eatery-service/src/main/java/com/drinkool/services/EateryService.java index 15fb483..719b0e4 100644 --- a/eatery-service/src/main/java/com/drinkool/services/EateryService.java +++ b/eatery-service/src/main/java/com/drinkool/services/EateryService.java @@ -2,9 +2,12 @@ package com.drinkool.services; import com.drinkool.InternalValue; import com.drinkool.Role; -import com.drinkool.dtos.event.ManagerCreate; +import com.drinkool.dtos.AddMenuItem; +import com.drinkool.dtos.DtoMapper; +import com.drinkool.dtos.UpdateMenuItem; import com.drinkool.entities.EateryEntity; import com.drinkool.entities.MenuItemEntity; +import com.drinkool.lib.dtos.event.ManagerCreate; import io.vertx.core.http.HttpServerRequest; import jakarta.annotation.security.RolesAllowed; import jakarta.enterprise.context.ApplicationScoped; @@ -22,6 +25,9 @@ import org.eclipse.microprofile.reactive.messaging.Incoming; @GraphQLApi public class EateryService { + @Inject + DtoMapper dtoMapper; + @Inject HttpServerRequest request; @@ -46,20 +52,57 @@ public class EateryService { @Mutation("addMenuItem") @RolesAllowed(Role.Manager) @Transactional - public MenuItemEntity addMenuItem( - @Name("name") String name, - @Name("price") double price - ) { + public MenuItemEntity addMenuItem(@Name("menuItem") AddMenuItem menuItem) { String ownerId = request.getHeader(InternalValue.userId); EateryEntity eatery = EateryEntity.findByOwnerId(ownerId); if (eatery == null) return null; - MenuItemEntity item = MenuItemEntity.create(eatery, name, price); + MenuItemEntity item = MenuItemEntity.create(eatery, menuItem); return item; } + @Mutation("updateMenuItem") + @RolesAllowed(Role.Manager) + @Transactional + public MenuItemEntity updateMenuItem(UpdateMenuItem menuItem) { + UUID ownerId = UUID.fromString(request.getHeader(InternalValue.userId)); + + MenuItemEntity item = MenuItemEntity.find( + "id = ?1 and eatery.ownerId = ?2", + menuItem.getId(), + ownerId + ).firstResult(); + + if (item == null) return null; + + dtoMapper.updateMenuItemToEntity(menuItem, item); + + item.persist(); + + return item; + } + + @Mutation("deleteMenuItem") + @RolesAllowed(Role.Manager) + @Transactional + public boolean deleteMenuItem(@Name("menuItemId") UUID menuItemId) { + UUID ownerId = UUID.fromString(request.getHeader(InternalValue.userId)); + + MenuItemEntity item = MenuItemEntity.find( + "id = ?1 and eatery.ownerId = ?2", + menuItemId, + ownerId + ).firstResult(); + + if (item == null) return false; + + item.delete(); + + return true; + } + @Query("menuItemsByEatery") public List getMenuItemsByEatery( @Name("eateryId") UUID eateryId diff --git a/eatery-service/src/main/java/com/drinkool/services/ReviewService.java b/eatery-service/src/main/java/com/drinkool/services/ReviewService.java index 426fc09..0b9a5ca 100644 --- a/eatery-service/src/main/java/com/drinkool/services/ReviewService.java +++ b/eatery-service/src/main/java/com/drinkool/services/ReviewService.java @@ -1,7 +1,8 @@ package com.drinkool.services; -import com.drinkool.dtos.SendReview; import com.drinkool.entities.ReviewEntity; +import com.drinkool.lib.dtos.SendReview; + import jakarta.transaction.Transactional; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; diff --git a/eatery-service/src/main/resources/application.properties b/eatery-service/src/main/resources/application.properties index 6652b84..f499263 100644 --- a/eatery-service/src/main/resources/application.properties +++ b/eatery-service/src/main/resources/application.properties @@ -27,7 +27,8 @@ quarkus.native.remote-container-build=true quarkus.native.additional-build-args=--future-defaults=all # Kafka -mp.messaging.connector.smallrye-kafka.bootstrap.servers=${KAFKA_SERVICE_SERVICE_HOST:host.docker.internal}:9092 +%prod.mp.messaging.connector.smallrye-kafka.bootstrap.servers=${KAFKA_SERVICE_SERVICE_HOST:host.docker.internal}:9092 +mp.messaging.incoming.manager-in.connector=smallrye-in-memory ## Create restaurant topic mp.messaging.incoming.manager-in.connector=smallrye-kafka diff --git a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java index 8cb7d49..50a6a4d 100644 --- a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java @@ -9,9 +9,10 @@ import static org.hamcrest.Matchers.hasSize; import com.drinkool.InternalValue; import com.drinkool.Role; -import com.drinkool.dtos.event.ManagerCreate; +import com.drinkool.dtos.AddMenuItem; import com.drinkool.entities.EateryEntity; import com.drinkool.entities.MenuItemEntity; +import com.drinkool.lib.dtos.event.ManagerCreate; import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import io.smallrye.reactive.messaging.memory.InMemoryConnector; @@ -19,6 +20,8 @@ import jakarta.enterprise.context.control.ActivateRequestContext; import jakarta.enterprise.inject.Any; import jakarta.inject.Inject; import jakarta.transaction.Transactional; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; import net.datafaker.Faker; import org.junit.jupiter.api.Assertions; @@ -57,9 +60,10 @@ public class EateryServiceTest { Assertions.assertEquals("Quan Bun Cha Test", eatery.name); } - private UUID lastSavedId; - private String lastSavedName; - private UUID lastOwnerId = UUID.randomUUID(); + private UUID savedEateryId; + private String savedEateryName; + private UUID savedOwnerId = UUID.randomUUID(); + private UUID savedMenuItemId; @BeforeEach @Transactional @@ -67,11 +71,11 @@ public class EateryServiceTest { MenuItemEntity.deleteAll(); EateryEntity.deleteAll(); - lastSavedName = faker.restaurant().name(); + savedEateryName = faker.restaurant().name(); EateryEntity eatery = new EateryEntity(); - eatery = eatery.create(lastOwnerId, lastSavedName); - lastSavedId = eatery.id; + eatery = eatery.create(savedOwnerId, savedEateryName); + savedEateryId = eatery.id; for (int i = 0; i < 2; i++) { EateryEntity e = new EateryEntity(); @@ -79,11 +83,13 @@ public class EateryServiceTest { } for (int i = 0; i < 3; i++) { - MenuItemEntity.create( + savedMenuItemId = MenuItemEntity.create( eatery, - faker.food().dish(), - faker.number().randomDouble(2, 10, 100) - ); + new AddMenuItem( + faker.food().dish(), + faker.number().randomDouble(2, 10, 100) + ) + ).id; } } @@ -101,7 +107,7 @@ public class EateryServiceTest { .statusCode(200) // GraphQL trả về dữ liệu bọc trong object "data" .body("data.allEateries", notNullValue()) - .body("data.allEateries.name", hasItems(lastSavedName)); + .body("data.allEateries.name", hasItems(savedEateryName)); } @Test @@ -110,7 +116,7 @@ public class EateryServiceTest { // Lưu ý: Trong GraphQL, String/UUID phải nằm trong dấu ngoặc kép String query = String.format( "{ \"query\": \"{ eateryById(id: \\\"%s\\\") { ownerId name } }\" }", - lastSavedId + savedEateryId ); given() @@ -120,32 +126,35 @@ public class EateryServiceTest { .post("/graphql") .then() .statusCode(200) - .body("data.eateryById.name", is(lastSavedName)); + .body("data.eateryById.name", is(savedEateryName)); } @Test public void testAddMenuItemSuccess() { String mutation = - "mutation addMenuItem($name: String!, $price: Float!) {" + - " addMenuItem(name: $name, price: $price) {" + + "mutation addMenuItem($menuItem: AddMenuItemInput!) {" + + " addMenuItem(menuItem: $menuItem) {" + " id" + " name" + " price" + " }" + "}"; - java.util.Map variables = new java.util.HashMap<>(); - variables.put("name", "Trà Sữa"); - variables.put("price", 30000.0); + Map menuItemData = new HashMap<>(); + menuItemData.put("name", "Trà Sữa"); + menuItemData.put("price", 30000.0); - java.util.Map requestBody = new java.util.HashMap<>(); + Map variables = new HashMap<>(); + variables.put("menuItem", menuItemData); + + Map requestBody = new HashMap<>(); requestBody.put("query", mutation); requestBody.put("variables", variables); given() .contentType(ContentType.JSON) .header(InternalValue.role, Role.Manager) - .header(InternalValue.userId, lastOwnerId) // Thay "x-user-id" bằng InternalValue.userId của bạn + .header(InternalValue.userId, savedOwnerId) // Thay "x-user-id" bằng InternalValue.userId của bạn .body(requestBody) .when() .post("/graphql") @@ -158,26 +167,29 @@ public class EateryServiceTest { @Test public void testAddMenuItemFailInvalidRole() { String mutation = - "mutation addMenuItem($name: String!, $price: Float!) {" + - " addMenuItem(name: $name, price: $price) {" + + "mutation addMenuItem($menuItem: AddMenuItemInput!) {" + + " addMenuItem(menuItem: $menuItem) {" + " id" + " name" + " price" + " }" + "}"; - java.util.Map variables = new java.util.HashMap<>(); - variables.put("name", "Trà Sữa"); - variables.put("price", 30000.0); + Map menuItemData = new HashMap<>(); + menuItemData.put("name", "Trà Sữa"); + menuItemData.put("price", 30000.0); - java.util.Map requestBody = new java.util.HashMap<>(); + Map variables = new HashMap<>(); + variables.put("menuItem", menuItemData); + + Map requestBody = new HashMap<>(); requestBody.put("query", mutation); requestBody.put("variables", variables); given() .contentType(ContentType.JSON) .header(InternalValue.role, Role.Customer) - .header(InternalValue.userId, lastOwnerId) + .header(InternalValue.userId, savedOwnerId) .body(requestBody) .when() .post("/graphql") @@ -190,7 +202,7 @@ public class EateryServiceTest { String mutation = "mutation { addMenuItem(name: \"Coffee\", price: 20000.0) { id } }"; - java.util.Map requestBody = new java.util.HashMap<>(); + Map requestBody = new HashMap<>(); requestBody.put("query", mutation); given() @@ -216,10 +228,10 @@ public class EateryServiceTest { " }" + "}"; - java.util.Map variables = new java.util.HashMap<>(); - variables.put("id", lastSavedId.toString()); + Map variables = new HashMap<>(); + variables.put("id", savedEateryId.toString()); - java.util.Map requestBody = new java.util.HashMap<>(); + Map requestBody = new HashMap<>(); requestBody.put("query", query); requestBody.put("variables", variables); @@ -244,10 +256,10 @@ public class EateryServiceTest { " }" + "}"; - java.util.Map variables = new java.util.HashMap<>(); + Map variables = new HashMap<>(); variables.put("id", randomId); - java.util.Map requestBody = new java.util.HashMap<>(); + Map requestBody = new HashMap<>(); requestBody.put("query", query); requestBody.put("variables", variables); @@ -260,4 +272,69 @@ public class EateryServiceTest { .statusCode(200) .body("data.menuItemsByEatery", hasSize(0)); // Phải trả về List rỗng như code bạn viết } + + @Test + public void testUpdateMenuItem_Success() { + String mutation = """ + mutation updateMenuItem($menuItem: UpdateMenuItemInput!) { + updateMenuItem(menuItem: $menuItem) { + id + name + price + } + } + """; + + String newValue = "Phở Bò"; + + Map menuItemData = new HashMap<>(); + menuItemData.put("id", savedMenuItemId); + menuItemData.put("name", newValue); + + Map variables = new HashMap<>(); + variables.put("menuItem", menuItemData); + + Map requestBody = new HashMap<>(); + requestBody.put("query", mutation); + requestBody.put("variables", variables); + + given() + .contentType(ContentType.JSON) + .header(InternalValue.role, Role.Manager) + .header(InternalValue.userId, savedOwnerId) + .body(requestBody) + .when() + .post("/graphql") + .then() + .body("data.updateMenuItem.name", is(newValue)) + .body("data.updateMenuItem.id", is(savedMenuItemId.toString())) + .statusCode(200); + } + + @Test + public void testDeleteMenuItem_Success() { + String mutation = """ + mutation deleteItem($input: String!) { + deleteMenuItem(menuItemId: $input) + } + """; + + Map variables = new HashMap<>(); + variables.put("input", savedMenuItemId.toString()); + + Map requestBody = new HashMap<>(); + requestBody.put("query", mutation); + requestBody.put("variables", variables); + + given() + .contentType(ContentType.JSON) + .header(InternalValue.role, Role.Manager) + .header(InternalValue.userId, savedOwnerId) + .body(requestBody) + .when() + .post("/graphql") + .then() + .statusCode(200) + .body("data.deleteMenuItem", is(true)); + } } diff --git a/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java index 5ed751e..bdab888 100644 --- a/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java @@ -3,8 +3,8 @@ package com.drinkool.services; import static io.restassured.RestAssured.given; import static org.junit.jupiter.api.Assertions.*; -import com.drinkool.dtos.SendReview; import com.drinkool.entities.ReviewEntity; +import com.drinkool.lib.dtos.SendReview; import com.drinkool.lib.models.ReviewModel; import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; diff --git a/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java b/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java index 36efce8..1cb2e87 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/CustomerController.java @@ -1,7 +1,7 @@ package com.drinkool.controller; import com.drinkool.*; -import com.drinkool.dtos.*; +import com.drinkool.lib.dtos.*; import com.drinkool.services.CustomerService; import io.smallrye.mutiny.Uni; import jakarta.inject.Inject; diff --git a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java index d54173e..2da0157 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java @@ -1,7 +1,8 @@ package com.drinkool.controller; import com.drinkool.InternalValue; -import com.drinkool.dtos.GraphqlDto; +import com.drinkool.lib.dtos.GraphqlDto; + import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient; import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClientBuilder; import jakarta.inject.Inject; diff --git a/gateway-service/src/main/java/com/drinkool/controller/IndexController.java b/gateway-service/src/main/java/com/drinkool/controller/IndexController.java index a212dfd..7e3d1b9 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/IndexController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/IndexController.java @@ -1,7 +1,7 @@ package com.drinkool.controller; import com.drinkool.Url; -import com.drinkool.dtos.SmsOtp; +import com.drinkool.lib.dtos.SmsOtp; import com.drinkool.services.BaseService; import io.smallrye.mutiny.Uni; import jakarta.inject.Inject; diff --git a/gateway-service/src/main/java/com/drinkool/controller/MainController.java b/gateway-service/src/main/java/com/drinkool/controller/MainController.java index f739339..7f378df 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/MainController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/MainController.java @@ -1,7 +1,7 @@ package com.drinkool.controller; import com.drinkool.Url; -import com.drinkool.dtos.Login; +import com.drinkool.lib.dtos.Login; import com.drinkool.services.CustomerService; import com.drinkool.services.ManagerService; import io.smallrye.mutiny.Uni; diff --git a/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java b/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java index 8b126f2..c95b504 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/ManagerController.java @@ -1,7 +1,7 @@ package com.drinkool.controller; import com.drinkool.*; -import com.drinkool.dtos.*; +import com.drinkool.lib.dtos.*; import com.drinkool.services.ManagerService; import io.smallrye.mutiny.Uni; import jakarta.inject.Inject; diff --git a/gateway-service/src/main/java/com/drinkool/services/BaseService.java b/gateway-service/src/main/java/com/drinkool/services/BaseService.java index 48a87a5..a07bc1d 100644 --- a/gateway-service/src/main/java/com/drinkool/services/BaseService.java +++ b/gateway-service/src/main/java/com/drinkool/services/BaseService.java @@ -1,7 +1,8 @@ package com.drinkool.services; import com.drinkool.Url; -import com.drinkool.dtos.SmsOtp; +import com.drinkool.lib.dtos.SmsOtp; + import io.smallrye.mutiny.Uni; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; diff --git a/gateway-service/src/main/java/com/drinkool/services/CustomerService.java b/gateway-service/src/main/java/com/drinkool/services/CustomerService.java index 5660e19..f6799a7 100644 --- a/gateway-service/src/main/java/com/drinkool/services/CustomerService.java +++ b/gateway-service/src/main/java/com/drinkool/services/CustomerService.java @@ -3,7 +3,8 @@ package com.drinkool.services; import com.drinkool.InternalValue; import com.drinkool.Role; import com.drinkool.Url; -import com.drinkool.dtos.*; +import com.drinkool.lib.dtos.*; + import io.smallrye.mutiny.Uni; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; diff --git a/gateway-service/src/main/java/com/drinkool/services/ManagerService.java b/gateway-service/src/main/java/com/drinkool/services/ManagerService.java index bae3afd..e0edfb3 100644 --- a/gateway-service/src/main/java/com/drinkool/services/ManagerService.java +++ b/gateway-service/src/main/java/com/drinkool/services/ManagerService.java @@ -3,7 +3,8 @@ package com.drinkool.services; import com.drinkool.InternalValue; import com.drinkool.Role; import com.drinkool.Url; -import com.drinkool.dtos.*; +import com.drinkool.lib.dtos.*; + import io.smallrye.mutiny.Uni; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; diff --git a/lib/pom.xml b/lib/pom.xml index a92793a..26901c6 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -41,7 +41,7 @@ org.projectlombok lombok - 1.18.30 + 1.18.46 provided @@ -62,5 +62,9 @@ 5.10.0 test + + io.quarkus + quarkus-smallrye-graphql + diff --git a/lib/src/main/java/com/drinkool/interfaces/EateryInterface.java b/lib/src/main/java/com/drinkool/interfaces/EateryInterface.java new file mode 100644 index 0000000..2afd36a --- /dev/null +++ b/lib/src/main/java/com/drinkool/interfaces/EateryInterface.java @@ -0,0 +1,12 @@ +package com.drinkool.interfaces; + +import java.util.UUID; + +public interface EateryInterface { + UUID getOwnerId(); + void setOwnerId(UUID x); + String getName(); + void setName(String x); + boolean getIsVerified(); + void setIsVerified(boolean x); +} diff --git a/lib/src/main/java/com/drinkool/interfaces/EntityInterface.java b/lib/src/main/java/com/drinkool/interfaces/EntityInterface.java new file mode 100644 index 0000000..89f517f --- /dev/null +++ b/lib/src/main/java/com/drinkool/interfaces/EntityInterface.java @@ -0,0 +1,8 @@ +package com.drinkool.interfaces; + +import java.util.UUID; + +public interface EntityInterface { + UUID getId(); + void setId(UUID x); +} diff --git a/lib/src/main/java/com/drinkool/interfaces/MenuItemInterface.java b/lib/src/main/java/com/drinkool/interfaces/MenuItemInterface.java new file mode 100644 index 0000000..74aaabd --- /dev/null +++ b/lib/src/main/java/com/drinkool/interfaces/MenuItemInterface.java @@ -0,0 +1,8 @@ +package com.drinkool.interfaces; + +public interface MenuItemInterface { + String getName(); + void setName(String x); + Double getPrice(); + void setPrice(Double x); +} diff --git a/lib/src/main/java/com/drinkool/dtos/AddInventory.java b/lib/src/main/java/com/drinkool/lib/dtos/AddInventory.java similarity index 70% rename from lib/src/main/java/com/drinkool/dtos/AddInventory.java rename to lib/src/main/java/com/drinkool/lib/dtos/AddInventory.java index 7c2a1f8..374742a 100644 --- a/lib/src/main/java/com/drinkool/dtos/AddInventory.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/AddInventory.java @@ -1,4 +1,4 @@ -package com.drinkool.dtos; +package com.drinkool.lib.dtos; public class AddInventory { diff --git a/lib/src/main/java/com/drinkool/dtos/GraphqlDto.java b/lib/src/main/java/com/drinkool/lib/dtos/GraphqlDto.java similarity index 76% rename from lib/src/main/java/com/drinkool/dtos/GraphqlDto.java rename to lib/src/main/java/com/drinkool/lib/dtos/GraphqlDto.java index a358ed0..309d3f2 100644 --- a/lib/src/main/java/com/drinkool/dtos/GraphqlDto.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/GraphqlDto.java @@ -1,4 +1,4 @@ -package com.drinkool.dtos; +package com.drinkool.lib.dtos; public class GraphqlDto { diff --git a/lib/src/main/java/com/drinkool/dtos/Login.java b/lib/src/main/java/com/drinkool/lib/dtos/Login.java similarity index 69% rename from lib/src/main/java/com/drinkool/dtos/Login.java rename to lib/src/main/java/com/drinkool/lib/dtos/Login.java index af5ca86..e87f3d8 100644 --- a/lib/src/main/java/com/drinkool/dtos/Login.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/Login.java @@ -1,4 +1,4 @@ -package com.drinkool.dtos; +package com.drinkool.lib.dtos; public class Login { diff --git a/lib/src/main/java/com/drinkool/dtos/ManagerSignup.java b/lib/src/main/java/com/drinkool/lib/dtos/ManagerSignup.java similarity index 70% rename from lib/src/main/java/com/drinkool/dtos/ManagerSignup.java rename to lib/src/main/java/com/drinkool/lib/dtos/ManagerSignup.java index 8857f0e..89db905 100644 --- a/lib/src/main/java/com/drinkool/dtos/ManagerSignup.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/ManagerSignup.java @@ -1,4 +1,4 @@ -package com.drinkool.dtos; +package com.drinkool.lib.dtos; public class ManagerSignup extends Signup { diff --git a/lib/src/main/java/com/drinkool/dtos/QuickLogin.java b/lib/src/main/java/com/drinkool/lib/dtos/QuickLogin.java similarity index 69% rename from lib/src/main/java/com/drinkool/dtos/QuickLogin.java rename to lib/src/main/java/com/drinkool/lib/dtos/QuickLogin.java index 6e4c3f8..adbb06b 100644 --- a/lib/src/main/java/com/drinkool/dtos/QuickLogin.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/QuickLogin.java @@ -1,4 +1,4 @@ -package com.drinkool.dtos; +package com.drinkool.lib.dtos; public class QuickLogin { diff --git a/lib/src/main/java/com/drinkool/dtos/QuickSignup.java b/lib/src/main/java/com/drinkool/lib/dtos/QuickSignup.java similarity index 63% rename from lib/src/main/java/com/drinkool/dtos/QuickSignup.java rename to lib/src/main/java/com/drinkool/lib/dtos/QuickSignup.java index aedb13d..3844736 100644 --- a/lib/src/main/java/com/drinkool/dtos/QuickSignup.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/QuickSignup.java @@ -1,4 +1,4 @@ -package com.drinkool.dtos; +package com.drinkool.lib.dtos; public class QuickSignup { diff --git a/lib/src/main/java/com/drinkool/dtos/SendReview.java b/lib/src/main/java/com/drinkool/lib/dtos/SendReview.java similarity index 84% rename from lib/src/main/java/com/drinkool/dtos/SendReview.java rename to lib/src/main/java/com/drinkool/lib/dtos/SendReview.java index c0fb899..2793753 100644 --- a/lib/src/main/java/com/drinkool/dtos/SendReview.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/SendReview.java @@ -1,4 +1,4 @@ -package com.drinkool.dtos; +package com.drinkool.lib.dtos; import com.drinkool.lib.models.ReviewModel; import java.util.UUID; diff --git a/lib/src/main/java/com/drinkool/dtos/Signup.java b/lib/src/main/java/com/drinkool/lib/dtos/Signup.java similarity index 75% rename from lib/src/main/java/com/drinkool/dtos/Signup.java rename to lib/src/main/java/com/drinkool/lib/dtos/Signup.java index d63b990..0db754a 100644 --- a/lib/src/main/java/com/drinkool/dtos/Signup.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/Signup.java @@ -1,4 +1,4 @@ -package com.drinkool.dtos; +package com.drinkool.lib.dtos; public class Signup { diff --git a/lib/src/main/java/com/drinkool/dtos/SmsOtp.java b/lib/src/main/java/com/drinkool/lib/dtos/SmsOtp.java similarity index 60% rename from lib/src/main/java/com/drinkool/dtos/SmsOtp.java rename to lib/src/main/java/com/drinkool/lib/dtos/SmsOtp.java index a7ff340..482733e 100644 --- a/lib/src/main/java/com/drinkool/dtos/SmsOtp.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/SmsOtp.java @@ -1,4 +1,4 @@ -package com.drinkool.dtos; +package com.drinkool.lib.dtos; public class SmsOtp { diff --git a/lib/src/main/java/com/drinkool/dtos/event/ManagerCreate.java b/lib/src/main/java/com/drinkool/lib/dtos/event/ManagerCreate.java similarity index 88% rename from lib/src/main/java/com/drinkool/dtos/event/ManagerCreate.java rename to lib/src/main/java/com/drinkool/lib/dtos/event/ManagerCreate.java index e337a6f..ef06c68 100644 --- a/lib/src/main/java/com/drinkool/dtos/event/ManagerCreate.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/event/ManagerCreate.java @@ -1,4 +1,4 @@ -package com.drinkool.dtos.event; +package com.drinkool.lib.dtos.event; import io.quarkus.runtime.annotations.RegisterForReflection; import java.util.UUID; diff --git a/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java b/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java index 0ee8e50..0a33368 100644 --- a/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java +++ b/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java @@ -1,13 +1,15 @@ package com.drinkool.lib.entities; import io.quarkus.hibernate.orm.panache.PanacheEntityBase; -import jakarta.persistence.*; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.MappedSuperclass; import java.util.UUID; @MappedSuperclass public class BaseEntity extends PanacheEntityBase { - @Id + @jakarta.persistence.Id @GeneratedValue(strategy = GenerationType.UUID) public UUID id; } diff --git a/scripts/test.sh b/scripts/test.sh index 3b7a38f..f7040bf 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -1 +1,33 @@ -mvn clean package -Dquarkus.container-image.push=false -Dquarkus.container-image.build=false \ No newline at end of file +#!/bin/bash + +# Khởi tạo giá trị mặc định +DEBUG_FLAG="" +TEST_FLAG="" + +# Duyệt qua các tham số đầu vào +for arg in "$@"; do + case $arg in + --debug) + DEBUG_FLAG="-Dmaven.surefire.debug" + shift # Bỏ qua flag này + ;; + --test=*) + # Lấy giá trị sau dấu = + TEST_NAME="${arg#*=}" + TEST_FLAG="-Dtest=$TEST_NAME" + shift + ;; + *) + # Các tham số không xác định (nếu cần xử lý thêm) + ;; + esac +done + +echo "Running: mvn clean package $DEBUG_FLAG $TEST_FLAG" + +# Chạy lệnh Maven +mvn clean package \ + -Dquarkus.container-image.push=false \ + -Dquarkus.container-image.build=false \ + $DEBUG_FLAG \ + $TEST_FLAG \ No newline at end of file From d104f8b2107bfc0d648602b6c39e7894ffecb0f5 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Wed, 6 May 2026 15:25:01 +0000 Subject: [PATCH 32/51] chore: release [ci skip] --- .vscode/launch.json | 28 +++++++++---------- .vscode/settings.json | 24 ++++++++-------- CHANGELOG.md | 7 +++++ account-service/pom.xml | 2 +- .../drinkool/services/CustomerService.java | 1 - .../com/drinkool/services/ManagerService.java | 1 - .../drinkool/services/AccountServiceTest.java | 1 - .../drinkool/services/BaseServiceTest.java | 1 - .../services/CustomerServiceTest.java | 1 - .../drinkool/services/ManagerServiceTest.java | 1 - eatery-service/pom.xml | 2 +- .../com/drinkool/services/ReviewService.java | 1 - gateway-service/pom.xml | 2 +- .../drinkool/controller/EateryController.java | 1 - .../com/drinkool/services/BaseService.java | 1 - .../drinkool/services/CustomerService.java | 1 - .../com/drinkool/services/ManagerService.java | 1 - k8s/base/account.yaml | 2 +- k8s/base/eatery.yaml | 2 +- k8s/base/gateway.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 22 files changed, 41 insertions(+), 45 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index f37ad13..1d6b29f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,15 +1,15 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "java", - "name": "Attach to Quarkus", - "request": "attach", - "hostName": "localhost", - "port": 5005 - } - ] -} \ No newline at end of file + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "java", + "name": "Attach to Quarkus", + "request": "attach", + "hostName": "localhost", + "port": 5005 + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 11c8332..20d9826 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,13 +1,13 @@ { - "files.exclude": { - "**/.git": true, - "**/.svn": true, - "**/.hg": true, - "**/.DS_Store": true, - "**/Thumbs.db": true, - "**/target": true, - "**/docker": true, - "node_modules": true - }, - "explorerExclude.backup": {} -} \ No newline at end of file + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/.DS_Store": true, + "**/Thumbs.db": true, + "**/target": true, + "**/docker": true, + "node_modules": true + }, + "explorerExclude.backup": {} +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 39b4aab..fe04fbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.20](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.19...v1.5.20) (2026-05-06) + + +### Bug Fixes + +* menu items CRUD ([#44](https://git.demonkernel.io.vn/FoodSurf/backend/issues/44)) ([43600fc](https://git.demonkernel.io.vn/FoodSurf/backend/commit/43600fc8cfa2cd93e1d33ee855a2934a49f8d663)) + ## [1.5.19](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.18...v1.5.19) (2026-05-05) diff --git a/account-service/pom.xml b/account-service/pom.xml index 9abcea1..8ab8059 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.19 + 1.5.20 ../pom.xml diff --git a/account-service/src/main/java/com/drinkool/services/CustomerService.java b/account-service/src/main/java/com/drinkool/services/CustomerService.java index 816925f..ee9f58d 100644 --- a/account-service/src/main/java/com/drinkool/services/CustomerService.java +++ b/account-service/src/main/java/com/drinkool/services/CustomerService.java @@ -3,7 +3,6 @@ package com.drinkool.services; import com.drinkool.*; import com.drinkool.entities.CustomerEntity; import com.drinkool.lib.dtos.*; - import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.*; diff --git a/account-service/src/main/java/com/drinkool/services/ManagerService.java b/account-service/src/main/java/com/drinkool/services/ManagerService.java index f78552e..5e76b17 100644 --- a/account-service/src/main/java/com/drinkool/services/ManagerService.java +++ b/account-service/src/main/java/com/drinkool/services/ManagerService.java @@ -4,7 +4,6 @@ import com.drinkool.*; import com.drinkool.entities.ManagerEntity; import com.drinkool.lib.dtos.*; import com.drinkool.lib.dtos.event.ManagerCreate; - import jakarta.enterprise.context.ApplicationScoped; import jakarta.transaction.Transactional; import jakarta.ws.rs.*; diff --git a/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java b/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java index 0688cd2..2ff15c6 100644 --- a/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/AccountServiceTest.java @@ -4,7 +4,6 @@ import static io.restassured.RestAssured.*; import com.drinkool.*; import com.drinkool.lib.dtos.*; - import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import org.junit.jupiter.api.Test; diff --git a/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java b/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java index c925bd4..db28019 100644 --- a/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/BaseServiceTest.java @@ -5,7 +5,6 @@ import static org.hamcrest.CoreMatchers.*; import com.drinkool.*; import com.drinkool.lib.dtos.*; - import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import org.junit.jupiter.api.Test; diff --git a/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java b/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java index 5a429f6..d22bfaa 100644 --- a/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/CustomerServiceTest.java @@ -6,7 +6,6 @@ import static org.junit.jupiter.api.Assertions.*; import com.drinkool.*; import com.drinkool.entities.CustomerEntity; import com.drinkool.lib.dtos.*; - import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; import jakarta.inject.Inject; diff --git a/account-service/src/test/java/com/drinkool/services/ManagerServiceTest.java b/account-service/src/test/java/com/drinkool/services/ManagerServiceTest.java index 4d72a95..f73700a 100644 --- a/account-service/src/test/java/com/drinkool/services/ManagerServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/ManagerServiceTest.java @@ -5,7 +5,6 @@ import static org.junit.jupiter.api.Assertions.*; import com.drinkool.*; import com.drinkool.lib.dtos.*; - import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.kafka.*; diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 334b2e6..dd4a2d1 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.19 + 1.5.20 ../pom.xml diff --git a/eatery-service/src/main/java/com/drinkool/services/ReviewService.java b/eatery-service/src/main/java/com/drinkool/services/ReviewService.java index 0b9a5ca..555ba74 100644 --- a/eatery-service/src/main/java/com/drinkool/services/ReviewService.java +++ b/eatery-service/src/main/java/com/drinkool/services/ReviewService.java @@ -2,7 +2,6 @@ package com.drinkool.services; import com.drinkool.entities.ReviewEntity; import com.drinkool.lib.dtos.SendReview; - import jakarta.transaction.Transactional; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 3b79a69..8ee6cf9 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.19 + 1.5.20 ../pom.xml diff --git a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java index 2da0157..8d7971a 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java @@ -2,7 +2,6 @@ package com.drinkool.controller; import com.drinkool.InternalValue; import com.drinkool.lib.dtos.GraphqlDto; - import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient; import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClientBuilder; import jakarta.inject.Inject; diff --git a/gateway-service/src/main/java/com/drinkool/services/BaseService.java b/gateway-service/src/main/java/com/drinkool/services/BaseService.java index a07bc1d..a78e90f 100644 --- a/gateway-service/src/main/java/com/drinkool/services/BaseService.java +++ b/gateway-service/src/main/java/com/drinkool/services/BaseService.java @@ -2,7 +2,6 @@ package com.drinkool.services; import com.drinkool.Url; import com.drinkool.lib.dtos.SmsOtp; - import io.smallrye.mutiny.Uni; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; diff --git a/gateway-service/src/main/java/com/drinkool/services/CustomerService.java b/gateway-service/src/main/java/com/drinkool/services/CustomerService.java index f6799a7..d1a3c4a 100644 --- a/gateway-service/src/main/java/com/drinkool/services/CustomerService.java +++ b/gateway-service/src/main/java/com/drinkool/services/CustomerService.java @@ -4,7 +4,6 @@ import com.drinkool.InternalValue; import com.drinkool.Role; import com.drinkool.Url; import com.drinkool.lib.dtos.*; - import io.smallrye.mutiny.Uni; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; diff --git a/gateway-service/src/main/java/com/drinkool/services/ManagerService.java b/gateway-service/src/main/java/com/drinkool/services/ManagerService.java index e0edfb3..1ec3216 100644 --- a/gateway-service/src/main/java/com/drinkool/services/ManagerService.java +++ b/gateway-service/src/main/java/com/drinkool/services/ManagerService.java @@ -4,7 +4,6 @@ import com.drinkool.InternalValue; import com.drinkool.Role; import com.drinkool.Url; import com.drinkool.lib.dtos.*; - import io.smallrye.mutiny.Uni; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; diff --git a/k8s/base/account.yaml b/k8s/base/account.yaml index b2c41ea..e98f9fa 100644 --- a/k8s/base/account.yaml +++ b/k8s/base/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.19 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.20 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/eatery.yaml b/k8s/base/eatery.yaml index 2d06b77..6f272fb 100644 --- a/k8s/base/eatery.yaml +++ b/k8s/base/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.19 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.20 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/gateway.yaml b/k8s/base/gateway.yaml index 910251b..3428d6f 100644 --- a/k8s/base/gateway.yaml +++ b/k8s/base/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.19 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.20 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index 26901c6..bc83c1a 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.19 + 1.5.20 ../pom.xml diff --git a/pom.xml b/pom.xml index f79cbd9..68b2ad8 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.19 + 1.5.20 pom 25 From e610111e667fa17b38095fd5e156ecd6b1c16604 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Thu, 7 May 2026 03:37:59 +0000 Subject: [PATCH 33/51] fix: add send review and get reviews (#45) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/45 --- .../java/com/drinkool/dtos/DtoMapper.java | 4 + .../com/drinkool/entities/ReviewEntity.java | 37 ++++--- .../com/drinkool/services/ReviewService.java | 67 +++++++++++-- .../drinkool/entities/ReviewEntityTest.java | 26 +++-- .../drinkool/services/ReviewServiceTest.java | 96 ++++++++++++++++--- .../drinkool/controller/EateryController.java | 30 ++++++ .../com/drinkool/services/ReviewService.java | 30 ++++++ .../src/main/resources/application.properties | 1 + lib/pom.xml | 47 +++++++-- lib/src/main/java/com/drinkool/Url.java | 1 + .../main/java/com/drinkool/enums/SortBy.java | 8 ++ .../drinkool/interfaces/ReviewInterface.java | 17 ++++ .../com/drinkool/lib/dtos/SendReview.java | 25 ++++- .../com/drinkool/lib/entities/BaseEntity.java | 9 ++ .../com/drinkool/lib/models/ReviewModel.java | 30 ------ 15 files changed, 331 insertions(+), 97 deletions(-) create mode 100644 gateway-service/src/main/java/com/drinkool/services/ReviewService.java create mode 100644 lib/src/main/java/com/drinkool/enums/SortBy.java create mode 100644 lib/src/main/java/com/drinkool/interfaces/ReviewInterface.java delete mode 100644 lib/src/main/java/com/drinkool/lib/models/ReviewModel.java diff --git a/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java b/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java index ea734ed..659bec5 100644 --- a/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java +++ b/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java @@ -1,6 +1,8 @@ package com.drinkool.dtos; import com.drinkool.entities.MenuItemEntity; +import com.drinkool.entities.ReviewEntity; +import com.drinkool.lib.dtos.SendReview; import org.mapstruct.BeanMapping; import org.mapstruct.Mapper; import org.mapstruct.MappingTarget; @@ -15,4 +17,6 @@ public interface DtoMapper { UpdateMenuItem input, @MappingTarget MenuItemEntity entity ); + + ReviewEntity toReviewEntity(SendReview source); } diff --git a/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java b/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java index 4477958..d563242 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/ReviewEntity.java @@ -1,35 +1,34 @@ package com.drinkool.entities; -import com.drinkool.lib.models.ReviewModel; +import com.drinkool.interfaces.ReviewInterface; +import com.drinkool.lib.entities.BaseEntity; import jakarta.persistence.*; -import jakarta.transaction.Transactional; import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; @Entity +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor @Table(name = "reviews") -public class ReviewEntity extends ReviewModel { +public class ReviewEntity extends BaseEntity implements ReviewInterface { public UUID reviewerId; public UUID eateryId; - private ReviewEntity(ReviewModel input) { - super(input); - } + public Integer rating; - @Transactional - public static ReviewEntity create( - UUID reviewerId, - UUID eateryId, - ReviewModel reviewInput - ) { - ReviewEntity review = new ReviewEntity(reviewInput); + public String comment; - review.reviewerId = reviewerId; - review.eateryId = eateryId; - - review.persist(); - - return review; + public void setRating(Integer score) { + if (score < 1 || score > 5) { + throw new IllegalArgumentException("InvalidRatingValue"); + } + this.rating = score; } } diff --git a/eatery-service/src/main/java/com/drinkool/services/ReviewService.java b/eatery-service/src/main/java/com/drinkool/services/ReviewService.java index 555ba74..397da26 100644 --- a/eatery-service/src/main/java/com/drinkool/services/ReviewService.java +++ b/eatery-service/src/main/java/com/drinkool/services/ReviewService.java @@ -1,20 +1,71 @@ package com.drinkool.services; +import com.drinkool.InternalValue; +import com.drinkool.Role; +import com.drinkool.Url; +import com.drinkool.dtos.DtoMapper; import com.drinkool.entities.ReviewEntity; +import com.drinkool.enums.SortBy; import com.drinkool.lib.dtos.SendReview; +import io.quarkus.panache.common.Sort; +import io.vertx.core.http.HttpServerRequest; +import jakarta.annotation.security.RolesAllowed; +import jakarta.inject.Inject; import jakarta.transaction.Transactional; -import jakarta.ws.rs.*; +import jakarta.ws.rs.DefaultValue; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.Response; +import java.util.UUID; -@Path("/api/review") +@Path(Url.Review) public class ReviewService { - @POST - @Path("/create") - @Transactional - public Response create(SendReview input) { - ReviewEntity.create(input.reviewerId, input.orderId, input.review); + @Inject + HttpServerRequest request; - return Response.status(201).build(); + @Inject + DtoMapper dtoMapper; + + @GET + @Transactional + @Path("/{eateryId}") + public Response getReviewsByEatery( + @PathParam("eateryId") UUID eateryId, + @QueryParam("sort") @DefaultValue("LATEST") SortBy sortBy + ) { + Sort sort = switch (sortBy) { + case LATEST -> Sort.descending("createDate"); + case OLDEST -> Sort.ascending("createDate"); + case HIGHEST -> Sort.descending("rating"); + case LOWEST -> Sort.ascending("rating"); + }; + + return Response.ok() + .entity(ReviewEntity.find("eateryId = ?1", sort, eateryId).list()) + .build(); + } + + @POST + @RolesAllowed(Role.Customer) + @Transactional + public Response receiveReview(SendReview input) { + UUID reviewerId = UUID.fromString(request.getHeader(InternalValue.userId)); + + try { + ReviewEntity entity = dtoMapper.toReviewEntity(input); + entity.setReviewerId(reviewerId); + + entity.persist(); + + return Response.status(Response.Status.CREATED).build(); + } catch (Exception e) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(e.getMessage()) + .build(); + } } } diff --git a/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java index 9dedee1..cf83d28 100644 --- a/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java +++ b/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java @@ -1,32 +1,34 @@ package com.drinkool.entities; -import com.drinkool.lib.models.ReviewModel; import io.quarkus.test.junit.QuarkusTest; import jakarta.transaction.Transactional; import java.util.UUID; +import net.datafaker.Faker; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @QuarkusTest public class ReviewEntityTest { + private final Faker faker = new Faker(); + @Test @Transactional public void testCreateReview() { - // 1. Chuẩn bị dữ liệu (Arrange) UUID testReviewerId = UUID.randomUUID(); UUID testEateryId = UUID.randomUUID(); + String comment = faker.famousLastWords().lastWords(); + int rating = faker.random().nextInt(1, 5); - // Truyền trực tiếp rating và comment vào constructor của ReviewModel - ReviewModel inputModel = new ReviewModel(5, "Món ăn tuyệt vời!"); - - // 2. Thực thi (Act) - ReviewEntity savedReview = ReviewEntity.create( + ReviewEntity savedReview = new ReviewEntity( testReviewerId, testEateryId, - inputModel + rating, + comment ); + savedReview.persist(); + // 3. Kiểm chứng (Assert) Assertions.assertNotNull( savedReview, @@ -42,12 +44,8 @@ public class ReviewEntityTest { savedReview.eateryId, "Eatery ID không khớp" ); - Assertions.assertEquals(5, savedReview.rating, "Rating không khớp"); - Assertions.assertEquals( - "Món ăn tuyệt vời!", - savedReview.comment, - "Comment không khớp" - ); + Assertions.assertEquals(rating, savedReview.rating, "Rating không khớp"); + Assertions.assertEquals(comment, savedReview.comment, "Comment không khớp"); Assertions.assertNotNull( savedReview.id, diff --git a/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java index bdab888..ae893f9 100644 --- a/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java @@ -1,43 +1,109 @@ package com.drinkool.services; import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.is; import static org.junit.jupiter.api.Assertions.*; +import com.drinkool.InternalValue; +import com.drinkool.Role; +import com.drinkool.Url; +import com.drinkool.entities.EateryEntity; +import com.drinkool.entities.MenuItemEntity; import com.drinkool.entities.ReviewEntity; import com.drinkool.lib.dtos.SendReview; -import com.drinkool.lib.models.ReviewModel; import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; -import java.util.Random; +import jakarta.transaction.Transactional; +import jakarta.ws.rs.core.Response; import java.util.UUID; +import net.datafaker.Faker; import org.junit.jupiter.api.*; @QuarkusTest public class ReviewServiceTest { + private final Faker faker = new Faker(); + + private UUID savedEateryId; + private String savedEateryName; + private UUID savedOwnerId = UUID.randomUUID(); + + @BeforeEach + @Transactional + void setup() { + ReviewEntity.deleteAll(); + MenuItemEntity.deleteAll(); + EateryEntity.deleteAll(); + + savedEateryName = faker.restaurant().name(); + + EateryEntity eatery = new EateryEntity(); + eatery = eatery.create(savedOwnerId, savedEateryName); + savedEateryId = eatery.id; + + for (int i = 0; i < 3; i++) { + ReviewEntity entity = new ReviewEntity( + UUID.randomUUID(), + savedEateryId, + faker.random().nextInt(1, 5), + faker.famousLastWords().lastWords() + ); + + entity.persist(); + } + } + @Test - void receiveReview() { - Random random = new Random(); - + void receiveReview_Success() { UUID reviewerId = UUID.randomUUID(); - UUID orderId = UUID.randomUUID(); - String comment = UUID.randomUUID().toString(); - int rating = random.nextInt(); + UUID eateryId = UUID.randomUUID(); + String comment = faker.famousLastWords().lastWords(); + int rating = faker.random().nextInt(1, 5); - SendReview input = new SendReview(); - input.reviewerId = reviewerId; - input.orderId = orderId; - ReviewModel reviewModel = new ReviewModel(rating, comment); - input.review = reviewModel; + SendReview input = new SendReview(reviewerId, eateryId, rating, comment); given() + .header(InternalValue.role, Role.Customer) + .header(InternalValue.userId, reviewerId) .contentType(ContentType.JSON) .body(input) .when() - .post("/api/review/create") + .post(Url.Review) .then() - .statusCode(201); + .statusCode(Response.Status.CREATED.getStatusCode()); assertEquals(1, ReviewEntity.find("reviewerId", reviewerId).count()); } + + @Test + void receiveReview_FailedDueToInvalidRating() { + UUID reviewerId = UUID.randomUUID(); + UUID eateryId = UUID.randomUUID(); + String comment = faker.famousLastWords().lastWords(); + int rating = faker.random().nextInt(6, 10); + + SendReview input = new SendReview(reviewerId, eateryId, rating, comment); + + given() + .header(InternalValue.role, Role.Customer) + .header(InternalValue.userId, UUID.randomUUID()) + .contentType(ContentType.JSON) + .body(input) + .when() + .post(Url.Review) + .then() + .contentType(ContentType.TEXT) + .body(is("InvalidRatingValue")) + .statusCode(Response.Status.BAD_REQUEST.getStatusCode()); + } + + @Test + public void testGetReviews_DefaultLatest() { + given() + .when() + .get(Url.Review + '/' + savedEateryId.toString()) + .then() + .statusCode(Response.Status.OK.getStatusCode()) + .contentType(ContentType.JSON); + } } diff --git a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java index 8d7971a..a708b4e 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java @@ -1,18 +1,29 @@ package com.drinkool.controller; import com.drinkool.InternalValue; +import com.drinkool.Url; +import com.drinkool.enums.SortBy; import com.drinkool.lib.dtos.GraphqlDto; +import com.drinkool.lib.dtos.SendReview; +import com.drinkool.services.ReviewService; import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient; import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClientBuilder; +import io.smallrye.mutiny.Uni; import jakarta.inject.Inject; import jakarta.json.bind.Jsonb; +import jakarta.ws.rs.DefaultValue; +import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; +import java.util.UUID; import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.rest.client.inject.RestClient; @Path("/api/eatery") public class EateryController { @@ -23,6 +34,25 @@ public class EateryController { @Inject Jsonb jsonb; + @Inject + @RestClient + ReviewService reviewService; + + @GET + @Path(Url.Review + "/{eateryId}") + Uni getReviewsByEatery( + @PathParam("eateryId") UUID eateryId, + @QueryParam("sort") @DefaultValue("LATEST") SortBy sortBy + ) { + return reviewService.getReviewsByEatery(eateryId, sortBy); + } + + @POST + @Path(Url.Review) + Uni receiveReview(SendReview input) { + return reviewService.receiveReview(input); + } + @POST @Path("/graphql") public Response forward( diff --git a/gateway-service/src/main/java/com/drinkool/services/ReviewService.java b/gateway-service/src/main/java/com/drinkool/services/ReviewService.java new file mode 100644 index 0000000..42311bc --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/services/ReviewService.java @@ -0,0 +1,30 @@ +package com.drinkool.services; + +import com.drinkool.Url; +import com.drinkool.enums.SortBy; +import com.drinkool.lib.dtos.SendReview; + +import io.smallrye.mutiny.Uni; +import jakarta.ws.rs.DefaultValue; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.Response; +import java.util.UUID; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@RegisterRestClient(configKey = "eatery") +@Path(Url.Review) +public interface ReviewService { + @GET + @Path("/{eateryId}") + public Uni getReviewsByEatery( + @PathParam("eateryId") UUID eateryId, + @QueryParam("sort") @DefaultValue("LATEST") SortBy sortBy + ); + + @POST + public Uni receiveReview(SendReview input); +} diff --git a/gateway-service/src/main/resources/application.properties b/gateway-service/src/main/resources/application.properties index ec3257a..e919d67 100644 --- a/gateway-service/src/main/resources/application.properties +++ b/gateway-service/src/main/resources/application.properties @@ -14,6 +14,7 @@ quarkus.native.additional-build-args=--future-defaults=all # Rest Client quarkus.rest-client.account.url=http://account-service +quarkus.rest-client.eatery.url=http://eatery-service # GraphQL Client quarkus.smallrye-graphql-client.eatery.url=http://eatery-service/graphql \ No newline at end of file diff --git a/lib/pom.xml b/lib/pom.xml index bc83c1a..a1a0976 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -1,8 +1,8 @@ - + 4.0.0 @@ -18,6 +18,7 @@ 25 25 UTF-8 + 1.18.46 @@ -41,7 +42,7 @@ org.projectlombok lombok - 1.18.46 + ${org.projectlombok.version} provided @@ -67,4 +68,38 @@ quarkus-smallrye-graphql - + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + true + + + org.projectlombok + lombok + ${org.projectlombok.version} + + + + + + + io.smallrye + jandex-maven-plugin + 3.2.7 + + + make-index + + jandex + + + + + + + \ No newline at end of file diff --git a/lib/src/main/java/com/drinkool/Url.java b/lib/src/main/java/com/drinkool/Url.java index e547d3c..6e30f67 100644 --- a/lib/src/main/java/com/drinkool/Url.java +++ b/lib/src/main/java/com/drinkool/Url.java @@ -9,4 +9,5 @@ public class Url { public static final String SmsOtp = "/sms_otp"; public static final String Me = "/me"; public static final String Logout = "/logout"; + public static final String Review = "/review"; } diff --git a/lib/src/main/java/com/drinkool/enums/SortBy.java b/lib/src/main/java/com/drinkool/enums/SortBy.java new file mode 100644 index 0000000..1b34848 --- /dev/null +++ b/lib/src/main/java/com/drinkool/enums/SortBy.java @@ -0,0 +1,8 @@ +package com.drinkool.enums; + +public enum SortBy { + LATEST, + OLDEST, + HIGHEST, + LOWEST, +} diff --git a/lib/src/main/java/com/drinkool/interfaces/ReviewInterface.java b/lib/src/main/java/com/drinkool/interfaces/ReviewInterface.java new file mode 100644 index 0000000..8a006df --- /dev/null +++ b/lib/src/main/java/com/drinkool/interfaces/ReviewInterface.java @@ -0,0 +1,17 @@ +package com.drinkool.interfaces; + +import java.util.UUID; + +public interface ReviewInterface { + UUID getReviewerId(); + void setReviewerId(UUID x); + + UUID getEateryId(); + void setEateryId(UUID x); + + Integer getRating(); + void setRating(Integer x); + + String getComment(); + void setComment(String x); +} diff --git a/lib/src/main/java/com/drinkool/lib/dtos/SendReview.java b/lib/src/main/java/com/drinkool/lib/dtos/SendReview.java index 2793753..950aa58 100644 --- a/lib/src/main/java/com/drinkool/lib/dtos/SendReview.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/SendReview.java @@ -1,11 +1,26 @@ package com.drinkool.lib.dtos; -import com.drinkool.lib.models.ReviewModel; +import com.drinkool.interfaces.ReviewInterface; +import io.quarkus.runtime.annotations.RegisterForReflection; import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; -public class SendReview { +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@RegisterForReflection +public class SendReview implements ReviewInterface { - public UUID reviewerId; - public UUID orderId; - public ReviewModel review; + private UUID reviewerId; + private UUID eateryId; + private Integer rating; + private String comment; + + public void setReviewerId(UUID x) { + return; + } } diff --git a/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java b/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java index 0a33368..a28ca88 100644 --- a/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java +++ b/lib/src/main/java/com/drinkool/lib/entities/BaseEntity.java @@ -4,7 +4,10 @@ import io.quarkus.hibernate.orm.panache.PanacheEntityBase; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.MappedSuperclass; +import java.time.LocalDateTime; import java.util.UUID; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; @MappedSuperclass public class BaseEntity extends PanacheEntityBase { @@ -12,4 +15,10 @@ public class BaseEntity extends PanacheEntityBase { @jakarta.persistence.Id @GeneratedValue(strategy = GenerationType.UUID) public UUID id; + + @CreationTimestamp + public LocalDateTime createDate; + + @UpdateTimestamp + public LocalDateTime updateDate; } diff --git a/lib/src/main/java/com/drinkool/lib/models/ReviewModel.java b/lib/src/main/java/com/drinkool/lib/models/ReviewModel.java deleted file mode 100644 index 6412d6f..0000000 --- a/lib/src/main/java/com/drinkool/lib/models/ReviewModel.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.drinkool.lib.models; - -import com.drinkool.lib.entities.BaseEntity; -import jakarta.persistence.*; -import java.time.LocalDateTime; - -@MappedSuperclass -public class ReviewModel extends BaseEntity { - - @Column - public int rating; - - @Column - public String comment; - - public ReviewModel(int rating, String comment) { - this.rating = rating; - this.comment = comment; - } - - public ReviewModel() {} - - public ReviewModel(ReviewModel input) { - this(input.rating, input.comment); - } - - @org.hibernate.annotations.CreationTimestamp - @Column(name = "review_date", updatable = false) - public LocalDateTime reviewDate; -} From 77d34d7a02ff787cf5d7b15c22831d3df8b727ee Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Thu, 7 May 2026 03:53:36 +0000 Subject: [PATCH 34/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- .../java/com/drinkool/services/ReviewService.java | 1 - k8s/base/account.yaml | 2 +- k8s/base/eatery.yaml | 2 +- k8s/base/gateway.yaml | 2 +- lib/pom.xml | 12 ++++++------ pom.xml | 2 +- 10 files changed, 20 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe04fbd..bc914d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.21](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.20...v1.5.21) (2026-05-07) + + +### Bug Fixes + +* add send review and get reviews ([#45](https://git.demonkernel.io.vn/FoodSurf/backend/issues/45)) ([e610111](https://git.demonkernel.io.vn/FoodSurf/backend/commit/e610111e667fa17b38095fd5e156ecd6b1c16604)) + ## [1.5.20](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.19...v1.5.20) (2026-05-06) diff --git a/account-service/pom.xml b/account-service/pom.xml index 8ab8059..64d40cf 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.20 + 1.5.21 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index dd4a2d1..374b67b 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.20 + 1.5.21 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 8ee6cf9..4e7d4d7 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.20 + 1.5.21 ../pom.xml diff --git a/gateway-service/src/main/java/com/drinkool/services/ReviewService.java b/gateway-service/src/main/java/com/drinkool/services/ReviewService.java index 42311bc..47d4a61 100644 --- a/gateway-service/src/main/java/com/drinkool/services/ReviewService.java +++ b/gateway-service/src/main/java/com/drinkool/services/ReviewService.java @@ -3,7 +3,6 @@ package com.drinkool.services; import com.drinkool.Url; import com.drinkool.enums.SortBy; import com.drinkool.lib.dtos.SendReview; - import io.smallrye.mutiny.Uni; import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.GET; diff --git a/k8s/base/account.yaml b/k8s/base/account.yaml index e98f9fa..f13e7cc 100644 --- a/k8s/base/account.yaml +++ b/k8s/base/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.20 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.21 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/eatery.yaml b/k8s/base/eatery.yaml index 6f272fb..64e1d3f 100644 --- a/k8s/base/eatery.yaml +++ b/k8s/base/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.20 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.21 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/gateway.yaml b/k8s/base/gateway.yaml index 3428d6f..f1720ca 100644 --- a/k8s/base/gateway.yaml +++ b/k8s/base/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.20 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.21 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index a1a0976..d133070 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -1,15 +1,15 @@ - + 4.0.0 com.drinkool drinkool - 1.5.20 + 1.5.21 ../pom.xml @@ -102,4 +102,4 @@ - \ No newline at end of file + diff --git a/pom.xml b/pom.xml index 68b2ad8..be9a5c5 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.20 + 1.5.21 pom 25 From bb828d7532fb6f849c247376e339c08f0759f91d Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Thu, 7 May 2026 08:43:19 +0000 Subject: [PATCH 35/51] fix: add cart service (#46) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/46 --- .vscode/settings.json | 4 +- .../src/main/resources/application.properties | 4 +- cart-service/.dockerignore | 5 + .../.mvn/wrapper/maven-wrapper.properties | 4 + cart-service/README.md | 76 +++++ cart-service/mvnw | 295 ++++++++++++++++++ cart-service/mvnw.cmd | 189 +++++++++++ cart-service/pom.xml | 189 +++++++++++ cart-service/src/main/docker/Dockerfile.jvm | 100 ++++++ .../src/main/docker/Dockerfile.legacy-jar | 96 ++++++ .../src/main/docker/Dockerfile.native | 32 ++ .../controllers/EateryController.java | 24 ++ .../src/main/java/com/drinkool/dtos/Cart.java | 18 ++ .../main/java/com/drinkool/dtos/CartItem.java | 14 + .../com/drinkool/services/CartService.java | 141 +++++++++ .../src/main/resources/application.properties | 23 ++ .../drinkool/services/CartServiceTest.java | 154 +++++++++ .../src/test/resources/application.properties | 2 + .../com/drinkool/services/EateryService.java | 40 +++ gateway-service/pom.xml | 14 + .../drinkool/controller/CartController.java | 27 ++ .../drinkool/controller/EateryController.java | 55 +--- .../com/drinkool/controller/GraphqlBase.java | 56 ++++ .../src/main/resources/application.properties | 3 +- .../src/test/resources/application.properties | 2 +- k8s/base/cart.yaml | 41 +++ lib/src/main/java/com/drinkool/Url.java | 1 + .../drinkool/lib/dtos/CartItemRequest.java | 9 + pom.xml | 1 + 29 files changed, 1566 insertions(+), 53 deletions(-) create mode 100644 cart-service/.dockerignore create mode 100644 cart-service/.mvn/wrapper/maven-wrapper.properties create mode 100644 cart-service/README.md create mode 100755 cart-service/mvnw create mode 100644 cart-service/mvnw.cmd create mode 100644 cart-service/pom.xml create mode 100644 cart-service/src/main/docker/Dockerfile.jvm create mode 100644 cart-service/src/main/docker/Dockerfile.legacy-jar create mode 100644 cart-service/src/main/docker/Dockerfile.native create mode 100644 cart-service/src/main/java/com/drinkool/controllers/EateryController.java create mode 100644 cart-service/src/main/java/com/drinkool/dtos/Cart.java create mode 100644 cart-service/src/main/java/com/drinkool/dtos/CartItem.java create mode 100644 cart-service/src/main/java/com/drinkool/services/CartService.java create mode 100644 cart-service/src/main/resources/application.properties create mode 100644 cart-service/src/test/java/com/drinkool/services/CartServiceTest.java create mode 100644 cart-service/src/test/resources/application.properties create mode 100644 gateway-service/src/main/java/com/drinkool/controller/CartController.java create mode 100644 gateway-service/src/main/java/com/drinkool/controller/GraphqlBase.java create mode 100644 k8s/base/cart.yaml create mode 100644 lib/src/main/java/com/drinkool/lib/dtos/CartItemRequest.java diff --git a/.vscode/settings.json b/.vscode/settings.json index 20d9826..1aa396c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,5 +9,7 @@ "**/docker": true, "node_modules": true }, - "explorerExclude.backup": {} + "explorerExclude.backup": {}, + "java.compile.nullAnalysis.mode": "automatic", + "java.configuration.updateBuildConfiguration": "automatic" } diff --git a/account-service/src/main/resources/application.properties b/account-service/src/main/resources/application.properties index e26a74b..87e6820 100644 --- a/account-service/src/main/resources/application.properties +++ b/account-service/src/main/resources/application.properties @@ -31,9 +31,9 @@ quarkus.native.resources.includes=com/google/i18n/phonenumbers/data/**/* # Kafka %prod.mp.messaging.connector.smallrye-kafka.bootstrap.servers=${KAFKA_SERVICE_SERVICE_HOST:host.docker.internal}:9092 +quarkus.messaging.kafka.serializer-generation.enabled=true ## Create restaurant topic mp.messaging.outgoing.manager-out.connector=smallrye-kafka mp.messaging.outgoing.manager-out.topic=create-restaurant -mp.messaging.outgoing.manager-out.value.serializer=io.quarkus.kafka.client.serialization.ObjectMapperSerializer -quarkus.messaging.kafka.serializer-generation.enabled=true \ No newline at end of file +mp.messaging.outgoing.manager-out.value.serializer=io.quarkus.kafka.client.serialization.ObjectMapperSerializer \ No newline at end of file diff --git a/cart-service/.dockerignore b/cart-service/.dockerignore new file mode 100644 index 0000000..94810d0 --- /dev/null +++ b/cart-service/.dockerignore @@ -0,0 +1,5 @@ +* +!target/*-runner +!target/*-runner.jar +!target/lib/* +!target/quarkus-app/* \ No newline at end of file diff --git a/cart-service/.mvn/wrapper/maven-wrapper.properties b/cart-service/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..533e775 --- /dev/null +++ b/cart-service/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,4 @@ +wrapperVersion=3.3.4 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip +distributionSha256Sum=305773a68d6ddfd413df58c82b3f8050e89778e777f3a745c8e5b8cbea4018ef diff --git a/cart-service/README.md b/cart-service/README.md new file mode 100644 index 0000000..dabca42 --- /dev/null +++ b/cart-service/README.md @@ -0,0 +1,76 @@ +# cart-service + +This project uses Quarkus, the Supersonic Subatomic Java Framework. + +If you want to learn more about Quarkus, please visit its website: . + +## Running the application in dev mode + +You can run your application in dev mode that enables live coding using: + +```shell script +./mvnw compile quarkus:dev +``` + +> **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at . + +## Packaging and running the application + +The application can be packaged using: + +```shell script +./mvnw package +``` + +It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory. +Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/quarkus-app/lib/` directory. + +The application is now runnable using `java -jar target/quarkus-app/quarkus-run.jar`. + +If you want to build an _über-jar_, execute the following command: + +```shell script +./mvnw package -Dquarkus.package.jar.type=uber-jar +``` + +The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`. + +## Creating a native executable + +You can create a native executable using: + +```shell script +./mvnw package -Dnative +``` + +Or, if you don't have GraalVM installed, you can run the native executable build in a container using: + +```shell script +./mvnw package -Dnative -Dquarkus.native.container-build=true +``` + +You can then execute your native executable with: `./target/cart-service-1.0.0-SNAPSHOT-runner` + +If you want to learn more about building native executables, please consult . + +## Related Guides + +- Hibernate Validator ([guide](https://quarkus.io/guides/validation)): Validate object properties (field, getter) and method parameters for your beans (REST, CDI, Jakarta Persistence) +- Messaging - Kafka Connector ([guide](https://quarkus.io/guides/kafka-getting-started)): Connect to Kafka with Reactive Messaging +- Redis Client ([guide](https://quarkus.io/guides/redis)): Connect to Redis in either imperative or reactive style +- REST Jackson ([guide](https://quarkus.io/guides/rest#json-serialisation)): Jackson serialization support for Quarkus REST. This extension is not compatible with the quarkus-resteasy extension, or any of the extensions that depend on it + +## Provided Code + +### Messaging codestart + +Use Quarkus Messaging + +[Related Apache Kafka guide section...](https://quarkus.io/guides/kafka-reactive-getting-started) + + +### REST + +Easily start your REST Web Services + +[Related guide section...](https://quarkus.io/guides/getting-started-reactive#reactive-jax-rs-resources) diff --git a/cart-service/mvnw b/cart-service/mvnw new file mode 100755 index 0000000..bd8896b --- /dev/null +++ b/cart-service/mvnw @@ -0,0 +1,295 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.4 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +scriptDir="$(dirname "$0")" +scriptName="$(basename "$0")" + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +actualDistributionDir="" + +# First try the expected directory name (for regular distributions) +if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then + if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then + actualDistributionDir="$distributionUrlNameMain" + fi +fi + +# If not found, search for any directory with the Maven executable (for snapshots) +if [ -z "$actualDistributionDir" ]; then + # enable globbing to iterate over items + set +f + for dir in "$TMP_DOWNLOAD_DIR"/*; do + if [ -d "$dir" ]; then + if [ -f "$dir/bin/$MVN_CMD" ]; then + actualDistributionDir="$(basename "$dir")" + break + fi + fi + done + set -f +fi + +if [ -z "$actualDistributionDir" ]; then + verbose "Contents of $TMP_DOWNLOAD_DIR:" + verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" + die "Could not find Maven distribution directory in extracted archive" +fi + +verbose "Found extracted Maven distribution directory: $actualDistributionDir" +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/cart-service/mvnw.cmd b/cart-service/mvnw.cmd new file mode 100644 index 0000000..5761d94 --- /dev/null +++ b/cart-service/mvnw.cmd @@ -0,0 +1,189 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.4 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' + +$MAVEN_M2_PATH = "$HOME/.m2" +if ($env:MAVEN_USER_HOME) { + $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" +} + +if (-not (Test-Path -Path $MAVEN_M2_PATH)) { + New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null +} + +$MAVEN_WRAPPER_DISTS = $null +if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { + $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" +} else { + $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" +} + +$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +$actualDistributionDir = "" + +# First try the expected directory name (for regular distributions) +$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" +$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" +if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { + $actualDistributionDir = $distributionUrlNameMain +} + +# If not found, search for any directory with the Maven executable (for snapshots) +if (!$actualDistributionDir) { + Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { + $testPath = Join-Path $_.FullName "bin/$MVN_CMD" + if (Test-Path -Path $testPath -PathType Leaf) { + $actualDistributionDir = $_.Name + } + } +} + +if (!$actualDistributionDir) { + Write-Error "Could not find Maven distribution directory in extracted archive" +} + +Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/cart-service/pom.xml b/cart-service/pom.xml new file mode 100644 index 0000000..c008cc0 --- /dev/null +++ b/cart-service/pom.xml @@ -0,0 +1,189 @@ + + + 4.0.0 + + + com.drinkool + drinkool + 1.5.21 + ../pom.xml + + + cart-service + quarkus + + + 3.15.0 + 25 + UTF-8 + UTF-8 + quarkus-bom + io.quarkus.platform + 3.34.6 + true + 3.5.4 + 1.18.46 + + + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + + + + + com.drinkool + lib + ${project.version} + + + org.projectlombok + lombok + ${org.projectlombok.version} + provided + + + io.quarkus + quarkus-container-image-docker + + + io.quarkus + quarkus-junit5-mockito + test + + + io.quarkus + quarkus-hibernate-validator + + + io.quarkus + quarkus-redis-client + + + io.quarkus + quarkus-rest-jackson + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-rest + + + io.quarkus + quarkus-rest-client-jackson + + + io.quarkus + quarkus-smallrye-graphql-client + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + build + generate-code + generate-code-tests + native-image-agent + + + + + + maven-compiler-plugin + ${compiler-plugin.version} + + true + + + + org.projectlombok + lombok + ${org.projectlombok.version} + + + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + + + + + + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + + native + + + native + + + + false + true + + + + diff --git a/cart-service/src/main/docker/Dockerfile.jvm b/cart-service/src/main/docker/Dockerfile.jvm new file mode 100644 index 0000000..cc8756b --- /dev/null +++ b/cart-service/src/main/docker/Dockerfile.jvm @@ -0,0 +1,100 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode +# +# Before building the container image run: +# +# ./mvnw package +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/cart-service-jvm . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/cart-service-jvm +# +# If you want to include the debug port into your docker image +# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005. +# Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005 +# when running the container +# +# Then run the container using : +# +# docker run -i --rm -p 8080:8080 quarkus/cart-service-jvm +# +# This image uses the `run-java.sh` script to run the application. +# This scripts computes the command line to execute your Java application, and +# includes memory/GC tuning. +# You can configure the behavior using the following environment properties: +# - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") - Be aware that this will override +# the default JVM options, use `JAVA_OPTS_APPEND` to append options +# - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options +# in JAVA_OPTS (example: "-Dsome.property=foo") +# - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is +# used to calculate a default maximal heap memory based on a containers restriction. +# If used in a container without any memory constraints for the container then this +# option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio +# of the container available memory as set here. The default is `50` which means 50% +# of the available memory is used as an upper boundary. You can skip this mechanism by +# setting this value to `0` in which case no `-Xmx` option is added. +# - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This +# is used to calculate a default initial heap memory based on the maximum heap memory. +# If used in a container without any memory constraints for the container then this +# option has no effect. If there is a memory constraint then `-Xms` is set to a ratio +# of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx` +# is used as the initial heap size. You can skip this mechanism by setting this value +# to `0` in which case no `-Xms` option is added (example: "25") +# - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS. +# This is used to calculate the maximum value of the initial heap memory. If used in +# a container without any memory constraints for the container then this option has +# no effect. If there is a memory constraint then `-Xms` is limited to the value set +# here. The default is 4096MB which means the calculated value of `-Xms` never will +# be greater than 4096MB. The value of this variable is expressed in MB (example: "4096") +# - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output +# when things are happening. This option, if set to true, will set +# `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true"). +# - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example: +# true"). +# - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787"). +# - CONTAINER_CORE_LIMIT: A calculated core limit as described in +# https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2") +# - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024"). +# - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion. +# (example: "20") +# - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking. +# (example: "40") +# - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection. +# (example: "4") +# - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus +# previous GC times. (example: "90") +# - GC_METASPACE_SIZE: The initial metaspace size. (example: "20") +# - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100") +# - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should +# contain the necessary JRE command-line options to specify the required GC, which +# will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC). +# - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080") +# - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080") +# - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be +# accessed directly. (example: "foo.example.com,bar.example.com") +# +# You can find more information about the UBI base runtime images and their configuration here: +# https://rh-openjdk.github.io/redhat-openjdk-containers/ +### +FROM registry.access.redhat.com/ubi8/openjdk-21:1.23 + +ENV LANGUAGE='en_US:en' + + +# We make four distinct layers so if there are application changes the library layers can be re-used +COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/ +COPY --chown=185 target/quarkus-app/*.jar /deployments/ +COPY --chown=185 target/quarkus-app/app/ /deployments/app/ +COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ + +EXPOSE 8080 +USER 185 +ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" + +ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ] + diff --git a/cart-service/src/main/docker/Dockerfile.legacy-jar b/cart-service/src/main/docker/Dockerfile.legacy-jar new file mode 100644 index 0000000..bbabecc --- /dev/null +++ b/cart-service/src/main/docker/Dockerfile.legacy-jar @@ -0,0 +1,96 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode +# +# Before building the container image run: +# +# ./mvnw package -Dquarkus.package.jar.type=legacy-jar +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/cart-service-legacy-jar . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/cart-service-legacy-jar +# +# If you want to include the debug port into your docker image +# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005. +# Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005 +# when running the container +# +# Then run the container using : +# +# docker run -i --rm -p 8080:8080 quarkus/cart-service-legacy-jar +# +# This image uses the `run-java.sh` script to run the application. +# This scripts computes the command line to execute your Java application, and +# includes memory/GC tuning. +# You can configure the behavior using the following environment properties: +# - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") - Be aware that this will override +# the default JVM options, use `JAVA_OPTS_APPEND` to append options +# - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options +# in JAVA_OPTS (example: "-Dsome.property=foo") +# - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is +# used to calculate a default maximal heap memory based on a containers restriction. +# If used in a container without any memory constraints for the container then this +# option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio +# of the container available memory as set here. The default is `50` which means 50% +# of the available memory is used as an upper boundary. You can skip this mechanism by +# setting this value to `0` in which case no `-Xmx` option is added. +# - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This +# is used to calculate a default initial heap memory based on the maximum heap memory. +# If used in a container without any memory constraints for the container then this +# option has no effect. If there is a memory constraint then `-Xms` is set to a ratio +# of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx` +# is used as the initial heap size. You can skip this mechanism by setting this value +# to `0` in which case no `-Xms` option is added (example: "25") +# - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS. +# This is used to calculate the maximum value of the initial heap memory. If used in +# a container without any memory constraints for the container then this option has +# no effect. If there is a memory constraint then `-Xms` is limited to the value set +# here. The default is 4096MB which means the calculated value of `-Xms` never will +# be greater than 4096MB. The value of this variable is expressed in MB (example: "4096") +# - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output +# when things are happening. This option, if set to true, will set +# `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true"). +# - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example: +# true"). +# - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787"). +# - CONTAINER_CORE_LIMIT: A calculated core limit as described in +# https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2") +# - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024"). +# - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion. +# (example: "20") +# - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking. +# (example: "40") +# - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection. +# (example: "4") +# - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus +# previous GC times. (example: "90") +# - GC_METASPACE_SIZE: The initial metaspace size. (example: "20") +# - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100") +# - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should +# contain the necessary JRE command-line options to specify the required GC, which +# will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC). +# - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080") +# - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080") +# - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be +# accessed directly. (example: "foo.example.com,bar.example.com") +# +# You can find more information about the UBI base runtime images and their configuration here: +# https://rh-openjdk.github.io/redhat-openjdk-containers/ +### +FROM registry.access.redhat.com/ubi8/openjdk-21:1.23 + +ENV LANGUAGE='en_US:en' + + +COPY target/lib/* /deployments/lib/ +COPY target/*-runner.jar /deployments/quarkus-run.jar + +EXPOSE 8080 +USER 185 +ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" + +ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ] diff --git a/cart-service/src/main/docker/Dockerfile.native b/cart-service/src/main/docker/Dockerfile.native new file mode 100644 index 0000000..ceaf1ba --- /dev/null +++ b/cart-service/src/main/docker/Dockerfile.native @@ -0,0 +1,32 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. +# It uses a micro base image, tuned for Quarkus native executables. +# It reduces the size of the resulting container image. +# Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. +# +# Before building the container image run: +# +# ./mvnw package -Dnative +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/cart-service . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/cart-service +# +# The `quay.io/quarkus/quarkus-micro-image:2.0` base image is based on UBI 9. +# To use UBI 8, switch to `quay.io/quarkus/quarkus-micro-image:2.0`. +### +FROM quay.io/quarkus/quarkus-micro-image:2.0 +WORKDIR /work/ +RUN chown 1001 /work \ + && chmod "g+rwX" /work \ + && chown 1001:root /work +COPY --chown=1001:root --chmod=0755 target/*-runner /work/application + +EXPOSE 8080 +USER 1001 + +ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] diff --git a/cart-service/src/main/java/com/drinkool/controllers/EateryController.java b/cart-service/src/main/java/com/drinkool/controllers/EateryController.java new file mode 100644 index 0000000..f4f3c8d --- /dev/null +++ b/cart-service/src/main/java/com/drinkool/controllers/EateryController.java @@ -0,0 +1,24 @@ +package com.drinkool.controllers; + +import io.smallrye.mutiny.Uni; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.core.Response; +import java.util.UUID; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@RegisterRestClient(configKey = "eatery") +@Path("/") +public interface EateryController { + @GET + @Path("/{id}") + Uni getEateryById(@PathParam("id") UUID id); + + @GET + @Path("/{eateryId}/{menuItemId}") + public Uni checkMenuItemExists( + @PathParam("eateryId") UUID eateryId, + @PathParam("menuItemId") UUID menuItemId + ); +} diff --git a/cart-service/src/main/java/com/drinkool/dtos/Cart.java b/cart-service/src/main/java/com/drinkool/dtos/Cart.java new file mode 100644 index 0000000..77ad94a --- /dev/null +++ b/cart-service/src/main/java/com/drinkool/dtos/Cart.java @@ -0,0 +1,18 @@ +package com.drinkool.dtos; + +import java.util.List; +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class Cart { + + public UUID Id; + public UUID userId; + public UUID eateryId; + public List items; +} diff --git a/cart-service/src/main/java/com/drinkool/dtos/CartItem.java b/cart-service/src/main/java/com/drinkool/dtos/CartItem.java new file mode 100644 index 0000000..56c0fa0 --- /dev/null +++ b/cart-service/src/main/java/com/drinkool/dtos/CartItem.java @@ -0,0 +1,14 @@ +package com.drinkool.dtos; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class CartItem { + + public String productId; + public Integer quantity; +} diff --git a/cart-service/src/main/java/com/drinkool/services/CartService.java b/cart-service/src/main/java/com/drinkool/services/CartService.java new file mode 100644 index 0000000..be0e54c --- /dev/null +++ b/cart-service/src/main/java/com/drinkool/services/CartService.java @@ -0,0 +1,141 @@ +package com.drinkool.services; + +import com.drinkool.InternalValue; +import com.drinkool.controllers.EateryController; +import com.drinkool.dtos.Cart; +import com.drinkool.dtos.CartItem; +import io.quarkus.redis.datasource.RedisDataSource; +import io.quarkus.redis.datasource.hash.HashCommands; +import io.quarkus.redis.datasource.value.ValueCommands; +import io.smallrye.mutiny.Uni; +import io.vertx.core.http.HttpServerRequest; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.core.Response; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.eclipse.microprofile.graphql.GraphQLApi; +import org.eclipse.microprofile.graphql.GraphQLException; +import org.eclipse.microprofile.graphql.Mutation; +import org.eclipse.microprofile.graphql.Name; +import org.eclipse.microprofile.graphql.Query; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +@ApplicationScoped +@GraphQLApi +public class CartService { + + @Inject + HttpServerRequest request; + + @Inject + @RestClient + EateryController eateryController; + + private final HashCommands hashCommands; + private final ValueCommands valueCommands; + + @Inject + public CartService(RedisDataSource ds) { + this.hashCommands = ds.hash(String.class); + this.valueCommands = ds.value(String.class); + } + + @Mutation("createCart") + public Uni createCart(@Name("eateryId") UUID eateryId) { + String userId = request.getHeader(InternalValue.userId); + + return eateryController + .getEateryById(eateryId) + .onItem() + .transform(response -> { + if (response.getStatus() != Response.Status.OK.getStatusCode()) { + throw new RuntimeException("NotFoundEatery"); + } + + String cartId = UUID.randomUUID().toString(); + String redisKey = "cart:" + cartId; + + hashCommands.hset( + redisKey, + Map.of( + "_metadata_owner", + userId != null ? userId : "GUEST", + "_metadata_eatery", + eateryId.toString() + ) + ); + + valueCommands + .getDataSource() + .key() + .expire(redisKey, Duration.ofDays(30)); + + return cartId; + }) + .onFailure() + .transform(f -> + new GraphQLException( + "Lỗi kết nối đến dịch vụ nhà hàng: " + f.getMessage() + ) + ); + } + + @Query("getCart") + public Cart getCart(@Name("cartId") UUID cartId) throws GraphQLException { + String key = "cart:" + cartId; + + Map data = hashCommands.hgetall(key); + + if (data.isEmpty()) { + throw new GraphQLException("NotFoundCart"); + } + + List items = new ArrayList<>(); + + data.forEach((k, v) -> { + if (!k.startsWith("_")) { + items.add(new CartItem(k, Integer.parseInt(v))); + } + }); + + return new Cart( + cartId, + UUID.fromString(data.get("_metadata_owner")), + UUID.fromString(data.get("_metadata_eatery")), + items + ); + } + + @Mutation("addItem") + public Uni addItem( + @Name("cartId") UUID cartId, + @Name("menuItemId") UUID menuItemId, + @Name("quantity") long quantity + ) { + String key = "cart:" + cartId; + + UUID eateryId = UUID.fromString(hashCommands.hget(key, "_metadata_eatery")); + + return eateryController + .checkMenuItemExists(eateryId, menuItemId) + .onItem() + .transform(response -> { + if (response.getStatus() != Response.Status.OK.getStatusCode()) { + throw new RuntimeException("NotFoundEatery"); + } + + hashCommands.hincrby(key, menuItemId.toString(), quantity); + hashCommands.getDataSource().key().expire(key, Duration.ofDays(30)); + + try { + return getCart(cartId); + } catch (Exception e) { + throw new RuntimeException(e.getMessage()); + } + }); + } +} diff --git a/cart-service/src/main/resources/application.properties b/cart-service/src/main/resources/application.properties new file mode 100644 index 0000000..754e8e6 --- /dev/null +++ b/cart-service/src/main/resources/application.properties @@ -0,0 +1,23 @@ +# Docker +quarkus.container-image.registry=vps.demonkernel.io.vn +quarkus.container-image.group=foodsurf +quarkus.container-image.name=gateway-service +quarkus.container-image.push=true +quarkus.container-image.build=true +quarkus.container-image.builder=docker +quarkus.container-image.additional-tags=latest + +# Build +quarkus.native.container-build=true +quarkus.native.remote-container-build=true +quarkus.native.additional-build-args=--future-defaults=all + +# Dependency +quarkus.index-dependency.lib.group-id=com.drinkool +quarkus.index-dependency.lib.artifact-id=lib + +# Redis +quarkus.redis.hosts=redis://${REDIS_SERVICE_SERVICE_HOST:localhost}:${REDIS_SERVICE_SERVICE_PORT:6379} + +# Rest Client +quarkus.rest-client.eatery.url=http://eatery-service diff --git a/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java b/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java new file mode 100644 index 0000000..52d26b0 --- /dev/null +++ b/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java @@ -0,0 +1,154 @@ +package com.drinkool.services; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.when; + +import com.drinkool.controllers.EateryController; +import com.drinkool.dtos.Cart; +import io.quarkus.redis.datasource.RedisDataSource; +import io.quarkus.redis.datasource.hash.HashCommands; +import io.quarkus.redis.datasource.value.ValueCommands; +import io.quarkus.test.InjectMock; +import io.quarkus.test.junit.QuarkusTest; +import io.smallrye.mutiny.Uni; +import io.smallrye.mutiny.helpers.test.UniAssertSubscriber; +import io.vertx.core.http.HttpServerRequest; +import jakarta.inject.Inject; +import jakarta.ws.rs.core.Response; +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import org.eclipse.microprofile.graphql.GraphQLException; +import org.eclipse.microprofile.rest.client.inject.RestClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class CartServiceTest { + + @Inject + CartService cartService; + + @InjectMock + HttpServerRequest request; + + @InjectMock + @RestClient + EateryController eateryController; + + @Inject + RedisDataSource redisDataSource; + + HashCommands hashCommands; + ValueCommands valueCommands; + + @BeforeEach + void setup() { + hashCommands = redisDataSource.hash(String.class); + valueCommands = redisDataSource.value(String.class); + } + + @Test + void testCreateCart_SuccessWithoutLogin() { + UUID eateryId = UUID.randomUUID(); + + when(eateryController.getEateryById(eateryId)).thenReturn( + Uni.createFrom().item(Response.ok().build()) + ); + + String cartId = cartService + .createCart(eateryId) + .subscribe() + .withSubscriber(UniAssertSubscriber.create()) + .awaitItem() + .getItem(); + + assertNotNull(cartId); + } + + @Test + void testGetCart_Success() throws Exception { + UUID cartId = UUID.randomUUID(); + UUID ownerId = UUID.randomUUID(); + UUID eateryId = UUID.randomUUID(); + String key = "cart:" + cartId; + + Map mockData = new HashMap<>(); + mockData.put("_metadata_owner", ownerId.toString()); + mockData.put("_metadata_eatery", eateryId.toString()); + mockData.put("product-1", "2"); + mockData.put("product-2", "5"); + + hashCommands.hset(key, mockData); + + Cart result = cartService.getCart(cartId); + + assertNotNull(result); + assertEquals(cartId, result.getId()); + assertEquals(ownerId, result.getUserId()); + assertEquals(eateryId, result.getEateryId()); + + assertEquals(2, result.getItems().size()); + + boolean hasProduct1 = result + .getItems() + .stream() + .anyMatch( + item -> + item.getProductId().equals("product-1") && item.getQuantity() == 2 + ); + + assertTrue(hasProduct1, "Phải chứa product-1 với số lượng 2"); + } + + @Test + void testGetCart_NotFound() { + UUID nonExistentId = UUID.randomUUID(); + + GraphQLException exception = assertThrows(GraphQLException.class, () -> { + cartService.getCart(nonExistentId); + }); + + assertEquals("NotFoundCart", exception.getMessage()); + } + + @Test + void testAddItem_Success() { + UUID cartId = UUID.randomUUID(); + UUID eateryId = UUID.randomUUID(); + UUID menuItemId = UUID.randomUUID(); + String key = "cart:" + cartId; + + hashCommands.hset(key, "_metadata_eatery", eateryId.toString()); + hashCommands.hset(key, "_metadata_owner", UUID.randomUUID().toString()); + + when(eateryController.checkMenuItemExists(eateryId, menuItemId)).thenReturn( + Uni.createFrom().item(Response.ok().build()) + ); + + Cart result = cartService + .addItem(cartId, menuItemId, 2L) + .await() + .atMost(Duration.ofSeconds(5)); + + assertNotNull(result); + assertEquals(cartId, result.getId()); + + boolean hasItem = result + .getItems() + .stream() + .anyMatch( + item -> + item.getProductId().equals(menuItemId.toString()) && + item.getQuantity() == 2 + ); + assertTrue(hasItem, "Sản phẩm phải có trong giỏ hàng sau khi thêm"); + + String quantityInRedis = hashCommands.hget(key, menuItemId.toString()); + assertEquals("2", quantityInRedis); + } +} diff --git a/cart-service/src/test/resources/application.properties b/cart-service/src/test/resources/application.properties new file mode 100644 index 0000000..8d4f431 --- /dev/null +++ b/cart-service/src/test/resources/application.properties @@ -0,0 +1,2 @@ +# Redis +quarkus.redis.hosts=redis://${REDIS_SERVICE_SERVICE_HOST:localhost}:${REDIS_SERVICE_SERVICE_PORT:6379} diff --git a/eatery-service/src/main/java/com/drinkool/services/EateryService.java b/eatery-service/src/main/java/com/drinkool/services/EateryService.java index 719b0e4..d7627e1 100644 --- a/eatery-service/src/main/java/com/drinkool/services/EateryService.java +++ b/eatery-service/src/main/java/com/drinkool/services/EateryService.java @@ -13,6 +13,10 @@ import jakarta.annotation.security.RolesAllowed; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.transaction.Transactional; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.core.Response; import java.util.List; import java.util.UUID; import org.eclipse.microprofile.graphql.GraphQLApi; @@ -23,6 +27,7 @@ import org.eclipse.microprofile.reactive.messaging.Incoming; @ApplicationScoped @GraphQLApi +@Path("/") public class EateryService { @Inject @@ -31,6 +36,41 @@ public class EateryService { @Inject HttpServerRequest request; + @GET + @Path("/{id}") + public Response checkEateryExists(@PathParam("id") UUID id) { + EateryEntity eatery = EateryEntity.findById(id); + + if (eatery == null) { + return Response.status(Response.Status.NOT_FOUND) + .entity("NotFoundEatery") + .build(); + } + + return Response.ok().build(); + } + + @GET + @Path("/{eateryId}/{menuItemId}") + public Response checkMenuItemExists( + @PathParam("eateryId") UUID eateryId, + @PathParam("menuItemId") UUID menuItemId + ) { + long count = MenuItemEntity.find( + "id = ?2 and eatery.id = ?1", + eateryId, + menuItemId + ).count(); + + if (count == 0) { + return Response.status(Response.Status.NOT_FOUND) + .entity("NotFoundMenuItem") + .build(); + } + + return Response.ok().build(); + } + @Incoming("manager-in") @Transactional public void consumeManagerSignup(ManagerCreate input) { diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 4e7d4d7..d579ed3 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -28,6 +28,7 @@ 3.32.4 true 3.5.4 + 1.18.46 @@ -48,6 +49,12 @@ jose4j 0.9.6 + + org.projectlombok + lombok + ${org.projectlombok.version} + provided + io.quarkus quarkus-security @@ -106,6 +113,13 @@ ${compiler-plugin.version} true + + + org.projectlombok + lombok + ${org.projectlombok.version} + + diff --git a/gateway-service/src/main/java/com/drinkool/controller/CartController.java b/gateway-service/src/main/java/com/drinkool/controller/CartController.java new file mode 100644 index 0000000..a8dd3f2 --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/controller/CartController.java @@ -0,0 +1,27 @@ +package com.drinkool.controller; + +import com.drinkool.lib.dtos.GraphqlDto; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.Response; +import lombok.Getter; +import org.eclipse.microprofile.config.inject.ConfigProperty; + +@Path("/api/cart") +@Getter +public class CartController extends GraphqlBase { + + @ConfigProperty(name = "quarkus.smallrye-graphql-client.cart.url") + String graphqlUrl; + + @POST + @Path("/graphql") + public Response forward( + GraphqlDto gqlRequest, + @Context HttpHeaders httpHeaders + ) { + return send(gqlRequest, httpHeaders); + } +} diff --git a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java index a708b4e..4b67108 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java @@ -1,16 +1,12 @@ package com.drinkool.controller; -import com.drinkool.InternalValue; import com.drinkool.Url; import com.drinkool.enums.SortBy; import com.drinkool.lib.dtos.GraphqlDto; import com.drinkool.lib.dtos.SendReview; import com.drinkool.services.ReviewService; -import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient; -import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClientBuilder; import io.smallrye.mutiny.Uni; import jakarta.inject.Inject; -import jakarta.json.bind.Jsonb; import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; @@ -19,20 +15,18 @@ import jakarta.ws.rs.PathParam; import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.UUID; +import lombok.Getter; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.rest.client.inject.RestClient; @Path("/api/eatery") -public class EateryController { +@Getter +public class EateryController extends GraphqlBase { @ConfigProperty(name = "quarkus.smallrye-graphql-client.eatery.url") - String eateryUrl; - - @Inject - Jsonb jsonb; + String graphqlUrl; @Inject @RestClient @@ -40,7 +34,7 @@ public class EateryController { @GET @Path(Url.Review + "/{eateryId}") - Uni getReviewsByEatery( + public Uni getReviewsByEatery( @PathParam("eateryId") UUID eateryId, @QueryParam("sort") @DefaultValue("LATEST") SortBy sortBy ) { @@ -49,7 +43,7 @@ public class EateryController { @POST @Path(Url.Review) - Uni receiveReview(SendReview input) { + public Uni receiveReview(SendReview input) { return reviewService.receiveReview(input); } @@ -59,41 +53,6 @@ public class EateryController { GraphqlDto gqlRequest, @Context HttpHeaders httpHeaders ) { - DynamicGraphQLClientBuilder builder = - DynamicGraphQLClientBuilder.newBuilder().url(eateryUrl); - - httpHeaders - .getRequestHeaders() - .forEach((name, values) -> { - String headerName = name.toLowerCase(); - - if (headerName.startsWith(InternalValue.headerId.toLowerCase())) { - if (!values.isEmpty()) { - builder.header(name, values.get(0)); - } - } - }); - - try (DynamicGraphQLClient tempClient = builder.build()) { - io.smallrye.graphql.client.Response response = tempClient.executeSync( - gqlRequest.query, - gqlRequest.variables - ); - - if (response.hasError()) { - return Response.status(400) - .entity(jsonb.toJson(response.getErrors())) - .build(); - } - - return Response.ok(jsonb.toJson(response.getData())) - .type(MediaType.APPLICATION_JSON) - .build(); - } catch (Exception e) { - e.printStackTrace(); - return Response.serverError() - .entity("Lỗi kết nối tới service Eatery") - .build(); - } + return send(gqlRequest, httpHeaders); } } diff --git a/gateway-service/src/main/java/com/drinkool/controller/GraphqlBase.java b/gateway-service/src/main/java/com/drinkool/controller/GraphqlBase.java new file mode 100644 index 0000000..1616c3c --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/controller/GraphqlBase.java @@ -0,0 +1,56 @@ +package com.drinkool.controller; + +import com.drinkool.InternalValue; +import com.drinkool.lib.dtos.GraphqlDto; +import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient; +import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClientBuilder; +import jakarta.inject.Inject; +import jakarta.json.bind.Jsonb; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +public abstract class GraphqlBase { + + @Inject + Jsonb jsonb; + + public abstract String getGraphqlUrl(); + + public Response send(GraphqlDto gqlRequest, HttpHeaders httpHeaders) { + DynamicGraphQLClientBuilder builder = + DynamicGraphQLClientBuilder.newBuilder().url(getGraphqlUrl()); + + httpHeaders + .getRequestHeaders() + .forEach((name, values) -> { + String headerName = name.toLowerCase(); + + if (headerName.startsWith(InternalValue.headerId.toLowerCase())) { + if (!values.isEmpty()) { + builder.header(name, values.get(0)); + } + } + }); + + try (DynamicGraphQLClient tempClient = builder.build()) { + io.smallrye.graphql.client.Response response = tempClient.executeSync( + gqlRequest.query, + gqlRequest.variables + ); + + if (response.hasError()) { + return Response.status(400) + .entity(jsonb.toJson(response.getErrors())) + .build(); + } + + return Response.ok(jsonb.toJson(response.getData())) + .type(MediaType.APPLICATION_JSON) + .build(); + } catch (Exception e) { + e.printStackTrace(); + return Response.serverError().entity("Lỗi kết nối tới service").build(); + } + } +} diff --git a/gateway-service/src/main/resources/application.properties b/gateway-service/src/main/resources/application.properties index e919d67..9f7a285 100644 --- a/gateway-service/src/main/resources/application.properties +++ b/gateway-service/src/main/resources/application.properties @@ -17,4 +17,5 @@ quarkus.rest-client.account.url=http://account-service quarkus.rest-client.eatery.url=http://eatery-service # GraphQL Client -quarkus.smallrye-graphql-client.eatery.url=http://eatery-service/graphql \ No newline at end of file +quarkus.smallrye-graphql-client.eatery.url=http://eatery-service/graphql +quarkus.smallrye-graphql-client.cart.url=http://cart-service/graphql diff --git a/gateway-service/src/test/resources/application.properties b/gateway-service/src/test/resources/application.properties index 9f91177..9dd6ce7 100644 --- a/gateway-service/src/test/resources/application.properties +++ b/gateway-service/src/test/resources/application.properties @@ -5,4 +5,4 @@ quarkus.http.host=0.0.0.0 gateway.jwt.secret=1uZk07Hqu1316z9YqrcSGPTTJDhMWU1ZhFSLBrDQvmU= # App configuration -quarkus.rest-client.account.url=http://account-service:8080 \ No newline at end of file +quarkus.rest-client.account.url=http://account-service:8080 diff --git a/k8s/base/cart.yaml b/k8s/base/cart.yaml new file mode 100644 index 0000000..3b51a24 --- /dev/null +++ b/k8s/base/cart.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cart-deploy +spec: + replicas: 1 + selector: + matchLabels: + app: cart + template: + metadata: + labels: + app: cart + spec: + containers: + - name: cart-pod + image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.21 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8080 + env: + - name: REDIS_SERVICE + value: "redis-service" + resources: + requests: + memory: "32Mi" + cpu: "50m" + limits: + memory: "64Mi" + cpu: "250m" +--- +apiVersion: v1 +kind: Service +metadata: + name: cart-service +spec: + selector: + app: cart + ports: + - port: 80 + targetPort: 8080 diff --git a/lib/src/main/java/com/drinkool/Url.java b/lib/src/main/java/com/drinkool/Url.java index 6e30f67..f02fa93 100644 --- a/lib/src/main/java/com/drinkool/Url.java +++ b/lib/src/main/java/com/drinkool/Url.java @@ -9,5 +9,6 @@ public class Url { public static final String SmsOtp = "/sms_otp"; public static final String Me = "/me"; public static final String Logout = "/logout"; + public static final String Cart = "/cart"; public static final String Review = "/review"; } diff --git a/lib/src/main/java/com/drinkool/lib/dtos/CartItemRequest.java b/lib/src/main/java/com/drinkool/lib/dtos/CartItemRequest.java new file mode 100644 index 0000000..155a092 --- /dev/null +++ b/lib/src/main/java/com/drinkool/lib/dtos/CartItemRequest.java @@ -0,0 +1,9 @@ +package com.drinkool.lib.dtos; + +import java.util.UUID; + +public class CartItemRequest { + + public UUID menuItemId; + public int quantity; +} diff --git a/pom.xml b/pom.xml index be9a5c5..21c20d5 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,7 @@ eatery-service account-service gateway-service + cart-service From 0d9e13899b35ec9e41381a161f6711d8eeb106f4 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Thu, 7 May 2026 09:13:19 +0000 Subject: [PATCH 36/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- cart-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s/base/account.yaml | 2 +- k8s/base/cart.yaml | 2 +- k8s/base/eatery.yaml | 2 +- k8s/base/gateway.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 11 files changed, 17 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc914d2..ef3afc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.22](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.21...v1.5.22) (2026-05-07) + + +### Bug Fixes + +* add cart service ([#46](https://git.demonkernel.io.vn/FoodSurf/backend/issues/46)) ([bb828d7](https://git.demonkernel.io.vn/FoodSurf/backend/commit/bb828d7532fb6f849c247376e339c08f0759f91d)) + ## [1.5.21](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.20...v1.5.21) (2026-05-07) diff --git a/account-service/pom.xml b/account-service/pom.xml index 64d40cf..c314733 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.21 + 1.5.22 ../pom.xml diff --git a/cart-service/pom.xml b/cart-service/pom.xml index c008cc0..fbee87a 100644 --- a/cart-service/pom.xml +++ b/cart-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.21 + 1.5.22 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 374b67b..fc3977c 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.21 + 1.5.22 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index d579ed3..41121ac 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.21 + 1.5.22 ../pom.xml diff --git a/k8s/base/account.yaml b/k8s/base/account.yaml index f13e7cc..2037fd1 100644 --- a/k8s/base/account.yaml +++ b/k8s/base/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.21 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.22 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/cart.yaml b/k8s/base/cart.yaml index 3b51a24..b2477ca 100644 --- a/k8s/base/cart.yaml +++ b/k8s/base/cart.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: cart-pod - image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.21 + image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.22 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/eatery.yaml b/k8s/base/eatery.yaml index 64e1d3f..5c22d9d 100644 --- a/k8s/base/eatery.yaml +++ b/k8s/base/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.21 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.22 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/gateway.yaml b/k8s/base/gateway.yaml index f1720ca..2b58937 100644 --- a/k8s/base/gateway.yaml +++ b/k8s/base/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.21 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.22 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index d133070..d39a5b1 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.21 + 1.5.22 ../pom.xml diff --git a/pom.xml b/pom.xml index 21c20d5..3e2dce1 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.21 + 1.5.22 pom 25 From da6f3295ddc8f34836ae7009c2c76e18e414b4df Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Thu, 7 May 2026 09:44:14 +0000 Subject: [PATCH 37/51] fix: resolved image issue (#47) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/47 --- cart-service/src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cart-service/src/main/resources/application.properties b/cart-service/src/main/resources/application.properties index 754e8e6..71ca8f2 100644 --- a/cart-service/src/main/resources/application.properties +++ b/cart-service/src/main/resources/application.properties @@ -1,7 +1,7 @@ # Docker quarkus.container-image.registry=vps.demonkernel.io.vn quarkus.container-image.group=foodsurf -quarkus.container-image.name=gateway-service +quarkus.container-image.name=cart-service quarkus.container-image.push=true quarkus.container-image.build=true quarkus.container-image.builder=docker From bd548278b450b10e08b7b31cd4620f409ab1a178 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Thu, 7 May 2026 10:11:08 +0000 Subject: [PATCH 38/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- cart-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s/base/account.yaml | 2 +- k8s/base/cart.yaml | 2 +- k8s/base/eatery.yaml | 2 +- k8s/base/gateway.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 11 files changed, 17 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef3afc3..28e001b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.23](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.22...v1.5.23) (2026-05-07) + + +### Bug Fixes + +* resolved image issue ([#47](https://git.demonkernel.io.vn/FoodSurf/backend/issues/47)) ([da6f329](https://git.demonkernel.io.vn/FoodSurf/backend/commit/da6f3295ddc8f34836ae7009c2c76e18e414b4df)) + ## [1.5.22](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.21...v1.5.22) (2026-05-07) diff --git a/account-service/pom.xml b/account-service/pom.xml index c314733..3d8bd51 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.22 + 1.5.23 ../pom.xml diff --git a/cart-service/pom.xml b/cart-service/pom.xml index fbee87a..9d6d072 100644 --- a/cart-service/pom.xml +++ b/cart-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.22 + 1.5.23 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index fc3977c..cbb6624 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.22 + 1.5.23 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 41121ac..88b9b5c 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.22 + 1.5.23 ../pom.xml diff --git a/k8s/base/account.yaml b/k8s/base/account.yaml index 2037fd1..6953ae9 100644 --- a/k8s/base/account.yaml +++ b/k8s/base/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.22 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.23 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/cart.yaml b/k8s/base/cart.yaml index b2477ca..b998474 100644 --- a/k8s/base/cart.yaml +++ b/k8s/base/cart.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: cart-pod - image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.22 + image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.23 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/eatery.yaml b/k8s/base/eatery.yaml index 5c22d9d..e89504e 100644 --- a/k8s/base/eatery.yaml +++ b/k8s/base/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.22 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.23 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/gateway.yaml b/k8s/base/gateway.yaml index 2b58937..6e15ea7 100644 --- a/k8s/base/gateway.yaml +++ b/k8s/base/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.22 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.23 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index d39a5b1..6b6db47 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.22 + 1.5.23 ../pom.xml diff --git a/pom.xml b/pom.xml index 3e2dce1..02aa2c1 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.22 + 1.5.23 pom 25 From 71575ec2ad5fbb402ec9ad17caba4314e0dd0454 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Thu, 7 May 2026 14:45:44 +0000 Subject: [PATCH 39/51] fix: add staff entity (#48) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/48 --- .vscode/settings.json | 3 +- account-service/pom.xml | 6 + .../com/drinkool/entities/ManagerEntity.java | 9 ++ .../com/drinkool/entities/StaffEntity.java | 30 +++++ .../drinkool/filters/HeaderRolesFilter.java | 7 + .../com/drinkool/services/AccountService.java | 5 + .../com/drinkool/services/ManagerService.java | 10 +- .../com/drinkool/services/StaffService.java | 71 +++++++++++ .../drinkool/services/StaffServiceTest.java | 120 ++++++++++++++++++ cart-service/pom.xml | 1 + .../drinkool/controller/EateryController.java | 10 +- .../com/drinkool/services/ReviewService.java | 8 +- lib/src/main/java/com/drinkool/Role.java | 1 + .../java/com/drinkool/lib/dtos/Login.java | 5 + .../java/com/drinkool/lib/dtos/Signup.java | 5 + 15 files changed, 282 insertions(+), 9 deletions(-) create mode 100644 account-service/src/main/java/com/drinkool/entities/StaffEntity.java create mode 100644 account-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java create mode 100644 account-service/src/main/java/com/drinkool/services/StaffService.java create mode 100644 account-service/src/test/java/com/drinkool/services/StaffServiceTest.java diff --git a/.vscode/settings.json b/.vscode/settings.json index 1aa396c..3e30470 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,7 +7,8 @@ "**/Thumbs.db": true, "**/target": true, "**/docker": true, - "node_modules": true + "node_modules": true, + "**/.mvn": true }, "explorerExclude.backup": {}, "java.compile.nullAnalysis.mode": "automatic", diff --git a/account-service/pom.xml b/account-service/pom.xml index 3d8bd51..b941572 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -54,6 +54,12 @@ jose4j 0.9.3 + + net.datafaker + datafaker + 2.0.2 + test + io.quarkus quarkus-messaging-kafka diff --git a/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java b/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java index 6d4691d..8b08ce8 100644 --- a/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java +++ b/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java @@ -3,11 +3,20 @@ package com.drinkool.entities; import com.drinkool.Role; import com.drinkool.models.UserModel; import jakarta.persistence.*; +import java.util.ArrayList; +import java.util.List; @Entity @Table(name = Role.Manager) public class ManagerEntity extends UserModel { + @OneToMany( + mappedBy = "serve", + cascade = CascadeType.ALL, + orphanRemoval = true + ) + public List staffs = new ArrayList<>(); + public ManagerEntity() { super(Role.Manager); } diff --git a/account-service/src/main/java/com/drinkool/entities/StaffEntity.java b/account-service/src/main/java/com/drinkool/entities/StaffEntity.java new file mode 100644 index 0000000..7ba98b8 --- /dev/null +++ b/account-service/src/main/java/com/drinkool/entities/StaffEntity.java @@ -0,0 +1,30 @@ +package com.drinkool.entities; + +import com.drinkool.Role; +import com.drinkool.models.UserModel; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.transaction.Transactional; + +@Entity +@Table(name = Role.Staff) +public class StaffEntity extends UserModel { + + @Transactional + public void signup( + String name, + String phone, + String rawPassword, + ManagerEntity serve + ) { + this.serve = serve; + super.signup(name, phone, rawPassword); + } + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "managerId") + public ManagerEntity serve; +} diff --git a/account-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java b/account-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java new file mode 100644 index 0000000..618b711 --- /dev/null +++ b/account-service/src/main/java/com/drinkool/filters/HeaderRolesFilter.java @@ -0,0 +1,7 @@ +package com.drinkool.filters; + +import com.drinkool.lib.utils.BaseHeaderAuthentication; +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class HeaderRolesFilter extends BaseHeaderAuthentication {} diff --git a/account-service/src/main/java/com/drinkool/services/AccountService.java b/account-service/src/main/java/com/drinkool/services/AccountService.java index caf12fd..b5843a1 100644 --- a/account-service/src/main/java/com/drinkool/services/AccountService.java +++ b/account-service/src/main/java/com/drinkool/services/AccountService.java @@ -3,6 +3,7 @@ package com.drinkool.services; import com.drinkool.Role; import com.drinkool.Url; import com.drinkool.entities.ManagerEntity; +import com.drinkool.entities.StaffEntity; import com.drinkool.lib.dtos.SmsOtp; import com.drinkool.models.UserModel; import jakarta.inject.Inject; @@ -28,6 +29,10 @@ public class AccountService { ManagerEntity.find("phone", input.phone).firstResult() != null ) return Response.accepted().entity(Role.Manager).build(); + if ( + StaffEntity.find("phone", input.phone).firstResult() != null + ) return Response.accepted().entity(Role.Staff).build(); + String otp = otpService.generateAndSaveOtp(input.phone); System.out.println("OTP cho " + input.phone + " là: " + otp); diff --git a/account-service/src/main/java/com/drinkool/services/ManagerService.java b/account-service/src/main/java/com/drinkool/services/ManagerService.java index 5e76b17..b9ef5f9 100644 --- a/account-service/src/main/java/com/drinkool/services/ManagerService.java +++ b/account-service/src/main/java/com/drinkool/services/ManagerService.java @@ -44,25 +44,25 @@ public class ManagerService extends BaseService { @POST @Path(Url.Login) public Response login(Login input) { - ManagerEntity customer = ManagerEntity.find( + ManagerEntity manager = ManagerEntity.find( "phone", input.phone ).firstResult(); - if (customer == null) return Response.status(Response.Status.BAD_REQUEST) + if (manager == null) return Response.status(Response.Status.BAD_REQUEST) .entity("InvalidPhoneNumber") .build(); - if (!customer.login(input.password)) return Response.status( + if (!manager.login(input.password)) return Response.status( Response.Status.BAD_REQUEST ) .entity("InvalidPassword") .build(); return Response.accepted() - .header(InternalValue.userId, customer.id.toString()) + .header(InternalValue.userId, manager.id.toString()) .header(InternalValue.role, Role.Manager) - .entity(customer) + .entity(manager) .build(); } } diff --git a/account-service/src/main/java/com/drinkool/services/StaffService.java b/account-service/src/main/java/com/drinkool/services/StaffService.java new file mode 100644 index 0000000..1a6c27c --- /dev/null +++ b/account-service/src/main/java/com/drinkool/services/StaffService.java @@ -0,0 +1,71 @@ +package com.drinkool.services; + +import com.drinkool.InternalValue; +import com.drinkool.Role; +import com.drinkool.Url; +import com.drinkool.entities.ManagerEntity; +import com.drinkool.entities.StaffEntity; +import com.drinkool.lib.dtos.Login; +import com.drinkool.lib.dtos.Signup; +import io.vertx.core.http.HttpServerRequest; +import jakarta.annotation.security.RolesAllowed; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Response; +import java.util.UUID; + +@Path(Role.Staff) +public class StaffService extends BaseService { + + @Inject + HttpServerRequest request; + + public StaffService() { + super(StaffEntity.class); + } + + @POST + @Path(Url.Signup) + @RolesAllowed(Role.Manager) + @Transactional + public Response signup(Signup input) { + UUID managerId = UUID.fromString(request.getHeader(InternalValue.userId)); + ManagerEntity manager = ManagerEntity.findById(managerId); + + if (manager == null) return Response.status(Response.Status.BAD_REQUEST) + .entity("InvalidManager") + .build(); + + StaffEntity staff = new StaffEntity(); + staff.signup(input.name, input.phone, input.password, manager); + + return Response.status(Response.Status.CREATED) + .header(InternalValue.userId, staff.id.toString()) + .header(InternalValue.role, Role.Staff) + .build(); + } + + @POST + @Path(Url.Login) + public Response login(Login input) { + StaffEntity staff = StaffEntity.find("phone", input.phone).firstResult(); + + if (staff == null) return Response.status(Response.Status.BAD_REQUEST) + .entity("InvalidPhoneNumber") + .build(); + + if (!staff.login(input.password)) return Response.status( + Response.Status.BAD_REQUEST + ) + .entity("InvalidPassword") + .build(); + + return Response.accepted() + .header(InternalValue.userId, staff.id.toString()) + .header(InternalValue.role, Role.Staff) + .entity(staff) + .build(); + } +} diff --git a/account-service/src/test/java/com/drinkool/services/StaffServiceTest.java b/account-service/src/test/java/com/drinkool/services/StaffServiceTest.java new file mode 100644 index 0000000..5cce294 --- /dev/null +++ b/account-service/src/test/java/com/drinkool/services/StaffServiceTest.java @@ -0,0 +1,120 @@ +package com.drinkool.services; + +import static io.restassured.RestAssured.*; +import static org.junit.jupiter.api.Assertions.*; + +import com.drinkool.*; +import com.drinkool.entities.StaffEntity; +import com.drinkool.lib.dtos.*; +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.kafka.*; +import io.restassured.http.ContentType; +import io.smallrye.reactive.messaging.kafka.companion.ConsumerTask; +import io.smallrye.reactive.messaging.kafka.companion.KafkaCompanion; +import jakarta.ws.rs.core.Response; +import java.time.Duration; +import net.datafaker.Faker; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +@QuarkusTest +@QuarkusTestResource(KafkaCompanionResource.class) +public class StaffServiceTest { + + private final Faker faker = new Faker(); + + private String managerId; + + @BeforeEach + void setup() { + ManagerSignup input = new ManagerSignup(); + input.name = "Ho Van Quan"; + input.phone = Utils.generateRandomPhone(); + input.password = "strong_password"; + input.eateryName = "Quan Com Ngon"; + + var response = given() + .contentType("application/json") + .body(input) + .when() + .post(Role.Manager + Url.Signup) + .then() + .statusCode(201) + .header(InternalValue.userId, org.hamcrest.Matchers.notNullValue()) + .header(InternalValue.role, Role.Manager) + .extract(); + + managerId = response.header(InternalValue.userId); + } + + @Test + void signup_Success() { + String staffName = faker.name().fullName(); + String staffPhone = Utils.generateRandomPhone(); + + Signup signup = new Signup( + staffName, + staffPhone, + faker.famousLastWords().lastWords() + ); + + given() + .contentType(ContentType.JSON) + .header(InternalValue.role, Role.Manager) + .header(InternalValue.userId, managerId) + .body(signup) + .when() + .post(Role.Staff + Url.Signup) + .then() + .statusCode(Response.Status.CREATED.getStatusCode()) + .header(InternalValue.userId, org.hamcrest.Matchers.notNullValue()) + .header(InternalValue.role, Role.Staff); + + StaffEntity staff = StaffEntity.find("phone", staffPhone).firstResult(); + + assertEquals(managerId, staff.serve.id.toString()); + } + + @Test + void signup_FailedDueToInvalidRole() { + given() + .contentType(ContentType.JSON) + .header(InternalValue.role, Role.Customer) + .header(InternalValue.userId, managerId) + .body("") + .when() + .post(Role.Staff + Url.Signup) + .then() + .statusCode(Response.Status.FORBIDDEN.getStatusCode()); + } + + @Test + void testLoginSuccess() { + String staffName = faker.name().fullName(); + String staffPhone = Utils.generateRandomPhone(); + String password = faker.famousLastWords().lastWords(); + + Signup signup = new Signup(staffName, staffPhone, password); + + given() + .contentType(ContentType.JSON) + .header(InternalValue.role, Role.Manager) + .header(InternalValue.userId, managerId) + .body(signup) + .when() + .post(Role.Staff + Url.Signup) + .then(); + + Login loginInput = new Login(staffPhone, password); + + given() + .contentType(ContentType.JSON) + .body(loginInput) + .when() + .post(Role.Staff + Url.Login) + .then() + .statusCode(Response.Status.ACCEPTED.getStatusCode()); + } +} diff --git a/cart-service/pom.xml b/cart-service/pom.xml index 9d6d072..8c4f4c4 100644 --- a/cart-service/pom.xml +++ b/cart-service/pom.xml @@ -181,6 +181,7 @@ + false false true diff --git a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java index 4b67108..53e718b 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/EateryController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/EateryController.java @@ -1,5 +1,6 @@ package com.drinkool.controller; +import com.drinkool.InternalValue; import com.drinkool.Url; import com.drinkool.enums.SortBy; import com.drinkool.lib.dtos.GraphqlDto; @@ -9,6 +10,7 @@ import io.smallrye.mutiny.Uni; import jakarta.inject.Inject; import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.GET; +import jakarta.ws.rs.HeaderParam; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; @@ -43,8 +45,12 @@ public class EateryController extends GraphqlBase { @POST @Path(Url.Review) - public Uni receiveReview(SendReview input) { - return reviewService.receiveReview(input); + public Uni receiveReview( + SendReview input, + @HeaderParam(InternalValue.userId) UUID userId, + @HeaderParam(InternalValue.role) String role + ) { + return reviewService.receiveReview(input, userId, role); } @POST diff --git a/gateway-service/src/main/java/com/drinkool/services/ReviewService.java b/gateway-service/src/main/java/com/drinkool/services/ReviewService.java index 47d4a61..8cee0e2 100644 --- a/gateway-service/src/main/java/com/drinkool/services/ReviewService.java +++ b/gateway-service/src/main/java/com/drinkool/services/ReviewService.java @@ -1,11 +1,13 @@ package com.drinkool.services; +import com.drinkool.InternalValue; import com.drinkool.Url; import com.drinkool.enums.SortBy; import com.drinkool.lib.dtos.SendReview; import io.smallrye.mutiny.Uni; import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.GET; +import jakarta.ws.rs.HeaderParam; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; @@ -25,5 +27,9 @@ public interface ReviewService { ); @POST - public Uni receiveReview(SendReview input); + public Uni receiveReview( + SendReview input, + @HeaderParam(InternalValue.userId) UUID userId, + @HeaderParam(InternalValue.role) String role + ); } diff --git a/lib/src/main/java/com/drinkool/Role.java b/lib/src/main/java/com/drinkool/Role.java index ee2e5e6..4cdeac9 100644 --- a/lib/src/main/java/com/drinkool/Role.java +++ b/lib/src/main/java/com/drinkool/Role.java @@ -4,4 +4,5 @@ public class Role { public static final String Customer = "customer"; public static final String Manager = "manager"; + public static final String Staff = "Staff"; } diff --git a/lib/src/main/java/com/drinkool/lib/dtos/Login.java b/lib/src/main/java/com/drinkool/lib/dtos/Login.java index e87f3d8..9719e11 100644 --- a/lib/src/main/java/com/drinkool/lib/dtos/Login.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/Login.java @@ -1,5 +1,10 @@ package com.drinkool.lib.dtos; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor public class Login { public String phone; diff --git a/lib/src/main/java/com/drinkool/lib/dtos/Signup.java b/lib/src/main/java/com/drinkool/lib/dtos/Signup.java index 0db754a..3d2af07 100644 --- a/lib/src/main/java/com/drinkool/lib/dtos/Signup.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/Signup.java @@ -1,5 +1,10 @@ package com.drinkool.lib.dtos; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor public class Signup { public String name; From e963b0f850bb7c97dfdccde8d622f4555c67e3eb Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Thu, 7 May 2026 15:15:43 +0000 Subject: [PATCH 40/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- cart-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s/base/account.yaml | 2 +- k8s/base/cart.yaml | 2 +- k8s/base/eatery.yaml | 2 +- k8s/base/gateway.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 11 files changed, 17 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28e001b..cf13133 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.24](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.23...v1.5.24) (2026-05-07) + + +### Bug Fixes + +* add staff entity ([#48](https://git.demonkernel.io.vn/FoodSurf/backend/issues/48)) ([71575ec](https://git.demonkernel.io.vn/FoodSurf/backend/commit/71575ec2ad5fbb402ec9ad17caba4314e0dd0454)) + ## [1.5.23](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.22...v1.5.23) (2026-05-07) diff --git a/account-service/pom.xml b/account-service/pom.xml index b941572..044cb38 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.23 + 1.5.24 ../pom.xml diff --git a/cart-service/pom.xml b/cart-service/pom.xml index 8c4f4c4..febe854 100644 --- a/cart-service/pom.xml +++ b/cart-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.23 + 1.5.24 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index cbb6624..6331087 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.23 + 1.5.24 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 88b9b5c..527d8b9 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.23 + 1.5.24 ../pom.xml diff --git a/k8s/base/account.yaml b/k8s/base/account.yaml index 6953ae9..dcfc889 100644 --- a/k8s/base/account.yaml +++ b/k8s/base/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.23 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.24 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/cart.yaml b/k8s/base/cart.yaml index b998474..7500e90 100644 --- a/k8s/base/cart.yaml +++ b/k8s/base/cart.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: cart-pod - image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.23 + image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.24 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/eatery.yaml b/k8s/base/eatery.yaml index e89504e..59a99b9 100644 --- a/k8s/base/eatery.yaml +++ b/k8s/base/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.23 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.24 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/gateway.yaml b/k8s/base/gateway.yaml index 6e15ea7..59f75e9 100644 --- a/k8s/base/gateway.yaml +++ b/k8s/base/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.23 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.24 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index 6b6db47..2f948b4 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.23 + 1.5.24 ../pom.xml diff --git a/pom.xml b/pom.xml index 02aa2c1..ec9ebe2 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.23 + 1.5.24 pom 25 From c6683b28dc303ab89b5285be122f570e914ec167 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Sun, 10 May 2026 14:10:20 +0000 Subject: [PATCH 41/51] fix: add upload images (#50) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/50 --- .devcontainer/Dockerfile | 3 +- .devcontainer/devcontainer.json | 4 +- .vscode/settings.json | 3 +- cart-service/pom.xml | 10 -- cart-service/src/main/docker/Dockerfile.jvm | 2 +- .../src/main/docker/Dockerfile.legacy-jar | 2 +- .../src/main/docker/Dockerfile.native | 2 +- .../java/com/drinkool/dtos/DtoMapper.java | 4 +- .../.mvn/wrapper/maven-wrapper.properties | 4 + file-service/pom.xml | 102 ++++++++++++++++++ file-service/python/Dockerfile | 32 ++++++ file-service/python/main.py | 52 +++++++++ file-service/python/requirements.txt | 5 + gateway-service/pom.xml | 4 +- .../drinkool/controller/FileController.java | 32 ++++++ .../drinkool/controller/MainController.java | 12 ++- .../drinkool/controller/StaffController.java | 33 ++++++ .../com/drinkool/services/FileService.java | 24 +++++ .../com/drinkool/services/StaffService.java | 31 ++++++ .../src/main/resources/application.properties | 1 + k8s/base/file.yaml | 69 ++++++++++++ k8s/base/kustomization.yaml | 2 + pom.xml | 1 + 23 files changed, 414 insertions(+), 20 deletions(-) create mode 100644 file-service/.mvn/wrapper/maven-wrapper.properties create mode 100644 file-service/pom.xml create mode 100644 file-service/python/Dockerfile create mode 100644 file-service/python/main.py create mode 100644 file-service/python/requirements.txt create mode 100644 gateway-service/src/main/java/com/drinkool/controller/FileController.java create mode 100644 gateway-service/src/main/java/com/drinkool/controller/StaffController.java create mode 100644 gateway-service/src/main/java/com/drinkool/services/FileService.java create mode 100644 gateway-service/src/main/java/com/drinkool/services/StaffService.java create mode 100644 k8s/base/file.yaml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 12d0c67..71702aa 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -26,7 +26,8 @@ RUN apt-get update --fix-missing && apt-get install --no-install-recommends --no kubectl \ openjdk-25-jdk-headless \ redis-server \ - maven + maven \ + python3-venv RUN jbang trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/ RUN jbang app install --fresh --force quarkus@quarkusio diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e44a899..b76a75a 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -23,7 +23,9 @@ "esbenp.prettier-vscode", "PeterSchmalfeldt.explorer-exclude", "redhat.java", - "ryanluker.vscode-coverage-gutters" + "ryanluker.vscode-coverage-gutters", + "ms-python.black-formatter", + "ms-python.python" ] } }, diff --git a/.vscode/settings.json b/.vscode/settings.json index 3e30470..efcd922 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,7 +8,8 @@ "**/target": true, "**/docker": true, "node_modules": true, - "**/.mvn": true + "**/.mvn": true, + "**/venv": true }, "explorerExclude.backup": {}, "java.compile.nullAnalysis.mode": "automatic", diff --git a/cart-service/pom.xml b/cart-service/pom.xml index febe854..d659d3f 100644 --- a/cart-service/pom.xml +++ b/cart-service/pom.xml @@ -111,16 +111,6 @@ quarkus-maven-plugin ${quarkus.platform.version} true - - - - build - generate-code - generate-code-tests - native-image-agent - - - maven-compiler-plugin diff --git a/cart-service/src/main/docker/Dockerfile.jvm b/cart-service/src/main/docker/Dockerfile.jvm index cc8756b..0936d37 100644 --- a/cart-service/src/main/docker/Dockerfile.jvm +++ b/cart-service/src/main/docker/Dockerfile.jvm @@ -80,7 +80,7 @@ # You can find more information about the UBI base runtime images and their configuration here: # https://rh-openjdk.github.io/redhat-openjdk-containers/ ### -FROM registry.access.redhat.com/ubi8/openjdk-21:1.23 +FROM registry.access.redhat.com/ubi9/openjdk-25:1.24 ENV LANGUAGE='en_US:en' diff --git a/cart-service/src/main/docker/Dockerfile.legacy-jar b/cart-service/src/main/docker/Dockerfile.legacy-jar index bbabecc..0b34a70 100644 --- a/cart-service/src/main/docker/Dockerfile.legacy-jar +++ b/cart-service/src/main/docker/Dockerfile.legacy-jar @@ -80,7 +80,7 @@ # You can find more information about the UBI base runtime images and their configuration here: # https://rh-openjdk.github.io/redhat-openjdk-containers/ ### -FROM registry.access.redhat.com/ubi8/openjdk-21:1.23 +FROM registry.access.redhat.com/ubi9/openjdk-25:1.24 ENV LANGUAGE='en_US:en' diff --git a/cart-service/src/main/docker/Dockerfile.native b/cart-service/src/main/docker/Dockerfile.native index ceaf1ba..133e8fa 100644 --- a/cart-service/src/main/docker/Dockerfile.native +++ b/cart-service/src/main/docker/Dockerfile.native @@ -19,7 +19,7 @@ # The `quay.io/quarkus/quarkus-micro-image:2.0` base image is based on UBI 9. # To use UBI 8, switch to `quay.io/quarkus/quarkus-micro-image:2.0`. ### -FROM quay.io/quarkus/quarkus-micro-image:2.0 +FROM quay.io/quarkus/ubi9-quarkus-micro-image:2.0 WORKDIR /work/ RUN chown 1001 /work \ && chmod "g+rwX" /work \ diff --git a/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java b/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java index 659bec5..62456e6 100644 --- a/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java +++ b/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java @@ -3,12 +3,14 @@ package com.drinkool.dtos; import com.drinkool.entities.MenuItemEntity; import com.drinkool.entities.ReviewEntity; import com.drinkool.lib.dtos.SendReview; +import jakarta.enterprise.context.ApplicationScoped; import org.mapstruct.BeanMapping; import org.mapstruct.Mapper; import org.mapstruct.MappingTarget; import org.mapstruct.NullValuePropertyMappingStrategy; -@Mapper(componentModel = "cdi") +@ApplicationScoped +@Mapper(componentModel = "jakarta") public interface DtoMapper { @BeanMapping( nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE diff --git a/file-service/.mvn/wrapper/maven-wrapper.properties b/file-service/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..ce33c1c --- /dev/null +++ b/file-service/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,4 @@ +wrapperVersion=3.3.4 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.15/apache-maven-3.9.15-bin.zip +distributionSha256Sum=b0d9292f06c5faded31ddcb6cb69099f316d6fea40a7778624b259bad9fed18a diff --git a/file-service/pom.xml b/file-service/pom.xml new file mode 100644 index 0000000..96d44cc --- /dev/null +++ b/file-service/pom.xml @@ -0,0 +1,102 @@ + + + 4.0.0 + + + com.drinkool + drinkool + 1.5.24 + ../pom.xml + + + file-service + + + vps.demonkernel.io.vn + foodsurf + file-service + true + + + ${quarkus.container-image.registry}/${quarkus.container-image.group}/${quarkus.container-image.name} + + + + + io.quarkus + quarkus-container-image-docker + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + docker-build-python + package + + exec + + + docker + ${project.basedir}/python + + build + -t + ${python.image.full.name}:${parent.version} + -t + ${python.image.full.name}:latest + . + + + + + + + + + + + + push-python-image + + + quarkus.container-image.push + true + + + + + + org.codehaus.mojo + exec-maven-plugin + + + docker-push-python + install + + exec + + + docker + + push + ${python.image.full.name} + + + + + + + + + + \ No newline at end of file diff --git a/file-service/python/Dockerfile b/file-service/python/Dockerfile new file mode 100644 index 0000000..4b4333e --- /dev/null +++ b/file-service/python/Dockerfile @@ -0,0 +1,32 @@ +# --- Stage 1: Build (Cài đặt thư viện) --- +FROM python:3.9-slim AS builder + +WORKDIR /build + +# Khởi tạo môi trường ảo để tách biệt thư viện +RUN python -m venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" + +COPY requirements.txt . +RUN pip install --upgrade --no-cache-dir -r requirements.txt + + +# --- Stage 2: Runtime (Chỉ chạy Prod) --- +FROM python:3.9-slim + +WORKDIR /app + +# Chỉ copy môi trường ảo đã build xong từ Stage 1 +COPY --from=builder /opt/venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" + +# Copy mã nguồn +COPY main.py . + +# Tạo folder lưu ảnh và phân quyền (tăng tính bảo mật) +RUN mkdir images && chmod 777 images + +# Chạy bằng Uvicorn với chế độ production (tắt reload) +# Port 80 theo yêu cầu trước đó của bạn +EXPOSE 80 +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80", "--workers", "4"] \ No newline at end of file diff --git a/file-service/python/main.py b/file-service/python/main.py new file mode 100644 index 0000000..3ca515d --- /dev/null +++ b/file-service/python/main.py @@ -0,0 +1,52 @@ +import uuid +import io +from fastapi import FastAPI, Request, HTTPException +from fastapi.responses import FileResponse +from pathlib import Path +from PIL import Image +import filetype + +app = FastAPI() + +STORAGE_DIR = Path("images") +STORAGE_DIR.mkdir(exist_ok=True) + + +@app.post("/") +async def upload_image(request: Request): + body = await request.body() + + if not body: + raise HTTPException(status_code=400, detail="Dữ liệu trống") + + kind = filetype.guess(body) + if kind is None or not kind.mime.startswith("image/"): + mime_type = kind.mime if kind else "không xác định" + raise HTTPException( + status_code=400, detail=f"Định dạng {mime_type} không được hỗ trợ" + ) + + try: + img = Image.open(io.BytesIO(body)) + + random_filename = f"{uuid.uuid4()}.webp" + file_path = STORAGE_DIR / random_filename + + img.save(file_path, format="WEBP", quality=80) + + return { + "status": "success", + "filename": random_filename, + "original_type": kind.mime, + } + + except Exception as e: + raise HTTPException(status_code=500, detail=f"Lỗi xử lý ảnh: {str(e)}") + + +@app.get("/{name}") +async def get_image(name: str): + file_path = STORAGE_DIR / name + if not file_path.exists(): + raise HTTPException(status_code=404, detail="NotFoundImage") + return FileResponse(file_path, media_type="image/webp") diff --git a/file-service/python/requirements.txt b/file-service/python/requirements.txt new file mode 100644 index 0000000..357be8c --- /dev/null +++ b/file-service/python/requirements.txt @@ -0,0 +1,5 @@ +fastapi +uvicorn +python-multipart +Pillow +filetype \ No newline at end of file diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 527d8b9..c143104 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -151,8 +151,8 @@ @{argLine} - - ${project.build.directory}/${project.build.finalName}-runner + ${project.build.directory}/${project.build.finalName}-runner org.jboss.logmanager.LogManager ${maven.home} diff --git a/gateway-service/src/main/java/com/drinkool/controller/FileController.java b/gateway-service/src/main/java/com/drinkool/controller/FileController.java new file mode 100644 index 0000000..d87ef15 --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/controller/FileController.java @@ -0,0 +1,32 @@ +package com.drinkool.controller; + +import com.drinkool.services.FileService; +import io.smallrye.mutiny.Uni; +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.core.Response; +import java.io.File; +import org.eclipse.microprofile.rest.client.inject.RestClient; +import org.jboss.resteasy.reactive.RestForm; + +@Path("/api/file") +public class FileController { + + @Inject + @RestClient + FileService fileService; + + @POST + public Uni upload(@RestForm File file) { + return fileService.upload(file); + } + + @GET + @Path("/{name}") + public Uni get(@PathParam("name") String name) { + return fileService.get(name); + } +} diff --git a/gateway-service/src/main/java/com/drinkool/controller/MainController.java b/gateway-service/src/main/java/com/drinkool/controller/MainController.java index 7f378df..eb31be8 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/MainController.java +++ b/gateway-service/src/main/java/com/drinkool/controller/MainController.java @@ -4,6 +4,7 @@ import com.drinkool.Url; import com.drinkool.lib.dtos.Login; import com.drinkool.services.CustomerService; import com.drinkool.services.ManagerService; +import com.drinkool.services.StaffService; import io.smallrye.mutiny.Uni; import jakarta.inject.Inject; import jakarta.ws.rs.POST; @@ -22,6 +23,10 @@ public class MainController extends BaseController { @RestClient CustomerService customerService; + @Inject + @RestClient + StaffService staffService; + @POST @Path(Url.Login) public Uni proxyLogin(Login input) { @@ -29,7 +34,12 @@ public class MainController extends BaseController { .login(input) .onFailure() .recoverWithUni(() -> { - return customerService.login(input); + return staffService + .login(input) + .onFailure() + .recoverWithUni(() -> { + return customerService.login(input); + }); }); } } diff --git a/gateway-service/src/main/java/com/drinkool/controller/StaffController.java b/gateway-service/src/main/java/com/drinkool/controller/StaffController.java new file mode 100644 index 0000000..47fe405 --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/controller/StaffController.java @@ -0,0 +1,33 @@ +package com.drinkool.controller; + +import com.drinkool.InternalValue; +import com.drinkool.Role; +import com.drinkool.Url; +import com.drinkool.lib.dtos.Signup; +import com.drinkool.services.StaffService; +import io.smallrye.mutiny.Uni; +import jakarta.inject.Inject; +import jakarta.ws.rs.HeaderParam; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Response; +import java.util.UUID; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +@Path("/api/" + Role.Staff) +public class StaffController { + + @Inject + @RestClient + StaffService staffService; + + @POST + @Path(Url.Signup) + public Uni signup( + Signup input, + @HeaderParam(InternalValue.userId) UUID userId, + @HeaderParam(InternalValue.role) String role + ) { + return staffService.signup(input, userId, role); + } +} diff --git a/gateway-service/src/main/java/com/drinkool/services/FileService.java b/gateway-service/src/main/java/com/drinkool/services/FileService.java new file mode 100644 index 0000000..cd04fb7 --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/services/FileService.java @@ -0,0 +1,24 @@ +package com.drinkool.services; + +import io.smallrye.mutiny.Uni; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.core.Response; + +import java.io.File; + +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; +import org.jboss.resteasy.reactive.RestForm; + +@RegisterRestClient(configKey = "file") +@Path("/") +public interface FileService { + @POST + Uni upload(@RestForm File file); + + @GET + @Path("/{name}") + Uni get(@PathParam("name") String name); +} diff --git a/gateway-service/src/main/java/com/drinkool/services/StaffService.java b/gateway-service/src/main/java/com/drinkool/services/StaffService.java new file mode 100644 index 0000000..6b6b2eb --- /dev/null +++ b/gateway-service/src/main/java/com/drinkool/services/StaffService.java @@ -0,0 +1,31 @@ +package com.drinkool.services; + +import com.drinkool.InternalValue; +import com.drinkool.Role; +import com.drinkool.Url; +import com.drinkool.lib.dtos.*; +import io.smallrye.mutiny.Uni; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.Response; +import java.util.*; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@RegisterRestClient(configKey = "account") +@Path(Role.Staff) +public interface StaffService { + @POST + @Path(Url.Signup) + Uni signup( + Signup input, + @HeaderParam(InternalValue.userId) UUID userId, + @HeaderParam(InternalValue.role) String role + ); + + @POST + @Path(Url.Login) + Uni login(Login input); + + @GET + @Path(Url.Me) + Uni me(@HeaderParam(InternalValue.userId) UUID id); +} diff --git a/gateway-service/src/main/resources/application.properties b/gateway-service/src/main/resources/application.properties index 9f7a285..e974aed 100644 --- a/gateway-service/src/main/resources/application.properties +++ b/gateway-service/src/main/resources/application.properties @@ -15,6 +15,7 @@ quarkus.native.additional-build-args=--future-defaults=all # Rest Client quarkus.rest-client.account.url=http://account-service quarkus.rest-client.eatery.url=http://eatery-service +quarkus.rest-client.file.url=http://file-service # GraphQL Client quarkus.smallrye-graphql-client.eatery.url=http://eatery-service/graphql diff --git a/k8s/base/file.yaml b/k8s/base/file.yaml new file mode 100644 index 0000000..d69d2a4 --- /dev/null +++ b/k8s/base/file.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: file-deploy +spec: + replicas: 1 + selector: + matchLabels: + app: file + template: + metadata: + labels: + app: file + spec: + containers: + - name: file-pod + image: git.demonkernel.io.vn/foodsurf/file-service:1.5.24 + imagePullPolicy: IfNotPresent + volumeMounts: + - name: file-volume + mountPath: /app/images + ports: + - containerPort: 8080 + resources: + requests: + memory: "128Mi" + cpu: "150m" + limits: + memory: "512Mi" + cpu: "450m" + volumes: + - name: file-volume + persistentVolumeClaim: + claimName: file-pvc +--- +apiVersion: v1 +kind: Service +metadata: + name: file-service +spec: + selector: + app: file + ports: + - port: 80 + targetPort: 80 +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: file-pv +spec: + capacity: + storage: 10Gi + accessModes: + - ReadWriteMany + nfs: + server: 192.168.1.100 + path: /data/images +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: file-pvc +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 10Gi diff --git a/k8s/base/kustomization.yaml b/k8s/base/kustomization.yaml index 76af622..678d10b 100644 --- a/k8s/base/kustomization.yaml +++ b/k8s/base/kustomization.yaml @@ -1,6 +1,8 @@ resources: - account.yaml - eatery.yaml + - cart.yaml + - file.yaml - gateway.yaml - redis.yaml - kafdrop.yaml diff --git a/pom.xml b/pom.xml index ec9ebe2..e109e52 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ account-service gateway-service cart-service + file-service From f0a52e53740a92436848a378ec049868db24c8f6 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Sun, 10 May 2026 14:28:07 +0000 Subject: [PATCH 42/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++ account-service/pom.xml | 2 +- cart-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- file-service/pom.xml | 30 +++++++++++-------- gateway-service/pom.xml | 2 +- .../com/drinkool/services/FileService.java | 2 -- k8s/base/account.yaml | 2 +- k8s/base/cart.yaml | 2 +- k8s/base/eatery.yaml | 2 +- k8s/base/file.yaml | 2 +- k8s/base/gateway.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 14 files changed, 36 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf13133..b8b3318 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.25](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.24...v1.5.25) (2026-05-10) + + +### Bug Fixes + +* add upload images ([#50](https://git.demonkernel.io.vn/FoodSurf/backend/issues/50)) ([c6683b2](https://git.demonkernel.io.vn/FoodSurf/backend/commit/c6683b28dc303ab89b5285be122f570e914ec167)) + ## [1.5.24](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.23...v1.5.24) (2026-05-07) diff --git a/account-service/pom.xml b/account-service/pom.xml index 044cb38..60330e0 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.24 + 1.5.25 ../pom.xml diff --git a/cart-service/pom.xml b/cart-service/pom.xml index d659d3f..843bc9d 100644 --- a/cart-service/pom.xml +++ b/cart-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.24 + 1.5.25 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index 6331087..c927c24 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.24 + 1.5.25 ../pom.xml diff --git a/file-service/pom.xml b/file-service/pom.xml index 96d44cc..4074fb7 100644 --- a/file-service/pom.xml +++ b/file-service/pom.xml @@ -1,24 +1,26 @@ - + 4.0.0 com.drinkool drinkool - 1.5.24 + 1.5.25 ../pom.xml file-service - vps.demonkernel.io.vn + vps.demonkernel.io.vn foodsurf - file-service + file-service true @@ -47,13 +49,16 @@ docker - ${project.basedir}/python + ${project.basedir}/python build -t - ${python.image.full.name}:${parent.version} + ${python.image.full.name}:${parent.version} -t - ${python.image.full.name}:latest + ${python.image.full.name}:latest . @@ -89,7 +94,8 @@ docker push - ${python.image.full.name} + ${python.image.full.name} @@ -99,4 +105,4 @@ - \ No newline at end of file + diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index c143104..d9ee6ba 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.24 + 1.5.25 ../pom.xml diff --git a/gateway-service/src/main/java/com/drinkool/services/FileService.java b/gateway-service/src/main/java/com/drinkool/services/FileService.java index cd04fb7..6b2f9d5 100644 --- a/gateway-service/src/main/java/com/drinkool/services/FileService.java +++ b/gateway-service/src/main/java/com/drinkool/services/FileService.java @@ -6,9 +6,7 @@ import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.core.Response; - import java.io.File; - import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; import org.jboss.resteasy.reactive.RestForm; diff --git a/k8s/base/account.yaml b/k8s/base/account.yaml index dcfc889..fd8a4f8 100644 --- a/k8s/base/account.yaml +++ b/k8s/base/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.24 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.25 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/cart.yaml b/k8s/base/cart.yaml index 7500e90..a7d00a4 100644 --- a/k8s/base/cart.yaml +++ b/k8s/base/cart.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: cart-pod - image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.24 + image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.25 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/eatery.yaml b/k8s/base/eatery.yaml index 59a99b9..7ea41e6 100644 --- a/k8s/base/eatery.yaml +++ b/k8s/base/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.24 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.25 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/file.yaml b/k8s/base/file.yaml index d69d2a4..ab236b2 100644 --- a/k8s/base/file.yaml +++ b/k8s/base/file.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: file-pod - image: git.demonkernel.io.vn/foodsurf/file-service:1.5.24 + image: git.demonkernel.io.vn/foodsurf/file-service:1.5.25 imagePullPolicy: IfNotPresent volumeMounts: - name: file-volume diff --git a/k8s/base/gateway.yaml b/k8s/base/gateway.yaml index 59f75e9..e9ba495 100644 --- a/k8s/base/gateway.yaml +++ b/k8s/base/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.24 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.25 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index 2f948b4..97e6369 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.24 + 1.5.25 ../pom.xml diff --git a/pom.xml b/pom.xml index e109e52..44ec424 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.24 + 1.5.25 pom 25 From 4290f482f4aa74467982cc5aa6293d9d308538d3 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Mon, 11 May 2026 07:27:14 +0000 Subject: [PATCH 43/51] fix: better getCart (#49) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/49 --- .gitea/workflows/publish.yaml | 2 +- .gitea/workflows/test.yaml | 4 +- .releaserc.yaml | 4 +- account-service/README.md | 10 +- account-service/mvnw | 295 ------------------ account-service/mvnw.cmd | 189 ----------- cart-service/README.md | 10 +- cart-service/mvnw | 295 ------------------ cart-service/mvnw.cmd | 189 ----------- .../drinkool/services/CartServiceTest.java | 2 + eatery-service/README.md | 10 +- eatery-service/mvnw | 295 ------------------ eatery-service/mvnw.cmd | 189 ----------- .../java/com/drinkool/dtos/AddMenuItem.java | 2 + .../java/com/drinkool/dtos/DtoMapper.java | 2 +- .../com/drinkool/dtos/UpdateMenuItem.java | 2 + .../com/drinkool/entities/MenuItemEntity.java | 3 + .../drinkool/services/EateryServiceTest.java | 3 +- file-service/python/main.py | 18 +- gateway-service/README.md | 10 +- gateway-service/mvnw | 295 ------------------ gateway-service/mvnw.cmd | 189 ----------- .../interfaces/MenuItemInterface.java | 2 + mvnw | 295 ------------------ mvnw.cmd | 189 ----------- 25 files changed, 44 insertions(+), 2460 deletions(-) delete mode 100755 account-service/mvnw delete mode 100644 account-service/mvnw.cmd delete mode 100755 cart-service/mvnw delete mode 100644 cart-service/mvnw.cmd delete mode 100755 eatery-service/mvnw delete mode 100644 eatery-service/mvnw.cmd delete mode 100755 gateway-service/mvnw delete mode 100644 gateway-service/mvnw.cmd delete mode 100755 mvnw delete mode 100644 mvnw.cmd diff --git a/.gitea/workflows/publish.yaml b/.gitea/workflows/publish.yaml index 5bf62e3..dcfb448 100644 --- a/.gitea/workflows/publish.yaml +++ b/.gitea/workflows/publish.yaml @@ -20,7 +20,7 @@ jobs: echo "Acquire::http::Proxy \"$http_proxy\";" > /etc/apt/apt.conf.d/80proxy apt-get update apt-get install -y --no-install-recommends --no-install-suggests \ - openjdk-25-jdk-headless docker-cli docker-buildx + openjdk-25-jdk-headless docker-cli docker-buildx maven - name: Setup SSH Key run: | diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index 6135fd9..c2644e2 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -32,7 +32,7 @@ jobs: echo "Acquire::http::Proxy \"$http_proxy\";" > /etc/apt/apt.conf.d/80proxy apt-get update apt-get install -y --no-install-recommends --no-install-suggests \ - openjdk-25-jdk-headless docker-cli docker-buildx zstd + openjdk-25-jdk-headless docker-cli docker-buildx zstd maven - uses: shogo82148/actions-setup-redis@v1 with: @@ -53,7 +53,7 @@ jobs: env: TESTCONTAINERS_RYUK_DISABLED: true run: | - ./mvnw -B clean install -Pnative \ + mvn -B clean install -Pnative \ -Dquarkus.container-image.push=false \ -Dquarkus.container-image.registry=git.demonkernel.io.vn diff --git a/.releaserc.yaml b/.releaserc.yaml index 7438140..94648bc 100644 --- a/.releaserc.yaml +++ b/.releaserc.yaml @@ -10,10 +10,10 @@ plugins: - "@semantic-release/changelog" - - "@semantic-release/exec" - prepareCmd: | - ./mvnw versions:set -DnewVersion=${nextRelease.version} && + mvn versions:set -DnewVersion=${nextRelease.version} && sed -i "/image:.*-service:/ s|:[^:]*$|:${nextRelease.version}|" k8s/base/*.yaml && if [ "${branch.name}" = "main" ]; then - ./mvnw package -B -Pnative -Dquarkus.container-image.tag=${nextRelease.version} -DskipTests + mvn package -B -Pnative -Dquarkus.container-image.tag=${nextRelease.version} -DskipTests fi - - "@saithodev/semantic-release-gitea" - giteaUrl: "https://git.demonkernel.io.vn/" diff --git a/account-service/README.md b/account-service/README.md index 9631e1d..590bef0 100644 --- a/account-service/README.md +++ b/account-service/README.md @@ -9,7 +9,7 @@ If you want to learn more about Quarkus, please visit its website: **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at . @@ -19,7 +19,7 @@ You can run your application in dev mode that enables live coding using: The application can be packaged using: ```shell script -./mvnw package +mvn package ``` It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory. @@ -30,7 +30,7 @@ The application is now runnable using `java -jar target/quarkus-app/quarkus-run. If you want to build an _über-jar_, execute the following command: ```shell script -./mvnw package -Dquarkus.package.jar.type=uber-jar +mvn package -Dquarkus.package.jar.type=uber-jar ``` The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`. @@ -40,13 +40,13 @@ The application, packaged as an _über-jar_, is now runnable using `java -jar ta You can create a native executable using: ```shell script -./mvnw package -Dnative +mvn package -Dnative ``` Or, if you don't have GraalVM installed, you can run the native executable build in a container using: ```shell script -./mvnw package -Dnative -Dquarkus.native.container-build=true +mvn package -Dnative -Dquarkus.native.container-build=true ``` You can then execute your native executable with: `./target/account-service-1.0.0-SNAPSHOT-runner` diff --git a/account-service/mvnw b/account-service/mvnw deleted file mode 100755 index bd8896b..0000000 --- a/account-service/mvnw +++ /dev/null @@ -1,295 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.3.4 -# -# Optional ENV vars -# ----------------- -# JAVA_HOME - location of a JDK home dir, required when download maven via java source -# MVNW_REPOURL - repo url base for downloading maven distribution -# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output -# ---------------------------------------------------------------------------- - -set -euf -[ "${MVNW_VERBOSE-}" != debug ] || set -x - -# OS specific support. -native_path() { printf %s\\n "$1"; } -case "$(uname)" in -CYGWIN* | MINGW*) - [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" - native_path() { cygpath --path --windows "$1"; } - ;; -esac - -# set JAVACMD and JAVACCMD -set_java_home() { - # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched - if [ -n "${JAVA_HOME-}" ]; then - if [ -x "$JAVA_HOME/jre/sh/java" ]; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - JAVACCMD="$JAVA_HOME/jre/sh/javac" - else - JAVACMD="$JAVA_HOME/bin/java" - JAVACCMD="$JAVA_HOME/bin/javac" - - if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then - echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 - echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 - return 1 - fi - fi - else - JAVACMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v java - )" || : - JAVACCMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v javac - )" || : - - if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then - echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 - return 1 - fi - fi -} - -# hash string like Java String::hashCode -hash_string() { - str="${1:-}" h=0 - while [ -n "$str" ]; do - char="${str%"${str#?}"}" - h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) - str="${str#?}" - done - printf %x\\n $h -} - -verbose() { :; } -[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } - -die() { - printf %s\\n "$1" >&2 - exit 1 -} - -trim() { - # MWRAPPER-139: - # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. - # Needed for removing poorly interpreted newline sequences when running in more - # exotic environments such as mingw bash on Windows. - printf "%s" "${1}" | tr -d '[:space:]' -} - -scriptDir="$(dirname "$0")" -scriptName="$(basename "$0")" - -# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties -while IFS="=" read -r key value; do - case "${key-}" in - distributionUrl) distributionUrl=$(trim "${value-}") ;; - distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; - esac -done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" -[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" - -case "${distributionUrl##*/}" in -maven-mvnd-*bin.*) - MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ - case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in - *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; - :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; - :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; - :Linux*x86_64*) distributionPlatform=linux-amd64 ;; - *) - echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 - distributionPlatform=linux-amd64 - ;; - esac - distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" - ;; -maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; -*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; -esac - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" -distributionUrlName="${distributionUrl##*/}" -distributionUrlNameMain="${distributionUrlName%.*}" -distributionUrlNameMain="${distributionUrlNameMain%-bin}" -MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" -MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" - -exec_maven() { - unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : - exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" -} - -if [ -d "$MAVEN_HOME" ]; then - verbose "found existing MAVEN_HOME at $MAVEN_HOME" - exec_maven "$@" -fi - -case "${distributionUrl-}" in -*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; -*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; -esac - -# prepare tmp dir -if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then - clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } - trap clean HUP INT TERM EXIT -else - die "cannot create temp dir" -fi - -mkdir -p -- "${MAVEN_HOME%/*}" - -# Download and Install Apache Maven -verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -verbose "Downloading from: $distributionUrl" -verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -# select .zip or .tar.gz -if ! command -v unzip >/dev/null; then - distributionUrl="${distributionUrl%.zip}.tar.gz" - distributionUrlName="${distributionUrl##*/}" -fi - -# verbose opt -__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' -[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v - -# normalize http auth -case "${MVNW_PASSWORD:+has-password}" in -'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; -has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; -esac - -if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then - verbose "Found wget ... using wget" - wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" -elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then - verbose "Found curl ... using curl" - curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" -elif set_java_home; then - verbose "Falling back to use Java to download" - javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" - targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" - cat >"$javaSource" <<-END - public class Downloader extends java.net.Authenticator - { - protected java.net.PasswordAuthentication getPasswordAuthentication() - { - return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); - } - public static void main( String[] args ) throws Exception - { - setDefault( new Downloader() ); - java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); - } - } - END - # For Cygwin/MinGW, switch paths to Windows format before running javac and java - verbose " - Compiling Downloader.java ..." - "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" - verbose " - Running Downloader.java ..." - "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" -fi - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -if [ -n "${distributionSha256Sum-}" ]; then - distributionSha256Result=false - if [ "$MVN_CMD" = mvnd.sh ]; then - echo "Checksum validation is not supported for maven-mvnd." >&2 - echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - elif command -v sha256sum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then - distributionSha256Result=true - fi - elif command -v shasum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then - distributionSha256Result=true - fi - else - echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 - echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - fi - if [ $distributionSha256Result = false ]; then - echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 - echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 - exit 1 - fi -fi - -# unzip and move -if command -v unzip >/dev/null; then - unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" -else - tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" -fi - -# Find the actual extracted directory name (handles snapshots where filename != directory name) -actualDistributionDir="" - -# First try the expected directory name (for regular distributions) -if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then - if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then - actualDistributionDir="$distributionUrlNameMain" - fi -fi - -# If not found, search for any directory with the Maven executable (for snapshots) -if [ -z "$actualDistributionDir" ]; then - # enable globbing to iterate over items - set +f - for dir in "$TMP_DOWNLOAD_DIR"/*; do - if [ -d "$dir" ]; then - if [ -f "$dir/bin/$MVN_CMD" ]; then - actualDistributionDir="$(basename "$dir")" - break - fi - fi - done - set -f -fi - -if [ -z "$actualDistributionDir" ]; then - verbose "Contents of $TMP_DOWNLOAD_DIR:" - verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" - die "Could not find Maven distribution directory in extracted archive" -fi - -verbose "Found extracted Maven distribution directory: $actualDistributionDir" -printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" -mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" - -clean || : -exec_maven "$@" diff --git a/account-service/mvnw.cmd b/account-service/mvnw.cmd deleted file mode 100644 index 5761d94..0000000 --- a/account-service/mvnw.cmd +++ /dev/null @@ -1,189 +0,0 @@ -<# : batch portion -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.3.4 -@REM -@REM Optional ENV vars -@REM MVNW_REPOURL - repo url base for downloading maven distribution -@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output -@REM ---------------------------------------------------------------------------- - -@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) -@SET __MVNW_CMD__= -@SET __MVNW_ERROR__= -@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% -@SET PSModulePath= -@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( - IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) -) -@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% -@SET __MVNW_PSMODULEP_SAVE= -@SET __MVNW_ARG0_NAME__= -@SET MVNW_USERNAME= -@SET MVNW_PASSWORD= -@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) -@echo Cannot start maven from wrapper >&2 && exit /b 1 -@GOTO :EOF -: end batch / begin powershell #> - -$ErrorActionPreference = "Stop" -if ($env:MVNW_VERBOSE -eq "true") { - $VerbosePreference = "Continue" -} - -# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties -$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl -if (!$distributionUrl) { - Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" -} - -switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { - "maven-mvnd-*" { - $USE_MVND = $true - $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" - $MVN_CMD = "mvnd.cmd" - break - } - default { - $USE_MVND = $false - $MVN_CMD = $script -replace '^mvnw','mvn' - break - } -} - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -if ($env:MVNW_REPOURL) { - $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } - $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" -} -$distributionUrlName = $distributionUrl -replace '^.*/','' -$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' - -$MAVEN_M2_PATH = "$HOME/.m2" -if ($env:MAVEN_USER_HOME) { - $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" -} - -if (-not (Test-Path -Path $MAVEN_M2_PATH)) { - New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null -} - -$MAVEN_WRAPPER_DISTS = $null -if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { - $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" -} else { - $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" -} - -$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" -$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' -$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" - -if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { - Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" - Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" - exit $? -} - -if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { - Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" -} - -# prepare tmp dir -$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile -$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" -$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null -trap { - if ($TMP_DOWNLOAD_DIR.Exists) { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } - } -} - -New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null - -# Download and Install Apache Maven -Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -Write-Verbose "Downloading from: $distributionUrl" -Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -$webclient = New-Object System.Net.WebClient -if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { - $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) -} -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum -if ($distributionSha256Sum) { - if ($USE_MVND) { - Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." - } - Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash - if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { - Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." - } -} - -# unzip and move -Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null - -# Find the actual extracted directory name (handles snapshots where filename != directory name) -$actualDistributionDir = "" - -# First try the expected directory name (for regular distributions) -$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" -$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" -if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { - $actualDistributionDir = $distributionUrlNameMain -} - -# If not found, search for any directory with the Maven executable (for snapshots) -if (!$actualDistributionDir) { - Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { - $testPath = Join-Path $_.FullName "bin/$MVN_CMD" - if (Test-Path -Path $testPath -PathType Leaf) { - $actualDistributionDir = $_.Name - } - } -} - -if (!$actualDistributionDir) { - Write-Error "Could not find Maven distribution directory in extracted archive" -} - -Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" -Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null -try { - Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null -} catch { - if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { - Write-Error "fail to move MAVEN_HOME" - } -} finally { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } -} - -Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/cart-service/README.md b/cart-service/README.md index dabca42..8ac50be 100644 --- a/cart-service/README.md +++ b/cart-service/README.md @@ -9,7 +9,7 @@ If you want to learn more about Quarkus, please visit its website: **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at . @@ -19,7 +19,7 @@ You can run your application in dev mode that enables live coding using: The application can be packaged using: ```shell script -./mvnw package +mvn package ``` It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory. @@ -30,7 +30,7 @@ The application is now runnable using `java -jar target/quarkus-app/quarkus-run. If you want to build an _über-jar_, execute the following command: ```shell script -./mvnw package -Dquarkus.package.jar.type=uber-jar +mvn package -Dquarkus.package.jar.type=uber-jar ``` The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`. @@ -40,13 +40,13 @@ The application, packaged as an _über-jar_, is now runnable using `java -jar ta You can create a native executable using: ```shell script -./mvnw package -Dnative +mvn package -Dnative ``` Or, if you don't have GraalVM installed, you can run the native executable build in a container using: ```shell script -./mvnw package -Dnative -Dquarkus.native.container-build=true +mvn package -Dnative -Dquarkus.native.container-build=true ``` You can then execute your native executable with: `./target/cart-service-1.0.0-SNAPSHOT-runner` diff --git a/cart-service/mvnw b/cart-service/mvnw deleted file mode 100755 index bd8896b..0000000 --- a/cart-service/mvnw +++ /dev/null @@ -1,295 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.3.4 -# -# Optional ENV vars -# ----------------- -# JAVA_HOME - location of a JDK home dir, required when download maven via java source -# MVNW_REPOURL - repo url base for downloading maven distribution -# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output -# ---------------------------------------------------------------------------- - -set -euf -[ "${MVNW_VERBOSE-}" != debug ] || set -x - -# OS specific support. -native_path() { printf %s\\n "$1"; } -case "$(uname)" in -CYGWIN* | MINGW*) - [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" - native_path() { cygpath --path --windows "$1"; } - ;; -esac - -# set JAVACMD and JAVACCMD -set_java_home() { - # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched - if [ -n "${JAVA_HOME-}" ]; then - if [ -x "$JAVA_HOME/jre/sh/java" ]; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - JAVACCMD="$JAVA_HOME/jre/sh/javac" - else - JAVACMD="$JAVA_HOME/bin/java" - JAVACCMD="$JAVA_HOME/bin/javac" - - if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then - echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 - echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 - return 1 - fi - fi - else - JAVACMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v java - )" || : - JAVACCMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v javac - )" || : - - if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then - echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 - return 1 - fi - fi -} - -# hash string like Java String::hashCode -hash_string() { - str="${1:-}" h=0 - while [ -n "$str" ]; do - char="${str%"${str#?}"}" - h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) - str="${str#?}" - done - printf %x\\n $h -} - -verbose() { :; } -[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } - -die() { - printf %s\\n "$1" >&2 - exit 1 -} - -trim() { - # MWRAPPER-139: - # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. - # Needed for removing poorly interpreted newline sequences when running in more - # exotic environments such as mingw bash on Windows. - printf "%s" "${1}" | tr -d '[:space:]' -} - -scriptDir="$(dirname "$0")" -scriptName="$(basename "$0")" - -# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties -while IFS="=" read -r key value; do - case "${key-}" in - distributionUrl) distributionUrl=$(trim "${value-}") ;; - distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; - esac -done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" -[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" - -case "${distributionUrl##*/}" in -maven-mvnd-*bin.*) - MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ - case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in - *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; - :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; - :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; - :Linux*x86_64*) distributionPlatform=linux-amd64 ;; - *) - echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 - distributionPlatform=linux-amd64 - ;; - esac - distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" - ;; -maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; -*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; -esac - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" -distributionUrlName="${distributionUrl##*/}" -distributionUrlNameMain="${distributionUrlName%.*}" -distributionUrlNameMain="${distributionUrlNameMain%-bin}" -MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" -MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" - -exec_maven() { - unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : - exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" -} - -if [ -d "$MAVEN_HOME" ]; then - verbose "found existing MAVEN_HOME at $MAVEN_HOME" - exec_maven "$@" -fi - -case "${distributionUrl-}" in -*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; -*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; -esac - -# prepare tmp dir -if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then - clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } - trap clean HUP INT TERM EXIT -else - die "cannot create temp dir" -fi - -mkdir -p -- "${MAVEN_HOME%/*}" - -# Download and Install Apache Maven -verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -verbose "Downloading from: $distributionUrl" -verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -# select .zip or .tar.gz -if ! command -v unzip >/dev/null; then - distributionUrl="${distributionUrl%.zip}.tar.gz" - distributionUrlName="${distributionUrl##*/}" -fi - -# verbose opt -__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' -[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v - -# normalize http auth -case "${MVNW_PASSWORD:+has-password}" in -'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; -has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; -esac - -if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then - verbose "Found wget ... using wget" - wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" -elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then - verbose "Found curl ... using curl" - curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" -elif set_java_home; then - verbose "Falling back to use Java to download" - javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" - targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" - cat >"$javaSource" <<-END - public class Downloader extends java.net.Authenticator - { - protected java.net.PasswordAuthentication getPasswordAuthentication() - { - return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); - } - public static void main( String[] args ) throws Exception - { - setDefault( new Downloader() ); - java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); - } - } - END - # For Cygwin/MinGW, switch paths to Windows format before running javac and java - verbose " - Compiling Downloader.java ..." - "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" - verbose " - Running Downloader.java ..." - "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" -fi - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -if [ -n "${distributionSha256Sum-}" ]; then - distributionSha256Result=false - if [ "$MVN_CMD" = mvnd.sh ]; then - echo "Checksum validation is not supported for maven-mvnd." >&2 - echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - elif command -v sha256sum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then - distributionSha256Result=true - fi - elif command -v shasum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then - distributionSha256Result=true - fi - else - echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 - echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - fi - if [ $distributionSha256Result = false ]; then - echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 - echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 - exit 1 - fi -fi - -# unzip and move -if command -v unzip >/dev/null; then - unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" -else - tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" -fi - -# Find the actual extracted directory name (handles snapshots where filename != directory name) -actualDistributionDir="" - -# First try the expected directory name (for regular distributions) -if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then - if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then - actualDistributionDir="$distributionUrlNameMain" - fi -fi - -# If not found, search for any directory with the Maven executable (for snapshots) -if [ -z "$actualDistributionDir" ]; then - # enable globbing to iterate over items - set +f - for dir in "$TMP_DOWNLOAD_DIR"/*; do - if [ -d "$dir" ]; then - if [ -f "$dir/bin/$MVN_CMD" ]; then - actualDistributionDir="$(basename "$dir")" - break - fi - fi - done - set -f -fi - -if [ -z "$actualDistributionDir" ]; then - verbose "Contents of $TMP_DOWNLOAD_DIR:" - verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" - die "Could not find Maven distribution directory in extracted archive" -fi - -verbose "Found extracted Maven distribution directory: $actualDistributionDir" -printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" -mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" - -clean || : -exec_maven "$@" diff --git a/cart-service/mvnw.cmd b/cart-service/mvnw.cmd deleted file mode 100644 index 5761d94..0000000 --- a/cart-service/mvnw.cmd +++ /dev/null @@ -1,189 +0,0 @@ -<# : batch portion -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.3.4 -@REM -@REM Optional ENV vars -@REM MVNW_REPOURL - repo url base for downloading maven distribution -@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output -@REM ---------------------------------------------------------------------------- - -@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) -@SET __MVNW_CMD__= -@SET __MVNW_ERROR__= -@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% -@SET PSModulePath= -@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( - IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) -) -@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% -@SET __MVNW_PSMODULEP_SAVE= -@SET __MVNW_ARG0_NAME__= -@SET MVNW_USERNAME= -@SET MVNW_PASSWORD= -@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) -@echo Cannot start maven from wrapper >&2 && exit /b 1 -@GOTO :EOF -: end batch / begin powershell #> - -$ErrorActionPreference = "Stop" -if ($env:MVNW_VERBOSE -eq "true") { - $VerbosePreference = "Continue" -} - -# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties -$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl -if (!$distributionUrl) { - Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" -} - -switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { - "maven-mvnd-*" { - $USE_MVND = $true - $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" - $MVN_CMD = "mvnd.cmd" - break - } - default { - $USE_MVND = $false - $MVN_CMD = $script -replace '^mvnw','mvn' - break - } -} - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -if ($env:MVNW_REPOURL) { - $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } - $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" -} -$distributionUrlName = $distributionUrl -replace '^.*/','' -$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' - -$MAVEN_M2_PATH = "$HOME/.m2" -if ($env:MAVEN_USER_HOME) { - $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" -} - -if (-not (Test-Path -Path $MAVEN_M2_PATH)) { - New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null -} - -$MAVEN_WRAPPER_DISTS = $null -if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { - $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" -} else { - $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" -} - -$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" -$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' -$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" - -if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { - Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" - Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" - exit $? -} - -if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { - Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" -} - -# prepare tmp dir -$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile -$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" -$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null -trap { - if ($TMP_DOWNLOAD_DIR.Exists) { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } - } -} - -New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null - -# Download and Install Apache Maven -Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -Write-Verbose "Downloading from: $distributionUrl" -Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -$webclient = New-Object System.Net.WebClient -if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { - $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) -} -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum -if ($distributionSha256Sum) { - if ($USE_MVND) { - Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." - } - Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash - if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { - Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." - } -} - -# unzip and move -Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null - -# Find the actual extracted directory name (handles snapshots where filename != directory name) -$actualDistributionDir = "" - -# First try the expected directory name (for regular distributions) -$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" -$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" -if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { - $actualDistributionDir = $distributionUrlNameMain -} - -# If not found, search for any directory with the Maven executable (for snapshots) -if (!$actualDistributionDir) { - Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { - $testPath = Join-Path $_.FullName "bin/$MVN_CMD" - if (Test-Path -Path $testPath -PathType Leaf) { - $actualDistributionDir = $_.Name - } - } -} - -if (!$actualDistributionDir) { - Write-Error "Could not find Maven distribution directory in extracted archive" -} - -Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" -Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null -try { - Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null -} catch { - if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { - Write-Error "fail to move MAVEN_HOME" - } -} finally { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } -} - -Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java b/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java index 52d26b0..62c999b 100644 --- a/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java +++ b/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java @@ -48,6 +48,8 @@ public class CartServiceTest { @BeforeEach void setup() { + redisDataSource.flushall(); + hashCommands = redisDataSource.hash(String.class); valueCommands = redisDataSource.value(String.class); } diff --git a/eatery-service/README.md b/eatery-service/README.md index 1824ac6..6890a0e 100644 --- a/eatery-service/README.md +++ b/eatery-service/README.md @@ -9,7 +9,7 @@ If you want to learn more about Quarkus, please visit its website: **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at . @@ -19,7 +19,7 @@ You can run your application in dev mode that enables live coding using: The application can be packaged using: ```shell script -./mvnw package +mvn package ``` It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory. @@ -30,7 +30,7 @@ The application is now runnable using `java -jar target/quarkus-app/quarkus-run. If you want to build an _über-jar_, execute the following command: ```shell script -./mvnw package -Dquarkus.package.jar.type=uber-jar +mvn package -Dquarkus.package.jar.type=uber-jar ``` The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`. @@ -40,13 +40,13 @@ The application, packaged as an _über-jar_, is now runnable using `java -jar ta You can create a native executable using: ```shell script -./mvnw package -Dnative +mvn package -Dnative ``` Or, if you don't have GraalVM installed, you can run the native executable build in a container using: ```shell script -./mvnw package -Dnative -Dquarkus.native.container-build=true +mvn package -Dnative -Dquarkus.native.container-build=true ``` You can then execute your native executable with: `./target/eatery-service-1.0.0-SNAPSHOT-runner` diff --git a/eatery-service/mvnw b/eatery-service/mvnw deleted file mode 100755 index bd8896b..0000000 --- a/eatery-service/mvnw +++ /dev/null @@ -1,295 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.3.4 -# -# Optional ENV vars -# ----------------- -# JAVA_HOME - location of a JDK home dir, required when download maven via java source -# MVNW_REPOURL - repo url base for downloading maven distribution -# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output -# ---------------------------------------------------------------------------- - -set -euf -[ "${MVNW_VERBOSE-}" != debug ] || set -x - -# OS specific support. -native_path() { printf %s\\n "$1"; } -case "$(uname)" in -CYGWIN* | MINGW*) - [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" - native_path() { cygpath --path --windows "$1"; } - ;; -esac - -# set JAVACMD and JAVACCMD -set_java_home() { - # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched - if [ -n "${JAVA_HOME-}" ]; then - if [ -x "$JAVA_HOME/jre/sh/java" ]; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - JAVACCMD="$JAVA_HOME/jre/sh/javac" - else - JAVACMD="$JAVA_HOME/bin/java" - JAVACCMD="$JAVA_HOME/bin/javac" - - if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then - echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 - echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 - return 1 - fi - fi - else - JAVACMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v java - )" || : - JAVACCMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v javac - )" || : - - if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then - echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 - return 1 - fi - fi -} - -# hash string like Java String::hashCode -hash_string() { - str="${1:-}" h=0 - while [ -n "$str" ]; do - char="${str%"${str#?}"}" - h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) - str="${str#?}" - done - printf %x\\n $h -} - -verbose() { :; } -[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } - -die() { - printf %s\\n "$1" >&2 - exit 1 -} - -trim() { - # MWRAPPER-139: - # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. - # Needed for removing poorly interpreted newline sequences when running in more - # exotic environments such as mingw bash on Windows. - printf "%s" "${1}" | tr -d '[:space:]' -} - -scriptDir="$(dirname "$0")" -scriptName="$(basename "$0")" - -# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties -while IFS="=" read -r key value; do - case "${key-}" in - distributionUrl) distributionUrl=$(trim "${value-}") ;; - distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; - esac -done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" -[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" - -case "${distributionUrl##*/}" in -maven-mvnd-*bin.*) - MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ - case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in - *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; - :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; - :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; - :Linux*x86_64*) distributionPlatform=linux-amd64 ;; - *) - echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 - distributionPlatform=linux-amd64 - ;; - esac - distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" - ;; -maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; -*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; -esac - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" -distributionUrlName="${distributionUrl##*/}" -distributionUrlNameMain="${distributionUrlName%.*}" -distributionUrlNameMain="${distributionUrlNameMain%-bin}" -MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" -MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" - -exec_maven() { - unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : - exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" -} - -if [ -d "$MAVEN_HOME" ]; then - verbose "found existing MAVEN_HOME at $MAVEN_HOME" - exec_maven "$@" -fi - -case "${distributionUrl-}" in -*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; -*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; -esac - -# prepare tmp dir -if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then - clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } - trap clean HUP INT TERM EXIT -else - die "cannot create temp dir" -fi - -mkdir -p -- "${MAVEN_HOME%/*}" - -# Download and Install Apache Maven -verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -verbose "Downloading from: $distributionUrl" -verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -# select .zip or .tar.gz -if ! command -v unzip >/dev/null; then - distributionUrl="${distributionUrl%.zip}.tar.gz" - distributionUrlName="${distributionUrl##*/}" -fi - -# verbose opt -__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' -[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v - -# normalize http auth -case "${MVNW_PASSWORD:+has-password}" in -'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; -has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; -esac - -if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then - verbose "Found wget ... using wget" - wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" -elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then - verbose "Found curl ... using curl" - curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" -elif set_java_home; then - verbose "Falling back to use Java to download" - javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" - targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" - cat >"$javaSource" <<-END - public class Downloader extends java.net.Authenticator - { - protected java.net.PasswordAuthentication getPasswordAuthentication() - { - return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); - } - public static void main( String[] args ) throws Exception - { - setDefault( new Downloader() ); - java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); - } - } - END - # For Cygwin/MinGW, switch paths to Windows format before running javac and java - verbose " - Compiling Downloader.java ..." - "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" - verbose " - Running Downloader.java ..." - "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" -fi - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -if [ -n "${distributionSha256Sum-}" ]; then - distributionSha256Result=false - if [ "$MVN_CMD" = mvnd.sh ]; then - echo "Checksum validation is not supported for maven-mvnd." >&2 - echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - elif command -v sha256sum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then - distributionSha256Result=true - fi - elif command -v shasum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then - distributionSha256Result=true - fi - else - echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 - echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - fi - if [ $distributionSha256Result = false ]; then - echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 - echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 - exit 1 - fi -fi - -# unzip and move -if command -v unzip >/dev/null; then - unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" -else - tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" -fi - -# Find the actual extracted directory name (handles snapshots where filename != directory name) -actualDistributionDir="" - -# First try the expected directory name (for regular distributions) -if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then - if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then - actualDistributionDir="$distributionUrlNameMain" - fi -fi - -# If not found, search for any directory with the Maven executable (for snapshots) -if [ -z "$actualDistributionDir" ]; then - # enable globbing to iterate over items - set +f - for dir in "$TMP_DOWNLOAD_DIR"/*; do - if [ -d "$dir" ]; then - if [ -f "$dir/bin/$MVN_CMD" ]; then - actualDistributionDir="$(basename "$dir")" - break - fi - fi - done - set -f -fi - -if [ -z "$actualDistributionDir" ]; then - verbose "Contents of $TMP_DOWNLOAD_DIR:" - verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" - die "Could not find Maven distribution directory in extracted archive" -fi - -verbose "Found extracted Maven distribution directory: $actualDistributionDir" -printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" -mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" - -clean || : -exec_maven "$@" diff --git a/eatery-service/mvnw.cmd b/eatery-service/mvnw.cmd deleted file mode 100644 index 5761d94..0000000 --- a/eatery-service/mvnw.cmd +++ /dev/null @@ -1,189 +0,0 @@ -<# : batch portion -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.3.4 -@REM -@REM Optional ENV vars -@REM MVNW_REPOURL - repo url base for downloading maven distribution -@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output -@REM ---------------------------------------------------------------------------- - -@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) -@SET __MVNW_CMD__= -@SET __MVNW_ERROR__= -@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% -@SET PSModulePath= -@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( - IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) -) -@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% -@SET __MVNW_PSMODULEP_SAVE= -@SET __MVNW_ARG0_NAME__= -@SET MVNW_USERNAME= -@SET MVNW_PASSWORD= -@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) -@echo Cannot start maven from wrapper >&2 && exit /b 1 -@GOTO :EOF -: end batch / begin powershell #> - -$ErrorActionPreference = "Stop" -if ($env:MVNW_VERBOSE -eq "true") { - $VerbosePreference = "Continue" -} - -# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties -$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl -if (!$distributionUrl) { - Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" -} - -switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { - "maven-mvnd-*" { - $USE_MVND = $true - $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" - $MVN_CMD = "mvnd.cmd" - break - } - default { - $USE_MVND = $false - $MVN_CMD = $script -replace '^mvnw','mvn' - break - } -} - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -if ($env:MVNW_REPOURL) { - $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } - $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" -} -$distributionUrlName = $distributionUrl -replace '^.*/','' -$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' - -$MAVEN_M2_PATH = "$HOME/.m2" -if ($env:MAVEN_USER_HOME) { - $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" -} - -if (-not (Test-Path -Path $MAVEN_M2_PATH)) { - New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null -} - -$MAVEN_WRAPPER_DISTS = $null -if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { - $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" -} else { - $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" -} - -$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" -$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' -$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" - -if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { - Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" - Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" - exit $? -} - -if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { - Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" -} - -# prepare tmp dir -$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile -$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" -$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null -trap { - if ($TMP_DOWNLOAD_DIR.Exists) { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } - } -} - -New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null - -# Download and Install Apache Maven -Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -Write-Verbose "Downloading from: $distributionUrl" -Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -$webclient = New-Object System.Net.WebClient -if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { - $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) -} -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum -if ($distributionSha256Sum) { - if ($USE_MVND) { - Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." - } - Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash - if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { - Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." - } -} - -# unzip and move -Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null - -# Find the actual extracted directory name (handles snapshots where filename != directory name) -$actualDistributionDir = "" - -# First try the expected directory name (for regular distributions) -$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" -$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" -if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { - $actualDistributionDir = $distributionUrlNameMain -} - -# If not found, search for any directory with the Maven executable (for snapshots) -if (!$actualDistributionDir) { - Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { - $testPath = Join-Path $_.FullName "bin/$MVN_CMD" - if (Test-Path -Path $testPath -PathType Leaf) { - $actualDistributionDir = $_.Name - } - } -} - -if (!$actualDistributionDir) { - Write-Error "Could not find Maven distribution directory in extracted archive" -} - -Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" -Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null -try { - Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null -} catch { - if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { - Write-Error "fail to move MAVEN_HOME" - } -} finally { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } -} - -Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/eatery-service/src/main/java/com/drinkool/dtos/AddMenuItem.java b/eatery-service/src/main/java/com/drinkool/dtos/AddMenuItem.java index fab4aed..67f5bd9 100644 --- a/eatery-service/src/main/java/com/drinkool/dtos/AddMenuItem.java +++ b/eatery-service/src/main/java/com/drinkool/dtos/AddMenuItem.java @@ -22,4 +22,6 @@ public class AddMenuItem implements MenuItemInterface { @NonNull private Double price; + + private String imageUrl; } diff --git a/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java b/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java index 62456e6..ca5a251 100644 --- a/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java +++ b/eatery-service/src/main/java/com/drinkool/dtos/DtoMapper.java @@ -10,7 +10,7 @@ import org.mapstruct.MappingTarget; import org.mapstruct.NullValuePropertyMappingStrategy; @ApplicationScoped -@Mapper(componentModel = "jakarta") +@Mapper(componentModel = "cdi") public interface DtoMapper { @BeanMapping( nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE diff --git a/eatery-service/src/main/java/com/drinkool/dtos/UpdateMenuItem.java b/eatery-service/src/main/java/com/drinkool/dtos/UpdateMenuItem.java index f25e2ff..ae5d20e 100644 --- a/eatery-service/src/main/java/com/drinkool/dtos/UpdateMenuItem.java +++ b/eatery-service/src/main/java/com/drinkool/dtos/UpdateMenuItem.java @@ -25,4 +25,6 @@ public class UpdateMenuItem implements EntityInterface, MenuItemInterface { String name; Double price; + + String imageUrl; } diff --git a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java index 93d57e4..d5c7412 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java @@ -24,6 +24,9 @@ public class MenuItemEntity extends BaseEntity implements MenuItemInterface { @JoinColumn(name = "eatery_id") public EateryEntity eatery; + @Column(nullable = true) + public String imageUrl; + MenuItemEntity() {} MenuItemEntity(MenuItemInterface input) { diff --git a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java index 50a6a4d..645cd80 100644 --- a/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/EateryServiceTest.java @@ -87,7 +87,8 @@ public class EateryServiceTest { eatery, new AddMenuItem( faker.food().dish(), - faker.number().randomDouble(2, 10, 100) + faker.number().randomDouble(2, 10, 100), + "" ) ).id; } diff --git a/file-service/python/main.py b/file-service/python/main.py index 3ca515d..939155a 100644 --- a/file-service/python/main.py +++ b/file-service/python/main.py @@ -1,6 +1,6 @@ import uuid import io -from fastapi import FastAPI, Request, HTTPException +from fastapi import FastAPI, File, UploadFile, HTTPException from fastapi.responses import FileResponse from pathlib import Path from PIL import Image @@ -13,18 +13,12 @@ STORAGE_DIR.mkdir(exist_ok=True) @app.post("/") -async def upload_image(request: Request): - body = await request.body() - - if not body: - raise HTTPException(status_code=400, detail="Dữ liệu trống") +async def upload_image(file: UploadFile = File(...)): + body = await file.read() kind = filetype.guess(body) - if kind is None or not kind.mime.startswith("image/"): - mime_type = kind.mime if kind else "không xác định" - raise HTTPException( - status_code=400, detail=f"Định dạng {mime_type} không được hỗ trợ" - ) + if not kind or not kind.mime.startswith("image/"): + raise HTTPException(status_code=400, detail="Chỉ chấp nhận file ảnh.") try: img = Image.open(io.BytesIO(body)) @@ -35,9 +29,7 @@ async def upload_image(request: Request): img.save(file_path, format="WEBP", quality=80) return { - "status": "success", "filename": random_filename, - "original_type": kind.mime, } except Exception as e: diff --git a/gateway-service/README.md b/gateway-service/README.md index 5f5744f..d2047fd 100644 --- a/gateway-service/README.md +++ b/gateway-service/README.md @@ -9,7 +9,7 @@ If you want to learn more about Quarkus, please visit its website: **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at . @@ -19,7 +19,7 @@ You can run your application in dev mode that enables live coding using: The application can be packaged using: ```shell script -./mvnw package +mvn package ``` It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory. @@ -30,7 +30,7 @@ The application is now runnable using `java -jar target/quarkus-app/quarkus-run. If you want to build an _über-jar_, execute the following command: ```shell script -./mvnw package -Dquarkus.package.jar.type=uber-jar +mvn package -Dquarkus.package.jar.type=uber-jar ``` The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`. @@ -40,13 +40,13 @@ The application, packaged as an _über-jar_, is now runnable using `java -jar ta You can create a native executable using: ```shell script -./mvnw package -Dnative +mvn package -Dnative ``` Or, if you don't have GraalVM installed, you can run the native executable build in a container using: ```shell script -./mvnw package -Dnative -Dquarkus.native.container-build=true +mvn package -Dnative -Dquarkus.native.container-build=true ``` You can then execute your native executable with: `./target/gateway-service-1.0.0-SNAPSHOT-runner` diff --git a/gateway-service/mvnw b/gateway-service/mvnw deleted file mode 100755 index bd8896b..0000000 --- a/gateway-service/mvnw +++ /dev/null @@ -1,295 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.3.4 -# -# Optional ENV vars -# ----------------- -# JAVA_HOME - location of a JDK home dir, required when download maven via java source -# MVNW_REPOURL - repo url base for downloading maven distribution -# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output -# ---------------------------------------------------------------------------- - -set -euf -[ "${MVNW_VERBOSE-}" != debug ] || set -x - -# OS specific support. -native_path() { printf %s\\n "$1"; } -case "$(uname)" in -CYGWIN* | MINGW*) - [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" - native_path() { cygpath --path --windows "$1"; } - ;; -esac - -# set JAVACMD and JAVACCMD -set_java_home() { - # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched - if [ -n "${JAVA_HOME-}" ]; then - if [ -x "$JAVA_HOME/jre/sh/java" ]; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - JAVACCMD="$JAVA_HOME/jre/sh/javac" - else - JAVACMD="$JAVA_HOME/bin/java" - JAVACCMD="$JAVA_HOME/bin/javac" - - if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then - echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 - echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 - return 1 - fi - fi - else - JAVACMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v java - )" || : - JAVACCMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v javac - )" || : - - if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then - echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 - return 1 - fi - fi -} - -# hash string like Java String::hashCode -hash_string() { - str="${1:-}" h=0 - while [ -n "$str" ]; do - char="${str%"${str#?}"}" - h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) - str="${str#?}" - done - printf %x\\n $h -} - -verbose() { :; } -[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } - -die() { - printf %s\\n "$1" >&2 - exit 1 -} - -trim() { - # MWRAPPER-139: - # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. - # Needed for removing poorly interpreted newline sequences when running in more - # exotic environments such as mingw bash on Windows. - printf "%s" "${1}" | tr -d '[:space:]' -} - -scriptDir="$(dirname "$0")" -scriptName="$(basename "$0")" - -# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties -while IFS="=" read -r key value; do - case "${key-}" in - distributionUrl) distributionUrl=$(trim "${value-}") ;; - distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; - esac -done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" -[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" - -case "${distributionUrl##*/}" in -maven-mvnd-*bin.*) - MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ - case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in - *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; - :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; - :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; - :Linux*x86_64*) distributionPlatform=linux-amd64 ;; - *) - echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 - distributionPlatform=linux-amd64 - ;; - esac - distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" - ;; -maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; -*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; -esac - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" -distributionUrlName="${distributionUrl##*/}" -distributionUrlNameMain="${distributionUrlName%.*}" -distributionUrlNameMain="${distributionUrlNameMain%-bin}" -MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" -MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" - -exec_maven() { - unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : - exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" -} - -if [ -d "$MAVEN_HOME" ]; then - verbose "found existing MAVEN_HOME at $MAVEN_HOME" - exec_maven "$@" -fi - -case "${distributionUrl-}" in -*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; -*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; -esac - -# prepare tmp dir -if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then - clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } - trap clean HUP INT TERM EXIT -else - die "cannot create temp dir" -fi - -mkdir -p -- "${MAVEN_HOME%/*}" - -# Download and Install Apache Maven -verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -verbose "Downloading from: $distributionUrl" -verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -# select .zip or .tar.gz -if ! command -v unzip >/dev/null; then - distributionUrl="${distributionUrl%.zip}.tar.gz" - distributionUrlName="${distributionUrl##*/}" -fi - -# verbose opt -__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' -[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v - -# normalize http auth -case "${MVNW_PASSWORD:+has-password}" in -'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; -has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; -esac - -if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then - verbose "Found wget ... using wget" - wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" -elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then - verbose "Found curl ... using curl" - curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" -elif set_java_home; then - verbose "Falling back to use Java to download" - javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" - targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" - cat >"$javaSource" <<-END - public class Downloader extends java.net.Authenticator - { - protected java.net.PasswordAuthentication getPasswordAuthentication() - { - return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); - } - public static void main( String[] args ) throws Exception - { - setDefault( new Downloader() ); - java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); - } - } - END - # For Cygwin/MinGW, switch paths to Windows format before running javac and java - verbose " - Compiling Downloader.java ..." - "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" - verbose " - Running Downloader.java ..." - "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" -fi - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -if [ -n "${distributionSha256Sum-}" ]; then - distributionSha256Result=false - if [ "$MVN_CMD" = mvnd.sh ]; then - echo "Checksum validation is not supported for maven-mvnd." >&2 - echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - elif command -v sha256sum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then - distributionSha256Result=true - fi - elif command -v shasum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then - distributionSha256Result=true - fi - else - echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 - echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - fi - if [ $distributionSha256Result = false ]; then - echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 - echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 - exit 1 - fi -fi - -# unzip and move -if command -v unzip >/dev/null; then - unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" -else - tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" -fi - -# Find the actual extracted directory name (handles snapshots where filename != directory name) -actualDistributionDir="" - -# First try the expected directory name (for regular distributions) -if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then - if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then - actualDistributionDir="$distributionUrlNameMain" - fi -fi - -# If not found, search for any directory with the Maven executable (for snapshots) -if [ -z "$actualDistributionDir" ]; then - # enable globbing to iterate over items - set +f - for dir in "$TMP_DOWNLOAD_DIR"/*; do - if [ -d "$dir" ]; then - if [ -f "$dir/bin/$MVN_CMD" ]; then - actualDistributionDir="$(basename "$dir")" - break - fi - fi - done - set -f -fi - -if [ -z "$actualDistributionDir" ]; then - verbose "Contents of $TMP_DOWNLOAD_DIR:" - verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" - die "Could not find Maven distribution directory in extracted archive" -fi - -verbose "Found extracted Maven distribution directory: $actualDistributionDir" -printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" -mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" - -clean || : -exec_maven "$@" diff --git a/gateway-service/mvnw.cmd b/gateway-service/mvnw.cmd deleted file mode 100644 index 5761d94..0000000 --- a/gateway-service/mvnw.cmd +++ /dev/null @@ -1,189 +0,0 @@ -<# : batch portion -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.3.4 -@REM -@REM Optional ENV vars -@REM MVNW_REPOURL - repo url base for downloading maven distribution -@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output -@REM ---------------------------------------------------------------------------- - -@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) -@SET __MVNW_CMD__= -@SET __MVNW_ERROR__= -@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% -@SET PSModulePath= -@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( - IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) -) -@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% -@SET __MVNW_PSMODULEP_SAVE= -@SET __MVNW_ARG0_NAME__= -@SET MVNW_USERNAME= -@SET MVNW_PASSWORD= -@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) -@echo Cannot start maven from wrapper >&2 && exit /b 1 -@GOTO :EOF -: end batch / begin powershell #> - -$ErrorActionPreference = "Stop" -if ($env:MVNW_VERBOSE -eq "true") { - $VerbosePreference = "Continue" -} - -# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties -$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl -if (!$distributionUrl) { - Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" -} - -switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { - "maven-mvnd-*" { - $USE_MVND = $true - $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" - $MVN_CMD = "mvnd.cmd" - break - } - default { - $USE_MVND = $false - $MVN_CMD = $script -replace '^mvnw','mvn' - break - } -} - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -if ($env:MVNW_REPOURL) { - $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } - $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" -} -$distributionUrlName = $distributionUrl -replace '^.*/','' -$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' - -$MAVEN_M2_PATH = "$HOME/.m2" -if ($env:MAVEN_USER_HOME) { - $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" -} - -if (-not (Test-Path -Path $MAVEN_M2_PATH)) { - New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null -} - -$MAVEN_WRAPPER_DISTS = $null -if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { - $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" -} else { - $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" -} - -$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" -$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' -$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" - -if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { - Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" - Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" - exit $? -} - -if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { - Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" -} - -# prepare tmp dir -$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile -$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" -$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null -trap { - if ($TMP_DOWNLOAD_DIR.Exists) { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } - } -} - -New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null - -# Download and Install Apache Maven -Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -Write-Verbose "Downloading from: $distributionUrl" -Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -$webclient = New-Object System.Net.WebClient -if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { - $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) -} -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum -if ($distributionSha256Sum) { - if ($USE_MVND) { - Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." - } - Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash - if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { - Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." - } -} - -# unzip and move -Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null - -# Find the actual extracted directory name (handles snapshots where filename != directory name) -$actualDistributionDir = "" - -# First try the expected directory name (for regular distributions) -$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" -$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" -if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { - $actualDistributionDir = $distributionUrlNameMain -} - -# If not found, search for any directory with the Maven executable (for snapshots) -if (!$actualDistributionDir) { - Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { - $testPath = Join-Path $_.FullName "bin/$MVN_CMD" - if (Test-Path -Path $testPath -PathType Leaf) { - $actualDistributionDir = $_.Name - } - } -} - -if (!$actualDistributionDir) { - Write-Error "Could not find Maven distribution directory in extracted archive" -} - -Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" -Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null -try { - Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null -} catch { - if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { - Write-Error "fail to move MAVEN_HOME" - } -} finally { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } -} - -Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/lib/src/main/java/com/drinkool/interfaces/MenuItemInterface.java b/lib/src/main/java/com/drinkool/interfaces/MenuItemInterface.java index 74aaabd..15bcffc 100644 --- a/lib/src/main/java/com/drinkool/interfaces/MenuItemInterface.java +++ b/lib/src/main/java/com/drinkool/interfaces/MenuItemInterface.java @@ -5,4 +5,6 @@ public interface MenuItemInterface { void setName(String x); Double getPrice(); void setPrice(Double x); + String getImageUrl(); + void setImageUrl(String x); } diff --git a/mvnw b/mvnw deleted file mode 100755 index bd8896b..0000000 --- a/mvnw +++ /dev/null @@ -1,295 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.3.4 -# -# Optional ENV vars -# ----------------- -# JAVA_HOME - location of a JDK home dir, required when download maven via java source -# MVNW_REPOURL - repo url base for downloading maven distribution -# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output -# ---------------------------------------------------------------------------- - -set -euf -[ "${MVNW_VERBOSE-}" != debug ] || set -x - -# OS specific support. -native_path() { printf %s\\n "$1"; } -case "$(uname)" in -CYGWIN* | MINGW*) - [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" - native_path() { cygpath --path --windows "$1"; } - ;; -esac - -# set JAVACMD and JAVACCMD -set_java_home() { - # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched - if [ -n "${JAVA_HOME-}" ]; then - if [ -x "$JAVA_HOME/jre/sh/java" ]; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - JAVACCMD="$JAVA_HOME/jre/sh/javac" - else - JAVACMD="$JAVA_HOME/bin/java" - JAVACCMD="$JAVA_HOME/bin/javac" - - if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then - echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 - echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 - return 1 - fi - fi - else - JAVACMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v java - )" || : - JAVACCMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v javac - )" || : - - if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then - echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 - return 1 - fi - fi -} - -# hash string like Java String::hashCode -hash_string() { - str="${1:-}" h=0 - while [ -n "$str" ]; do - char="${str%"${str#?}"}" - h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) - str="${str#?}" - done - printf %x\\n $h -} - -verbose() { :; } -[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } - -die() { - printf %s\\n "$1" >&2 - exit 1 -} - -trim() { - # MWRAPPER-139: - # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. - # Needed for removing poorly interpreted newline sequences when running in more - # exotic environments such as mingw bash on Windows. - printf "%s" "${1}" | tr -d '[:space:]' -} - -scriptDir="$(dirname "$0")" -scriptName="$(basename "$0")" - -# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties -while IFS="=" read -r key value; do - case "${key-}" in - distributionUrl) distributionUrl=$(trim "${value-}") ;; - distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; - esac -done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" -[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" - -case "${distributionUrl##*/}" in -maven-mvnd-*bin.*) - MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ - case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in - *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; - :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; - :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; - :Linux*x86_64*) distributionPlatform=linux-amd64 ;; - *) - echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 - distributionPlatform=linux-amd64 - ;; - esac - distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" - ;; -maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; -*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; -esac - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" -distributionUrlName="${distributionUrl##*/}" -distributionUrlNameMain="${distributionUrlName%.*}" -distributionUrlNameMain="${distributionUrlNameMain%-bin}" -MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" -MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" - -exec_maven() { - unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : - exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" -} - -if [ -d "$MAVEN_HOME" ]; then - verbose "found existing MAVEN_HOME at $MAVEN_HOME" - exec_maven "$@" -fi - -case "${distributionUrl-}" in -*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; -*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; -esac - -# prepare tmp dir -if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then - clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } - trap clean HUP INT TERM EXIT -else - die "cannot create temp dir" -fi - -mkdir -p -- "${MAVEN_HOME%/*}" - -# Download and Install Apache Maven -verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -verbose "Downloading from: $distributionUrl" -verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -# select .zip or .tar.gz -if ! command -v unzip >/dev/null; then - distributionUrl="${distributionUrl%.zip}.tar.gz" - distributionUrlName="${distributionUrl##*/}" -fi - -# verbose opt -__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' -[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v - -# normalize http auth -case "${MVNW_PASSWORD:+has-password}" in -'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; -has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; -esac - -if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then - verbose "Found wget ... using wget" - wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" -elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then - verbose "Found curl ... using curl" - curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" -elif set_java_home; then - verbose "Falling back to use Java to download" - javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" - targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" - cat >"$javaSource" <<-END - public class Downloader extends java.net.Authenticator - { - protected java.net.PasswordAuthentication getPasswordAuthentication() - { - return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); - } - public static void main( String[] args ) throws Exception - { - setDefault( new Downloader() ); - java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); - } - } - END - # For Cygwin/MinGW, switch paths to Windows format before running javac and java - verbose " - Compiling Downloader.java ..." - "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" - verbose " - Running Downloader.java ..." - "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" -fi - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -if [ -n "${distributionSha256Sum-}" ]; then - distributionSha256Result=false - if [ "$MVN_CMD" = mvnd.sh ]; then - echo "Checksum validation is not supported for maven-mvnd." >&2 - echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - elif command -v sha256sum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then - distributionSha256Result=true - fi - elif command -v shasum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then - distributionSha256Result=true - fi - else - echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 - echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - fi - if [ $distributionSha256Result = false ]; then - echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 - echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 - exit 1 - fi -fi - -# unzip and move -if command -v unzip >/dev/null; then - unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" -else - tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" -fi - -# Find the actual extracted directory name (handles snapshots where filename != directory name) -actualDistributionDir="" - -# First try the expected directory name (for regular distributions) -if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then - if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then - actualDistributionDir="$distributionUrlNameMain" - fi -fi - -# If not found, search for any directory with the Maven executable (for snapshots) -if [ -z "$actualDistributionDir" ]; then - # enable globbing to iterate over items - set +f - for dir in "$TMP_DOWNLOAD_DIR"/*; do - if [ -d "$dir" ]; then - if [ -f "$dir/bin/$MVN_CMD" ]; then - actualDistributionDir="$(basename "$dir")" - break - fi - fi - done - set -f -fi - -if [ -z "$actualDistributionDir" ]; then - verbose "Contents of $TMP_DOWNLOAD_DIR:" - verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" - die "Could not find Maven distribution directory in extracted archive" -fi - -verbose "Found extracted Maven distribution directory: $actualDistributionDir" -printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" -mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" - -clean || : -exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd deleted file mode 100644 index 5761d94..0000000 --- a/mvnw.cmd +++ /dev/null @@ -1,189 +0,0 @@ -<# : batch portion -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.3.4 -@REM -@REM Optional ENV vars -@REM MVNW_REPOURL - repo url base for downloading maven distribution -@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output -@REM ---------------------------------------------------------------------------- - -@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) -@SET __MVNW_CMD__= -@SET __MVNW_ERROR__= -@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% -@SET PSModulePath= -@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( - IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) -) -@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% -@SET __MVNW_PSMODULEP_SAVE= -@SET __MVNW_ARG0_NAME__= -@SET MVNW_USERNAME= -@SET MVNW_PASSWORD= -@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) -@echo Cannot start maven from wrapper >&2 && exit /b 1 -@GOTO :EOF -: end batch / begin powershell #> - -$ErrorActionPreference = "Stop" -if ($env:MVNW_VERBOSE -eq "true") { - $VerbosePreference = "Continue" -} - -# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties -$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl -if (!$distributionUrl) { - Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" -} - -switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { - "maven-mvnd-*" { - $USE_MVND = $true - $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" - $MVN_CMD = "mvnd.cmd" - break - } - default { - $USE_MVND = $false - $MVN_CMD = $script -replace '^mvnw','mvn' - break - } -} - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -if ($env:MVNW_REPOURL) { - $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } - $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" -} -$distributionUrlName = $distributionUrl -replace '^.*/','' -$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' - -$MAVEN_M2_PATH = "$HOME/.m2" -if ($env:MAVEN_USER_HOME) { - $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" -} - -if (-not (Test-Path -Path $MAVEN_M2_PATH)) { - New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null -} - -$MAVEN_WRAPPER_DISTS = $null -if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { - $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" -} else { - $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" -} - -$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" -$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' -$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" - -if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { - Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" - Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" - exit $? -} - -if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { - Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" -} - -# prepare tmp dir -$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile -$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" -$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null -trap { - if ($TMP_DOWNLOAD_DIR.Exists) { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } - } -} - -New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null - -# Download and Install Apache Maven -Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -Write-Verbose "Downloading from: $distributionUrl" -Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -$webclient = New-Object System.Net.WebClient -if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { - $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) -} -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum -if ($distributionSha256Sum) { - if ($USE_MVND) { - Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." - } - Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash - if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { - Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." - } -} - -# unzip and move -Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null - -# Find the actual extracted directory name (handles snapshots where filename != directory name) -$actualDistributionDir = "" - -# First try the expected directory name (for regular distributions) -$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" -$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" -if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { - $actualDistributionDir = $distributionUrlNameMain -} - -# If not found, search for any directory with the Maven executable (for snapshots) -if (!$actualDistributionDir) { - Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { - $testPath = Join-Path $_.FullName "bin/$MVN_CMD" - if (Test-Path -Path $testPath -PathType Leaf) { - $actualDistributionDir = $_.Name - } - } -} - -if (!$actualDistributionDir) { - Write-Error "Could not find Maven distribution directory in extracted archive" -} - -Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" -Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null -try { - Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null -} catch { - if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { - Write-Error "fail to move MAVEN_HOME" - } -} finally { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } -} - -Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" From 29bba8b9f8c048f8d020b4084cdb78cef761228e Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Mon, 11 May 2026 07:40:48 +0000 Subject: [PATCH 44/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- cart-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- file-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s/base/account.yaml | 2 +- k8s/base/cart.yaml | 2 +- k8s/base/eatery.yaml | 2 +- k8s/base/file.yaml | 2 +- k8s/base/gateway.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 13 files changed, 19 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8b3318..239a99c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.26](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.25...v1.5.26) (2026-05-11) + + +### Bug Fixes + +* better getCart ([#49](https://git.demonkernel.io.vn/FoodSurf/backend/issues/49)) ([4290f48](https://git.demonkernel.io.vn/FoodSurf/backend/commit/4290f482f4aa74467982cc5aa6293d9d308538d3)) + ## [1.5.25](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.24...v1.5.25) (2026-05-10) diff --git a/account-service/pom.xml b/account-service/pom.xml index 60330e0..cf4deb2 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.25 + 1.5.26 ../pom.xml diff --git a/cart-service/pom.xml b/cart-service/pom.xml index 843bc9d..75a1685 100644 --- a/cart-service/pom.xml +++ b/cart-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.25 + 1.5.26 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index c927c24..a7fe62e 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.25 + 1.5.26 ../pom.xml diff --git a/file-service/pom.xml b/file-service/pom.xml index 4074fb7..7187409 100644 --- a/file-service/pom.xml +++ b/file-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.25 + 1.5.26 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index d9ee6ba..8948d51 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.25 + 1.5.26 ../pom.xml diff --git a/k8s/base/account.yaml b/k8s/base/account.yaml index fd8a4f8..057deac 100644 --- a/k8s/base/account.yaml +++ b/k8s/base/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.25 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.26 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/cart.yaml b/k8s/base/cart.yaml index a7d00a4..44c2745 100644 --- a/k8s/base/cart.yaml +++ b/k8s/base/cart.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: cart-pod - image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.25 + image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.26 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/eatery.yaml b/k8s/base/eatery.yaml index 7ea41e6..b5be87e 100644 --- a/k8s/base/eatery.yaml +++ b/k8s/base/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.25 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.26 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/file.yaml b/k8s/base/file.yaml index ab236b2..eb01827 100644 --- a/k8s/base/file.yaml +++ b/k8s/base/file.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: file-pod - image: git.demonkernel.io.vn/foodsurf/file-service:1.5.25 + image: git.demonkernel.io.vn/foodsurf/file-service:1.5.26 imagePullPolicy: IfNotPresent volumeMounts: - name: file-volume diff --git a/k8s/base/gateway.yaml b/k8s/base/gateway.yaml index e9ba495..b9be3e1 100644 --- a/k8s/base/gateway.yaml +++ b/k8s/base/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.25 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.26 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index 97e6369..5cb2d4b 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.25 + 1.5.26 ../pom.xml diff --git a/pom.xml b/pom.xml index 44ec424..cb043a4 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.25 + 1.5.26 pom 25 From 345d4c056ccf6ab5f7c455a17e8a3eedfde3ac62 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Tue, 12 May 2026 02:14:21 +0000 Subject: [PATCH 45/51] fix: add shift features (#51) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/51 --- .gitea/workflows/test.yaml | 47 ++-- .../com/drinkool/services/StaffService.java | 2 + .../drinkool/services/StaffServiceTest.java | 4 - .../java/com/drinkool/dtos/CreateShift.java | 21 ++ .../java/com/drinkool/dtos/RegisterShift.java | 10 + .../com/drinkool/entities/EateryEntity.java | 7 + .../com/drinkool/entities/ShiftEntity.java | 32 +++ .../entities/ShiftRegistrationEntity.java | 37 +++ .../com/drinkool/services/ShiftService.java | 206 ++++++++++++++++ .../drinkool/services/ShiftServiceTest.java | 230 ++++++++++++++++++ gateway-service/pom.xml | 30 +-- .../src/main/resources/application.properties | 3 + .../main/java/com/drinkool/InternalValue.java | 1 + scripts/build.sh | 1 + 14 files changed, 598 insertions(+), 33 deletions(-) create mode 100644 eatery-service/src/main/java/com/drinkool/dtos/CreateShift.java create mode 100644 eatery-service/src/main/java/com/drinkool/dtos/RegisterShift.java create mode 100644 eatery-service/src/main/java/com/drinkool/entities/ShiftEntity.java create mode 100644 eatery-service/src/main/java/com/drinkool/entities/ShiftRegistrationEntity.java create mode 100644 eatery-service/src/main/java/com/drinkool/services/ShiftService.java create mode 100644 eatery-service/src/test/java/com/drinkool/services/ShiftServiceTest.java diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index c2644e2..f1b7150 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -15,18 +15,40 @@ permissions: checks: write jobs: - build-and-test: + build: runs-on: ubuntu-latest - steps: - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - name: Install dependencies with Proxy - env: - http_proxy: "http://host.docker.internal:3142" - https_proxy: "http://host.docker.internal:3142" + - name: Install JDK and Maven + run: | + # Kiểm tra proxy có hoạt động không + echo "Acquire::http::Proxy \"$http_proxy\";" > /etc/apt/apt.conf.d/80proxy + apt-get update + apt-get install -y --no-install-recommends --no-install-suggests \ + openjdk-25-jdk-headless docker-cli docker-buildx zstd maven + + - name: Cache Maven packages + uses: actions/cache@v4 + with: + path: | + ~/.m2/repository + **/target/native-image-cache + **/target/reports + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-maven- + + - name: Build native with Maven + run: | + mvn -B clean install -DskipTests -Pnative \ + -Dquarkus.container-image.push=false + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Install JDK and Maven run: | # Kiểm tra proxy có hoạt động không echo "Acquire::http::Proxy \"$http_proxy\";" > /etc/apt/apt.conf.d/80proxy @@ -46,16 +68,13 @@ jobs: **/target/native-image-cache **/target/reports key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- + restore-keys: ${{ runner.os }}-maven- - - name: Build and Test all module + - name: Run Tests env: TESTCONTAINERS_RYUK_DISABLED: true run: | - mvn -B clean install -Pnative \ - -Dquarkus.container-image.push=false \ - -Dquarkus.container-image.registry=git.demonkernel.io.vn + mvn clean test -Dquarkus.main.run-tests=true - name: Publish Test Report uses: dorny/test-reporter@v3 diff --git a/account-service/src/main/java/com/drinkool/services/StaffService.java b/account-service/src/main/java/com/drinkool/services/StaffService.java index 1a6c27c..e948890 100644 --- a/account-service/src/main/java/com/drinkool/services/StaffService.java +++ b/account-service/src/main/java/com/drinkool/services/StaffService.java @@ -43,6 +43,7 @@ public class StaffService extends BaseService { return Response.status(Response.Status.CREATED) .header(InternalValue.userId, staff.id.toString()) + .header(InternalValue.managerId, manager.id.toString()) .header(InternalValue.role, Role.Staff) .build(); } @@ -64,6 +65,7 @@ public class StaffService extends BaseService { return Response.accepted() .header(InternalValue.userId, staff.id.toString()) + .header(InternalValue.managerId, staff.serve.id.toString()) .header(InternalValue.role, Role.Staff) .entity(staff) .build(); diff --git a/account-service/src/test/java/com/drinkool/services/StaffServiceTest.java b/account-service/src/test/java/com/drinkool/services/StaffServiceTest.java index 5cce294..c13b0e5 100644 --- a/account-service/src/test/java/com/drinkool/services/StaffServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/StaffServiceTest.java @@ -10,12 +10,8 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.kafka.*; import io.restassured.http.ContentType; -import io.smallrye.reactive.messaging.kafka.companion.ConsumerTask; -import io.smallrye.reactive.messaging.kafka.companion.KafkaCompanion; import jakarta.ws.rs.core.Response; -import java.time.Duration; import net.datafaker.Faker; -import org.eclipse.microprofile.config.inject.ConfigProperty; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/eatery-service/src/main/java/com/drinkool/dtos/CreateShift.java b/eatery-service/src/main/java/com/drinkool/dtos/CreateShift.java new file mode 100644 index 0000000..222287a --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/dtos/CreateShift.java @@ -0,0 +1,21 @@ +package com.drinkool.dtos; + +import java.time.LocalTime; +import org.eclipse.microprofile.graphql.NonNull; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class CreateShift { + + @NonNull + public String name; + + @NonNull + public LocalTime startTime; + + @NonNull + public LocalTime endTime; + + public Integer maxStaff; +} diff --git a/eatery-service/src/main/java/com/drinkool/dtos/RegisterShift.java b/eatery-service/src/main/java/com/drinkool/dtos/RegisterShift.java new file mode 100644 index 0000000..5c4776a --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/dtos/RegisterShift.java @@ -0,0 +1,10 @@ +package com.drinkool.dtos; + +import java.util.UUID; +import org.eclipse.microprofile.graphql.NonNull; + +public class RegisterShift { + + @NonNull + public UUID shiftId; +} diff --git a/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java b/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java index f60ff5f..f9a04d1 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/EateryEntity.java @@ -27,6 +27,13 @@ public class EateryEntity extends BaseEntity { ) public List menuItems = new ArrayList<>(); + @OneToMany( + mappedBy = "eatery", + cascade = CascadeType.ALL, + orphanRemoval = true + ) + public List shifts = new ArrayList<>(); + public EateryEntity() {} @Transactional diff --git a/eatery-service/src/main/java/com/drinkool/entities/ShiftEntity.java b/eatery-service/src/main/java/com/drinkool/entities/ShiftEntity.java new file mode 100644 index 0000000..5738ced --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/entities/ShiftEntity.java @@ -0,0 +1,32 @@ +package com.drinkool.entities; + +import com.drinkool.lib.entities.BaseEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import java.time.LocalTime; +import java.util.UUID; + +@Entity +@Table +public class ShiftEntity extends BaseEntity { + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "eatery_id") + public EateryEntity eatery; + + @Column(nullable = false) + public String name; + + @Column(nullable = false) + public LocalTime startTime; + + @Column(nullable = false) + public LocalTime endTime; + + @Column(nullable = true) + public Integer maxStaff; +} diff --git a/eatery-service/src/main/java/com/drinkool/entities/ShiftRegistrationEntity.java b/eatery-service/src/main/java/com/drinkool/entities/ShiftRegistrationEntity.java new file mode 100644 index 0000000..22f643c --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/entities/ShiftRegistrationEntity.java @@ -0,0 +1,37 @@ +package com.drinkool.entities; + +import com.drinkool.lib.entities.BaseEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + +import java.util.List; +import java.util.UUID; + +@Entity +@Table +public class ShiftRegistrationEntity extends BaseEntity { + + @Column(nullable = false) + public UUID staffId; + + @ManyToOne + public ShiftEntity shift; + + public static long countByShift(UUID shiftId) { + return count("shift.id = ?1", shiftId); + } + + public static List findOverlappingShifts( + UUID staffId, + ShiftEntity registratingShift + ) { + return list( + "staffId = ?1 and shift.startTime < ?2 and shift.endTime > ?3", + staffId, + registratingShift.endTime, + registratingShift.startTime + ); + } +} diff --git a/eatery-service/src/main/java/com/drinkool/services/ShiftService.java b/eatery-service/src/main/java/com/drinkool/services/ShiftService.java new file mode 100644 index 0000000..b789b95 --- /dev/null +++ b/eatery-service/src/main/java/com/drinkool/services/ShiftService.java @@ -0,0 +1,206 @@ +package com.drinkool.services; + +import com.drinkool.InternalValue; +import com.drinkool.Role; +import com.drinkool.dtos.CreateShift; +import com.drinkool.dtos.RegisterShift; +import com.drinkool.entities.EateryEntity; +import com.drinkool.entities.ShiftEntity; +import com.drinkool.entities.ShiftRegistrationEntity; +import io.vertx.core.http.HttpServerRequest; +import jakarta.annotation.security.RolesAllowed; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; +import org.eclipse.microprofile.graphql.*; + +@GraphQLApi +@ApplicationScoped +public class ShiftService { + + @Inject + HttpServerRequest request; + + // --- QUERIES --- + + @Query("allShifts") + @Description("Lấy danh sách tất cả các loại ca trực") + @RolesAllowed({ Role.Staff, Role.Manager }) + public List getAllShifts() throws GraphQLException { + String ownerId = request.getHeader(InternalValue.managerId); + if (ownerId == null || ownerId.isEmpty()) { + ownerId = request.getHeader(InternalValue.userId); + } + + EateryEntity eatery = EateryEntity.findByOwnerId(ownerId); + + return ShiftEntity.list("eatery", eatery); + } + + @Query("myRegistrations") + @Description("Lấy danh sách ca trực mà nhân viên hiện tại đã đăng ký") + @RolesAllowed(Role.Staff) + public List getMyShifts() { + String userId = request.getHeader(InternalValue.userId); + return ShiftRegistrationEntity.list("staffId", UUID.fromString(userId)); + } + + @Query("allRegistrations") + @Description("Manager xem toàn bộ danh sách đăng ký của tất cả nhân viên") + @RolesAllowed(Role.Manager) + public List getAllRegistrations() { + return ShiftRegistrationEntity.listAll(); + } + + // --- MUTATIONS --- + + @Mutation("registerShift") + @Description("Nhân viên đăng ký vào một ca trực cụ thể") + @RolesAllowed(Role.Staff) + @Transactional + public ShiftRegistrationEntity registerShift( + @Name("registration") RegisterShift registration + ) throws GraphQLException { + String userIdStr = request.getHeader(InternalValue.userId); + String managerIdStr = request.getHeader(InternalValue.managerId); + UUID staffId = UUID.fromString(userIdStr); + + EateryEntity eatery = EateryEntity.findByOwnerId(managerIdStr); + if (eatery == null) throw new GraphQLException("NotFoundEatery"); + + ShiftEntity shift = ShiftEntity.find( + "id = ?1 and eatery.id = ?2", + registration.shiftId, + eatery.id + ).firstResult(); + if (shift == null) throw new GraphQLException("NotFoundShift"); + + List overlappingShifts = + ShiftRegistrationEntity.findOverlappingShifts(staffId, shift); + + if (!overlappingShifts.isEmpty()) { + String ids = overlappingShifts + .stream() + .map(reg -> reg.shift.id.toString()) + .distinct() + .collect(Collectors.joining(", ")); + throw new GraphQLException("OverlappingShift: " + ids); + } + + long currentStaffCount = ShiftRegistrationEntity.countByShift(shift.id); + if (shift.maxStaff != null && currentStaffCount >= shift.maxStaff) { + throw new GraphQLException("FulledShift"); + } + + ShiftRegistrationEntity record = new ShiftRegistrationEntity(); + record.staffId = staffId; + record.shift = shift; + record.persist(); + + return record; + } + + @Mutation("createShift") + @Description("Quản lý tạo mới một loại ca trực") + @RolesAllowed(Role.Manager) + @Transactional + public ShiftEntity createShift(@Name("shiftInput") CreateShift input) + throws GraphQLException { + String ownerId = request.getHeader(InternalValue.userId); + + EateryEntity eatery = EateryEntity.findByOwnerId(ownerId); + if (eatery == null) return null; + + ShiftEntity shift = new ShiftEntity(); + shift.eatery = eatery; + shift.name = input.name; + shift.startTime = input.startTime; + shift.endTime = input.endTime; + shift.maxStaff = input.maxStaff; + + if (shift.endTime.isBefore(shift.startTime)) { + throw new GraphQLException("InvalidEndTime"); + } + + shift.persist(); + return shift; + } + + @Mutation("updateShift") + @Description("Quản lý cập nhật thông tin ca trực") + @RolesAllowed(Role.Manager) + @Transactional + public ShiftEntity updateShift( + @Name("id") UUID id, + @Name("shiftInput") CreateShift input + ) throws GraphQLException { + ShiftEntity shift = ShiftEntity.findById(id); + if (shift == null) throw new GraphQLException("NotFoundShift"); + + String ownerId = request.getHeader(InternalValue.userId); + if ( + !shift.eatery.ownerId.toString().equals(ownerId) + ) throw new GraphQLException("InvalidShiftId"); + + shift.name = input.name; + shift.startTime = input.startTime; + shift.endTime = input.endTime; + shift.maxStaff = input.maxStaff; + + if (shift.endTime.isBefore(shift.startTime)) { + throw new GraphQLException("InvalidEndTime"); + } + + return shift; + } + + @Mutation("deleteShift") + @Description("Quản lý xóa một ca trực") + @RolesAllowed(Role.Manager) + @Transactional + public boolean deleteShift(@Name("id") UUID id) throws GraphQLException { + String ownerId = request.getHeader(InternalValue.userId); + + EateryEntity eatery = EateryEntity.findByOwnerId(ownerId); + if (eatery == null) { + throw new GraphQLException("NotFoundEatery"); + } + + ShiftEntity shift = ShiftEntity.find( + "id = ?1 and eatery = ?2", + id, + eatery + ).firstResult(); + if (shift == null) { + throw new GraphQLException("NotFoundShiftOrAccessDenied"); + } + + long count = ShiftRegistrationEntity.count("shift.id", id); + if (count > 0) throw new GraphQLException( + "CannotDeleteShiftWithRegistrations" + ); + + return ShiftEntity.deleteById(id); + } + + @Mutation("cancelRegistration") + @Description("Nhân viên hủy ca đã đăng ký") + @RolesAllowed(Role.Staff) + @Transactional + public boolean cancelRegistration(@Name("registrationId") UUID id) + throws GraphQLException { + String userId = request.getHeader(InternalValue.userId); + ShiftRegistrationEntity reg = ShiftRegistrationEntity.findById(id); + + if (reg == null) throw new GraphQLException("RegistrationNotFound"); + if (!reg.staffId.equals(UUID.fromString(userId))) { + throw new GraphQLException("NotYourRegistration"); + } + + reg.delete(); + return true; + } +} diff --git a/eatery-service/src/test/java/com/drinkool/services/ShiftServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/ShiftServiceTest.java new file mode 100644 index 0000000..4108692 --- /dev/null +++ b/eatery-service/src/test/java/com/drinkool/services/ShiftServiceTest.java @@ -0,0 +1,230 @@ +package com.drinkool.services; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.Matchers.*; + +import com.drinkool.InternalValue; +import com.drinkool.Role; +import com.drinkool.entities.EateryEntity; +import com.drinkool.entities.ShiftEntity; +import com.drinkool.entities.ShiftRegistrationEntity; +import io.quarkus.test.junit.QuarkusTest; +import jakarta.transaction.Transactional; +import java.time.LocalTime; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class ShiftServiceTest { + + @BeforeEach + @Transactional + void setup() { + ShiftRegistrationEntity.deleteAll(); + ShiftEntity.deleteAll(); + } + + // --- TEST QUERIES --- + + @Test + void testGetAllShifts() { + UUID ownerId = createMockOwner(); + EateryEntity eatery = createMockEatery(ownerId); + + createMockShift("Ca Sáng", "08:00:00", "12:00:00", eatery); + + given() + .header(InternalValue.role, Role.Manager) + .header(InternalValue.userId, ownerId) + .contentType("application/json") + .body("{ \"query\": \"{ allShifts { name startTime } }\" }") + .when() + .post("/graphql") + .then() + .statusCode(200) + .body("data.allShifts", hasSize(1)) + .body("data.allShifts[0].name", is("Ca Sáng")); + } + + // --- TEST MUTATIONS --- + + @Test + void testCreateShift_AsManager() { + String query = """ + mutation Create($input: CreateShiftInput!) + { createShift(shiftInput: $input) { id name } }"""; + + Map input = new HashMap<>(); + input.put("name", "Ca Sáng"); + input.put("startTime", "08:00:00"); + input.put("endTime", "12:00:00"); + input.put("maxStaff", 5); + + Map body = new HashMap<>(); + body.put("query", query); + body.put("variables", Map.of("input", input)); + + UUID ownerId = createMockOwner(); + createMockEatery(ownerId); + + given() + .contentType("application/json") + .header(InternalValue.role, Role.Manager) + .header(InternalValue.userId, ownerId) + .body(body) + .when() + .post("/graphql") + .then() + .statusCode(200) + .body("data.createShift.name", is("Ca Sáng")); + } + + @Test + void testRegisterShift_Success() { + UUID ownerId = createMockOwner(); + EateryEntity eatery = createMockEatery(ownerId); + + ShiftEntity shift = createMockShift( + "Ca Tối", + "18:00:00", + "22:00:00", + eatery + ); + UUID staffId = UUID.randomUUID(); + + String mutation = String.format( + "mutation { registerShift(registration: { shiftId: \\\"%s\\\" }) { id staffId } }", + shift.id + ); + + given() + .contentType("application/json") + .header(InternalValue.role, Role.Staff) + .header(InternalValue.userId, staffId.toString()) + .header(InternalValue.managerId, ownerId.toString()) + .body("{ \"query\": \"" + mutation + "\" }") + .when() + .post("/graphql") + .then() + .statusCode(200) + .body("data.registerShift.staffId", is(staffId.toString())); + } + + @Test + void testRegisterShift_Overlap_Fail() { + UUID ownerId = createMockOwner(); + EateryEntity eatery = createMockEatery(ownerId); + UUID staffId = UUID.randomUUID(); + + // Tạo 2 ca bị trùng giờ nhau + ShiftEntity shift1 = createMockShift( + "Ca 1", + "08:00:00", + "12:00:00", + eatery + ); + ShiftEntity shift2 = createMockShift( + "Ca 2", + "10:00:00", + "14:00:00", + eatery + ); + + // Đăng ký ca 1 trước + registerStaffToShift(staffId, shift1); + + // Đăng ký ca 2 (sẽ bị overlap) + String mutation = String.format( + "mutation { registerShift(registration: { shiftId: \\\"%s\\\" }) { id } }", + shift2.id + ); + + given() + .contentType("application/json") + .header(InternalValue.userId, staffId.toString()) + .header(InternalValue.managerId, ownerId.toString()) + .header(InternalValue.role, Role.Staff) + .body("{ \"query\": \"" + mutation + "\" }") + .when() + .post("/graphql") + .then() + .statusCode(200) + .body("errors", notNullValue()) + .body("errors[0].message", containsString("OverlappingShift")); + } + + @Test + void testDeleteShift_WithRegistrations_Fail() { + UUID ownerId = createMockOwner(); + EateryEntity eatery = createMockEatery(ownerId); + ShiftEntity shift = createMockShift( + "Ca Xóa", + "08:00:00", + "12:00:00", + eatery + ); + registerStaffToShift(UUID.randomUUID(), shift); + + String mutation = String.format( + "mutation { deleteShift(id: \\\"%s\\\") }", + shift.id + ); + + given() + .header(InternalValue.userId, ownerId.toString()) + .header(InternalValue.role, Role.Manager) + .contentType("application/json") + .body("{ \"query\": \"" + mutation + "\" }") + .when() + .post("/graphql") + .then() + .statusCode(200) + .body("errors[0].message", is("CannotDeleteShiftWithRegistrations")); + } + + // --- HELPER METHODS --- + + @Transactional + ShiftEntity createMockShift( + String name, + String start, + String end, + EateryEntity eatery + ) { + ShiftEntity shift = new ShiftEntity(); + shift.eatery = eatery; + shift.name = name; + shift.startTime = LocalTime.parse(start); + shift.endTime = LocalTime.parse(end); + shift.maxStaff = 5; + shift.persist(); + return shift; + } + + @Transactional + void registerStaffToShift(UUID staffId, ShiftEntity shift) { + ShiftRegistrationEntity reg = new ShiftRegistrationEntity(); + reg.staffId = staffId; + reg.shift = shift; + reg.persist(); + } + + @Transactional + public UUID createMockOwner() { + return UUID.randomUUID(); + } + + @Transactional + public EateryEntity createMockEatery(UUID ownerId) { + EateryEntity eatery = new EateryEntity(); + eatery.name = "Nhà hàng " + ownerId.toString().substring(0, 5); + eatery.ownerId = ownerId; + eatery.persist(); + + EateryEntity.getEntityManager().flush(); + return eatery; + } +} diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 8948d51..148dd83 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -1,8 +1,8 @@ - + 4.0.0 @@ -20,11 +20,9 @@ 3.15.0 25 UTF-8 - UTF-8 + UTF-8 quarkus-bom - io.quarkus.platform + io.quarkus.platform 3.32.4 true 3.5.4 @@ -55,6 +53,10 @@ ${org.projectlombok.version} provided + + io.quarkus + quarkus-smallrye-openapi + io.quarkus quarkus-security @@ -128,8 +130,7 @@ @{argLine} - org.jboss.logmanager.LogManager + org.jboss.logmanager.LogManager ${maven.home} 1 @@ -151,10 +152,9 @@ @{argLine} - ${project.build.directory}/${project.build.finalName}-runner - org.jboss.logmanager.LogManager + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager ${maven.home} @@ -176,4 +176,4 @@ - + \ No newline at end of file diff --git a/gateway-service/src/main/resources/application.properties b/gateway-service/src/main/resources/application.properties index e974aed..7b1b4a7 100644 --- a/gateway-service/src/main/resources/application.properties +++ b/gateway-service/src/main/resources/application.properties @@ -11,6 +11,9 @@ quarkus.container-image.additional-tags=latest quarkus.native.container-build=true quarkus.native.remote-container-build=true quarkus.native.additional-build-args=--future-defaults=all +quarkus.swagger-ui.always-include=false +quarkus.swagger-ui.request-interceptor=true +quarkus.swagger-ui.path=/api # Rest Client quarkus.rest-client.account.url=http://account-service diff --git a/lib/src/main/java/com/drinkool/InternalValue.java b/lib/src/main/java/com/drinkool/InternalValue.java index f0865a4..685289d 100644 --- a/lib/src/main/java/com/drinkool/InternalValue.java +++ b/lib/src/main/java/com/drinkool/InternalValue.java @@ -6,4 +6,5 @@ public class InternalValue { public static final String headerId = "X-Internal-"; public static final String userId = headerId + "UserId"; public static final String role = headerId + "Role"; + public static final String managerId = headerId + "ManagerId"; } diff --git a/scripts/build.sh b/scripts/build.sh index 83dcb7a..a2d6acd 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,4 +1,5 @@ mvn clean package -DskipTests \ + -Dquarkus.swagger-ui.always-include=true \ -Dquarkus.container-image.push=false \ -Dquarkus.container-image.registry=git.demonkernel.io.vn \ "$@" From 6032a7c31bbca269d3bcc97a479e518312554da2 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Tue, 12 May 2026 02:40:32 +0000 Subject: [PATCH 46/51] chore: release [ci skip] --- CHANGELOG.md | 8 +++++++ .../java/com/drinkool/dtos/CreateShift.java | 3 +-- .../entities/ShiftRegistrationEntity.java | 1 - .../drinkool/services/ShiftServiceTest.java | 2 +- gateway-service/pom.xml | 22 +++++++++++-------- 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 239a99c..27b12ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [1.5.26](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.25...v1.5.26) (2026-05-12) + + +### Bug Fixes + +* add shift features ([#51](https://git.demonkernel.io.vn/FoodSurf/backend/issues/51)) ([345d4c0](https://git.demonkernel.io.vn/FoodSurf/backend/commit/345d4c056ccf6ab5f7c455a17e8a3eedfde3ac62)) +* better getCart ([#49](https://git.demonkernel.io.vn/FoodSurf/backend/issues/49)) ([4290f48](https://git.demonkernel.io.vn/FoodSurf/backend/commit/4290f482f4aa74467982cc5aa6293d9d308538d3)) + ## [1.5.26](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.25...v1.5.26) (2026-05-11) diff --git a/eatery-service/src/main/java/com/drinkool/dtos/CreateShift.java b/eatery-service/src/main/java/com/drinkool/dtos/CreateShift.java index 222287a..b43ee20 100644 --- a/eatery-service/src/main/java/com/drinkool/dtos/CreateShift.java +++ b/eatery-service/src/main/java/com/drinkool/dtos/CreateShift.java @@ -1,9 +1,8 @@ package com.drinkool.dtos; import java.time.LocalTime; -import org.eclipse.microprofile.graphql.NonNull; - import lombok.NoArgsConstructor; +import org.eclipse.microprofile.graphql.NonNull; @NoArgsConstructor public class CreateShift { diff --git a/eatery-service/src/main/java/com/drinkool/entities/ShiftRegistrationEntity.java b/eatery-service/src/main/java/com/drinkool/entities/ShiftRegistrationEntity.java index 22f643c..b1caf35 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/ShiftRegistrationEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/ShiftRegistrationEntity.java @@ -5,7 +5,6 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; - import java.util.List; import java.util.UUID; diff --git a/eatery-service/src/test/java/com/drinkool/services/ShiftServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/ShiftServiceTest.java index 4108692..f9b89e4 100644 --- a/eatery-service/src/test/java/com/drinkool/services/ShiftServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/ShiftServiceTest.java @@ -103,7 +103,7 @@ public class ShiftServiceTest { given() .contentType("application/json") .header(InternalValue.role, Role.Staff) - .header(InternalValue.userId, staffId.toString()) + .header(InternalValue.userId, staffId.toString()) .header(InternalValue.managerId, ownerId.toString()) .body("{ \"query\": \"" + mutation + "\" }") .when() diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 148dd83..9f7ac51 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -1,8 +1,8 @@ - + 4.0.0 @@ -20,9 +20,11 @@ 3.15.0 25 UTF-8 - UTF-8 + UTF-8 quarkus-bom - io.quarkus.platform + io.quarkus.platform 3.32.4 true 3.5.4 @@ -130,7 +132,8 @@ @{argLine} - org.jboss.logmanager.LogManager + org.jboss.logmanager.LogManager ${maven.home} 1 @@ -154,7 +157,8 @@ ${project.build.directory}/${project.build.finalName}-runner - org.jboss.logmanager.LogManager + org.jboss.logmanager.LogManager ${maven.home} @@ -176,4 +180,4 @@ - \ No newline at end of file + From 88244cb56f28193cd8cb0da78d5b8d290870284b Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Tue, 12 May 2026 05:22:08 +0000 Subject: [PATCH 47/51] fix: add payment features (#52) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/52 --- .gitea/workflows/test.yaml | 10 ++- .releaserc.yaml | 2 +- .../com/drinkool/entities/ManagerEntity.java | 16 ++++ .../drinkool/services/CustomerService.java | 1 - .../com/drinkool/services/ManagerService.java | 41 ++++++++- .../com/drinkool/services/StaffService.java | 1 - .../controllers/ManagerController.java | 22 +++++ .../src/main/java/com/drinkool/dtos/Cart.java | 2 + .../main/java/com/drinkool/dtos/CartItem.java | 3 + .../com/drinkool/services/CartService.java | 87 +++++++++++++++---- .../src/main/resources/application.properties | 1 + .../drinkool/services/CartServiceTest.java | 10 ++- .../com/drinkool/services/EateryService.java | 22 ++--- .../src/main/resources/application.properties | 6 +- file-service/pom.xml | 4 +- .../com/drinkool/lib/dtos/ManagerSignup.java | 2 + 16 files changed, 190 insertions(+), 40 deletions(-) create mode 100644 cart-service/src/main/java/com/drinkool/controllers/ManagerController.java diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index f1b7150..6a8b018 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -20,7 +20,10 @@ jobs: steps: - uses: actions/checkout@v6 - - name: Install JDK and Maven + - name: Install dependencies with Proxy + env: + http_proxy: "http://host.docker.internal:3142" + https_proxy: "http://host.docker.internal:3142" run: | # Kiểm tra proxy có hoạt động không echo "Acquire::http::Proxy \"$http_proxy\";" > /etc/apt/apt.conf.d/80proxy @@ -48,7 +51,10 @@ jobs: steps: - uses: actions/checkout@v6 - - name: Install JDK and Maven + - name: Install dependencies with Proxy + env: + http_proxy: "http://host.docker.internal:3142" + https_proxy: "http://host.docker.internal:3142" run: | # Kiểm tra proxy có hoạt động không echo "Acquire::http::Proxy \"$http_proxy\";" > /etc/apt/apt.conf.d/80proxy diff --git a/.releaserc.yaml b/.releaserc.yaml index 94648bc..7437b9a 100644 --- a/.releaserc.yaml +++ b/.releaserc.yaml @@ -13,7 +13,7 @@ plugins: mvn versions:set -DnewVersion=${nextRelease.version} && sed -i "/image:.*-service:/ s|:[^:]*$|:${nextRelease.version}|" k8s/base/*.yaml && if [ "${branch.name}" = "main" ]; then - mvn package -B -Pnative -Dquarkus.container-image.tag=${nextRelease.version} -DskipTests + mvn package -B -Pnative -Dquarkus.container-image.tag=${nextRelease.version} -DskipTests -Ppush fi - - "@saithodev/semantic-release-gitea" - giteaUrl: "https://git.demonkernel.io.vn/" diff --git a/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java b/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java index 8b08ce8..8649b9c 100644 --- a/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java +++ b/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java @@ -3,6 +3,7 @@ package com.drinkool.entities; import com.drinkool.Role; import com.drinkool.models.UserModel; import jakarta.persistence.*; +import jakarta.transaction.Transactional; import java.util.ArrayList; import java.util.List; @@ -17,7 +18,22 @@ public class ManagerEntity extends UserModel { ) public List staffs = new ArrayList<>(); + @Column(nullable = true) + public String bankAccount; + public ManagerEntity() { super(Role.Manager); } + + @Transactional + public void signup( + String name, + String phone, + String bankAccount, + String rawPassword + ) { + this.bankAccount = bankAccount; + + super.signup(name, phone, rawPassword); + } } diff --git a/account-service/src/main/java/com/drinkool/services/CustomerService.java b/account-service/src/main/java/com/drinkool/services/CustomerService.java index ee9f58d..a57abc9 100644 --- a/account-service/src/main/java/com/drinkool/services/CustomerService.java +++ b/account-service/src/main/java/com/drinkool/services/CustomerService.java @@ -65,7 +65,6 @@ public class CustomerService extends BaseService { return Response.accepted() .header(InternalValue.userId, customer.id.toString()) .header(InternalValue.role, Role.Customer) - .entity(customer) .build(); } diff --git a/account-service/src/main/java/com/drinkool/services/ManagerService.java b/account-service/src/main/java/com/drinkool/services/ManagerService.java index b9ef5f9..ddb77fe 100644 --- a/account-service/src/main/java/com/drinkool/services/ManagerService.java +++ b/account-service/src/main/java/com/drinkool/services/ManagerService.java @@ -8,6 +8,7 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.transaction.Transactional; import jakarta.ws.rs.*; import jakarta.ws.rs.core.*; +import java.util.UUID; import org.eclipse.microprofile.reactive.messaging.*; @Path(Role.Manager) @@ -27,7 +28,12 @@ public class ManagerService extends BaseService { public Response signup(ManagerSignup input) { ManagerEntity newManager = new ManagerEntity(); - newManager.signup(input.name, input.phone, input.password); + newManager.signup( + input.name, + input.phone, + input.bankAccount, + input.password + ); ManagerCreate message = new ManagerCreate(); message.id = newManager.id; @@ -62,7 +68,38 @@ public class ManagerService extends BaseService { return Response.accepted() .header(InternalValue.userId, manager.id.toString()) .header(InternalValue.role, Role.Manager) - .entity(manager) .build(); } + + @GET + @Path("/{id}/payment-qr") + public Response getManagerPaymentQr( + @PathParam("id") UUID id, + @QueryParam("amount") Long amount, + @QueryParam("cartId") String cartId + ) { + ManagerEntity manager = ManagerEntity.findById(id); + if (manager == null) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("ManagerNotFound") + .build(); + } + + if (manager.bankAccount == null || manager.bankAccount.isEmpty()) { + return Response.status(Response.Status.BAD_REQUEST) + .entity("ManagerHasNotConfiguredBankInfo") + .build(); + } + + String description = cartId; + + return Response.ok( + String.format( + "https://img.vietqr.io/image/%s-compact.png?amount=%d&addInfo=%s", + manager.bankAccount, + amount, + description + ) + ).build(); + } } diff --git a/account-service/src/main/java/com/drinkool/services/StaffService.java b/account-service/src/main/java/com/drinkool/services/StaffService.java index e948890..b8bcaef 100644 --- a/account-service/src/main/java/com/drinkool/services/StaffService.java +++ b/account-service/src/main/java/com/drinkool/services/StaffService.java @@ -67,7 +67,6 @@ public class StaffService extends BaseService { .header(InternalValue.userId, staff.id.toString()) .header(InternalValue.managerId, staff.serve.id.toString()) .header(InternalValue.role, Role.Staff) - .entity(staff) .build(); } } diff --git a/cart-service/src/main/java/com/drinkool/controllers/ManagerController.java b/cart-service/src/main/java/com/drinkool/controllers/ManagerController.java new file mode 100644 index 0000000..043950c --- /dev/null +++ b/cart-service/src/main/java/com/drinkool/controllers/ManagerController.java @@ -0,0 +1,22 @@ +package com.drinkool.controllers; + +import com.drinkool.Role; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.Response; +import java.util.UUID; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@RegisterRestClient(configKey = "eatery") +@Path(Role.Manager) +public interface ManagerController { + @GET + @Path(Role.Manager + "/{id}/payment-qr") + public Response getManagerPaymentQr( + @PathParam("id") UUID id, + @QueryParam("amount") Long amount, + @QueryParam("cartId") String cartId + ); +} diff --git a/cart-service/src/main/java/com/drinkool/dtos/Cart.java b/cart-service/src/main/java/com/drinkool/dtos/Cart.java index 77ad94a..0466563 100644 --- a/cart-service/src/main/java/com/drinkool/dtos/Cart.java +++ b/cart-service/src/main/java/com/drinkool/dtos/Cart.java @@ -15,4 +15,6 @@ public class Cart { public UUID userId; public UUID eateryId; public List items; + public long totalAmount; + public String paymentQrUrl; } diff --git a/cart-service/src/main/java/com/drinkool/dtos/CartItem.java b/cart-service/src/main/java/com/drinkool/dtos/CartItem.java index 56c0fa0..bcb9e23 100644 --- a/cart-service/src/main/java/com/drinkool/dtos/CartItem.java +++ b/cart-service/src/main/java/com/drinkool/dtos/CartItem.java @@ -11,4 +11,7 @@ public class CartItem { public String productId; public Integer quantity; + + public Double priceAtTimeOfAdding; + public Double subTotal; } diff --git a/cart-service/src/main/java/com/drinkool/services/CartService.java b/cart-service/src/main/java/com/drinkool/services/CartService.java index be0e54c..7c2c6ed 100644 --- a/cart-service/src/main/java/com/drinkool/services/CartService.java +++ b/cart-service/src/main/java/com/drinkool/services/CartService.java @@ -2,19 +2,20 @@ package com.drinkool.services; import com.drinkool.InternalValue; import com.drinkool.controllers.EateryController; +import com.drinkool.controllers.ManagerController; import com.drinkool.dtos.Cart; import com.drinkool.dtos.CartItem; import io.quarkus.redis.datasource.RedisDataSource; import io.quarkus.redis.datasource.hash.HashCommands; import io.quarkus.redis.datasource.value.ValueCommands; import io.smallrye.mutiny.Uni; +import io.smallrye.mutiny.infrastructure.Infrastructure; import io.vertx.core.http.HttpServerRequest; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.ws.rs.core.Response; import java.time.Duration; import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.UUID; import org.eclipse.microprofile.graphql.GraphQLApi; @@ -35,6 +36,10 @@ public class CartService { @RestClient EateryController eateryController; + @Inject + @RestClient + ManagerController managerController; + private final HashCommands hashCommands; private final ValueCommands valueCommands; @@ -50,6 +55,7 @@ public class CartService { return eateryController .getEateryById(eateryId) + .emitOn(Infrastructure.getDefaultWorkerPool()) .onItem() .transform(response -> { if (response.getStatus() != Response.Status.OK.getStatusCode()) { @@ -58,6 +64,7 @@ public class CartService { String cartId = UUID.randomUUID().toString(); String redisKey = "cart:" + cartId; + String ownerId = response.getEntity().toString(); hashCommands.hset( redisKey, @@ -65,7 +72,9 @@ public class CartService { "_metadata_owner", userId != null ? userId : "GUEST", "_metadata_eatery", - eateryId.toString() + eateryId.toString(), + "_metadata_eateryManagerId", + ownerId ) ); @@ -87,27 +96,56 @@ public class CartService { @Query("getCart") public Cart getCart(@Name("cartId") UUID cartId) throws GraphQLException { String key = "cart:" + cartId; + String priceKey = "cart_prices:" + cartId; Map data = hashCommands.hgetall(key); + Map itemPrices = hashCommands.hgetall(priceKey); + String managerId = hashCommands.hget(key, "_metadata_eateryManagerId"); if (data.isEmpty()) { throw new GraphQLException("NotFoundCart"); } - List items = new ArrayList<>(); + Cart cart = new Cart(); + cart.Id = cartId; + cart.eateryId = UUID.fromString(data.get("_metadata_eatery")); + cart.userId = UUID.fromString(data.get("_metadata_owner")); + cart.items = new ArrayList<>(); - data.forEach((k, v) -> { - if (!k.startsWith("_")) { - items.add(new CartItem(k, Integer.parseInt(v))); - } - }); + long total = 0; - return new Cart( - cartId, - UUID.fromString(data.get("_metadata_owner")), - UUID.fromString(data.get("_metadata_eatery")), - items - ); + for (Map.Entry entry : data.entrySet()) { + String field = entry.getKey(); + if (field.startsWith("_metadata_")) continue; + + Integer qty = Integer.parseInt(entry.getValue()); + Double price = Double.parseDouble(itemPrices.getOrDefault(field, "0")); + Double subTotal = qty * price; + + CartItem item = new CartItem(); + item.productId = field; + item.quantity = qty; + item.priceAtTimeOfAdding = price; + item.subTotal = subTotal; + + cart.items.add(item); + total += subTotal; + } + cart.totalAmount = total; + + try { + Response response = managerController.getManagerPaymentQr( + UUID.fromString(managerId), + total, + cartId.toString() + ); + + cart.paymentQrUrl = response.readEntity(String.class); + } catch (Exception e) { + cart.paymentQrUrl = ""; + } + + return cart; } @Mutation("addItem") @@ -117,19 +155,36 @@ public class CartService { @Name("quantity") long quantity ) { String key = "cart:" + cartId; + String priceKey = "cart_prices:" + cartId; - UUID eateryId = UUID.fromString(hashCommands.hget(key, "_metadata_eatery")); + String eateryIdStr = hashCommands.hget(key, "_metadata_eatery"); + if (eateryIdStr == null) throw new RuntimeException("CartNotFound"); + + UUID eateryId = UUID.fromString(eateryIdStr); return eateryController .checkMenuItemExists(eateryId, menuItemId) .onItem() .transform(response -> { if (response.getStatus() != Response.Status.OK.getStatusCode()) { - throw new RuntimeException("NotFoundEatery"); + throw new RuntimeException("NotFoundMenuItemInEatery"); } + Double menuItemPrice = response.readEntity(Double.class); + hashCommands.hincrby(key, menuItemId.toString(), quantity); + + hashCommands.hset( + priceKey, + menuItemId.toString(), + String.valueOf(menuItemPrice) + ); + hashCommands.getDataSource().key().expire(key, Duration.ofDays(30)); + hashCommands + .getDataSource() + .key() + .expire(priceKey, Duration.ofDays(30)); try { return getCart(cartId); diff --git a/cart-service/src/main/resources/application.properties b/cart-service/src/main/resources/application.properties index 71ca8f2..78018a6 100644 --- a/cart-service/src/main/resources/application.properties +++ b/cart-service/src/main/resources/application.properties @@ -21,3 +21,4 @@ quarkus.redis.hosts=redis://${REDIS_SERVICE_SERVICE_HOST:localhost}:${REDIS_SERV # Rest Client quarkus.rest-client.eatery.url=http://eatery-service +quarkus.rest-client.account.url=http://account-service diff --git a/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java b/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java index 62c999b..daa25b1 100644 --- a/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java +++ b/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java @@ -7,6 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.when; import com.drinkool.controllers.EateryController; +import com.drinkool.controllers.ManagerController; import com.drinkool.dtos.Cart; import io.quarkus.redis.datasource.RedisDataSource; import io.quarkus.redis.datasource.hash.HashCommands; @@ -40,6 +41,11 @@ public class CartServiceTest { @RestClient EateryController eateryController; + + @InjectMock + @RestClient + ManagerController managerController; + @Inject RedisDataSource redisDataSource; @@ -59,7 +65,7 @@ public class CartServiceTest { UUID eateryId = UUID.randomUUID(); when(eateryController.getEateryById(eateryId)).thenReturn( - Uni.createFrom().item(Response.ok().build()) + Uni.createFrom().item(Response.ok(UUID.randomUUID()).build()) ); String cartId = cartService @@ -129,7 +135,7 @@ public class CartServiceTest { hashCommands.hset(key, "_metadata_owner", UUID.randomUUID().toString()); when(eateryController.checkMenuItemExists(eateryId, menuItemId)).thenReturn( - Uni.createFrom().item(Response.ok().build()) + Uni.createFrom().item(Response.ok(17.0).build()) ); Cart result = cartService diff --git a/eatery-service/src/main/java/com/drinkool/services/EateryService.java b/eatery-service/src/main/java/com/drinkool/services/EateryService.java index d7627e1..0f3fd7c 100644 --- a/eatery-service/src/main/java/com/drinkool/services/EateryService.java +++ b/eatery-service/src/main/java/com/drinkool/services/EateryService.java @@ -42,33 +42,33 @@ public class EateryService { EateryEntity eatery = EateryEntity.findById(id); if (eatery == null) { - return Response.status(Response.Status.NOT_FOUND) + return Response.status(Response.Status.BAD_REQUEST) .entity("NotFoundEatery") .build(); } - return Response.ok().build(); + return Response.ok(eatery.ownerId.toString()).build(); } @GET @Path("/{eateryId}/{menuItemId}") - public Response checkMenuItemExists( + public Response getMenuItemPrice( @PathParam("eateryId") UUID eateryId, @PathParam("menuItemId") UUID menuItemId ) { - long count = MenuItemEntity.find( - "id = ?2 and eatery.id = ?1", - eateryId, - menuItemId - ).count(); + MenuItemEntity menuItem = MenuItemEntity.find( + "id = ?1 and eatery.id = ?2", + menuItemId, + eateryId + ).firstResult(); - if (count == 0) { - return Response.status(Response.Status.NOT_FOUND) + if (menuItem == null) { + return Response.status(Response.Status.BAD_REQUEST) .entity("NotFoundMenuItem") .build(); } - return Response.ok().build(); + return Response.ok(menuItem.price).build(); } @Incoming("manager-in") diff --git a/eatery-service/src/main/resources/application.properties b/eatery-service/src/main/resources/application.properties index f499263..953717c 100644 --- a/eatery-service/src/main/resources/application.properties +++ b/eatery-service/src/main/resources/application.properties @@ -28,10 +28,12 @@ quarkus.native.additional-build-args=--future-defaults=all # Kafka %prod.mp.messaging.connector.smallrye-kafka.bootstrap.servers=${KAFKA_SERVICE_SERVICE_HOST:host.docker.internal}:9092 -mp.messaging.incoming.manager-in.connector=smallrye-in-memory ## Create restaurant topic mp.messaging.incoming.manager-in.connector=smallrye-kafka mp.messaging.incoming.manager-in.topic=create-restaurant mp.messaging.incoming.manager-in.auto.offset.reset=earliest -quarkus.messaging.kafka.serializer-generation.enabled=true \ No newline at end of file +quarkus.messaging.kafka.serializer-generation.enabled=true + +# Rest Client +quarkus.rest-client.account.url=http://account-service diff --git a/file-service/pom.xml b/file-service/pom.xml index 7187409..c70ab81 100644 --- a/file-service/pom.xml +++ b/file-service/pom.xml @@ -71,7 +71,7 @@ - push-python-image + push quarkus.container-image.push @@ -86,7 +86,7 @@ docker-push-python - install + package exec diff --git a/lib/src/main/java/com/drinkool/lib/dtos/ManagerSignup.java b/lib/src/main/java/com/drinkool/lib/dtos/ManagerSignup.java index 89db905..57cbcb1 100644 --- a/lib/src/main/java/com/drinkool/lib/dtos/ManagerSignup.java +++ b/lib/src/main/java/com/drinkool/lib/dtos/ManagerSignup.java @@ -3,4 +3,6 @@ package com.drinkool.lib.dtos; public class ManagerSignup extends Signup { public String eateryName; + + public String bankAccount; } From 67775810224009b510e20818f979568aaed0f46d Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Tue, 12 May 2026 05:51:30 +0000 Subject: [PATCH 48/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- cart-service/pom.xml | 2 +- .../test/java/com/drinkool/services/CartServiceTest.java | 1 - eatery-service/pom.xml | 2 +- file-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s/base/account.yaml | 2 +- k8s/base/cart.yaml | 2 +- k8s/base/eatery.yaml | 2 +- k8s/base/file.yaml | 2 +- k8s/base/gateway.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 14 files changed, 19 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27b12ba..fe1a75a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.27](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.26...v1.5.27) (2026-05-12) + + +### Bug Fixes + +* add payment features ([#52](https://git.demonkernel.io.vn/FoodSurf/backend/issues/52)) ([88244cb](https://git.demonkernel.io.vn/FoodSurf/backend/commit/88244cb56f28193cd8cb0da78d5b8d290870284b)) + ## [1.5.26](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.25...v1.5.26) (2026-05-12) diff --git a/account-service/pom.xml b/account-service/pom.xml index cf4deb2..6c2dc25 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.26 + 1.5.27 ../pom.xml diff --git a/cart-service/pom.xml b/cart-service/pom.xml index 75a1685..178a18a 100644 --- a/cart-service/pom.xml +++ b/cart-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.26 + 1.5.27 ../pom.xml diff --git a/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java b/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java index daa25b1..b487f74 100644 --- a/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java +++ b/cart-service/src/test/java/com/drinkool/services/CartServiceTest.java @@ -41,7 +41,6 @@ public class CartServiceTest { @RestClient EateryController eateryController; - @InjectMock @RestClient ManagerController managerController; diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index a7fe62e..bef4c30 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.26 + 1.5.27 ../pom.xml diff --git a/file-service/pom.xml b/file-service/pom.xml index c70ab81..0e99995 100644 --- a/file-service/pom.xml +++ b/file-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.26 + 1.5.27 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 9f7ac51..d369184 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.26 + 1.5.27 ../pom.xml diff --git a/k8s/base/account.yaml b/k8s/base/account.yaml index 057deac..4764abc 100644 --- a/k8s/base/account.yaml +++ b/k8s/base/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.26 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.27 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/cart.yaml b/k8s/base/cart.yaml index 44c2745..1ec2073 100644 --- a/k8s/base/cart.yaml +++ b/k8s/base/cart.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: cart-pod - image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.26 + image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.27 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/eatery.yaml b/k8s/base/eatery.yaml index b5be87e..ab2afb2 100644 --- a/k8s/base/eatery.yaml +++ b/k8s/base/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.26 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.27 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/file.yaml b/k8s/base/file.yaml index eb01827..fc09cc4 100644 --- a/k8s/base/file.yaml +++ b/k8s/base/file.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: file-pod - image: git.demonkernel.io.vn/foodsurf/file-service:1.5.26 + image: git.demonkernel.io.vn/foodsurf/file-service:1.5.27 imagePullPolicy: IfNotPresent volumeMounts: - name: file-volume diff --git a/k8s/base/gateway.yaml b/k8s/base/gateway.yaml index b9be3e1..42d3e5c 100644 --- a/k8s/base/gateway.yaml +++ b/k8s/base/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.26 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.27 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index 5cb2d4b..1bfda6a 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.26 + 1.5.27 ../pom.xml diff --git a/pom.xml b/pom.xml index cb043a4..f803ad9 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.26 + 1.5.27 pom 25 From 43734b51aafad7f823ff5d34322cc6fb6f4e6699 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Tue, 12 May 2026 15:01:58 +0000 Subject: [PATCH 49/51] fix: resolved minor issue (#53) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/53 --- .../src/main/java/com/drinkool/services/CartService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cart-service/src/main/java/com/drinkool/services/CartService.java b/cart-service/src/main/java/com/drinkool/services/CartService.java index 7c2c6ed..a5b038a 100644 --- a/cart-service/src/main/java/com/drinkool/services/CartService.java +++ b/cart-service/src/main/java/com/drinkool/services/CartService.java @@ -109,7 +109,8 @@ public class CartService { Cart cart = new Cart(); cart.Id = cartId; cart.eateryId = UUID.fromString(data.get("_metadata_eatery")); - cart.userId = UUID.fromString(data.get("_metadata_owner")); + String ownerStr = data.get("_metadata_owner"); + cart.userId = "GUEST".equals(ownerStr) ? null : UUID.fromString(ownerStr); cart.items = new ArrayList<>(); long total = 0; From 4a0e0e935cc6900e16e363e5afc0b8ceff5eddc2 Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Tue, 12 May 2026 15:20:49 +0000 Subject: [PATCH 50/51] chore: release [ci skip] --- CHANGELOG.md | 7 +++++++ account-service/pom.xml | 2 +- cart-service/pom.xml | 2 +- eatery-service/pom.xml | 2 +- file-service/pom.xml | 2 +- gateway-service/pom.xml | 2 +- k8s/base/account.yaml | 2 +- k8s/base/cart.yaml | 2 +- k8s/base/eatery.yaml | 2 +- k8s/base/file.yaml | 2 +- k8s/base/gateway.yaml | 2 +- lib/pom.xml | 2 +- pom.xml | 2 +- 13 files changed, 19 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe1a75a..816bf1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.5.28](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.27...v1.5.28) (2026-05-12) + + +### Bug Fixes + +* resolved minor issue ([#53](https://git.demonkernel.io.vn/FoodSurf/backend/issues/53)) ([43734b5](https://git.demonkernel.io.vn/FoodSurf/backend/commit/43734b51aafad7f823ff5d34322cc6fb6f4e6699)) + ## [1.5.27](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.26...v1.5.27) (2026-05-12) diff --git a/account-service/pom.xml b/account-service/pom.xml index 6c2dc25..1d342a8 100644 --- a/account-service/pom.xml +++ b/account-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.27 + 1.5.28 ../pom.xml diff --git a/cart-service/pom.xml b/cart-service/pom.xml index 178a18a..cdf7905 100644 --- a/cart-service/pom.xml +++ b/cart-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.27 + 1.5.28 ../pom.xml diff --git a/eatery-service/pom.xml b/eatery-service/pom.xml index bef4c30..702635b 100644 --- a/eatery-service/pom.xml +++ b/eatery-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.27 + 1.5.28 ../pom.xml diff --git a/file-service/pom.xml b/file-service/pom.xml index 0e99995..b95e829 100644 --- a/file-service/pom.xml +++ b/file-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.27 + 1.5.28 ../pom.xml diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index d369184..794651e 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.27 + 1.5.28 ../pom.xml diff --git a/k8s/base/account.yaml b/k8s/base/account.yaml index 4764abc..db4bdc8 100644 --- a/k8s/base/account.yaml +++ b/k8s/base/account.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: account-pod - image: git.demonkernel.io.vn/foodsurf/account-service:1.5.27 + image: git.demonkernel.io.vn/foodsurf/account-service:1.5.28 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/cart.yaml b/k8s/base/cart.yaml index 1ec2073..45868ea 100644 --- a/k8s/base/cart.yaml +++ b/k8s/base/cart.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: cart-pod - image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.27 + image: git.demonkernel.io.vn/foodsurf/cart-service:1.5.28 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/eatery.yaml b/k8s/base/eatery.yaml index ab2afb2..212de0f 100644 --- a/k8s/base/eatery.yaml +++ b/k8s/base/eatery.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: eatery-pod - image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.27 + image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.28 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/k8s/base/file.yaml b/k8s/base/file.yaml index fc09cc4..e673642 100644 --- a/k8s/base/file.yaml +++ b/k8s/base/file.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: file-pod - image: git.demonkernel.io.vn/foodsurf/file-service:1.5.27 + image: git.demonkernel.io.vn/foodsurf/file-service:1.5.28 imagePullPolicy: IfNotPresent volumeMounts: - name: file-volume diff --git a/k8s/base/gateway.yaml b/k8s/base/gateway.yaml index 42d3e5c..dbf049b 100644 --- a/k8s/base/gateway.yaml +++ b/k8s/base/gateway.yaml @@ -14,7 +14,7 @@ spec: spec: containers: - name: gateway-pod - image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.27 + image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.28 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 diff --git a/lib/pom.xml b/lib/pom.xml index 1bfda6a..f0fcc46 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -9,7 +9,7 @@ com.drinkool drinkool - 1.5.27 + 1.5.28 ../pom.xml diff --git a/pom.xml b/pom.xml index f803ad9..668ba46 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ 4.0.0 com.drinkool drinkool - 1.5.27 + 1.5.28 pom 25 From d45ed26a07ca5af39ea63e82a9e6453e4aedf0c4 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Wed, 13 May 2026 03:24:18 +0000 Subject: [PATCH 51/51] fix: better graphql response (#54) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/54 --- .../com/drinkool/entities/ManagerEntity.java | 4 ++++ .../com/drinkool/services/ManagerService.java | 1 + .../com/drinkool/controller/GraphqlBase.java | 24 +++++++++++++------ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java b/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java index 8649b9c..5c7d8a0 100644 --- a/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java +++ b/account-service/src/main/java/com/drinkool/entities/ManagerEntity.java @@ -2,6 +2,8 @@ package com.drinkool.entities; import com.drinkool.Role; import com.drinkool.models.UserModel; +import com.fasterxml.jackson.annotation.JsonIgnore; + import jakarta.persistence.*; import jakarta.transaction.Transactional; import java.util.ArrayList; @@ -11,6 +13,7 @@ import java.util.List; @Table(name = Role.Manager) public class ManagerEntity extends UserModel { + @JsonIgnore @OneToMany( mappedBy = "serve", cascade = CascadeType.ALL, @@ -18,6 +21,7 @@ public class ManagerEntity extends UserModel { ) public List staffs = new ArrayList<>(); + @JsonIgnore @Column(nullable = true) public String bankAccount; diff --git a/account-service/src/main/java/com/drinkool/services/ManagerService.java b/account-service/src/main/java/com/drinkool/services/ManagerService.java index ddb77fe..de00fcc 100644 --- a/account-service/src/main/java/com/drinkool/services/ManagerService.java +++ b/account-service/src/main/java/com/drinkool/services/ManagerService.java @@ -66,6 +66,7 @@ public class ManagerService extends BaseService { .build(); return Response.accepted() + .entity(manager) .header(InternalValue.userId, manager.id.toString()) .header(InternalValue.role, Role.Manager) .build(); diff --git a/gateway-service/src/main/java/com/drinkool/controller/GraphqlBase.java b/gateway-service/src/main/java/com/drinkool/controller/GraphqlBase.java index 1616c3c..bc34a95 100644 --- a/gateway-service/src/main/java/com/drinkool/controller/GraphqlBase.java +++ b/gateway-service/src/main/java/com/drinkool/controller/GraphqlBase.java @@ -9,6 +9,9 @@ import jakarta.json.bind.Jsonb; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public abstract class GraphqlBase { @@ -39,18 +42,25 @@ public abstract class GraphqlBase { gqlRequest.variables ); - if (response.hasError()) { - return Response.status(400) - .entity(jsonb.toJson(response.getErrors())) - .build(); - } + Map gqlBody = new HashMap<>(); - return Response.ok(jsonb.toJson(response.getData())) + gqlBody.put("data", response.getData()); + gqlBody.put("errors", response.getErrors()); + return Response.ok(jsonb.toJson(gqlBody)) .type(MediaType.APPLICATION_JSON) .build(); } catch (Exception e) { e.printStackTrace(); - return Response.serverError().entity("Lỗi kết nối tới service").build(); + Map errorBody = new HashMap<>(); + errorBody.put( + "errors", + List.of(Map.of("message", "Lỗi kết nối tới service: " + e.getMessage())) + ); + + return Response.serverError() + .type(MediaType.APPLICATION_JSON) + .entity(jsonb.toJson(errorBody)) + .build(); } } }