From 2d74e55334415e5097b6e2afa657c0437012967c Mon Sep 17 00:00:00 2001 From: Rurutia1027 Date: Wed, 22 Apr 2026 23:45:52 +0800 Subject: [PATCH 1/5] first commit gitignore --- .gitignore | 4 +++- .../context/HeaderUserContextResolver.java | 4 ++++ .../context/UserContextAutoConfiguration.java | 4 ++++ .../context/UserContextInterceptor.java | 4 ++++ .../common/context/UserContextResolver.java | 4 ++++ identity-domain-api/pom.xml | 20 +++++++++++++++++++ .../api/dto/req/IdentityUserQueryReqDTO.java | 0 .../api/dto/resp/IdentityUserItemRespDTO.java | 0 .../dto/resp/IdentityUserQueryRespDTO.java | 0 identity-service/pom.xml | 20 +++++++++++++++++++ .../controller/IdentityUserController.java | 4 ++++ .../identity/service/IdentityUserService.java | 4 ++++ .../service/impl/IdentityUserServiceImpl.java | 4 ++++ .../src/main/resources/application.yaml | 0 14 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 common/src/main/java/com/tus/coupon/common/context/HeaderUserContextResolver.java create mode 100644 common/src/main/java/com/tus/coupon/common/context/UserContextAutoConfiguration.java create mode 100644 common/src/main/java/com/tus/coupon/common/context/UserContextInterceptor.java create mode 100644 common/src/main/java/com/tus/coupon/common/context/UserContextResolver.java create mode 100644 identity-domain-api/pom.xml create mode 100644 identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/req/IdentityUserQueryReqDTO.java create mode 100644 identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserItemRespDTO.java create mode 100644 identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserQueryRespDTO.java create mode 100644 identity-service/pom.xml create mode 100644 identity-service/src/main/java/com/tus/coupon/identity/controller/IdentityUserController.java create mode 100644 identity-service/src/main/java/com/tus/coupon/identity/service/IdentityUserService.java create mode 100644 identity-service/src/main/java/com/tus/coupon/identity/service/impl/IdentityUserServiceImpl.java create mode 100644 identity-service/src/main/resources/application.yaml diff --git a/.gitignore b/.gitignore index 0f35273..86b114d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ /common/target/ /merchant-service/target/ /distribution-service/target/ -./merchant-service/target/ \ No newline at end of file +./merchant-service/target/ +/identity-service/target/ +/identity-domain-api/target/ diff --git a/common/src/main/java/com/tus/coupon/common/context/HeaderUserContextResolver.java b/common/src/main/java/com/tus/coupon/common/context/HeaderUserContextResolver.java new file mode 100644 index 0000000..c1d06a4 --- /dev/null +++ b/common/src/main/java/com/tus/coupon/common/context/HeaderUserContextResolver.java @@ -0,0 +1,4 @@ +package com.tus.coupon.common.context; + +public class HeaderUserContextResolver { +} diff --git a/common/src/main/java/com/tus/coupon/common/context/UserContextAutoConfiguration.java b/common/src/main/java/com/tus/coupon/common/context/UserContextAutoConfiguration.java new file mode 100644 index 0000000..9a49654 --- /dev/null +++ b/common/src/main/java/com/tus/coupon/common/context/UserContextAutoConfiguration.java @@ -0,0 +1,4 @@ +package com.tus.coupon.common.context; + +public class UserContextAutoConfiguration { +} diff --git a/common/src/main/java/com/tus/coupon/common/context/UserContextInterceptor.java b/common/src/main/java/com/tus/coupon/common/context/UserContextInterceptor.java new file mode 100644 index 0000000..f67e0a3 --- /dev/null +++ b/common/src/main/java/com/tus/coupon/common/context/UserContextInterceptor.java @@ -0,0 +1,4 @@ +package com.tus.coupon.common.context; + +public class UserContextInterceptor { +} diff --git a/common/src/main/java/com/tus/coupon/common/context/UserContextResolver.java b/common/src/main/java/com/tus/coupon/common/context/UserContextResolver.java new file mode 100644 index 0000000..5d9c96d --- /dev/null +++ b/common/src/main/java/com/tus/coupon/common/context/UserContextResolver.java @@ -0,0 +1,4 @@ +package com.tus.coupon.common.context; + +public interface UserContextResolver { +} diff --git a/identity-domain-api/pom.xml b/identity-domain-api/pom.xml new file mode 100644 index 0000000..f179d64 --- /dev/null +++ b/identity-domain-api/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + com.tus.coupon + coupon-all + 0.0.1-SNAPSHOT + + + coupon-identity-domain-api + + + 17 + 17 + UTF-8 + + + \ No newline at end of file diff --git a/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/req/IdentityUserQueryReqDTO.java b/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/req/IdentityUserQueryReqDTO.java new file mode 100644 index 0000000..e69de29 diff --git a/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserItemRespDTO.java b/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserItemRespDTO.java new file mode 100644 index 0000000..e69de29 diff --git a/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserQueryRespDTO.java b/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserQueryRespDTO.java new file mode 100644 index 0000000..e69de29 diff --git a/identity-service/pom.xml b/identity-service/pom.xml new file mode 100644 index 0000000..dbaa0e2 --- /dev/null +++ b/identity-service/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + com.tus.coupon + coupon-all + 0.0.1-SNAPSHOT + + + coupon-identity-service + + + 17 + 17 + UTF-8 + + + \ No newline at end of file diff --git a/identity-service/src/main/java/com/tus/coupon/identity/controller/IdentityUserController.java b/identity-service/src/main/java/com/tus/coupon/identity/controller/IdentityUserController.java new file mode 100644 index 0000000..18ac17f --- /dev/null +++ b/identity-service/src/main/java/com/tus/coupon/identity/controller/IdentityUserController.java @@ -0,0 +1,4 @@ +package com.tus.coupon.identity.controller; + +public class IdentityUserController { +} diff --git a/identity-service/src/main/java/com/tus/coupon/identity/service/IdentityUserService.java b/identity-service/src/main/java/com/tus/coupon/identity/service/IdentityUserService.java new file mode 100644 index 0000000..19efe89 --- /dev/null +++ b/identity-service/src/main/java/com/tus/coupon/identity/service/IdentityUserService.java @@ -0,0 +1,4 @@ +package com.tus.coupon.identity.service; + +public interface IdentityUserService { +} diff --git a/identity-service/src/main/java/com/tus/coupon/identity/service/impl/IdentityUserServiceImpl.java b/identity-service/src/main/java/com/tus/coupon/identity/service/impl/IdentityUserServiceImpl.java new file mode 100644 index 0000000..f6f43e8 --- /dev/null +++ b/identity-service/src/main/java/com/tus/coupon/identity/service/impl/IdentityUserServiceImpl.java @@ -0,0 +1,4 @@ +package com.tus.coupon.identity.service.impl; + +public class IdentityUserServiceImpl { +} diff --git a/identity-service/src/main/resources/application.yaml b/identity-service/src/main/resources/application.yaml new file mode 100644 index 0000000..e69de29 From 5f491eacc2589ada109b2f306cfdf4ca30b667fd Mon Sep 17 00:00:00 2001 From: Rurutia1027 Date: Wed, 22 Apr 2026 23:46:44 +0800 Subject: [PATCH 2/5] since coupon delivery relay on user info fetch api, so we modfiy the user dto and user context, also add user info request interceptor on common module --- .../context/HeaderUserContextResolver.java | 45 ++++++++++++++++++- .../coupon/common/context/UserContext.java | 21 +++++++++ .../context/UserContextAutoConfiguration.java | 26 +++++++++++ .../context/UserContextInterceptor.java | 30 ++++++++++++- .../common/context/UserContextResolver.java | 3 ++ .../coupon/common/context/UserInfoDTO.java | 6 +++ 6 files changed, 129 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/com/tus/coupon/common/context/HeaderUserContextResolver.java b/common/src/main/java/com/tus/coupon/common/context/HeaderUserContextResolver.java index c1d06a4..cca3292 100644 --- a/common/src/main/java/com/tus/coupon/common/context/HeaderUserContextResolver.java +++ b/common/src/main/java/com/tus/coupon/common/context/HeaderUserContextResolver.java @@ -1,4 +1,47 @@ package com.tus.coupon.common.context; -public class HeaderUserContextResolver { +import cn.hutool.core.util.StrUtil; +import jakarta.servlet.http.HttpServletRequest; + +import java.util.UUID; + +public class HeaderUserContextResolver implements UserContextResolver { + public static final String HEADER_USER_ID = "X-User-Id"; + public static final String HEADER_USERNAME = "X-Username"; + public static final String HEADER_SHOP_NUMBER = "X-Shop-Number"; + public static final String HEADER_TENANT_ID = "X-Tenant-Id"; + public static final String HEADER_TRACE_ID = "X-Trace-Id"; + + + @Override + public UserInfoDTO resolve(HttpServletRequest request) { + String userId = request.getHeader(HEADER_USER_ID); + String username = request.getHeader(HEADER_USERNAME); + String shopNumberStr = request.getHeader(HEADER_SHOP_NUMBER); + String tenantId = request.getHeader(HEADER_TENANT_ID); + String traceId = request.getHeader(HEADER_TRACE_ID); + + Long shopNumber = null; + if (StrUtil.isNotBlank(shopNumberStr) && StrUtil.isNumeric(shopNumberStr)) { + shopNumber = Long.parseLong(shopNumberStr); + } + + if (StrUtil.isBlank(userId)) { + userId = "anonymous"; + } + if (StrUtil.isBlank(username)) { + username = "anonymous"; + } + if (StrUtil.isBlank(traceId)) { + traceId = UUID.randomUUID().toString(); + } + + return UserInfoDTO.builder() + .userId(userId) + .username(username) + .shopNumber(shopNumber) + .tenantId(tenantId) + .traceId(traceId) + .build(); + } } diff --git a/common/src/main/java/com/tus/coupon/common/context/UserContext.java b/common/src/main/java/com/tus/coupon/common/context/UserContext.java index fea4352..df6560d 100644 --- a/common/src/main/java/com/tus/coupon/common/context/UserContext.java +++ b/common/src/main/java/com/tus/coupon/common/context/UserContext.java @@ -1,6 +1,7 @@ package com.tus.coupon.common.context; import com.alibaba.ttl.TransmittableThreadLocal; +import com.tus.coupon.common.exception.ClientException; import java.util.Optional; @@ -13,6 +14,15 @@ public static void setUser(UserInfoDTO user) { USER_THREAD_LOCAL.set(user); } + public static UserInfoDTO getUser() { + return USER_THREAD_LOCAL.get(); + } + + public static UserInfoDTO requireUser() { + return Optional.ofNullable(USER_THREAD_LOCAL.get()) + .orElseThrow(() -> new ClientException("User context is required but missing")); + } + // fetch user id from user context public static String getUserId() { UserInfoDTO userInfoDTO = USER_THREAD_LOCAL.get(); @@ -31,6 +41,17 @@ public static Long getShopNumber() { return Optional.ofNullable(userInfoDTO).map(UserInfoDTO::getShopNumber).orElse(null); } + public static String getTenantId() { + UserInfoDTO userInfoDTO = USER_THREAD_LOCAL.get(); + return Optional.ofNullable(userInfoDTO).map(UserInfoDTO::getTenantId).orElse(null); + } + + public static String getTraceId() { + UserInfoDTO userInfoDTO = USER_THREAD_LOCAL.get(); + return Optional.ofNullable(userInfoDTO).map(UserInfoDTO::getTraceId).orElse(null); + } + + // clean user context public static void removeUser() { USER_THREAD_LOCAL.remove(); diff --git a/common/src/main/java/com/tus/coupon/common/context/UserContextAutoConfiguration.java b/common/src/main/java/com/tus/coupon/common/context/UserContextAutoConfiguration.java index 9a49654..a1d1bae 100644 --- a/common/src/main/java/com/tus/coupon/common/context/UserContextAutoConfiguration.java +++ b/common/src/main/java/com/tus/coupon/common/context/UserContextAutoConfiguration.java @@ -1,4 +1,30 @@ package com.tus.coupon.common.context; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@AutoConfiguration public class UserContextAutoConfiguration { + + @Bean + public UserContextResolver userContextResolver() { + return new HeaderUserContextResolver(); + } + + @Bean + public UserContextInterceptor userContextInterceptor(UserContextResolver userContextResolver) { + return new UserContextInterceptor(userContextResolver); + } + + @Bean + public WebMvcConfigurer userContextWebMvcConfigurer(UserContextInterceptor userContextInterceptor) { + return new WebMvcConfigurer() { + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(userContextInterceptor).addPathPatterns("/**"); + } + }; + } } diff --git a/common/src/main/java/com/tus/coupon/common/context/UserContextInterceptor.java b/common/src/main/java/com/tus/coupon/common/context/UserContextInterceptor.java index f67e0a3..1978d2a 100644 --- a/common/src/main/java/com/tus/coupon/common/context/UserContextInterceptor.java +++ b/common/src/main/java/com/tus/coupon/common/context/UserContextInterceptor.java @@ -1,4 +1,32 @@ package com.tus.coupon.common.context; -public class UserContextInterceptor { +import jakarta.annotation.Nullable; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.servlet.HandlerInterceptor; + +public class UserContextInterceptor implements HandlerInterceptor { + private final UserContextResolver userContextResolver; + + public UserContextInterceptor(UserContextResolver userContextResolver) { + this.userContextResolver = userContextResolver; + } + + @Override + public boolean preHandle(@Nullable HttpServletRequest request, + @Nullable HttpServletResponse response, + @Nullable Object handler) throws Exception { + if (request != null) { + UserContext.setUser(userContextResolver.resolve(request)); + } + return true; + } + + @Override + public void afterCompletion(@Nullable HttpServletRequest request, + @Nullable HttpServletResponse response, + @Nullable Object handler, + Exception ex) throws Exception { + UserContext.removeUser(); + } } diff --git a/common/src/main/java/com/tus/coupon/common/context/UserContextResolver.java b/common/src/main/java/com/tus/coupon/common/context/UserContextResolver.java index 5d9c96d..58e7ff0 100644 --- a/common/src/main/java/com/tus/coupon/common/context/UserContextResolver.java +++ b/common/src/main/java/com/tus/coupon/common/context/UserContextResolver.java @@ -1,4 +1,7 @@ package com.tus.coupon.common.context; +import jakarta.servlet.http.HttpServletRequest; + public interface UserContextResolver { + UserInfoDTO resolve(HttpServletRequest request); } diff --git a/common/src/main/java/com/tus/coupon/common/context/UserInfoDTO.java b/common/src/main/java/com/tus/coupon/common/context/UserInfoDTO.java index 0c7dda2..b1c133f 100644 --- a/common/src/main/java/com/tus/coupon/common/context/UserInfoDTO.java +++ b/common/src/main/java/com/tus/coupon/common/context/UserInfoDTO.java @@ -18,4 +18,10 @@ public class UserInfoDTO { // shop number private Long shopNumber; + + // tenant id + private String tenantId; + + // trace id + private String traceId; } From 033e82765998e482a26cc6a4ef32face8da45a8a Mon Sep 17 00:00:00 2001 From: Rurutia1027 Date: Wed, 22 Apr 2026 23:47:21 +0800 Subject: [PATCH 3/5] modify user configuration forward compatible with user info dto modificaiton --- .../java/com/tus/coupon/merchant/config/UserConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/merchant-service/src/main/java/com/tus/coupon/merchant/config/UserConfiguration.java b/merchant-service/src/main/java/com/tus/coupon/merchant/config/UserConfiguration.java index dd37c01..833d754 100644 --- a/merchant-service/src/main/java/com/tus/coupon/merchant/config/UserConfiguration.java +++ b/merchant-service/src/main/java/com/tus/coupon/merchant/config/UserConfiguration.java @@ -32,7 +32,8 @@ static class UserTransmitInterceptor implements HandlerInterceptor { @Override public boolean preHandle(@Nullable HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Object handler) throws Exception { UserInfoDTO userInfoDTO = new UserInfoDTO(UUID.randomUUID().toString(), - UUID.randomUUID().toString(), UUID.randomUUID().node()); + UUID.randomUUID().toString(), UUID.randomUUID().node(), + UUID.randomUUID().toString(), UUID.randomUUID().toString()); UserContext.setUser(userInfoDTO); return true; } From 2ac249b38e96939c02a0552c2ba21d04a642986a Mon Sep 17 00:00:00 2001 From: Rurutia1027 Date: Wed, 22 Apr 2026 23:47:57 +0800 Subject: [PATCH 4/5] we gonne expose user info fetch api to identity domain api side, and the backend svc provided by the backend service --- identity-domain-api/pom.xml | 18 +++++++---- .../identity/api/dto/IdentityUserApi.java | 32 +++++++++++++++++++ .../api/dto/req/IdentityUserQueryReqDTO.java | 18 +++++++++++ .../api/dto/resp/IdentityUserItemRespDTO.java | 15 +++++++++ .../dto/resp/IdentityUserQueryRespDTO.java | 14 ++++++++ 5 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/IdentityUserApi.java diff --git a/identity-domain-api/pom.xml b/identity-domain-api/pom.xml index f179d64..83fda1a 100644 --- a/identity-domain-api/pom.xml +++ b/identity-domain-api/pom.xml @@ -11,10 +11,16 @@ coupon-identity-domain-api - - 17 - 17 - UTF-8 - + + + org.springframework + spring-web + - \ No newline at end of file + + ${project.groupId} + coupon-common + ${project.version} + + + diff --git a/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/IdentityUserApi.java b/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/IdentityUserApi.java new file mode 100644 index 0000000..633b258 --- /dev/null +++ b/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/IdentityUserApi.java @@ -0,0 +1,32 @@ +package com.tus.coupon.identity.api.dto; + +import com.tus.coupon.common.web.Result; +import com.tus.coupon.identity.api.dto.req.IdentityUserQueryReqDTO; +import com.tus.coupon.identity.api.dto.resp.IdentityUserQueryRespDTO; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +public interface IdentityUserApi { + + @GetMapping("/api/identity/users/query") + Result queryUsers( + @RequestParam(required = false) Long taskId, + @RequestParam(required = false) String shopNumber, + @RequestParam(required = false) Long cursor, + @RequestParam(required = false) Integer limit + ); + + static IdentityUserQueryReqDTO buildReq( + Long taskId, + String shopNumber, + Long cursor, + Integer limit + ) { + IdentityUserQueryReqDTO request = new IdentityUserQueryReqDTO(); + request.setTaskId(taskId); + request.setShopNumber(shopNumber); + request.setCursor(cursor); + request.setLimit(limit); + return request; + } +} diff --git a/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/req/IdentityUserQueryReqDTO.java b/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/req/IdentityUserQueryReqDTO.java index e69de29..9029301 100644 --- a/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/req/IdentityUserQueryReqDTO.java +++ b/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/req/IdentityUserQueryReqDTO.java @@ -0,0 +1,18 @@ +package com.tus.coupon.identity.api.dto.req; + +import lombok.Data; + +@Data +public class IdentityUserQueryReqDTO { + // optional: query users by coupon task id + private Long taskId; + + // optional: query users by merchant shop number + private String shopNumber; + + // cursor based pagination, use user table id + private Long cursor; + + // page size + private Integer limit; +} diff --git a/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserItemRespDTO.java b/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserItemRespDTO.java index e69de29..94bbc5d 100644 --- a/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserItemRespDTO.java +++ b/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserItemRespDTO.java @@ -0,0 +1,15 @@ +package com.tus.coupon.identity.api.dto.resp; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class IdentityUserItemRespDTO { + private Long id; + private String userId; + private String username; + private String shopNumber; + private String phone; + private String mail; +} diff --git a/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserQueryRespDTO.java b/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserQueryRespDTO.java index e69de29..39c76db 100644 --- a/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserQueryRespDTO.java +++ b/identity-domain-api/src/main/java/com/tus/coupon/identity/api/dto/resp/IdentityUserQueryRespDTO.java @@ -0,0 +1,14 @@ +package com.tus.coupon.identity.api.dto.resp; + +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Data +@Builder +public class IdentityUserQueryRespDTO { + private List users; + private Long nextCursor; + private Boolean hasMore; +} From 8ec1ef31114694e5ab36c9d4f47c5790a990f9ba Mon Sep 17 00:00:00 2001 From: Rurutia1027 Date: Wed, 22 Apr 2026 23:48:37 +0800 Subject: [PATCH 5/5] add identity service for furture authenticaiton, authorization, rbac and login, also add user info fetch endpoint impl for coupon delivery --- identity-service/pom.xml | 50 ++++++++++-- .../coupon/identity/IdentityApplication.java | 16 ++++ .../controller/IdentityUserController.java | 32 +++++++- .../identity/service/IdentityUserService.java | 4 + .../service/impl/IdentityUserServiceImpl.java | 76 ++++++++++++++++++- .../src/main/resources/application.yaml | 10 +++ pom.xml | 2 + 7 files changed, 182 insertions(+), 8 deletions(-) create mode 100644 identity-service/src/main/java/com/tus/coupon/identity/IdentityApplication.java diff --git a/identity-service/pom.xml b/identity-service/pom.xml index dbaa0e2..fcf0406 100644 --- a/identity-service/pom.xml +++ b/identity-service/pom.xml @@ -11,10 +11,50 @@ coupon-identity-service - - 17 - 17 - UTF-8 - + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-jdbc + + + + com.baomidou + mybatis-plus-boot-starter + + + + com.mysql + mysql-connector-j + runtime + + + + ${project.groupId} + coupon-common + ${project.version} + + + + ${project.groupId} + coupon-identity-domain-api + ${project.version} + + + io.swagger.core.v3 + swagger-annotations-jakarta + 2.2.22 + compile + + \ No newline at end of file diff --git a/identity-service/src/main/java/com/tus/coupon/identity/IdentityApplication.java b/identity-service/src/main/java/com/tus/coupon/identity/IdentityApplication.java new file mode 100644 index 0000000..12ee1fe --- /dev/null +++ b/identity-service/src/main/java/com/tus/coupon/identity/IdentityApplication.java @@ -0,0 +1,16 @@ +package com.tus.coupon.identity; + +import com.tus.coupon.common.context.UserContextAutoConfiguration; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Import; + +@SpringBootApplication +@MapperScan("com.tus.coupon.common.dao.mapper") +@Import(UserContextAutoConfiguration.class) +public class IdentityApplication { + public static void main(String[] args) { + SpringApplication.run(IdentityApplication.class, args); + } +} diff --git a/identity-service/src/main/java/com/tus/coupon/identity/controller/IdentityUserController.java b/identity-service/src/main/java/com/tus/coupon/identity/controller/IdentityUserController.java index 18ac17f..e8312b5 100644 --- a/identity-service/src/main/java/com/tus/coupon/identity/controller/IdentityUserController.java +++ b/identity-service/src/main/java/com/tus/coupon/identity/controller/IdentityUserController.java @@ -1,4 +1,32 @@ package com.tus.coupon.identity.controller; -public class IdentityUserController { -} +import com.tus.coupon.common.web.Result; +import com.tus.coupon.common.web.Results; +import com.tus.coupon.identity.api.dto.IdentityUserApi; +import com.tus.coupon.identity.api.dto.req.IdentityUserQueryReqDTO; +import com.tus.coupon.identity.api.dto.resp.IdentityUserQueryRespDTO; +import com.tus.coupon.identity.service.IdentityUserService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@Tag(name = "Identity User Controller") +public class IdentityUserController implements IdentityUserApi { + private final IdentityUserService identityUserService; + + @Override + @Operation(summary = "Query users for coupon distribution") + public Result queryUsers( + @RequestParam(required = false) Long taskId, + @RequestParam(required = false) String shopNumber, + @RequestParam(required = false) Long cursor, + @RequestParam(required = false) Integer limit + ) { + IdentityUserQueryReqDTO request = IdentityUserApi.buildReq(taskId, shopNumber, cursor, limit); + return Results.success(identityUserService.queryUsers(request)); + } +} \ No newline at end of file diff --git a/identity-service/src/main/java/com/tus/coupon/identity/service/IdentityUserService.java b/identity-service/src/main/java/com/tus/coupon/identity/service/IdentityUserService.java index 19efe89..7d92c22 100644 --- a/identity-service/src/main/java/com/tus/coupon/identity/service/IdentityUserService.java +++ b/identity-service/src/main/java/com/tus/coupon/identity/service/IdentityUserService.java @@ -1,4 +1,8 @@ package com.tus.coupon.identity.service; +import com.tus.coupon.identity.api.dto.req.IdentityUserQueryReqDTO; +import com.tus.coupon.identity.api.dto.resp.IdentityUserQueryRespDTO; + public interface IdentityUserService { + IdentityUserQueryRespDTO queryUsers(IdentityUserQueryReqDTO requestParam); } diff --git a/identity-service/src/main/java/com/tus/coupon/identity/service/impl/IdentityUserServiceImpl.java b/identity-service/src/main/java/com/tus/coupon/identity/service/impl/IdentityUserServiceImpl.java index f6f43e8..e6aa417 100644 --- a/identity-service/src/main/java/com/tus/coupon/identity/service/impl/IdentityUserServiceImpl.java +++ b/identity-service/src/main/java/com/tus/coupon/identity/service/impl/IdentityUserServiceImpl.java @@ -1,4 +1,78 @@ package com.tus.coupon.identity.service.impl; -public class IdentityUserServiceImpl { +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.tus.coupon.common.dao.entity.UserDO; +import com.tus.coupon.common.dao.mapper.UserMapper; +import com.tus.coupon.common.exception.ClientException; +import com.tus.coupon.identity.api.dto.req.IdentityUserQueryReqDTO; +import com.tus.coupon.identity.api.dto.resp.IdentityUserItemRespDTO; +import com.tus.coupon.identity.api.dto.resp.IdentityUserQueryRespDTO; +import com.tus.coupon.identity.service.IdentityUserService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class IdentityUserServiceImpl implements IdentityUserService { + private static final int DEFAULT_LIMIT = 100; + private static final int MAX_LIMIT = 500; + + private final UserMapper userMapper; + + @Override + public IdentityUserQueryRespDTO queryUsers(IdentityUserQueryReqDTO requestParam) { + if (requestParam == null) { + throw new ClientException("Identity user query request should not be null"); + } + + Integer limit = requestParam.getLimit(); + if (limit == null || limit <= 0) { + limit = DEFAULT_LIMIT; + } + + if (limit > MAX_LIMIT) { + throw new ClientException("Requested limit exceeds max allowed size: " + MAX_LIMIT); + } + + long cursor = requestParam.getCursor() == null ? 0L : requestParam.getCursor(); + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(UserDO.class) + .gt(UserDO::getId, cursor) + .eq(UserDO::getDelFlag, 0) + .eq(StrUtil.isNotBlank(requestParam.getShopNumber()), UserDO::getShopNumber, requestParam.getShopNumber()) + .orderByAsc(UserDO::getId) + .last("LIMIT " + limit); + + List userDOList = userMapper.selectList(queryWrapper); + if (userDOList == null || userDOList.isEmpty()) { + return IdentityUserQueryRespDTO.builder() + .users(Collections.emptyList()) + .hasMore(Boolean.FALSE) + .nextCursor(cursor) + .build(); + } + + List users = userDOList.stream() + .map(each -> IdentityUserItemRespDTO.builder() + .id(each.getId()) + .userId(String.valueOf(each.getId())) + .username(each.getUsername()) + .shopNumber(each.getShopNumber()) + .phone(each.getPhone()) + .mail(each.getMail()) + .build()) + .toList(); + + Long nextCursor = userDOList.get(userDOList.size() - 1).getId(); + boolean hasMore = userDOList.size() >= limit; + return IdentityUserQueryRespDTO.builder() + .users(users) + .nextCursor(nextCursor) + .hasMore(hasMore) + .build(); + } } diff --git a/identity-service/src/main/resources/application.yaml b/identity-service/src/main/resources/application.yaml index e69de29..c2f8118 100644 --- a/identity-service/src/main/resources/application.yaml +++ b/identity-service/src/main/resources/application.yaml @@ -0,0 +1,10 @@ +server: + port: 10030 + +spring: + application: + name: coupon-identity + +mybatis-plus: + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl diff --git a/pom.xml b/pom.xml index 3b27281..c745af4 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,8 @@ merchant-service common distribution-service + identity-service + identity-domain-api