feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
<?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>io.destiny</groupId>
|
||||
<artifactId>everything-is-suitable-api</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>everything-is-suitable-client-api</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Everything Is Suitable Client API</name>
|
||||
<description>Client API layer for Everything Is Suitable API</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.destiny</groupId>
|
||||
<artifactId>everything-is-suitable-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.destiny</groupId>
|
||||
<artifactId>everything-is-suitable-biz</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.destiny</groupId>
|
||||
<artifactId>everything-is-suitable-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
package io.destiny.client.api.config;
|
||||
|
||||
import io.destiny.client.api.handler.ClientAuthHandler;
|
||||
import io.destiny.client.api.handler.UnifiedLoginHandler;
|
||||
import org.springdoc.core.annotations.RouterOperation;
|
||||
import org.springdoc.core.annotations.RouterOperations;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.*;
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
|
||||
|
||||
@Configuration
|
||||
public class ClientRouterConfig {
|
||||
|
||||
@Bean
|
||||
@RouterOperations({
|
||||
@RouterOperation(path = "/client/auth/register", method = RequestMethod.POST, beanClass = ClientAuthHandler.class, beanMethod = "register"),
|
||||
@RouterOperation(path = "/client/auth/logout/{userId}", method = RequestMethod.POST, beanClass = ClientAuthHandler.class, beanMethod = "logout"),
|
||||
@RouterOperation(path = "/client/auth/status/{userId}", method = RequestMethod.GET, beanClass = ClientAuthHandler.class, beanMethod = "checkLoginStatus")
|
||||
})
|
||||
public RouterFunction<ServerResponse> clientAuthRouter(ClientAuthHandler clientAuthHandler) {
|
||||
return route()
|
||||
.path("/client/auth", builder -> builder
|
||||
.POST("/register", accept(MediaType.APPLICATION_JSON),
|
||||
clientAuthHandler::register)
|
||||
.POST("/logout/{userId}", clientAuthHandler::logout)
|
||||
.GET("/status/{userId}", clientAuthHandler::checkLoginStatus))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@RouterOperations({
|
||||
@RouterOperation(path = "/client/login/unified", method = RequestMethod.POST, beanClass = UnifiedLoginHandler.class, beanMethod = "unifiedLogin"),
|
||||
@RouterOperation(path = "/client/login/password", method = RequestMethod.POST, beanClass = UnifiedLoginHandler.class, beanMethod = "passwordLogin"),
|
||||
@RouterOperation(path = "/client/login/wechat", method = RequestMethod.POST, beanClass = UnifiedLoginHandler.class, beanMethod = "wechatLogin"),
|
||||
@RouterOperation(path = "/client/login/douyin", method = RequestMethod.POST, beanClass = UnifiedLoginHandler.class, beanMethod = "douyinLogin"),
|
||||
@RouterOperation(path = "/client/login/sms", method = RequestMethod.POST, beanClass = UnifiedLoginHandler.class, beanMethod = "smsLogin")
|
||||
})
|
||||
public RouterFunction<ServerResponse> unifiedLoginRouter(UnifiedLoginHandler unifiedLoginHandler) {
|
||||
return route()
|
||||
.path("/client/login", builder -> builder
|
||||
.POST("/unified", accept(MediaType.APPLICATION_JSON),
|
||||
unifiedLoginHandler::unifiedLogin)
|
||||
.POST("/password", accept(MediaType.APPLICATION_JSON),
|
||||
unifiedLoginHandler::passwordLogin)
|
||||
.POST("/wechat", accept(MediaType.APPLICATION_JSON),
|
||||
unifiedLoginHandler::wechatLogin)
|
||||
.POST("/douyin", accept(MediaType.APPLICATION_JSON),
|
||||
unifiedLoginHandler::douyinLogin)
|
||||
.POST("/sms", accept(MediaType.APPLICATION_JSON),
|
||||
unifiedLoginHandler::smsLogin))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
package io.destiny.client.api.handler;
|
||||
|
||||
import io.destiny.client.core.domain.ClientUser;
|
||||
import io.destiny.client.core.service.ClientUserAuthService;
|
||||
import io.destiny.client.core.strategy.LoginStrategyProxy;
|
||||
import io.destiny.client.dto.ClientUserLoginRequest;
|
||||
import io.destiny.client.dto.ClientUserRegisterRequest;
|
||||
import io.destiny.client.dto.ClientUserResponse;
|
||||
import io.destiny.client.dto.LoginRequest;
|
||||
import io.destiny.common.exception.ApplicationException;
|
||||
import io.destiny.common.response.Result;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
@Tag(name = "客户端认证", description = "客户端用户认证相关接口")
|
||||
public class ClientAuthHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ClientAuthHandler.class);
|
||||
|
||||
private final ClientUserAuthService clientUserAuthService;
|
||||
private final LoginStrategyProxy loginStrategyProxy;
|
||||
|
||||
public ClientAuthHandler(ClientUserAuthService clientUserAuthService,
|
||||
LoginStrategyProxy loginStrategyProxy) {
|
||||
this.clientUserAuthService = clientUserAuthService;
|
||||
this.loginStrategyProxy = loginStrategyProxy;
|
||||
}
|
||||
|
||||
@Operation(summary = "用户注册", description = "新用户注册,需要提供用户名、密码、邮箱和手机号")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "注册成功", content = @Content(schema = @Schema(implementation = ClientUserResponse.class))),
|
||||
@ApiResponse(responseCode = "400", description = "请求参数错误"),
|
||||
@ApiResponse(responseCode = "500", description = "服务器内部错误")
|
||||
})
|
||||
public Mono<ServerResponse> register(ServerRequest request) {
|
||||
return request.bodyToMono(ClientUserRegisterRequest.class)
|
||||
.flatMap(registerRequest -> {
|
||||
logger.info("Registering user: {}", registerRequest.getUsername());
|
||||
ClientUser clientUser = registerRequest.toDomain();
|
||||
return clientUserAuthService.register(clientUser)
|
||||
.map(ClientUserResponse::from);
|
||||
})
|
||||
.map(response -> Result.success("User registered successfully", response))
|
||||
.flatMap(result -> ServerResponse.ok()
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(result))
|
||||
.onErrorResume(ApplicationException.class, e -> {
|
||||
logger.error("Registration failed: {}", e.getMessage());
|
||||
String code = e.getExceptionCode() != null ? e.getExceptionCode().getCode()
|
||||
: "REGISTRATION_ERROR";
|
||||
return ServerResponse.badRequest()
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Result.error(code, e.getMessage()));
|
||||
})
|
||||
.onErrorResume(Exception.class, e -> {
|
||||
logger.error("Unexpected error during registration", e);
|
||||
return ServerResponse.status(500)
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Result.error("REGISTRATION_ERROR",
|
||||
"Registration failed"));
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "用户登录", description = "用户登录获取访问令牌和刷新令牌")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "登录成功", content = @Content(schema = @Schema(implementation = ClientUserResponse.class))),
|
||||
@ApiResponse(responseCode = "401", description = "用户名或密码错误"),
|
||||
@ApiResponse(responseCode = "500", description = "服务器内部错误")
|
||||
})
|
||||
public Mono<ServerResponse> login(ServerRequest request) {
|
||||
return request.bodyToMono(ClientUserLoginRequest.class)
|
||||
.map(loginRequest -> {
|
||||
String clientIp = getClientIp(request);
|
||||
loginRequest.setIpAddress(clientIp);
|
||||
return loginRequest;
|
||||
})
|
||||
.flatMap(loginRequest -> {
|
||||
logger.info("User login attempt: {} from IP: {}", loginRequest.getUsername(),
|
||||
loginRequest.getIpAddress());
|
||||
|
||||
LoginRequest loginRequestWrapper = new LoginRequest();
|
||||
loginRequestWrapper.setLoginType("password");
|
||||
loginRequestWrapper.setIpAddress(loginRequest.getIpAddress());
|
||||
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("username", loginRequest.getUsername());
|
||||
data.put("password", loginRequest.getPassword());
|
||||
loginRequestWrapper.setData(data);
|
||||
|
||||
return loginStrategyProxy.login(loginRequestWrapper);
|
||||
})
|
||||
.map(response -> Result.success("Login successful", response))
|
||||
.flatMap(result -> ServerResponse.ok()
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(result))
|
||||
.onErrorResume(ApplicationException.class, e -> {
|
||||
logger.error("Login failed: {}", e.getMessage());
|
||||
String code = e.getExceptionCode() != null ? e.getExceptionCode().getCode()
|
||||
: "LOGIN_ERROR";
|
||||
return ServerResponse.status(401)
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Result.error(code, e.getMessage()));
|
||||
})
|
||||
.onErrorResume(Exception.class, e -> {
|
||||
logger.error("Unexpected error during login", e);
|
||||
return ServerResponse.status(500)
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Result.error("LOGIN_ERROR", "Login failed"));
|
||||
});
|
||||
}
|
||||
|
||||
private String getClientIp(ServerRequest request) {
|
||||
String xForwardedFor = request.headers().firstHeader("X-Forwarded-For");
|
||||
if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
|
||||
return xForwardedFor.split(",")[0].trim();
|
||||
}
|
||||
|
||||
String xRealIp = request.headers().firstHeader("X-Real-IP");
|
||||
if (xRealIp != null && !xRealIp.isEmpty()) {
|
||||
return xRealIp;
|
||||
}
|
||||
|
||||
return request.remoteAddress()
|
||||
.map(address -> address.getAddress().getHostAddress())
|
||||
.orElse("unknown");
|
||||
}
|
||||
|
||||
@Operation(summary = "用户登出", description = "用户登出,清除登录状态")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "登出成功"),
|
||||
@ApiResponse(responseCode = "400", description = "请求参数错误"),
|
||||
@ApiResponse(responseCode = "500", description = "服务器内部错误")
|
||||
})
|
||||
public Mono<ServerResponse> logout(ServerRequest request) {
|
||||
Long userId = Long.parseLong(request.pathVariable("userId"));
|
||||
logger.info("User logout: {}", userId);
|
||||
|
||||
return clientUserAuthService.logout(userId)
|
||||
.then(Mono.defer(() -> ServerResponse.ok()
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Result.success(null, "Logout successful"))))
|
||||
.onErrorResume(Exception.class, e -> {
|
||||
logger.error("Logout failed for user: {}", userId, e);
|
||||
return ServerResponse.status(500)
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Result.error("LOGOUT_ERROR", "Logout failed"));
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "检查登录状态", description = "检查用户是否已登录")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "查询成功", content = @Content(schema = @Schema(implementation = Boolean.class))),
|
||||
@ApiResponse(responseCode = "400", description = "请求参数错误"),
|
||||
@ApiResponse(responseCode = "500", description = "服务器内部错误")
|
||||
})
|
||||
public Mono<ServerResponse> checkLoginStatus(ServerRequest request) {
|
||||
Long userId = Long.parseLong(request.pathVariable("userId"));
|
||||
logger.info("Checking login status for user: {}", userId);
|
||||
|
||||
return clientUserAuthService.checkLoginStatus(userId)
|
||||
.map(isLoggedIn -> Result.success(isLoggedIn))
|
||||
.flatMap(result -> ServerResponse.ok()
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(result))
|
||||
.onErrorResume(Exception.class, e -> {
|
||||
logger.error("Failed to check login status for user: {}", userId, e);
|
||||
return ServerResponse.status(500)
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(Result.error("STATUS_CHECK_ERROR",
|
||||
"Failed to check login status"));
|
||||
});
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package io.destiny.client.api.handler;
|
||||
|
||||
import io.destiny.biz.dto.DailyFortuneRequest;
|
||||
import io.destiny.biz.dto.DailyFortuneResponse;
|
||||
import io.destiny.biz.service.IFortuneAnalysisService;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@Component
|
||||
public class ClientFortuneHandler {
|
||||
|
||||
private final IFortuneAnalysisService fortuneService;
|
||||
|
||||
public ClientFortuneHandler(IFortuneAnalysisService fortuneService) {
|
||||
this.fortuneService = fortuneService;
|
||||
}
|
||||
|
||||
public Mono<ServerResponse> getDailyFortune(ServerRequest request) {
|
||||
String userId = request.queryParam("userId").orElse("");
|
||||
String date = request.queryParam("date").orElse("");
|
||||
|
||||
return ServerResponse.ok()
|
||||
.bodyValue("{\"message\":\"Daily fortune - to be implemented\"}");
|
||||
}
|
||||
|
||||
public Mono<ServerResponse> getMonthlyFortune(ServerRequest request) {
|
||||
return ServerResponse.ok()
|
||||
.bodyValue("{\"message\":\"Monthly fortune - to be implemented\"}");
|
||||
}
|
||||
|
||||
public Mono<ServerResponse> getYearlyFortune(ServerRequest request) {
|
||||
return ServerResponse.ok()
|
||||
.bodyValue("{\"message\":\"Yearly fortune - to be implemented\"}");
|
||||
}
|
||||
}
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
package io.destiny.client.api.handler;
|
||||
|
||||
import io.destiny.client.core.exception.GlobalExceptionHandler;
|
||||
import io.destiny.client.core.strategy.LoginStrategyProxy;
|
||||
import io.destiny.client.dto.LoginRequest;
|
||||
import io.destiny.client.dto.WechatLoginRequest;
|
||||
import io.destiny.client.dto.DouyinLoginRequest;
|
||||
import io.destiny.client.dto.SmsLoginRequest;
|
||||
import io.destiny.client.dto.PasswordLoginRequest;
|
||||
import io.destiny.common.response.Result;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@Component
|
||||
@Tag(name = "统一登录", description = "统一登录相关接口")
|
||||
public class UnifiedLoginHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(UnifiedLoginHandler.class);
|
||||
|
||||
private final LoginStrategyProxy loginStrategyProxy;
|
||||
private final GlobalExceptionHandler globalExceptionHandler;
|
||||
|
||||
public UnifiedLoginHandler(LoginStrategyProxy loginStrategyProxy, GlobalExceptionHandler globalExceptionHandler) {
|
||||
this.loginStrategyProxy = loginStrategyProxy;
|
||||
this.globalExceptionHandler = globalExceptionHandler;
|
||||
}
|
||||
|
||||
@Operation(summary = "统一登录", description = "支持多种登录方式的统一登录接口")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "登录成功", content = @Content(schema = @Schema(implementation = Result.class))),
|
||||
@ApiResponse(responseCode = "400", description = "请求参数错误"),
|
||||
@ApiResponse(responseCode = "500", description = "服务器内部错误")
|
||||
})
|
||||
public Mono<ServerResponse> unifiedLogin(ServerRequest request) {
|
||||
return request.bodyToMono(LoginRequest.class)
|
||||
.flatMap(loginRequest -> {
|
||||
String clientIp = getClientIp(request);
|
||||
loginRequest.setIpAddress(clientIp);
|
||||
|
||||
logger.info("Unified login request - Type: {}, IP: {}",
|
||||
loginRequest.getLoginType(), clientIp);
|
||||
|
||||
return loginStrategyProxy.login(loginRequest);
|
||||
})
|
||||
.map(response -> Result.success("Login successful", response))
|
||||
.flatMap(result -> ServerResponse.ok()
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(result))
|
||||
.onErrorResume(ex -> {
|
||||
try {
|
||||
return globalExceptionHandler.handleException(ex, request.exchange());
|
||||
} catch (IllegalStateException e) {
|
||||
return globalExceptionHandler.handleException(ex, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "微信登录", description = "使用微信授权码登录")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "登录成功", content = @Content(schema = @Schema(implementation = Result.class))),
|
||||
@ApiResponse(responseCode = "400", description = "请求参数错误"),
|
||||
@ApiResponse(responseCode = "500", description = "服务器内部错误")
|
||||
})
|
||||
public Mono<ServerResponse> wechatLogin(ServerRequest request) {
|
||||
return request.bodyToMono(WechatLoginRequest.class)
|
||||
.flatMap(wechatRequest -> {
|
||||
String clientIp = getClientIp(request);
|
||||
|
||||
LoginRequest loginRequest = new LoginRequest();
|
||||
loginRequest.setLoginType("wechat");
|
||||
loginRequest.setIpAddress(clientIp);
|
||||
loginRequest.setData(wechatRequest);
|
||||
|
||||
logger.info("WeChat login request - IP: {}", clientIp);
|
||||
|
||||
return loginStrategyProxy.login(loginRequest);
|
||||
})
|
||||
.map(response -> Result.success("WeChat login successful", response))
|
||||
.flatMap(result -> ServerResponse.ok()
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(result))
|
||||
.onErrorResume(ex -> {
|
||||
try {
|
||||
return globalExceptionHandler.handleException(ex, request.exchange());
|
||||
} catch (IllegalStateException e) {
|
||||
return globalExceptionHandler.handleException(ex, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "抖音登录", description = "使用抖音授权码登录")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "登录成功", content = @Content(schema = @Schema(implementation = Result.class))),
|
||||
@ApiResponse(responseCode = "400", description = "请求参数错误"),
|
||||
@ApiResponse(responseCode = "500", description = "服务器内部错误")
|
||||
})
|
||||
public Mono<ServerResponse> douyinLogin(ServerRequest request) {
|
||||
return request.bodyToMono(DouyinLoginRequest.class)
|
||||
.flatMap(douyinRequest -> {
|
||||
String clientIp = getClientIp(request);
|
||||
|
||||
LoginRequest loginRequest = new LoginRequest();
|
||||
loginRequest.setLoginType("douyin");
|
||||
loginRequest.setIpAddress(clientIp);
|
||||
loginRequest.setData(douyinRequest);
|
||||
|
||||
logger.info("Douyin login request - IP: {}", clientIp);
|
||||
|
||||
return loginStrategyProxy.login(loginRequest);
|
||||
})
|
||||
.map(response -> Result.success("Douyin login successful", response))
|
||||
.flatMap(result -> ServerResponse.ok()
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(result))
|
||||
.onErrorResume(ex -> {
|
||||
try {
|
||||
return globalExceptionHandler.handleException(ex, request.exchange());
|
||||
} catch (IllegalStateException e) {
|
||||
return globalExceptionHandler.handleException(ex, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Operation(summary = "短信验证码登录", description = "使用手机号和短信验证码登录")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "登录成功", content = @Content(schema = @Schema(implementation = Result.class))),
|
||||
@ApiResponse(responseCode = "400", description = "请求参数错误"),
|
||||
@ApiResponse(responseCode = "500", description = "服务器内部错误")
|
||||
})
|
||||
public Mono<ServerResponse> smsLogin(ServerRequest request) {
|
||||
return request.bodyToMono(SmsLoginRequest.class)
|
||||
.flatMap(smsRequest -> {
|
||||
String clientIp = getClientIp(request);
|
||||
|
||||
LoginRequest loginRequest = new LoginRequest();
|
||||
loginRequest.setLoginType("sms");
|
||||
loginRequest.setIpAddress(clientIp);
|
||||
loginRequest.setData(smsRequest);
|
||||
|
||||
logger.info("SMS login request - Phone: {}, IP: {}",
|
||||
smsRequest.getPhone(), clientIp);
|
||||
|
||||
return loginStrategyProxy.login(loginRequest);
|
||||
})
|
||||
.map(response -> Result.success("SMS login successful", response))
|
||||
.flatMap(result -> ServerResponse.ok()
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(result))
|
||||
.onErrorResume(ex -> globalExceptionHandler.handleException(ex, request.exchange()));
|
||||
}
|
||||
|
||||
@Operation(summary = "密码登录", description = "使用用户名和密码登录")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "200", description = "登录成功", content = @Content(schema = @Schema(implementation = Result.class))),
|
||||
@ApiResponse(responseCode = "400", description = "请求参数错误"),
|
||||
@ApiResponse(responseCode = "500", description = "服务器内部错误")
|
||||
})
|
||||
public Mono<ServerResponse> passwordLogin(ServerRequest request) {
|
||||
return request.bodyToMono(PasswordLoginRequest.class)
|
||||
.flatMap(passwordRequest -> {
|
||||
String clientIp = getClientIp(request);
|
||||
|
||||
LoginRequest loginRequest = new LoginRequest();
|
||||
loginRequest.setLoginType("password");
|
||||
loginRequest.setIpAddress(clientIp);
|
||||
loginRequest.setData(passwordRequest);
|
||||
|
||||
logger.info("Password login request - Username: {}, IP: {}",
|
||||
passwordRequest.getUsername(), clientIp);
|
||||
|
||||
return loginStrategyProxy.login(loginRequest);
|
||||
})
|
||||
.map(response -> Result.success("Password login successful", response))
|
||||
.flatMap(result -> ServerResponse.ok()
|
||||
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
|
||||
.bodyValue(result))
|
||||
.onErrorResume(ex -> globalExceptionHandler.handleException(ex, request.exchange()));
|
||||
}
|
||||
|
||||
private String getClientIp(ServerRequest request) {
|
||||
String xForwardedFor = request.headers().firstHeader("X-Forwarded-For");
|
||||
if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
|
||||
return xForwardedFor.split(",")[0].trim();
|
||||
}
|
||||
|
||||
String xRealIp = request.headers().firstHeader("X-Real-IP");
|
||||
if (xRealIp != null && !xRealIp.isEmpty()) {
|
||||
return xRealIp;
|
||||
}
|
||||
|
||||
return request.remoteAddress()
|
||||
.map(address -> address.getAddress().getHostAddress())
|
||||
.orElse("unknown");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user