Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@
/common/target/
/merchant-service/target/
/distribution-service/target/
./merchant-service/target/
./merchant-service/target/
/identity-service/target/
/identity-domain-api/target/
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.tus.coupon.common.context;

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();
}
}
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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();
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +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("/**");
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.tus.coupon.common.context;

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();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.tus.coupon.common.context;

import jakarta.servlet.http.HttpServletRequest;

public interface UserContextResolver {
UserInfoDTO resolve(HttpServletRequest request);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,10 @@ public class UserInfoDTO {

// shop number
private Long shopNumber;

// tenant id
private String tenantId;

// trace id
private String traceId;
}
26 changes: 26 additions & 0 deletions identity-domain-api/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.tus.coupon</groupId>
<artifactId>coupon-all</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>

<artifactId>coupon-identity-domain-api</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>

<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>coupon-common</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -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<IdentityUserQueryRespDTO> 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;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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<IdentityUserItemRespDTO> users;
private Long nextCursor;
private Boolean hasMore;
}
60 changes: 60 additions & 0 deletions identity-service/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.tus.coupon</groupId>
<artifactId>coupon-all</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>

<artifactId>coupon-identity-service</artifactId>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>

<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>coupon-common</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>coupon-identity-domain-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations-jakarta</artifactId>
<version>2.2.22</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -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);
}
}
Loading
Loading