Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 692f6d76c6 | |||
| 0b4a5b35be | |||
| 564ef48d02 | |||
|
|
ececf1f8ce | ||
|
|
b228ed3c9e | ||
|
|
df9c17f4e6 | ||
|
|
45caaa1e25 | ||
|
|
31ddd5c4fe | ||
|
|
d64de39541 | ||
|
|
94d5d8cabe | ||
|
|
44133d3667 | ||
|
|
a1a23bec7a | ||
|
|
b7f6d3477d | ||
|
|
4597623cd9 | ||
|
|
3fce5b2f01 | ||
|
|
0ea6e13064 | ||
|
|
23cb31d4fe |
33
.gitea/workflows/dev.yaml
Normal file
33
.gitea/workflows/dev.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
name: dev middleware install
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: gitea-runner-group-myplayer
|
||||||
|
container:
|
||||||
|
image: ${{ vars.HARBOR_URL }}/candlelight/action_deployer:v0.0.1
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: setup kubeconfig
|
||||||
|
env:
|
||||||
|
KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.kube
|
||||||
|
echo "${KUBE_CONFIG}" > ~/.kube/config
|
||||||
|
- name: helm login
|
||||||
|
env:
|
||||||
|
HARBOR_USERNAME: ${{ secrets.HARBOR_ROBOT }}
|
||||||
|
HARBOR_PASSWORD: ${{ secrets.HARBOR_ROBOT_SECRET }}
|
||||||
|
HARBOR_URL: ${{ vars.HARBOR_URL }}
|
||||||
|
run: helm registry login ${HARBOR_URL} --username ${HARBOR_USERNAME} --password ${HARBOR_PASSWORD}
|
||||||
|
- name: deploy middleware in testing
|
||||||
|
env:
|
||||||
|
PROJECT_NAME: ${{ vars.PROJECT_NAME }}
|
||||||
|
run: |
|
||||||
|
helm upgrade --install ${PROJECT_NAME}-dev-rabbitmq oci://registry.merlin.xin/charts/bitnamicharts/rabbitmq --version 16.0.14 --namespace testing --values dev-rabbitmq.yaml
|
||||||
|
helm upgrade --install ${PROJECT_NAME}-dev-redis oci://registry.merlin.xin/charts/bitnamicharts/redis --version 24.1.3 --namespace testing --values dev-redis.yaml
|
||||||
20
dev-rabbitmq.yaml
Normal file
20
dev-rabbitmq.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
global:
|
||||||
|
security:
|
||||||
|
allowInsecureImages: true
|
||||||
|
storageClass: longhorn-hdd
|
||||||
|
|
||||||
|
persistence:
|
||||||
|
size: 1Gi
|
||||||
|
|
||||||
|
image:
|
||||||
|
registry: registry.merlin.xin
|
||||||
|
repository: mirrors/bitnamilegacy/rabbitmq
|
||||||
|
tag: 4.1.3-debian-12-r1
|
||||||
|
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 0.1
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 0.2
|
||||||
|
memory: 256Mi
|
||||||
32
dev-redis.yaml
Normal file
32
dev-redis.yaml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
global:
|
||||||
|
security:
|
||||||
|
allowInsecureImages: true
|
||||||
|
storageClass: longhorn-hdd
|
||||||
|
|
||||||
|
image:
|
||||||
|
registry: registry.merlin.xin
|
||||||
|
repository: mirrors/bitnamilegacy/redis
|
||||||
|
tag: 8.2.1-debian-12-r0
|
||||||
|
|
||||||
|
kubectl:
|
||||||
|
image:
|
||||||
|
registry: harbor.merlin.xin
|
||||||
|
repository: mirrors/bitnamilegacy/kubectl
|
||||||
|
tag: 1.33.4-debian-12-r0
|
||||||
|
|
||||||
|
architecture: standalone
|
||||||
|
replica:
|
||||||
|
replicaCount: 0
|
||||||
|
|
||||||
|
master:
|
||||||
|
count: 1
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 0.1
|
||||||
|
memory: 128Mi
|
||||||
|
limits:
|
||||||
|
cpu: 0.2
|
||||||
|
memory: 256Mi
|
||||||
|
persistence:
|
||||||
|
size: 1Gi
|
||||||
|
|
||||||
2
mvnw.cmd
vendored
2
mvnw.cmd
vendored
@@ -23,7 +23,7 @@
|
|||||||
@REM
|
@REM
|
||||||
@REM Optional ENV vars
|
@REM Optional ENV vars
|
||||||
@REM MVNW_REPOURL - repo url base for downloading maven distribution
|
@REM MVNW_REPOURL - repo url base for downloading maven distribution
|
||||||
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
|
@REM MVNW_USERNAME/MVNW_PASSWORD - userinfo and password for downloading maven
|
||||||
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
|
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
|
||||||
@REM ----------------------------------------------------------------------------
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
65
pom.xml
65
pom.xml
@@ -13,19 +13,6 @@
|
|||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<name>myplayer-backend</name>
|
<name>myplayer-backend</name>
|
||||||
<description>myplayer-backend</description>
|
<description>myplayer-backend</description>
|
||||||
<url/>
|
|
||||||
<licenses>
|
|
||||||
<license/>
|
|
||||||
</licenses>
|
|
||||||
<developers>
|
|
||||||
<developer/>
|
|
||||||
</developers>
|
|
||||||
<scm>
|
|
||||||
<connection/>
|
|
||||||
<developerConnection/>
|
|
||||||
<tag/>
|
|
||||||
<url/>
|
|
||||||
</scm>
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -51,9 +38,14 @@
|
|||||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.kafka</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-kafka</artifactId>
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
@@ -64,18 +56,13 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<optional>true</optional>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.kafka</groupId>
|
|
||||||
<artifactId>spring-kafka-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-test</artifactId>
|
<artifactId>spring-security-test</artifactId>
|
||||||
@@ -105,11 +92,27 @@
|
|||||||
<artifactId>mybatis-plus-jsqlparser</artifactId>
|
<artifactId>mybatis-plus-jsqlparser</artifactId>
|
||||||
<version>3.5.11</version>
|
<version>3.5.11</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mybatis</groupId>
|
||||||
|
<artifactId>mybatis-spring</artifactId>
|
||||||
|
<version>3.0.4</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt</artifactId>
|
<artifactId>jjwt</artifactId>
|
||||||
<version>0.12.6</version>
|
<version>0.12.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springdoc</groupId>
|
||||||
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
|
<version>2.8.14</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>2.0.45</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -122,29 +125,9 @@
|
|||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<annotationProcessorPaths>
|
|
||||||
<path>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
</path>
|
|
||||||
</annotationProcessorPaths>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
<configuration>
|
|
||||||
<excludes>
|
|
||||||
<exclude>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
</exclude>
|
|
||||||
</excludes>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|||||||
@@ -2,8 +2,11 @@ package xin.merlin.myplayerbackend;
|
|||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import xin.merlin.myplayerbackend.config.security.JwtProperties;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
|
@EnableConfigurationProperties(JwtProperties.class)
|
||||||
public class MyplayerBackendApplication {
|
public class MyplayerBackendApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package xin.merlin.myplayerbackend.config;
|
||||||
|
|
||||||
|
import org.springframework.amqp.core.Queue;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class RabbitMQConfig {
|
||||||
|
|
||||||
|
public static final String WS_MESSAGE_QUEUE = "ws.message";
|
||||||
|
|
||||||
|
public static final String WS_VIDEO_QUEUE = "ws.video";
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Queue wsMessageQueue() {
|
||||||
|
return new Queue(WS_MESSAGE_QUEUE, true); // 持久化队列
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Queue wsVideoQueue() {
|
||||||
|
return new Queue(WS_VIDEO_QUEUE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package xin.merlin.myplayerbackend.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||||
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class RedisConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
|
||||||
|
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||||
|
template.setConnectionFactory(factory);
|
||||||
|
|
||||||
|
template.setKeySerializer(new StringRedisSerializer());
|
||||||
|
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
|
||||||
|
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package xin.merlin.myplayerbackend.config;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.socket.config.annotation.EnableWebSocket;
|
||||||
|
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
|
||||||
|
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
|
||||||
|
import xin.merlin.myplayerbackend.config.security.WebsocketInterceptor;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.CustomWebSocketHandler;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSocket
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class WebsocketConfig implements WebSocketConfigurer {
|
||||||
|
|
||||||
|
private final CustomWebSocketHandler handler;
|
||||||
|
|
||||||
|
private final WebsocketInterceptor interceptor;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
|
||||||
|
registry.addHandler(handler, "/ws/online").addInterceptors(interceptor).setAllowedOrigins("*");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package xin.merlin.myplayerbackend.config.security;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.security.authentication.InsufficientAuthenticationException;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||||
|
@Override
|
||||||
|
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
|
||||||
|
String message = "认证失败";
|
||||||
|
if (exception instanceof InsufficientAuthenticationException) {
|
||||||
|
message = "未提供认证信息";
|
||||||
|
}
|
||||||
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
response.setContentType("application/json;charset=utf-8");
|
||||||
|
response.getWriter().write(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,12 +35,12 @@ public class JWTAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (!jwtUtil.isTokenExpired(token)) {
|
if (!jwtUtil.isTokenExpired(token)) {
|
||||||
System.out.println(token);
|
// System.out.println("token expired: " + token);
|
||||||
String username = jwtUtil.getUAccount(token);
|
String account = jwtUtil.getAccount(token);
|
||||||
|
|
||||||
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
if (account != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||||
UsernamePasswordAuthenticationToken authenticationToken =
|
UsernamePasswordAuthenticationToken authenticationToken =
|
||||||
new UsernamePasswordAuthenticationToken(username, null, Collections.emptyList());
|
new UsernamePasswordAuthenticationToken(account, null, Collections.emptyList());
|
||||||
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package xin.merlin.myplayerbackend.config.security;
|
package xin.merlin.myplayerbackend.config.security;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
@@ -22,21 +21,24 @@ public class SecurityConfig {
|
|||||||
private final JWTAuthenticationFilter jwtAuthenticationFilter;
|
private final JWTAuthenticationFilter jwtAuthenticationFilter;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity http,CustomAuthenticationEntryPoint entryPoint) throws Exception {
|
||||||
http
|
http
|
||||||
.csrf(AbstractHttpConfigurer::disable)
|
.csrf(AbstractHttpConfigurer::disable)
|
||||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||||
.authorizeHttpRequests(authz -> authz
|
.authorizeHttpRequests(authz -> authz
|
||||||
.requestMatchers(
|
.requestMatchers(
|
||||||
"/login",
|
"/error",
|
||||||
"/register",
|
"/shadow/**",
|
||||||
"/health",
|
"/health",
|
||||||
"/code/**",
|
"/code/**",
|
||||||
"/blog/**"
|
"/v3/api-docs/**",
|
||||||
|
"/account/mail/verify/**",
|
||||||
|
"/ws/**"
|
||||||
).permitAll()
|
).permitAll()
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
)
|
)
|
||||||
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
|
||||||
|
.exceptionHandling(ex -> ex.authenticationEntryPoint(entryPoint));
|
||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
@@ -48,7 +50,7 @@ public class SecurityConfig {
|
|||||||
@Override
|
@Override
|
||||||
public void addCorsMappings(CorsRegistry registry) {
|
public void addCorsMappings(CorsRegistry registry) {
|
||||||
registry.addMapping("/**")
|
registry.addMapping("/**")
|
||||||
.allowedOriginPatterns("*") // 开发阶段允许所有来源
|
.allowedOriginPatterns("*")
|
||||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||||
.allowedHeaders("*")
|
.allowedHeaders("*")
|
||||||
.exposedHeaders("Authorization")
|
.exposedHeaders("Authorization")
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package xin.merlin.myplayerbackend.config.security;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.server.ServerHttpRequest;
|
||||||
|
import org.springframework.http.server.ServerHttpResponse;
|
||||||
|
import org.springframework.http.server.ServletServerHttpRequest;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.socket.WebSocketHandler;
|
||||||
|
import org.springframework.web.socket.server.HandshakeInterceptor;
|
||||||
|
import xin.merlin.myplayerbackend.utils.JwtUtil;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class WebsocketInterceptor implements HandshakeInterceptor {
|
||||||
|
|
||||||
|
private final JwtUtil jwtUtil;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
|
||||||
|
try {
|
||||||
|
// 获取 token
|
||||||
|
List<String> protocols = request.getHeaders().get("Sec-WebSocket-Protocol");
|
||||||
|
String token = null;
|
||||||
|
if (protocols == null){
|
||||||
|
log.info("no token!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String tokenHeader = protocols.get(0);
|
||||||
|
// System.out.println(tokenHeader);
|
||||||
|
response.getHeaders().add("Sec-WebSocket-Protocol",tokenHeader);
|
||||||
|
token = tokenHeader.replace("token-", "");
|
||||||
|
if (jwtUtil.isTokenExpired(token)){
|
||||||
|
log.info("token expired");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
String account = jwtUtil.getAccount(token);
|
||||||
|
attributes.put("id", id);
|
||||||
|
attributes.put("account", account);
|
||||||
|
if (request instanceof ServletServerHttpRequest servletRequest) {
|
||||||
|
String userName = servletRequest.getServletRequest().getParameter("name");
|
||||||
|
if (userName != null) {
|
||||||
|
attributes.put("name", userName); // 将u_name存储到Attributes中
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package xin.merlin.myplayerbackend.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import xin.merlin.myplayerbackend.entity.http.Code;
|
||||||
|
import xin.merlin.myplayerbackend.service.impl.AccountServiceImpl;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.Response;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 账户相关接口:
|
||||||
|
* 修改邮箱
|
||||||
|
* 修改密码
|
||||||
|
* */
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/account")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AccountController {
|
||||||
|
|
||||||
|
private final AccountServiceImpl accountService;
|
||||||
|
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
@PostMapping("/change/email")
|
||||||
|
Response changeEmail(@RequestBody Code code, @RequestParam String email){
|
||||||
|
return accountService.changeEmail(code,email);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/mail/verify/{encode}")
|
||||||
|
Response verifyEmail(@PathVariable String encode){
|
||||||
|
return accountService.verifyEmail(encode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/change/password")
|
||||||
|
Response changePassword(@RequestBody Code code){
|
||||||
|
return accountService.resetPassword(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @PostMapping("/init")
|
||||||
|
// Response init(@RequestBody Account account) {
|
||||||
|
// try {
|
||||||
|
// if(account==null||account.getAccount()==null) return Response.success(ResultCode.ACCOUNT_INFO_LOST);
|
||||||
|
// account.setPassword(passwordEncoder.encode(account.getPassword()));
|
||||||
|
// accountService.init(account);
|
||||||
|
// return Response.success(ResultCode.SUCCESS);
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// log.error(e.getMessage());
|
||||||
|
// return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package xin.merlin.myplayerbackend.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Audit;
|
||||||
|
import xin.merlin.myplayerbackend.service.UploadService;
|
||||||
|
import xin.merlin.myplayerbackend.service.impl.AuditServiceImpl;
|
||||||
|
import xin.merlin.myplayerbackend.utils.JwtUtil;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.Response;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.ResultCode;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/audit")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AuditController {
|
||||||
|
|
||||||
|
private final AuditServiceImpl auditService;
|
||||||
|
|
||||||
|
private final UploadService uploadService;
|
||||||
|
|
||||||
|
private final JwtUtil jwtUtil;
|
||||||
|
|
||||||
|
@PostMapping("/upload/avatar")
|
||||||
|
@Transactional
|
||||||
|
Response uploadAvatar(@RequestParam("avatar") MultipartFile file,
|
||||||
|
@RequestParam("type") Integer type,
|
||||||
|
@RequestParam("applicant") Integer applicant,
|
||||||
|
@RequestParam("influence") Integer influence) throws IOException {
|
||||||
|
try {
|
||||||
|
String target = uploadService.uploadAvatar(file,type,influence);
|
||||||
|
Audit oldAudit = auditService.getOne(
|
||||||
|
Wrappers.<Audit>lambdaQuery().eq(Audit::getType, type)
|
||||||
|
.eq(Audit::getApplicant,applicant).eq(Audit::getInfluence,influence));
|
||||||
|
|
||||||
|
Audit audit = new Audit(type,applicant,influence,target);
|
||||||
|
if(oldAudit != null) {
|
||||||
|
audit = new Audit(oldAudit.getA_id(),type,applicant,influence,target);
|
||||||
|
}
|
||||||
|
auditService.saveOrUpdate(audit);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 管理员api
|
||||||
|
|
||||||
|
@GetMapping("/get/all")
|
||||||
|
Response getAll(@RequestHeader("Authorization")String token,@RequestParam Integer size,@RequestParam Integer page) {
|
||||||
|
token = token.substring(7);
|
||||||
|
if(!jwtUtil.isAdmin(token)) return Response.success(ResultCode.ACCOUNT_PERMISSION_DENY);
|
||||||
|
return Response.success(ResultCode.SUCCESS,auditService.page(new Page<Audit>().setCurrent(page).setSize(size), Wrappers.<Audit>lambdaQuery().orderByAsc(Audit::getType)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO:完善完基础类别的增删改查之后,统一处理审核
|
||||||
|
@PostMapping("/update/status")
|
||||||
|
Response updateStatus(@RequestHeader("Authorization")String token,@RequestBody Audit audit) {
|
||||||
|
token = token.substring(7);
|
||||||
|
if(!jwtUtil.isAdmin(token)) return Response.success(ResultCode.ACCOUNT_PERMISSION_DENY);
|
||||||
|
|
||||||
|
auditService.passTypeOne(audit);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package xin.merlin.myplayerbackend.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Account;
|
||||||
|
import xin.merlin.myplayerbackend.entity.http.Code;
|
||||||
|
import xin.merlin.myplayerbackend.service.CodeService;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.Response;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.ResultCode;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 验证码controller
|
||||||
|
* 包含发送和验证逻辑*/
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/code")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CodeController {
|
||||||
|
|
||||||
|
private final CodeService codeService;
|
||||||
|
|
||||||
|
//发送验证码
|
||||||
|
@PostMapping("/send")
|
||||||
|
Response send(@RequestBody Account account){
|
||||||
|
try {
|
||||||
|
return codeService.send(account);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//验证验证码是否存在、可用、正确
|
||||||
|
@PostMapping("/verify")
|
||||||
|
Response verify(@RequestBody Code code){
|
||||||
|
try {
|
||||||
|
return codeService.verify(code);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package xin.merlin.myplayerbackend.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Friends;
|
||||||
|
import xin.merlin.myplayerbackend.service.impl.FriendsServiceImpl;
|
||||||
|
import xin.merlin.myplayerbackend.service.impl.InvitingServiceImpl;
|
||||||
|
import xin.merlin.myplayerbackend.utils.JwtUtil;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.Response;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.ResultCode;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RequestMapping("/friend")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class FriendController {
|
||||||
|
|
||||||
|
private final FriendsServiceImpl friendsService;
|
||||||
|
|
||||||
|
private final InvitingServiceImpl invitingService;
|
||||||
|
|
||||||
|
private final JwtUtil jwtUtil;
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
Response getFriend(@RequestHeader("Authorization")String token, @RequestParam Integer size, @RequestParam Integer page) {
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
return Response.success(ResultCode.SUCCESS,friendsService.getFriends(id,size,page));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/delete")
|
||||||
|
Response deleteFriend(@RequestHeader("Authorization")String token, @RequestParam Integer f_id) {
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
friendsService.removeFriend(id,f_id);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/nickname")
|
||||||
|
Response nickname(@RequestHeader("Authorization")String token, @RequestBody Friends friends) {
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if (!id.equals(friends.getId())) return Response.success(ResultCode.SERVER_ERROR);
|
||||||
|
friendsService.saveOrUpdate(friends);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/status")
|
||||||
|
Response status(@RequestBody List<Integer> friends) {
|
||||||
|
try {
|
||||||
|
return Response.success(ResultCode.SUCCESS,friendsService.status(friends));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
package xin.merlin.myplayerbackend.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import xin.merlin.myplayerbackend.entity.GroupInfo;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Groups;
|
||||||
|
import xin.merlin.myplayerbackend.entity.UserInfo;
|
||||||
|
import xin.merlin.myplayerbackend.service.impl.GroupServiceImpl;
|
||||||
|
import xin.merlin.myplayerbackend.service.impl.GroupsServiceImpl;
|
||||||
|
import xin.merlin.myplayerbackend.utils.JwtUtil;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.Response;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.ResultCode;
|
||||||
|
|
||||||
|
import static com.baomidou.mybatisplus.extension.ddl.DdlScriptErrorHandler.PrintlnLogErrorHandler.log;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/group")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class GroupController {
|
||||||
|
|
||||||
|
private final GroupServiceImpl groupService;
|
||||||
|
|
||||||
|
private final GroupsServiceImpl groupsService;
|
||||||
|
|
||||||
|
private final JwtUtil jwtUtil;
|
||||||
|
|
||||||
|
private Boolean isAdmin(Integer id,Integer g_id){
|
||||||
|
return groupsService.groupIsAdmin(id,g_id)==0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/create")
|
||||||
|
Response createGroup(@RequestHeader("Authorization")String token, @RequestBody GroupInfo groupInfo){
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
return Response.success(ResultCode.SUCCESS, groupService.createGroup(id,groupInfo));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
Response getGroup(@RequestHeader("Authorization")String token){
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
return Response.success(ResultCode.SUCCESS,groupService.getGroups(id));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/search")
|
||||||
|
Response searchGroup(@RequestBody GroupInfo groupInfo){
|
||||||
|
// TODO:视情况开放api参数currentPage和 pageSize
|
||||||
|
try {
|
||||||
|
Integer currentPage = 1;
|
||||||
|
Integer pageSize = 10;
|
||||||
|
return Response.success(ResultCode.SUCCESS,groupService.searchGroups(groupInfo,currentPage,pageSize));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主动加入群聊
|
||||||
|
@GetMapping("/join/{g_id}")
|
||||||
|
Response joinGroup(@RequestHeader("Authorization")String token, @PathVariable Integer g_id){
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if(!groupService.joinGroup(id,g_id)) return Response.success(ResultCode.GROUP_USER_EXISTED);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/join/{g_id}")
|
||||||
|
Response joinGroup(@PathVariable Integer g_id,@RequestBody UserInfo userInfo){
|
||||||
|
try {
|
||||||
|
if(!groupService.joinGroup(userInfo.getId(),g_id)) return Response.success(ResultCode.GROUP_USER_EXISTED);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/leave/{g_id}")
|
||||||
|
Response leaveGroup(@RequestHeader("Authorization")String token, @PathVariable Integer g_id){
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if(!groupService.leaveGroup(id,g_id)) return Response.success(ResultCode.GROUP_USER_NOT_EXISTED);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/leave/{g_id}")
|
||||||
|
Response leaveGroup(@RequestHeader("Authorization")String token,@PathVariable Integer g_id,@RequestBody UserInfo userInfo){
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if(!isAdmin(id,g_id)) return Response.success(ResultCode.ACCOUNT_PERMISSION_DENY);
|
||||||
|
if(!groupService.leaveGroup(userInfo.getId(),g_id)) return Response.success(ResultCode.GROUP_USER_NOT_EXISTED);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/update")
|
||||||
|
Response updatePlayroom(@RequestHeader("Authorization")String token, @RequestBody GroupInfo groupInfo) {
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if(!isAdmin(id,groupInfo.getG_id())) return Response.success(ResultCode.ACCOUNT_PERMISSION_DENY);
|
||||||
|
groupService.updateById(groupInfo);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/delete")
|
||||||
|
Response deletePlayroom(@RequestHeader("Authorization")String token, @RequestBody GroupInfo groupInfo) {
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if(!isAdmin(id,groupInfo.getG_id())) return Response.success(ResultCode.ACCOUNT_PERMISSION_DENY);
|
||||||
|
return Response.success(ResultCode.SUCCESS,groupService.deletePlayroom(groupInfo));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/member/{g_id}")
|
||||||
|
Response getMember(@PathVariable("g_id")Integer g_id,@RequestParam Integer currentPage,@RequestParam Integer pageSize){
|
||||||
|
try {
|
||||||
|
return Response.success(ResultCode.SUCCESS,groupService.getMember(g_id,currentPage,pageSize));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/member/delete/{g_id}")
|
||||||
|
Response deleteMember(@RequestHeader("Authorization")String token, @PathVariable("g_id")Integer g_id, @RequestBody UserInfo userInfo){
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if(!isAdmin(id,g_id)) return Response.success(ResultCode.ACCOUNT_PERMISSION_DENY);
|
||||||
|
groupsService.remove(Wrappers.<Groups>lambdaQuery().eq(Groups::getG_id,g_id).eq(Groups::getId,userInfo.getId()));
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package xin.merlin.myplayerbackend.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.Response;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.ResultCode;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class HealthController {
|
||||||
|
|
||||||
|
@GetMapping("/health")
|
||||||
|
Response health() {
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package xin.merlin.myplayerbackend.controller;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Inviting;
|
||||||
|
import xin.merlin.myplayerbackend.entity.UserInfo;
|
||||||
|
import xin.merlin.myplayerbackend.service.impl.InvitingServiceImpl;
|
||||||
|
import xin.merlin.myplayerbackend.service.impl.PlayroomsServiceImpl;
|
||||||
|
import xin.merlin.myplayerbackend.utils.JwtUtil;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.Response;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.ResultCode;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static com.baomidou.mybatisplus.extension.ddl.DdlScriptErrorHandler.PrintlnLogErrorHandler.log;
|
||||||
|
|
||||||
|
@RequestMapping("/inviting")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class InvitingController {
|
||||||
|
|
||||||
|
private final InvitingServiceImpl invitingService;
|
||||||
|
|
||||||
|
private final PlayroomsServiceImpl playroomsService;
|
||||||
|
|
||||||
|
private final JwtUtil jwtUtil;
|
||||||
|
|
||||||
|
// playroom鉴权
|
||||||
|
private Boolean isAdmin(Integer id,Integer r_id){
|
||||||
|
return playroomsService.playroomIsAdmin(id,r_id)==0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/friends")
|
||||||
|
Response requestFriend(@RequestHeader("Authorization")String token, @RequestBody UserInfo userInfo) {
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if (Objects.equals(id, userInfo.getId())) return Response.success(ResultCode.INVITING_ILLEGAL_REQUEST);
|
||||||
|
if(!invitingService.inviting(id,userInfo.getId(),null)) return Response.success(ResultCode.INVITING_RE_REQUEST);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
Response getFriend(@RequestHeader("Authorization")String token, @RequestParam Integer pageSize, @RequestParam Integer currentPage) {
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
return Response.success(ResultCode.SUCCESS, invitingService.getInvitingDetail(id, pageSize, currentPage));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/handle")
|
||||||
|
Response handleFriend(@RequestHeader("Authorization")String token, @RequestBody Inviting inviting) {
|
||||||
|
try {
|
||||||
|
if (Objects.equals(inviting.getInviter(), inviting.getTarget())) return Response.success(ResultCode.ACCOUNT_PERMISSION_DENY);
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if(!inviting.getTarget().equals(id)) return Response.success(ResultCode.INVITING_ILLEGAL_RESPONSE);
|
||||||
|
if(!invitingService.handleFriendInviting(inviting)) return Response.success(ResultCode.INVITING_ILLEGAL_REQUEST);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/playroom")
|
||||||
|
Response playRoom(@RequestBody Inviting inviting) {
|
||||||
|
try {
|
||||||
|
if(inviting.getRoom()==null || !inviting.getStatus().equals(0)) return Response.success(ResultCode.INVITING_REQUEST_ERROR);
|
||||||
|
if(!invitingService.inviting(inviting.getInviter(),inviting.getTarget(),inviting.getRoom())) return Response.success(ResultCode.INVITING_RE_REQUEST);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 管理员获取playroom
|
||||||
|
@GetMapping("/playroom/get/{r_id}")
|
||||||
|
Response playroomGet(@RequestHeader("Authorization")String token,@PathVariable("r_id") Integer r_id, @RequestParam Integer pageSize, @RequestParam Integer currentPage) {
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if (!isAdmin(id,r_id)) return Response.success(ResultCode.INVITING_AUTH_ERROR);
|
||||||
|
return Response.success(ResultCode.SUCCESS, invitingService.getSelfInvitingDetail(r_id, pageSize, currentPage));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 管理员对请求进行审批
|
||||||
|
@PostMapping("/playroom/handle/{r_id}")
|
||||||
|
Response playroomHandle(@RequestHeader("Authorization")String token,@PathVariable("r_id") Integer r_id, @RequestBody Inviting inviting) {
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if (!isAdmin(id,r_id)) return Response.success(ResultCode.INVITING_AUTH_ERROR);
|
||||||
|
if(!invitingService.handlePlayroomInviting(inviting)) return Response.success(ResultCode.INVITING_ILLEGAL_REQUEST);
|
||||||
|
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package xin.merlin.myplayerbackend.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Account;
|
||||||
|
import xin.merlin.myplayerbackend.entity.http.Code;
|
||||||
|
import xin.merlin.myplayerbackend.service.CodeService;
|
||||||
|
import xin.merlin.myplayerbackend.service.LoginService;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.Response;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.ResultCode;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 登录controller
|
||||||
|
* 包括:登录和注册逻辑
|
||||||
|
* */
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/shadow")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class LoginController {
|
||||||
|
|
||||||
|
private final LoginService loginService;
|
||||||
|
|
||||||
|
private final CodeService codeService;
|
||||||
|
|
||||||
|
private final HttpServletRequest request;
|
||||||
|
|
||||||
|
// 账户密码登录逻辑
|
||||||
|
@PostMapping("/login")
|
||||||
|
Response login(@RequestBody Account account){
|
||||||
|
try {
|
||||||
|
return loginService.login(account);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证码登录逻辑
|
||||||
|
@PostMapping("/login/byCode")
|
||||||
|
Response login(@RequestBody Code code){
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册逻辑
|
||||||
|
@PostMapping("/register")
|
||||||
|
Response register(@RequestBody Code code){
|
||||||
|
if(code.getCode()==null|| code.getCode().isEmpty() || code.getC_id()==null || code.getC_id().isEmpty()) return Response.success(ResultCode.MAIL_VERIFY_NOT_EXIST);
|
||||||
|
try {
|
||||||
|
return loginService.register(code,request.getRemoteAddr());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
package xin.merlin.myplayerbackend.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import xin.merlin.myplayerbackend.entity.PlayroomInfo;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Playrooms;
|
||||||
|
import xin.merlin.myplayerbackend.entity.UserInfo;
|
||||||
|
import xin.merlin.myplayerbackend.service.impl.PlayroomServiceImpl;
|
||||||
|
import xin.merlin.myplayerbackend.service.impl.PlayroomsServiceImpl;
|
||||||
|
import xin.merlin.myplayerbackend.utils.JwtUtil;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.Response;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.ResultCode;
|
||||||
|
|
||||||
|
import static com.baomidou.mybatisplus.extension.ddl.DdlScriptErrorHandler.PrintlnLogErrorHandler.log;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/playroom")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PlayroomController {
|
||||||
|
|
||||||
|
private final JwtUtil jwtUtil;
|
||||||
|
|
||||||
|
private final PlayroomServiceImpl playroomService;
|
||||||
|
|
||||||
|
private final PlayroomsServiceImpl playroomsService;
|
||||||
|
|
||||||
|
private Boolean isAdmin(Integer id,Integer r_id){
|
||||||
|
return playroomsService.playroomIsAdmin(id,r_id)==0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/create")
|
||||||
|
Response createPlayroom(@RequestHeader("Authorization")String token, @RequestBody PlayroomInfo playroomInfo) {
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
return Response.success(ResultCode.SUCCESS, playroomService.createPlayroom(id,playroomInfo));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
Response getPlayroom(@RequestHeader("Authorization")String token){
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
|
||||||
|
return Response.success(ResultCode.SUCCESS,playroomService.getPlayrooms(id));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/search")
|
||||||
|
Response searchPlayroom(@RequestBody PlayroomInfo playroomInfo) {
|
||||||
|
// TODO:视情况开放api参数currentPage和 pageSize
|
||||||
|
try {
|
||||||
|
Integer currentPage = 1;
|
||||||
|
Integer pageSize = 10;
|
||||||
|
|
||||||
|
return Response.success(ResultCode.SUCCESS,playroomService.searchPlayroom(playroomInfo,currentPage,pageSize));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/update")
|
||||||
|
Response updatePlayroom(@RequestHeader("Authorization")String token, @RequestBody PlayroomInfo playroomInfo) {
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if(!isAdmin(id,playroomInfo.getR_id())) return Response.success(ResultCode.ACCOUNT_PERMISSION_DENY);
|
||||||
|
playroomService.updateById(playroomInfo);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/delete")
|
||||||
|
Response deletePlayroom(@RequestHeader("Authorization")String token, @RequestBody PlayroomInfo playroomInfo) {
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if(!isAdmin(id,playroomInfo.getR_id())) return Response.success(ResultCode.ACCOUNT_PERMISSION_DENY);
|
||||||
|
return Response.success(ResultCode.SUCCESS,playroomService.deletePlayroom(playroomInfo));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/member/{r_id}")
|
||||||
|
Response getMember(@PathVariable("r_id")Integer r_id,@RequestParam Integer currentPage,@RequestParam Integer pageSize){
|
||||||
|
try {
|
||||||
|
return Response.success(ResultCode.SUCCESS,playroomService.getMember(r_id,currentPage,pageSize));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/member/delete/{r_id}")
|
||||||
|
Response deleteMember(@RequestHeader("Authorization")String token, @PathVariable("r_id")Integer r_id, @RequestBody UserInfo userInfo){
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
if(!isAdmin(id,r_id)) return Response.success(ResultCode.ACCOUNT_PERMISSION_DENY);
|
||||||
|
playroomsService.remove(Wrappers.<Playrooms>lambdaQuery().eq(Playrooms::getR_id,r_id).eq(Playrooms::getId,userInfo.getId()));
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package xin.merlin.myplayerbackend.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import xin.merlin.myplayerbackend.entity.UserInfo;
|
||||||
|
import xin.merlin.myplayerbackend.service.impl.UserServiceImpl;
|
||||||
|
import xin.merlin.myplayerbackend.utils.JwtUtil;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.Response;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.ResultCode;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/user")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class UserController {
|
||||||
|
|
||||||
|
private final UserServiceImpl userService;
|
||||||
|
|
||||||
|
private final JwtUtil jwtUtil;
|
||||||
|
|
||||||
|
Boolean consistencyTest(String token, Integer id) {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer i = jwtUtil.getId(token);
|
||||||
|
return Objects.equals(i, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/info")
|
||||||
|
Response getInfo(@RequestHeader("Authorization")String token){
|
||||||
|
try {
|
||||||
|
token = token.substring(7);
|
||||||
|
Integer id = jwtUtil.getId(token);
|
||||||
|
return Response.success(ResultCode.SUCCESS,userService.getOne(Wrappers.<UserInfo>lambdaQuery().eq(UserInfo::getId,id)));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/update")
|
||||||
|
Response updateInfo(@RequestHeader("Authorization")String token,@RequestBody UserInfo userinfo){
|
||||||
|
try {
|
||||||
|
if(!consistencyTest(token,userinfo.getId())) return Response.success(ResultCode.USER_ILLEGAL_REQUEST);
|
||||||
|
userService.updateById(userinfo);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(),e);
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/search")
|
||||||
|
Response search(@RequestBody UserInfo userinfo){
|
||||||
|
// TODO:视情况开放api参数currentPage和 pageSize
|
||||||
|
Integer currentPage = 1;
|
||||||
|
Integer pageSize = 10;
|
||||||
|
try {
|
||||||
|
if(userinfo.getU_id()!=null){
|
||||||
|
return Response.success(ResultCode.SUCCESS, Map.of("result",userService.searchByUID(userinfo.getU_id(),currentPage,pageSize)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return Response.success(ResultCode.SUCCESS, Map.of("result",userService.searchByName(userinfo.getU_name(),currentPage,pageSize)));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(),e);
|
||||||
|
return Response.fail(ResultCode.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
29
src/main/java/xin/merlin/myplayerbackend/entity/Account.java
Normal file
29
src/main/java/xin/merlin/myplayerbackend/entity/Account.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("account")
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Account {
|
||||||
|
@TableId(value = "id",type = IdType.AUTO)
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private String account;
|
||||||
|
private String password;
|
||||||
|
private String ip;
|
||||||
|
// 1 user; 0 admin
|
||||||
|
private Integer character;
|
||||||
|
|
||||||
|
public Account(String account, String password, String ip, Integer character) {
|
||||||
|
this.account = account;
|
||||||
|
this.password = password;
|
||||||
|
this.ip = ip;
|
||||||
|
this.character = character;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/main/java/xin/merlin/myplayerbackend/entity/Audit.java
Normal file
29
src/main/java/xin/merlin/myplayerbackend/entity/Audit.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("audit")
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Audit {
|
||||||
|
@TableId("a_id")
|
||||||
|
private Integer a_id;
|
||||||
|
// 约定:type == 0 已通过审核, 1 用户头像待审核, 2 群聊头像待审核, 3 playroom头像待审核, 4 修改邮箱请求, 5 已经通过验证的邮箱修改请求, 6 已过期的审核请求
|
||||||
|
private Integer type;
|
||||||
|
private Integer applicant;
|
||||||
|
private Integer influence;
|
||||||
|
private String changed;
|
||||||
|
|
||||||
|
public Audit(Integer type,Integer applicant,Integer influence,String changed) {
|
||||||
|
this.type = type;
|
||||||
|
this.applicant = applicant;
|
||||||
|
this.influence = influence;
|
||||||
|
this.changed = changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/main/java/xin/merlin/myplayerbackend/entity/Friends.java
Normal file
17
src/main/java/xin/merlin/myplayerbackend/entity/Friends.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("friends")
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Friends {
|
||||||
|
private Integer id;
|
||||||
|
private Integer f_id;
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("groupinfo")
|
||||||
|
public class GroupInfo {
|
||||||
|
@TableId("g_id")
|
||||||
|
private Integer g_id;
|
||||||
|
|
||||||
|
private String g_name;
|
||||||
|
private String g_introduction;
|
||||||
|
private String g_avatar;
|
||||||
|
}
|
||||||
16
src/main/java/xin/merlin/myplayerbackend/entity/Groups.java
Normal file
16
src/main/java/xin/merlin/myplayerbackend/entity/Groups.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("groups")
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Groups {
|
||||||
|
private Integer g_id;
|
||||||
|
private Integer id;
|
||||||
|
private Integer role;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("inviting")
|
||||||
|
public class Inviting {
|
||||||
|
@TableId("i_id")
|
||||||
|
private Integer i_id;
|
||||||
|
|
||||||
|
private Integer inviter;
|
||||||
|
private Integer target;
|
||||||
|
// 0 表示未处理 1 表示同意 2 表示拒绝
|
||||||
|
private Integer status;
|
||||||
|
private Integer room;
|
||||||
|
private LocalDateTime time;
|
||||||
|
}
|
||||||
20
src/main/java/xin/merlin/myplayerbackend/entity/Message.java
Normal file
20
src/main/java/xin/merlin/myplayerbackend/entity/Message.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("message")
|
||||||
|
public class Message {
|
||||||
|
@TableId("m_id")
|
||||||
|
private Integer m_id;
|
||||||
|
|
||||||
|
private Integer from;
|
||||||
|
private Integer to;
|
||||||
|
private String content;
|
||||||
|
private LocalDateTime time;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("playroominfo")
|
||||||
|
public class PlayroomInfo {
|
||||||
|
@TableId(value = "r_id",type = IdType.AUTO)
|
||||||
|
private Integer r_id;
|
||||||
|
|
||||||
|
private String r_name;
|
||||||
|
private String r_introduction;
|
||||||
|
private String r_avatar;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("playrooms")
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Playrooms {
|
||||||
|
private Integer r_id;
|
||||||
|
private Integer id;
|
||||||
|
private Integer role;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("userinfo")
|
||||||
|
public class UserInfo {
|
||||||
|
private String u_id;
|
||||||
|
@TableId("id")
|
||||||
|
private Integer id;
|
||||||
|
private String u_name;
|
||||||
|
private String u_introduction;
|
||||||
|
private String u_avatar;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity.http;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class Code {
|
||||||
|
private String account;
|
||||||
|
private String c_id;
|
||||||
|
private String code;
|
||||||
|
private String password;
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity.http;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import xin.merlin.myplayerbackend.entity.UserInfo;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class Friend {
|
||||||
|
|
||||||
|
private String u_id;
|
||||||
|
private Integer id;
|
||||||
|
private String u_name;
|
||||||
|
private String u_introduction;
|
||||||
|
private String u_avatar;
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
public Friend(UserInfo userInfo,String nickname) {
|
||||||
|
this.id = userInfo.getId();
|
||||||
|
this.u_id = userInfo.getU_id();
|
||||||
|
this.u_name = userInfo.getU_name();
|
||||||
|
this.u_introduction = userInfo.getU_introduction();
|
||||||
|
this.u_avatar = userInfo.getU_avatar();
|
||||||
|
this.nickname = nickname;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity.http;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import xin.merlin.myplayerbackend.entity.GroupInfo;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Groups;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class GroupDetails {
|
||||||
|
private Integer g_id;
|
||||||
|
private String g_name;
|
||||||
|
private String g_introduction;
|
||||||
|
private String g_avatar;
|
||||||
|
private Integer id;
|
||||||
|
private Integer role;
|
||||||
|
|
||||||
|
public GroupDetails(GroupInfo groupInfo, Groups groups) {
|
||||||
|
this.g_id = groupInfo.getG_id();
|
||||||
|
this.g_name = groupInfo.getG_name();
|
||||||
|
this.g_introduction = groupInfo.getG_introduction();
|
||||||
|
this.g_avatar = groupInfo.getG_avatar();
|
||||||
|
this.id = groups.getId();
|
||||||
|
this.role = groups.getRole();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity.http;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Inviting;
|
||||||
|
import xin.merlin.myplayerbackend.entity.UserInfo;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class InvitingDetails {
|
||||||
|
private Integer i_id;
|
||||||
|
|
||||||
|
private Integer inviter;
|
||||||
|
private String inviter_name;
|
||||||
|
private String inviter_avatar;
|
||||||
|
|
||||||
|
private Integer target;
|
||||||
|
// 0 表示未处理 1 表示已处理
|
||||||
|
private Integer status;
|
||||||
|
private Integer room;
|
||||||
|
private LocalDateTime time;
|
||||||
|
|
||||||
|
public InvitingDetails(Inviting inviting, UserInfo userInfo) {
|
||||||
|
this.i_id = inviting.getI_id();
|
||||||
|
this.inviter = inviting.getInviter();
|
||||||
|
this.target = inviting.getTarget();
|
||||||
|
this.status = inviting.getStatus();
|
||||||
|
this.room = inviting.getRoom();
|
||||||
|
this.inviter_name = userInfo.getU_name();
|
||||||
|
this.inviter_avatar = userInfo.getU_avatar();
|
||||||
|
this.time = inviting.getTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package xin.merlin.myplayerbackend.entity.http;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import xin.merlin.myplayerbackend.entity.PlayroomInfo;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Playrooms;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class PlayroomDetails {
|
||||||
|
private Integer id;
|
||||||
|
private Integer r_id;
|
||||||
|
private String r_name;
|
||||||
|
private String r_introduction;
|
||||||
|
private String r_avatar;
|
||||||
|
private Integer role;
|
||||||
|
|
||||||
|
public PlayroomDetails(PlayroomInfo playroomInfo, Playrooms playrooms) {
|
||||||
|
this.id = playrooms.getId();
|
||||||
|
this.r_id = playrooms.getR_id();
|
||||||
|
this.role = playrooms.getRole();
|
||||||
|
this.r_name = playroomInfo.getR_name();
|
||||||
|
this.r_introduction = playroomInfo.getR_introduction();
|
||||||
|
this.r_avatar = playroomInfo.getR_avatar();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package xin.merlin.myplayerbackend.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Account;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface AccountMapper extends BaseMapper<Account> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package xin.merlin.myplayerbackend.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Audit;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface AuditMapper extends BaseMapper<Audit> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package xin.merlin.myplayerbackend.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Friends;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface FriendsMapper extends BaseMapper<Friends> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package xin.merlin.myplayerbackend.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import xin.merlin.myplayerbackend.entity.GroupInfo;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface GroupMapper extends BaseMapper<GroupInfo> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package xin.merlin.myplayerbackend.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Groups;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface GroupsMapper extends BaseMapper<Groups> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package xin.merlin.myplayerbackend.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Inviting;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface InvitingMapper extends BaseMapper<Inviting> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package xin.merlin.myplayerbackend.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Message;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface MessageMapper extends BaseMapper<Message> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package xin.merlin.myplayerbackend.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import xin.merlin.myplayerbackend.entity.PlayroomInfo;
|
||||||
|
import xin.merlin.myplayerbackend.entity.http.PlayroomDetails;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface PlayroomMapper extends BaseMapper<PlayroomInfo> {
|
||||||
|
List<PlayroomDetails> selectPlayroomDetails(@Param("userId") Integer id);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<select id="selectPlayroomDetails" resultType="xin.merlin.myplayerbackend.entity.http.PlayroomDetails">
|
||||||
|
SELECT
|
||||||
|
pr.id AS id,
|
||||||
|
pr.r_id AS r_id,
|
||||||
|
pr.role AS role,
|
||||||
|
pi.r_name AS r_name,
|
||||||
|
pi.r_introduction AS r_introduction,
|
||||||
|
pi.r_avatar AS r_avatar
|
||||||
|
FROM playrooms pr
|
||||||
|
LEFT JOIN playroominfo pi ON pr.r_id = pi.r_id
|
||||||
|
WHERE pr.id = #{userId}
|
||||||
|
</select>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package xin.merlin.myplayerbackend.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Playrooms;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface PlayroomsMapper extends BaseMapper<Playrooms> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package xin.merlin.myplayerbackend.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import xin.merlin.myplayerbackend.entity.UserInfo;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface UserMapper extends BaseMapper<UserInfo> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Account;
|
||||||
|
import xin.merlin.myplayerbackend.entity.http.Code;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.Response;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.ResultCode;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CodeService {
|
||||||
|
// 验证码字典
|
||||||
|
private static final Cache<String, String> waitingList = Caffeine.newBuilder()
|
||||||
|
.expireAfterWrite(5, TimeUnit.MINUTES)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 抛出以便登录时访问字典
|
||||||
|
public Cache<String, String> getWaitingList() {
|
||||||
|
return waitingList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 冷却缓存:限制邮箱请求频率
|
||||||
|
private static final Cache<String, Boolean> emailCooldown = Caffeine.newBuilder()
|
||||||
|
.expireAfterWrite(60, TimeUnit.SECONDS) // 冷却 60 秒
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 验证码验证次数
|
||||||
|
private static final Cache<String, Integer> codeFailCount = Caffeine.newBuilder()
|
||||||
|
.expireAfterWrite(5, TimeUnit.MINUTES)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// // 验证因子队列
|
||||||
|
// private static final Cache<String, String> authList = Caffeine.newBuilder()
|
||||||
|
// .expireAfterWrite(5, TimeUnit.MINUTES)
|
||||||
|
// .build();
|
||||||
|
//
|
||||||
|
// // 验证因子队列对外可访问
|
||||||
|
// public Cache<String, String> getAuthList() {
|
||||||
|
// return authList;
|
||||||
|
// }
|
||||||
|
|
||||||
|
private final MailService mailService;
|
||||||
|
|
||||||
|
// 发送验证码
|
||||||
|
public Response send(Account account){
|
||||||
|
String a = account.getAccount();
|
||||||
|
if(a==null) return Response.success(ResultCode.MAIL_ACCOUNT_NOT_PROVIDED);
|
||||||
|
log.info("sending code to ----->{}", a);
|
||||||
|
|
||||||
|
// 检查是否在冷却中
|
||||||
|
if (emailCooldown.getIfPresent(a) != null) {
|
||||||
|
return Response.success(ResultCode.MAIL_REQUEST_TOO_FAST);
|
||||||
|
}
|
||||||
|
String tempId = UUID.randomUUID().toString()
|
||||||
|
.replace("-", "");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 加入验证码字典
|
||||||
|
waitingList.put(tempId, mailService.sendMail(a));
|
||||||
|
// 加入验证码冷却
|
||||||
|
emailCooldown.put(a, true);
|
||||||
|
return Response.success(ResultCode.SUCCESS, Map.of("c_id", tempId));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//验证验证码是否存在、可用、正确
|
||||||
|
public Response verify(Code code){
|
||||||
|
String c_id = code.getC_id();
|
||||||
|
String account = code.getAccount();
|
||||||
|
String c = code.getCode();
|
||||||
|
if(c_id==null||account==null||c==null) return Response.success(ResultCode.MAIL_INFO_LOST);
|
||||||
|
Integer count = codeFailCount.getIfPresent(c_id);
|
||||||
|
|
||||||
|
//设置并查看最大尝试次数
|
||||||
|
try {
|
||||||
|
if(count == null){
|
||||||
|
codeFailCount.put(c_id, 1);
|
||||||
|
}else if(count<=5){
|
||||||
|
codeFailCount.put(c_id, count+1);
|
||||||
|
}else {
|
||||||
|
codeFailCount.invalidate(c_id);
|
||||||
|
return Response.success(ResultCode.MAIL_VERIFY_FAIL_TOO_MANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
//执行验证逻辑
|
||||||
|
String tempCode = waitingList.getIfPresent(c_id);
|
||||||
|
log.info("verifying...{},{}--?=--{}", account,code, tempCode);
|
||||||
|
if (tempCode == null) return Response.success(ResultCode.MAIL_VERIFY_NOT_EXIST);
|
||||||
|
if (!tempCode.equals(code.getCode())) return Response.success(ResultCode.MAIL_VERIFY_CODE_ERROR);
|
||||||
|
codeFailCount.invalidate(c_id);
|
||||||
|
emailCooldown.invalidate(account);
|
||||||
|
// waitingList.invalidate(c_id);
|
||||||
|
//// 生成认证因子
|
||||||
|
// String auth = UUID.randomUUID().toString();
|
||||||
|
// authList.put(auth, account);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Account;
|
||||||
|
import xin.merlin.myplayerbackend.entity.UserInfo;
|
||||||
|
import xin.merlin.myplayerbackend.entity.http.Code;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.AccountMapper;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.UserMapper;
|
||||||
|
import xin.merlin.myplayerbackend.utils.JwtUtil;
|
||||||
|
import xin.merlin.myplayerbackend.utils.RandomCode;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.Response;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.ResultCode;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class LoginService{
|
||||||
|
|
||||||
|
private final AccountMapper accountMapper;
|
||||||
|
|
||||||
|
private final UserMapper userMapper;
|
||||||
|
|
||||||
|
private final CodeService codeService;
|
||||||
|
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
private final JwtUtil jwtUtil;
|
||||||
|
|
||||||
|
|
||||||
|
// 账户密码登录服务逻辑
|
||||||
|
public Response login(Account account){
|
||||||
|
try {
|
||||||
|
Account ta = accountMapper.selectOne(Wrappers.<Account>lambdaQuery().eq(Account::getAccount,account.getAccount()));
|
||||||
|
if(ta == null) return Response.success(ResultCode.USER_NOT_FOUND);
|
||||||
|
if(!passwordEncoder.matches(account.getPassword(),ta.getPassword())){
|
||||||
|
return Response.success(ResultCode.ACCOUNT_PWD_ERROR);
|
||||||
|
}
|
||||||
|
String token = jwtUtil.generateToken(ta);
|
||||||
|
|
||||||
|
UserInfo userinfo = userMapper.selectOne(Wrappers.<UserInfo>lambdaQuery().eq(UserInfo::getId,ta.getId()));
|
||||||
|
return Response.success(ResultCode.SUCCESS, Map.of("token",token,"token_type","Bearer","userinfo",userinfo));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 注册服务逻辑
|
||||||
|
@Transactional
|
||||||
|
public Response register(Code code, String ip){
|
||||||
|
try {
|
||||||
|
if(accountMapper.selectOne(Wrappers.<Account>lambdaQuery().eq(Account::getAccount,code.getAccount())) != null) return Response.success(ResultCode.ACCOUNT_EXIST);
|
||||||
|
Response response = codeService.verify(code);
|
||||||
|
if(response.getCode().equals("200")){
|
||||||
|
Account account = new Account(code.getAccount(),passwordEncoder.encode(code.getPassword()),ip,1);
|
||||||
|
accountMapper.insert(account);
|
||||||
|
account = accountMapper.selectOne(Wrappers.<Account>lambdaQuery().eq(Account::getAccount, account.getAccount()));
|
||||||
|
UserInfo u = new UserInfo();
|
||||||
|
u.setId(account.getId());
|
||||||
|
do{
|
||||||
|
u.setU_id(RandomCode.generateID());
|
||||||
|
}while (userMapper.selectOne(Wrappers.<UserInfo>lambdaQuery().eq(UserInfo::getU_id,u.getU_id()))!=null);
|
||||||
|
userMapper.insert(u);
|
||||||
|
u = userMapper.selectById(u.getId());
|
||||||
|
codeService.getWaitingList().invalidate(code.getC_id());
|
||||||
|
return Response.success(ResultCode.SUCCESS,Map.of("token",jwtUtil.generateToken(account),"token_type","Bearer","userinfo",u));
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.mail.MailException;
|
||||||
|
import org.springframework.mail.SimpleMailMessage;
|
||||||
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class MailService {
|
||||||
|
|
||||||
|
private final JavaMailSender mailSender;
|
||||||
|
|
||||||
|
@Value("${spring.mail.username}")
|
||||||
|
private String mail;
|
||||||
|
|
||||||
|
public String sendMail(String receiver){
|
||||||
|
try {
|
||||||
|
String code = Double.toString(Math.random()).substring(2,8);
|
||||||
|
SimpleMailMessage message = new SimpleMailMessage();
|
||||||
|
message.setFrom(mail);
|
||||||
|
message.setTo(receiver);
|
||||||
|
message.setSubject("Welcome to use Merlin`s product");
|
||||||
|
message.setText("欢迎使用Merlin.xin产品! \n"+"您的验证码为:"+code+"\n有效期五分钟,请勿泄露!");
|
||||||
|
mailSender.send(message);
|
||||||
|
return code;
|
||||||
|
} catch (MailException e) {
|
||||||
|
log.error("e: ", e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean sendTextMail(String receiver, String text){
|
||||||
|
try {
|
||||||
|
SimpleMailMessage message = new SimpleMailMessage();
|
||||||
|
message.setFrom(mail);
|
||||||
|
message.setTo(receiver);
|
||||||
|
message.setSubject("Welcome to use Merlin`s product");
|
||||||
|
message.setText("欢迎使用Merlin.xin产品! \n"+text);
|
||||||
|
mailSender.send(message);
|
||||||
|
return true;
|
||||||
|
} catch (MailException e) {
|
||||||
|
log.error("e: ", e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service;
|
||||||
|
|
||||||
|
import jakarta.annotation.PreDestroy;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class OnlineStatusService {
|
||||||
|
|
||||||
|
private static final String ONLINE_USERS_KEY = "online:users";
|
||||||
|
|
||||||
|
private final StringRedisTemplate redis;
|
||||||
|
|
||||||
|
/** 用户上线 */
|
||||||
|
public void online(Integer uid) {
|
||||||
|
redis.opsForSet().add(ONLINE_USERS_KEY, uid.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 用户下线 */
|
||||||
|
public void offline(Integer uid) {
|
||||||
|
redis.opsForSet().remove(ONLINE_USERS_KEY, uid.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 是否在线 */
|
||||||
|
public boolean isOnline(Integer uid) {
|
||||||
|
return Boolean.TRUE.equals(redis.opsForSet().isMember(ONLINE_USERS_KEY, uid.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取所有在线用户 */
|
||||||
|
public Set<String> getOnlineUsers() {
|
||||||
|
return redis.opsForSet().members(ONLINE_USERS_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
public void cleanup() {
|
||||||
|
// 清空在线状态
|
||||||
|
redis.delete(ONLINE_USERS_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class UploadService {
|
||||||
|
|
||||||
|
@Value("${resources.user.avatar}")
|
||||||
|
private String userAvatarDir;
|
||||||
|
|
||||||
|
@Value("${resources.group.avatar}")
|
||||||
|
private String groupAvatarDir;
|
||||||
|
|
||||||
|
@Value("${resources.playroom.avatar}")
|
||||||
|
private String playroomAvatarDir;
|
||||||
|
|
||||||
|
@Value("${resources.public}")
|
||||||
|
private String publicAvatarDir;
|
||||||
|
|
||||||
|
private static final List<String> AVATAR_ALLOWED_EXTENSIONS = Arrays.asList(".jpg", ".jpeg", ".png", ".gif");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传用户、群组、放映室头像
|
||||||
|
* @param file 目标文件
|
||||||
|
* @param type 上传类型
|
||||||
|
* @param influence 受影响的id
|
||||||
|
* @return host后的访问url
|
||||||
|
* @throws IOException 抛出io异常
|
||||||
|
*/
|
||||||
|
public String uploadAvatar(MultipartFile file, Integer type,Integer influence) throws IOException {
|
||||||
|
String DIR = switch (type) {
|
||||||
|
case 1 -> userAvatarDir;
|
||||||
|
case 2 -> groupAvatarDir;
|
||||||
|
case 3 -> playroomAvatarDir;
|
||||||
|
default -> publicAvatarDir;
|
||||||
|
};
|
||||||
|
String fileName = getFilename(file, influence, DIR);
|
||||||
|
Path targetPath = Paths.get(DIR, fileName);
|
||||||
|
Files.copy(file.getInputStream(), targetPath, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
|
||||||
|
return "/resources/user/avatar/" + fileName; // 返回访问 URL
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param file 目标文件
|
||||||
|
* @param influence 受影响的id
|
||||||
|
* @param DIR 储存的位置
|
||||||
|
* @return fileName 文件在储存之后的名字
|
||||||
|
* @throws IOException 抛出io异常
|
||||||
|
*/
|
||||||
|
private static String getFilename(MultipartFile file, Integer influence, String DIR) throws IOException {
|
||||||
|
File dir = new File(DIR);
|
||||||
|
if (!dir.exists()) dir.mkdirs();
|
||||||
|
|
||||||
|
// 取文件扩展名并检查是否合法
|
||||||
|
String originalFileName = file.getOriginalFilename();
|
||||||
|
String fileExtension = "";
|
||||||
|
if (originalFileName != null && originalFileName.contains(".")) {
|
||||||
|
fileExtension = originalFileName.substring(originalFileName.lastIndexOf(".")).toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AVATAR_ALLOWED_EXTENSIONS.contains(fileExtension)) {
|
||||||
|
throw new IOException("仅支持 JPG, PNG, GIF 格式");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 以id进行命名,方便直接替换
|
||||||
|
return influence.toString() + fileExtension;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Account;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Audit;
|
||||||
|
import xin.merlin.myplayerbackend.entity.http.Code;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.AccountMapper;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.AuditMapper;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.UserMapper;
|
||||||
|
import xin.merlin.myplayerbackend.service.CodeService;
|
||||||
|
import xin.merlin.myplayerbackend.service.MailService;
|
||||||
|
import xin.merlin.myplayerbackend.utils.AESUtil;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.Response;
|
||||||
|
import xin.merlin.myplayerbackend.utils.result.ResultCode;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> {
|
||||||
|
|
||||||
|
private static final Cache<Integer, String> verifyURL = Caffeine.newBuilder()
|
||||||
|
.expireAfterWrite(24, TimeUnit.HOURS)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private final AccountMapper accountMapper;
|
||||||
|
|
||||||
|
private final AuditMapper auditMapper;
|
||||||
|
|
||||||
|
private final CodeService codeService;
|
||||||
|
|
||||||
|
private final MailService mailService;
|
||||||
|
|
||||||
|
private final AESUtil aesUtil;
|
||||||
|
|
||||||
|
private final PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
private Integer findByAccount(String account) {
|
||||||
|
Account accountEntity = accountMapper.selectOne(
|
||||||
|
Wrappers.<Account>lambdaQuery()
|
||||||
|
.select(Account::getId)
|
||||||
|
.eq(Account::getAccount, account)
|
||||||
|
);
|
||||||
|
return accountEntity == null ? null : accountEntity.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param code 验证码因子结构体
|
||||||
|
* @param email 新邮箱
|
||||||
|
* @return Response响应体
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public Response changeEmail(Code code, String email) {
|
||||||
|
try {
|
||||||
|
Response response = codeService.verify(code);
|
||||||
|
if (response.getCode().equals("200")){
|
||||||
|
Integer id = findByAccount(code.getAccount());
|
||||||
|
Audit audit = auditMapper.selectOne(Wrappers.<Audit>lambdaQuery().eq(Audit::getType,4).eq(Audit::getApplicant,id).eq(Audit::getInfluence,id));
|
||||||
|
if (audit != null){
|
||||||
|
audit.setType(6);
|
||||||
|
auditMapper.updateById(audit);
|
||||||
|
}
|
||||||
|
String url = aesUtil.encrypt(id+":"+email);
|
||||||
|
if (id != null) {
|
||||||
|
verifyURL.put(id, url);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Response.success(ResultCode.MAIL_INFO_LOST);
|
||||||
|
}
|
||||||
|
mailService.sendTextMail(email,"验证链接:\n"+"https://myplayer.merlin.xin/account/mail/verify/"+ url+"\n链接一天内有效,请尽快验证");
|
||||||
|
auditMapper.insert(new Audit(4,id,id,email));
|
||||||
|
codeService.getWaitingList().invalidate(code.getC_id());
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param encode 认证链接
|
||||||
|
* @return response响应体
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public Response verifyEmail(String encode) {
|
||||||
|
try {
|
||||||
|
Map<String, String> decode = aesUtil.decryptAndSplit(encode);
|
||||||
|
Integer id = Integer.parseInt(decode.get("id"));
|
||||||
|
String email = decode.get("email");
|
||||||
|
Audit audit = auditMapper.selectOne(Wrappers.<Audit>lambdaQuery().eq(Audit::getType,4).eq(Audit::getApplicant,id).eq(Audit::getInfluence,id));
|
||||||
|
if (audit == null) return Response.success(ResultCode.AUDIT_NO_RECORD);
|
||||||
|
if (!encode.equals(verifyURL.getIfPresent(id))){
|
||||||
|
audit.setType(6);
|
||||||
|
auditMapper.updateById(audit);
|
||||||
|
return Response.success(ResultCode.AUDIT_NO_RECORD);
|
||||||
|
}
|
||||||
|
if (!audit.getChanged().equals(email)) return Response.success(ResultCode.ACCOUNT_ILLEGAL_CHANGE);
|
||||||
|
Account account = accountMapper.selectById(id);
|
||||||
|
account.setAccount(email);
|
||||||
|
accountMapper.updateById(account);
|
||||||
|
audit.setType(5);
|
||||||
|
auditMapper.updateById(audit);
|
||||||
|
verifyURL.invalidate(id);
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param code 验证码认证因子
|
||||||
|
* @return response响应体
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public Response resetPassword(Code code){
|
||||||
|
try {
|
||||||
|
Response response = codeService.verify(code);
|
||||||
|
if (response.getCode().equals("200")){
|
||||||
|
Integer id = findByAccount(code.getAccount());
|
||||||
|
Account account = accountMapper.selectById(id);
|
||||||
|
account.setPassword(passwordEncoder.encode(code.getPassword()));
|
||||||
|
accountMapper.updateById(account);
|
||||||
|
codeService.getWaitingList().invalidate(code.getC_id());
|
||||||
|
return Response.success(ResultCode.SUCCESS);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Transactional
|
||||||
|
// public void init(Account account) {
|
||||||
|
// try {
|
||||||
|
// account = accountMapper.selectOne(Wrappers.<Account>lambdaQuery().eq(Account::getAccount, account.getAccount()));
|
||||||
|
// if(accountMapper.updateById(account)==0) throw new RuntimeException(account.getAccount()+"初始化未成功");
|
||||||
|
// User u = new User();
|
||||||
|
// u.setId(account.getId());
|
||||||
|
// do{
|
||||||
|
// u.setU_id(RandomCode.generateID());
|
||||||
|
// }while (userMapper.selectById(u.getU_id())!=null);
|
||||||
|
// userMapper.insert(u);
|
||||||
|
// } catch (RuntimeException e) {
|
||||||
|
// throw new RuntimeException(e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Audit;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.AuditMapper;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.UserMapper;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AuditServiceImpl extends ServiceImpl<AuditMapper, Audit> {
|
||||||
|
|
||||||
|
private final AuditMapper auditMapper;
|
||||||
|
|
||||||
|
private final UserMapper userMapper;
|
||||||
|
|
||||||
|
public Boolean passTypeOne(Audit audit) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Friends;
|
||||||
|
import xin.merlin.myplayerbackend.entity.UserInfo;
|
||||||
|
import xin.merlin.myplayerbackend.entity.http.Friend;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.FriendsMapper;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.UserMapper;
|
||||||
|
import xin.merlin.myplayerbackend.service.OnlineStatusService;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class FriendsServiceImpl extends ServiceImpl<FriendsMapper, Friends> {
|
||||||
|
|
||||||
|
private final FriendsMapper friendsMapper;
|
||||||
|
|
||||||
|
private final UserMapper userMapper;
|
||||||
|
|
||||||
|
private final OnlineStatusService onlineStatusService;
|
||||||
|
|
||||||
|
public List<Friend> getFriends(Integer id, Integer size, Integer page) {
|
||||||
|
|
||||||
|
List<Friends> friends = friendsMapper.selectList(new Page<>(page,size),Wrappers.<Friends>lambdaQuery().eq(Friends::getId, id));
|
||||||
|
List<Friend> fs = new ArrayList<>();
|
||||||
|
for (Friends f : friends) {
|
||||||
|
|
||||||
|
fs.add(new Friend(userMapper.selectOne(Wrappers.<UserInfo>lambdaQuery().eq(UserInfo::getId,f.getF_id())),f.getNickname()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void removeFriend(Integer id, Integer f_id) {
|
||||||
|
try {
|
||||||
|
friendsMapper.delete(Wrappers.<Friends>lambdaQuery().eq(Friends::getF_id,f_id).eq(Friends::getId,id));
|
||||||
|
friendsMapper.delete(Wrappers.<Friends>lambdaQuery().eq(Friends::getF_id,id).eq(Friends::getId,f_id));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Integer,Integer> status(List<Integer> friends){
|
||||||
|
try {
|
||||||
|
Map<Integer,Integer> map = new HashMap<>();
|
||||||
|
for (Integer f : friends) {
|
||||||
|
if(onlineStatusService.isOnline(f)){
|
||||||
|
map.put(f,1);
|
||||||
|
}else {
|
||||||
|
map.put(f,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import xin.merlin.myplayerbackend.entity.*;
|
||||||
|
import xin.merlin.myplayerbackend.entity.http.GroupDetails;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.GroupMapper;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.GroupsMapper;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.UserMapper;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class GroupServiceImpl extends ServiceImpl<GroupMapper, GroupInfo> {
|
||||||
|
|
||||||
|
private final UserMapper userMapper;
|
||||||
|
|
||||||
|
private final GroupMapper groupMapper;
|
||||||
|
|
||||||
|
private final GroupsMapper groupsMapper;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public GroupInfo createGroup(Integer id, GroupInfo groupInfo) {
|
||||||
|
try {
|
||||||
|
groupMapper.insert(groupInfo);
|
||||||
|
groupsMapper.insert(new Groups(groupInfo.getG_id(),id,0));
|
||||||
|
return groupInfo;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 优化点:使用xml语句写关联查询
|
||||||
|
public List<GroupDetails> getGroups(Integer id) {
|
||||||
|
try {
|
||||||
|
List<Groups> groups = groupsMapper.selectList(Wrappers.<Groups>lambdaQuery().eq(Groups::getId,id));
|
||||||
|
// System.out.println(groups);
|
||||||
|
List<GroupDetails> groupDetails = new ArrayList<>();
|
||||||
|
for (Groups group : groups) {
|
||||||
|
groupDetails.add(new GroupDetails(groupMapper.selectById(group.getG_id()),group));
|
||||||
|
}
|
||||||
|
return groupDetails;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Page<GroupInfo> searchGroups(GroupInfo groupInfo, Integer currentPage, Integer pageSize) {
|
||||||
|
try {
|
||||||
|
return groupMapper.selectPage(new Page<>(currentPage,pageSize),Wrappers.<GroupInfo>lambdaQuery().like(GroupInfo::getG_name,groupInfo.getG_name()));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Integer deletePlayroom(GroupInfo groupInfo) {
|
||||||
|
try {
|
||||||
|
groupsMapper.delete(Wrappers.<Groups>lambdaQuery().eq(Groups::getG_id,groupInfo.getG_id()));
|
||||||
|
return groupMapper.deleteById(groupInfo.getG_id());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<UserInfo> getMember(Integer g_id, Integer currentPage, Integer pageSize) {
|
||||||
|
try {
|
||||||
|
List<Groups> ids = groupsMapper.selectPage(new Page<>(currentPage,pageSize),Wrappers.<Groups>lambdaQuery().eq(Groups::getG_id,g_id)).getRecords();
|
||||||
|
List<UserInfo> members = new ArrayList<>();
|
||||||
|
for(Groups group:ids){
|
||||||
|
members.add(userMapper.selectById(group.getId()));
|
||||||
|
}
|
||||||
|
return members;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Boolean joinGroup(Integer id, Integer g_id) {
|
||||||
|
try {
|
||||||
|
if(groupsMapper.selectOne(Wrappers.<Groups>lambdaQuery().eq(Groups::getG_id,g_id).eq(Groups::getId,id))!=null) return false;
|
||||||
|
else {
|
||||||
|
groupsMapper.insert(new Groups(g_id,id,1));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean leaveGroup(Integer id, Integer g_id) {
|
||||||
|
try {
|
||||||
|
if(groupsMapper.selectOne(Wrappers.<Groups>lambdaQuery().eq(Groups::getG_id,g_id).eq(Groups::getId,id))==null) return false;
|
||||||
|
else {
|
||||||
|
groupsMapper.delete(Wrappers.<Groups>lambdaQuery().eq(Groups::getG_id,g_id).eq(Groups::getId,id));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Groups;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.GroupsMapper;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class GroupsServiceImpl extends ServiceImpl<GroupsMapper, Groups> {
|
||||||
|
|
||||||
|
private final GroupsMapper groupsMapper;
|
||||||
|
|
||||||
|
public Integer groupIsAdmin(Integer id, Integer g_id) {
|
||||||
|
try {
|
||||||
|
Groups groups = groupsMapper.selectOne(Wrappers.<Groups>lambdaQuery().eq(Groups::getId,id).eq(Groups::getG_id,g_id));
|
||||||
|
if (groups == null) return 1;
|
||||||
|
else return groups.getRole();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Friends;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Inviting;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Playrooms;
|
||||||
|
import xin.merlin.myplayerbackend.entity.UserInfo;
|
||||||
|
import xin.merlin.myplayerbackend.entity.http.InvitingDetails;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.FriendsMapper;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.InvitingMapper;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.PlayroomsMapper;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.UserMapper;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class InvitingServiceImpl extends ServiceImpl<InvitingMapper, Inviting> {
|
||||||
|
|
||||||
|
private final InvitingMapper invitingMapper;
|
||||||
|
|
||||||
|
private final UserMapper userMapper;
|
||||||
|
|
||||||
|
private final FriendsMapper friendsMapper;
|
||||||
|
|
||||||
|
private final PlayroomsMapper playroomsMapper;
|
||||||
|
|
||||||
|
// TODO: 修改关联查询逻辑
|
||||||
|
private Map<String, Object> getInvitingDetails(List<Inviting> invitings) {
|
||||||
|
List<InvitingDetails> invitingDetails = new ArrayList<>();
|
||||||
|
for (Inviting inviting : invitings){
|
||||||
|
InvitingDetails invitingDetail = new InvitingDetails(inviting,
|
||||||
|
userMapper.selectOne(Wrappers.<UserInfo>lambdaQuery().eq(UserInfo::getId,inviting.getInviter())));
|
||||||
|
invitingDetails.add(invitingDetail);
|
||||||
|
}
|
||||||
|
return Map.of("result",invitingDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean inviting(Integer inviter, Integer target,Integer room){
|
||||||
|
Inviting inviting = new Inviting();
|
||||||
|
inviting.setInviter(inviter);
|
||||||
|
inviting.setTarget(target);
|
||||||
|
inviting.setStatus(0);
|
||||||
|
inviting.setTime(LocalDateTime.now());
|
||||||
|
if (room != null){
|
||||||
|
inviting.setRoom(room);
|
||||||
|
}
|
||||||
|
if (invitingMapper.selectCount(Wrappers.<Inviting>lambdaQuery().eq(Inviting::getInviter,inviter).eq(Inviting::getTarget,target).eq(Inviting::getStatus,0).isNull(Inviting::getRoom)) > 0) return false;
|
||||||
|
return invitingMapper.insert(inviting) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String,Object> getInvitingDetail(Integer target, Integer size, Integer page){
|
||||||
|
try {
|
||||||
|
List<Inviting> invitings = invitingMapper.selectList(new Page<>(page,size), Wrappers.<Inviting>lambdaQuery().eq(Inviting::getTarget,target));
|
||||||
|
return getInvitingDetails(invitings);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String,Object> getSelfInvitingDetail(Integer room, Integer size, Integer page){
|
||||||
|
try {
|
||||||
|
List<Inviting> invitings = invitingMapper.selectList(new Page<>(page,size), Wrappers.<Inviting>lambdaQuery().eq(Inviting::getRoom,room).apply("inviter = target"));
|
||||||
|
return getInvitingDetails(invitings);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Boolean handleFriendInviting(Inviting inviting) {
|
||||||
|
try {
|
||||||
|
if (inviting.getStatus().equals(0)) return false;
|
||||||
|
else{
|
||||||
|
if(inviting.getStatus().equals(1)){
|
||||||
|
friendsMapper.insert(new Friends(inviting.getInviter(), inviting.getTarget(), null));
|
||||||
|
friendsMapper.insert(new Friends(inviting.getTarget(), inviting.getInviter(), null));
|
||||||
|
}
|
||||||
|
inviting.setTime(LocalDateTime.now());
|
||||||
|
invitingMapper.updateById(inviting);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// public Integer playroomIsAdmin(Integer id, Integer r_id) {
|
||||||
|
// try {
|
||||||
|
// Playrooms playrooms = playroomsMapper.selectOne(Wrappers.<Playrooms>lambdaQuery().eq(Playrooms::getId,id).eq(Playrooms::getR_id,r_id));
|
||||||
|
// if (playrooms == null) return 1;
|
||||||
|
// else return playrooms.getRole();
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// log.error(e.getMessage());
|
||||||
|
// throw new RuntimeException(e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
public Boolean handlePlayroomInviting(Inviting inviting) {
|
||||||
|
try {
|
||||||
|
if (inviting.getStatus().equals(0) || inviting.getRoom() == null) return false;
|
||||||
|
else if (inviting.getStatus().equals(1)){
|
||||||
|
playroomsMapper.insert(new Playrooms(inviting.getRoom(), inviting.getTarget(), 1));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Message;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.MessageMapper;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import xin.merlin.myplayerbackend.entity.PlayroomInfo;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Playrooms;
|
||||||
|
import xin.merlin.myplayerbackend.entity.UserInfo;
|
||||||
|
import xin.merlin.myplayerbackend.entity.http.PlayroomDetails;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.PlayroomMapper;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.PlayroomsMapper;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.UserMapper;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PlayroomServiceImpl extends ServiceImpl<PlayroomMapper, PlayroomInfo> {
|
||||||
|
|
||||||
|
private final PlayroomMapper playroomMapper;
|
||||||
|
|
||||||
|
private final PlayroomsMapper playroomsMapper;
|
||||||
|
|
||||||
|
private final UserMapper userMapper;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public PlayroomInfo createPlayroom(Integer id, PlayroomInfo playroomInfo) {
|
||||||
|
try {
|
||||||
|
playroomMapper.insert(playroomInfo);
|
||||||
|
playroomsMapper.insert(new Playrooms(playroomInfo.getR_id(),id,0));
|
||||||
|
return playroomInfo;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 优化点:使用xml语句写关联查询
|
||||||
|
public List<PlayroomDetails> getPlayrooms(Integer id) {
|
||||||
|
try {
|
||||||
|
List<Playrooms> playrooms = playroomsMapper.selectList(Wrappers.<Playrooms>lambdaQuery().eq(Playrooms::getId,id));
|
||||||
|
// System.out.println(playrooms);
|
||||||
|
List<PlayroomDetails> playroomDetails = new ArrayList<>();
|
||||||
|
for (Playrooms playroom : playrooms) {
|
||||||
|
playroomDetails.add(new PlayroomDetails(playroomMapper.selectById(playroom.getR_id()),playroom));
|
||||||
|
}
|
||||||
|
|
||||||
|
return playroomDetails;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Page<PlayroomInfo> searchPlayroom(PlayroomInfo playroomInfo, Integer currentPage, Integer pageSize) {
|
||||||
|
try {
|
||||||
|
return playroomMapper.selectPage(new Page<>(currentPage,pageSize),Wrappers.<PlayroomInfo>lambdaQuery().like(PlayroomInfo::getR_name,playroomInfo.getR_name()));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Integer deletePlayroom(PlayroomInfo playroomInfo) {
|
||||||
|
try {
|
||||||
|
playroomsMapper.delete(Wrappers.<Playrooms>lambdaQuery().eq(Playrooms::getR_id,playroomInfo.getR_id()));
|
||||||
|
return playroomMapper.deleteById(playroomInfo.getR_id());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<UserInfo> getMember(Integer r_id, Integer currentPage, Integer pageSize) {
|
||||||
|
try {
|
||||||
|
List<Playrooms> ids = playroomsMapper.selectPage(new Page<>(currentPage,pageSize),Wrappers.<Playrooms>lambdaQuery().eq(Playrooms::getR_id,r_id)).getRecords();
|
||||||
|
List<UserInfo> members = new ArrayList<>();
|
||||||
|
for(Playrooms playroom:ids){
|
||||||
|
members.add(userMapper.selectById(playroom.getId()));
|
||||||
|
}
|
||||||
|
return members;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import xin.merlin.myplayerbackend.entity.PlayroomInfo;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Playrooms;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.PlayroomMapper;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.PlayroomsMapper;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PlayroomsServiceImpl extends ServiceImpl<PlayroomsMapper, Playrooms> {
|
||||||
|
|
||||||
|
private final PlayroomsMapper playroomsMapper;
|
||||||
|
|
||||||
|
|
||||||
|
public Integer playroomIsAdmin(Integer id, Integer r_id) {
|
||||||
|
try {
|
||||||
|
Playrooms playrooms = playroomsMapper.selectOne(Wrappers.<Playrooms>lambdaQuery().eq(Playrooms::getId,id).eq(Playrooms::getR_id,r_id));
|
||||||
|
if (playrooms == null) return 1;
|
||||||
|
else return playrooms.getRole();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package xin.merlin.myplayerbackend.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import xin.merlin.myplayerbackend.entity.UserInfo;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.UserMapper;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class UserServiceImpl extends ServiceImpl<UserMapper, UserInfo> {
|
||||||
|
|
||||||
|
private final UserMapper userMapper;
|
||||||
|
|
||||||
|
public Object searchByUID(String u_id,Integer currentPage,Integer pageSize) {
|
||||||
|
try {
|
||||||
|
Page<UserInfo> page = new Page<>(currentPage, pageSize);
|
||||||
|
return userMapper.selectList(page,Wrappers.<UserInfo>lambdaQuery().like(UserInfo::getU_id, u_id));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object searchByName(String u_name,Integer currentPage,Integer pageSize) {
|
||||||
|
try {
|
||||||
|
Page<UserInfo> page = new Page<>(currentPage, pageSize);
|
||||||
|
return userMapper.selectList(page,Wrappers.<UserInfo>lambdaQuery().like(UserInfo::getU_name, u_name));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
67
src/main/java/xin/merlin/myplayerbackend/utils/AESUtil.java
Normal file
67
src/main/java/xin/merlin/myplayerbackend/utils/AESUtil.java
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AESUtil {
|
||||||
|
|
||||||
|
// 16 位密钥(必须 16/24/32 位)
|
||||||
|
private final String key;
|
||||||
|
|
||||||
|
private static final String ALGORITHM = "AES";
|
||||||
|
|
||||||
|
public AESUtil(@Value("${aes.key}") String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 加密 */
|
||||||
|
public String encrypt(String plainText) {
|
||||||
|
try {
|
||||||
|
Cipher cipher = Cipher.getInstance(ALGORITHM);
|
||||||
|
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
|
||||||
|
byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return Base64.getEncoder().encodeToString(encrypted);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("AES 加密失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 解密 */
|
||||||
|
public String decrypt(String cipherText) {
|
||||||
|
try {
|
||||||
|
Cipher cipher = Cipher.getInstance(ALGORITHM);
|
||||||
|
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, keySpec);
|
||||||
|
byte[] decoded = Base64.getDecoder().decode(cipherText);
|
||||||
|
byte[] original = cipher.doFinal(decoded);
|
||||||
|
return new String(original, StandardCharsets.UTF_8);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("AES 解密失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> decryptAndSplit(String cipherText) {
|
||||||
|
String plainText = this.decrypt(cipherText); // 先解密
|
||||||
|
String[] parts = plainText.split(":", 2); // 只分割一次,防止 email 里有 :
|
||||||
|
|
||||||
|
if (parts.length != 2) {
|
||||||
|
throw new IllegalArgumentException("解密数据格式不正确:" + plainText);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> result = new HashMap<>();
|
||||||
|
result.put("id", parts[0]);
|
||||||
|
result.put("email", parts[1]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -3,9 +3,12 @@ package xin.merlin.myplayerbackend.utils;
|
|||||||
import io.jsonwebtoken.*;
|
import io.jsonwebtoken.*;
|
||||||
import io.jsonwebtoken.security.Keys;
|
import io.jsonwebtoken.security.Keys;
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import jakarta.annotation.PreDestroy;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import xin.merlin.myplayerbackend.config.security.JwtProperties;
|
import xin.merlin.myplayerbackend.config.security.JwtProperties;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Account;
|
||||||
|
|
||||||
|
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
@@ -13,6 +16,8 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class JwtUtil {
|
public class JwtUtil {
|
||||||
@@ -35,17 +40,28 @@ public class JwtUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
public void destroy() {
|
||||||
|
log.info("JWT 组件正在关闭...");
|
||||||
|
// 如有线程池、定时任务、IO 连接,在这里 shutdown/close
|
||||||
|
// 本例仅把引用置空,帮助 GC(可选)
|
||||||
|
this.jwtParser = null;
|
||||||
|
this.key = null;
|
||||||
|
log.info("JWT 组件已关闭");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成 JWT Token
|
* 生成 JWT Token
|
||||||
*/
|
*/
|
||||||
public String generateToken(String uAccount, Integer uId) {
|
public String generateToken(Account account) {
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
Date expireDate = new Date(now.getTime() + jwtProperties.getExpire() * 1000L);
|
Date expireDate = new Date(now.getTime() + jwtProperties.getExpire() * 1000L);
|
||||||
|
|
||||||
return Jwts.builder()
|
return Jwts.builder()
|
||||||
.subject(uAccount)
|
.subject(account.getAccount())
|
||||||
.claim("id", uId)
|
.claim("id", account.getId())
|
||||||
.claim("account", uAccount)
|
.claim("account", account.getAccount())
|
||||||
|
.claim("character", account.getCharacter())
|
||||||
.id(UUID.randomUUID().toString())
|
.id(UUID.randomUUID().toString())
|
||||||
.issuedAt(now)
|
.issuedAt(now)
|
||||||
.expiration(expireDate)
|
.expiration(expireDate)
|
||||||
@@ -57,10 +73,10 @@ public class JwtUtil {
|
|||||||
/**
|
/**
|
||||||
* 解析 Token 获取 Claims
|
* 解析 Token 获取 Claims
|
||||||
*/
|
*/
|
||||||
public Claims getClaims(String token) {
|
private Claims getClaims(String token) {
|
||||||
try {
|
try {
|
||||||
Jws<Claims> jws = jwtParser.parseSignedClaims(token);
|
Jws<Claims> jws = jwtParser.parseSignedClaims(token);
|
||||||
System.out.println(jws.getPayload());
|
// System.out.println(jws.getPayload());
|
||||||
return jws.getPayload();
|
return jws.getPayload();
|
||||||
} catch (ExpiredJwtException e) {
|
} catch (ExpiredJwtException e) {
|
||||||
throw new TokenExpiredException("Token 已过期", e);
|
throw new TokenExpiredException("Token 已过期", e);
|
||||||
@@ -82,7 +98,7 @@ public class JwtUtil {
|
|||||||
/**
|
/**
|
||||||
* 获取账号
|
* 获取账号
|
||||||
*/
|
*/
|
||||||
public String getUAccount(String token) {
|
public String getAccount(String token) {
|
||||||
Claims claims = getClaims(token);
|
Claims claims = getClaims(token);
|
||||||
return claims.getSubject();
|
return claims.getSubject();
|
||||||
}
|
}
|
||||||
@@ -90,9 +106,19 @@ public class JwtUtil {
|
|||||||
/**
|
/**
|
||||||
* 获取用户ID
|
* 获取用户ID
|
||||||
*/
|
*/
|
||||||
public String getUId(String token) {
|
public Integer getId(String token) {
|
||||||
Claims claims = getClaims(token);
|
Claims claims = getClaims(token);
|
||||||
return claims.get("id", String.class);
|
return claims.get("id", Integer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public Integer getCharacter(String token) {
|
||||||
|
// Claims claims = getClaims(token);
|
||||||
|
// return claims.get("character", Integer.class);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public Boolean isAdmin(String token) {
|
||||||
|
Claims claims = getClaims(token);
|
||||||
|
return claims.get("character", Integer.class)==0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自定义异常类
|
// 自定义异常类
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class RandomCode {
|
||||||
|
|
||||||
|
private static final Random rand = new Random();
|
||||||
|
|
||||||
|
public static String generateID(){
|
||||||
|
// 生成一个0到999999999的随机数,然后格式化为9位数字字符串
|
||||||
|
return String.format("%09d", rand.nextInt(1000000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateCode(){
|
||||||
|
// 生成一个0到999999的随机数,然后格式化为6位数字字符串
|
||||||
|
return String.format("%06d", rand.nextInt(1000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
|
||||||
|
public class SHA256Util {
|
||||||
|
|
||||||
|
public static String sha256(String s) {
|
||||||
|
try {
|
||||||
|
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||||
|
byte[] bytes = md.digest(s.getBytes(StandardCharsets.UTF_8));
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (byte b : bytes) sb.append(String.format("%02x", b));
|
||||||
|
return sb.toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public class SecretKeyGenerator {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SecretKey key = Keys.secretKeyFor(io.jsonwebtoken.SignatureAlgorithm.HS256);
|
||||||
|
String base64Key = Base64.getEncoder().encodeToString(key.getEncoded());
|
||||||
|
System.out.println("Your secure Base64 key:");
|
||||||
|
System.out.println(base64Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,23 +10,23 @@ import java.time.LocalDateTime;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class Response<T> {
|
public class Response<T> {
|
||||||
private int code;
|
private String code;
|
||||||
private String message;
|
private String message;
|
||||||
private T data;
|
private T data;
|
||||||
|
|
||||||
// 请求成功
|
// 请求成功
|
||||||
public static <T> Response<T> success(ResultCode code , T data){
|
public static <T> Response<T> success(ResultCode code , T data){
|
||||||
System.out.println( LocalDateTime.now()+" success : \n"+code);
|
System.out.println( LocalDateTime.now()+" success : "+code);
|
||||||
return new Response<T>(code.getCode(), code.getMessage(), data);
|
return new Response<T>(code.getCode(), code.getMessage(), data);
|
||||||
}
|
}
|
||||||
public static <T> Response<T> success(ResultCode code){
|
public static <T> Response<T> success(ResultCode code){
|
||||||
System.out.println( LocalDateTime.now()+" success : \n"+code);
|
System.out.println( LocalDateTime.now()+" success : "+code);
|
||||||
return new Response<T>(code.getCode(), code.getMessage(),null);
|
return new Response<T>(code.getCode(), code.getMessage(),null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 请求失败
|
// 请求失败
|
||||||
public static <T> Response<T> fail(ResultCode code){
|
public static <T> Response<T> fail(ResultCode code){
|
||||||
System.out.println( LocalDateTime.now()+" fail : \n"+code);
|
System.out.println( LocalDateTime.now()+" fail : "+code);
|
||||||
return new Response<T>(code.getCode(),code.getMessage(), null);
|
return new Response<T>(code.getCode(),code.getMessage(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,29 +8,64 @@ import lombok.Getter;
|
|||||||
@Getter
|
@Getter
|
||||||
public enum ResultCode {
|
public enum ResultCode {
|
||||||
|
|
||||||
SUCCESS(200, "成功"),
|
SUCCESS("200", "成功"),
|
||||||
BAD_REQUEST(400, "请求参数错误"),
|
BAD_REQUEST("400", "请求参数错误"),
|
||||||
UNAUTHORIZED(401, "未认证或登录已过期"),
|
UNAUTHORIZED("401", "未认证或登录已过期"),
|
||||||
FORBIDDEN(403, "无权限访问"),
|
FORBIDDEN("403", "无权限访问"),
|
||||||
NOT_FOUND(404, "资源不存在"),
|
NOT_FOUND("404", "资源不存在"),
|
||||||
SERVER_ERROR(500, "服务器内部错误"),
|
SERVER_ERROR("500", "服务器内部错误"),
|
||||||
|
|
||||||
|
|
||||||
// 自定义业务错误码
|
// 自定义业务错误码
|
||||||
USER_BANNED(1000,"用户被封禁"),
|
|
||||||
USER_NOT_FOUND(1001, "用户不存在"),
|
//账户相关
|
||||||
USER_EXIST(1003,"用户已存在"),
|
ACCOUNT_EXIST("3001","账户已存在"),
|
||||||
USER_PASSWORD_ERROR(1004,"用户密码错误"),
|
ACCOUNT_NOT_INIT("3002","账户未初始化"),
|
||||||
USER_VERIFICATION_ERROR(1005,"验证码不存在或错误"),
|
ACCOUNT_PWD_ERROR("3003","账户密码错误"),
|
||||||
USER_SEND_TOO_FAST(1006,"用户请求过快"),
|
ACCOUNT_INFO_LOST("3004","账户信息丢失"),
|
||||||
USER_SEND_TOO_OFTEN(1007,"请求次数过多,已被限制"),
|
ACCOUNT_ILLEGAL_CHANGE("3005","账户非法篡改"),
|
||||||
ORDER_NOT_FOUND(2000, "订单不存在");
|
ACCOUNT_PERMISSION_DENY("3006","用户权限不足"),
|
||||||
|
|
||||||
|
//用户相关
|
||||||
|
USER_BANNED("4000","用户被封禁"),
|
||||||
|
USER_NOT_FOUND("4001", "用户不存在"),
|
||||||
|
USER_EXIST("4003","用户已存在"),
|
||||||
|
USER_PASSWORD_ERROR("4004","用户密码错误"),
|
||||||
|
USER_VERIFICATION_ERROR("4005","验证码不存在或错误"),
|
||||||
|
USER_SEND_TOO_FAST("4006","用户请求过快"),
|
||||||
|
USER_SEND_TOO_OFTEN("4007","请求次数过多,已被限制"),
|
||||||
|
USER_ILLEGAL_REQUEST("4008", "用户非法请求"),
|
||||||
|
|
||||||
|
//邮箱相关
|
||||||
|
MAIL_ACCOUNT_NOT_PROVIDED("4101","未提供验证码接受账户"),
|
||||||
|
MAIL_REQUEST_TOO_FAST("4102","验证码请求过于频繁"),
|
||||||
|
MAIL_INFO_LOST("4103","验证信息丢失"),
|
||||||
|
MAIL_VERIFY_FAIL_TOO_MANY("4104","验证码错误过多,请重新申请验证码"),
|
||||||
|
MAIL_VERIFY_NOT_EXIST("4105","验证码元素丢失,请重新申请验证码"),
|
||||||
|
MAIL_VERIFY_CODE_ERROR("4106","验证码错误,请重新输入"),
|
||||||
|
|
||||||
|
//审核相关
|
||||||
|
AUDIT_NO_RECORD("4201","无审核记录条目"),
|
||||||
|
|
||||||
|
//邀请相关
|
||||||
|
INVITING_REQUEST_ERROR("4301","邀请请求错误"),
|
||||||
|
INVITING_ILLEGAL_REQUEST("4302","非法邀请"),
|
||||||
|
INVITING_ILLEGAL_RESPONSE("4303","非法邀请"),
|
||||||
|
INVITING_RE_REQUEST("4304","重复请求"),
|
||||||
|
INVITING_AUTH_ERROR("4305","权限错误"),
|
||||||
|
|
||||||
|
//群组相关
|
||||||
|
GROUP_USER_EXISTED("4401","用户已加入群组"),
|
||||||
|
GROUP_USER_NOT_EXISTED("4402","用户不在群组")
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private final int code;
|
|
||||||
|
private final String code;
|
||||||
private final String message;
|
private final String message;
|
||||||
|
|
||||||
ResultCode(int code, String message) {
|
ResultCode(String code, String message) {
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils.websocket;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
|
import org.springframework.context.event.ContextClosedEvent;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.socket.CloseStatus;
|
||||||
|
import org.springframework.web.socket.TextMessage;
|
||||||
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
|
import org.springframework.web.socket.handler.TextWebSocketHandler;
|
||||||
|
import xin.merlin.myplayerbackend.config.RabbitMQConfig;
|
||||||
|
import xin.merlin.myplayerbackend.service.OnlineStatusService;
|
||||||
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CustomWebSocketHandler extends TextWebSocketHandler {
|
||||||
|
|
||||||
|
private final WebSocketSessionManager webSocketSessionManager;
|
||||||
|
|
||||||
|
private final RabbitTemplate rabbitTemplate;
|
||||||
|
|
||||||
|
private final OnlineStatusService onlineStatusService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
|
||||||
|
/*
|
||||||
|
TODO:这里需要处理在数据库中未发送的离线消息
|
||||||
|
初步想法:
|
||||||
|
开多线程,分页获取所有相关信息,然后送入rabbitmq,送入之后删除对应的message
|
||||||
|
|
||||||
|
但是需要处理的是,用户一上线即下线的问题,如何终止这个多线程任务以及送入rabbitmq的message可能又会回到数据库中并出现重复数据
|
||||||
|
*/
|
||||||
|
Integer userId = (Integer) session.getAttributes().get("id");
|
||||||
|
|
||||||
|
onlineStatusService.online(userId);
|
||||||
|
|
||||||
|
webSocketSessionManager.addSession(userId, session);
|
||||||
|
log.info("用户 {} 已连接", userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
|
||||||
|
String payload = message.getPayload();
|
||||||
|
rabbitTemplate.convertAndSend(RabbitMQConfig.WS_MESSAGE_QUEUE, payload);
|
||||||
|
|
||||||
|
// JSONObject msg = JSON.parseObject(payload);
|
||||||
|
// String type = msg.getString("type");
|
||||||
|
// switch (type) {
|
||||||
|
// case "chat":
|
||||||
|
// Integer toUser = msg.getInteger("toUser");
|
||||||
|
// webSocketSessionManager.sendToUser(toUser, payload);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case "broadcast":
|
||||||
|
// webSocketSessionManager.broadcast(payload);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// case "signal":
|
||||||
|
// webSocketSessionManager.sendToUser(msg.getInteger("toUser"), payload);
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
|
||||||
|
Integer userId = (Integer) session.getAttributes().get("id");
|
||||||
|
|
||||||
|
onlineStatusService.offline(userId);
|
||||||
|
|
||||||
|
webSocketSessionManager.removeSession(userId);
|
||||||
|
log.info("用户 {} 已断开", userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventListener
|
||||||
|
public void onShutdown(ContextClosedEvent event) {
|
||||||
|
log.info("Shutting down... closing websocket sessions");
|
||||||
|
webSocketSessionManager.closeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils.websocket;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import xin.merlin.myplayerbackend.config.RabbitMQConfig;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.command.CommandDispatcher;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class WebSocketMessageConsumer {
|
||||||
|
|
||||||
|
private final WebSocketSessionManager sessionManager;
|
||||||
|
|
||||||
|
private final CommandDispatcher commandDispatcher;
|
||||||
|
|
||||||
|
@RabbitListener(queues = RabbitMQConfig.WS_MESSAGE_QUEUE)
|
||||||
|
public void onMessage(String json) {
|
||||||
|
try {
|
||||||
|
JSONObject msg = JSON.parseObject(json);
|
||||||
|
commandDispatcher.dispatch(msg);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.info(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RabbitListener(queues = RabbitMQConfig.WS_VIDEO_QUEUE)
|
||||||
|
public void onVideoMessage(String json) {
|
||||||
|
try {
|
||||||
|
JSONObject msg = JSON.parseObject(json);
|
||||||
|
commandDispatcher.dispatch(msg);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.info(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils.websocket;
|
||||||
|
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.socket.CloseStatus;
|
||||||
|
import org.springframework.web.socket.TextMessage;
|
||||||
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class WebSocketSessionManager {
|
||||||
|
|
||||||
|
private static final Map<Integer, WebSocketSession> websocketSessions = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public void addSession(Integer id, WebSocketSession session) {websocketSessions.put(id, session);}
|
||||||
|
|
||||||
|
public WebSocketSession getSession(Integer id) {return websocketSessions.get(id);}
|
||||||
|
|
||||||
|
public void removeSession(Integer id) {websocketSessions.remove(id);}
|
||||||
|
|
||||||
|
public Map<Integer, WebSocketSession> getSessions() {return websocketSessions;}
|
||||||
|
|
||||||
|
public void sendToUser(Integer userId, String message) throws IOException {
|
||||||
|
WebSocketSession session = websocketSessions.get(userId);
|
||||||
|
if (session != null && session.isOpen()) {
|
||||||
|
session.sendMessage(new TextMessage(message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void broadcast(String message) throws IOException {
|
||||||
|
for (WebSocketSession session : websocketSessions.values()) {
|
||||||
|
if (session.isOpen()) {
|
||||||
|
session.sendMessage(new TextMessage(message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeAll() {
|
||||||
|
websocketSessions.forEach((uid, session) -> {
|
||||||
|
try {
|
||||||
|
session.close(CloseStatus.GOING_AWAY);
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils.websocket.command;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface BaseCommandHandler {
|
||||||
|
void handle(JSONObject msg) throws IOException;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils.websocket.command;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.command.impl.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CommandDispatcher {
|
||||||
|
private final Ping pingCommand;
|
||||||
|
private final Message messageCommand;
|
||||||
|
private final Typing typingCommand;
|
||||||
|
private final Heartbeat heartbeatCommand;
|
||||||
|
private final SystemNotify systemNotifyCommand;
|
||||||
|
private final PersonalNotify personalNotifyCommand;
|
||||||
|
private final GroupMessage groupMessageCommand;
|
||||||
|
|
||||||
|
public void dispatch(JSONObject msg) throws IOException {
|
||||||
|
String cmd = msg.getString("cmd");
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case "PING" -> pingCommand.handle(msg);
|
||||||
|
case "MESSAGE" -> messageCommand.handle(msg);
|
||||||
|
case "TYPING" -> typingCommand.handle(msg);
|
||||||
|
case "HEARTBEAT" -> heartbeatCommand.handle(msg);
|
||||||
|
case "SYSTEM_NOTIFY" -> systemNotifyCommand.handle(msg);
|
||||||
|
case "PERSONAL_NOTIFY" -> personalNotifyCommand.handle(msg);
|
||||||
|
case "GROUP_MESSAGE" -> groupMessageCommand.handle(msg);
|
||||||
|
|
||||||
|
default -> {
|
||||||
|
System.err.println("Unknown command: " + cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils.websocket.command.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import xin.merlin.myplayerbackend.entity.Groups;
|
||||||
|
import xin.merlin.myplayerbackend.mapper.GroupsMapper;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.WebSocketSessionManager;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.command.BaseCommandHandler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class GroupMessage implements BaseCommandHandler {
|
||||||
|
|
||||||
|
private final GroupsMapper groupsMapper;
|
||||||
|
|
||||||
|
private final WebSocketSessionManager sessionManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(JSONObject msg) throws IOException {
|
||||||
|
|
||||||
|
Integer userId = msg.getInteger("from");
|
||||||
|
Integer groupId = msg.getInteger("group");
|
||||||
|
|
||||||
|
List<Object> objs = groupsMapper.selectObjs(
|
||||||
|
Wrappers.<Groups>lambdaQuery()
|
||||||
|
.select(Groups::getId)
|
||||||
|
.eq(Groups::getG_id, groupId)
|
||||||
|
.ne(Groups::getId, userId)
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Integer> ids = objs.stream()
|
||||||
|
.map(o -> (Integer) o)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
for (Integer id : ids) {
|
||||||
|
JSONObject copy = new JSONObject(msg);
|
||||||
|
copy.put("to", id);
|
||||||
|
sessionManager.sendToUser(id, copy.toJSONString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils.websocket.command.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.command.BaseCommandHandler;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class Heartbeat implements BaseCommandHandler {
|
||||||
|
|
||||||
|
private final RedisTemplate<String, String> redis;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(JSONObject msg) {
|
||||||
|
String userId = msg.getString("from");
|
||||||
|
redis.opsForValue().set("online:" + userId, "1", Duration.ofMinutes(5));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils.websocket.command.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.WebSocketSessionManager;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.command.BaseCommandHandler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class Message implements BaseCommandHandler {
|
||||||
|
|
||||||
|
private final WebSocketSessionManager sessionManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(JSONObject msg) throws IOException {
|
||||||
|
/*
|
||||||
|
TODO: 这里需要处理如果目标用户不在线,如何去完成消息的存储
|
||||||
|
*/
|
||||||
|
String to = msg.getString("to");
|
||||||
|
sessionManager.sendToUser(Integer.valueOf(to), msg.toJSONString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils.websocket.command.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.WebSocketSessionManager;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.command.BaseCommandHandler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PersonalNotify implements BaseCommandHandler {
|
||||||
|
|
||||||
|
private final WebSocketSessionManager sessionManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(JSONObject msg) throws IOException {
|
||||||
|
String to = msg.getString("to");
|
||||||
|
sessionManager.sendToUser(Integer.valueOf(to), msg.toJSONString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils.websocket.command.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.WebSocketSessionManager;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.command.BaseCommandHandler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class Ping implements BaseCommandHandler {
|
||||||
|
|
||||||
|
private final WebSocketSessionManager sessionManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(JSONObject msg) throws IOException {
|
||||||
|
String from = msg.getString("from");
|
||||||
|
msg.put("cmd", "PONG");
|
||||||
|
sessionManager.sendToUser(Integer.valueOf(from), msg.toJSONString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils.websocket.command.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.WebSocketSessionManager;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.command.BaseCommandHandler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SystemNotify implements BaseCommandHandler {
|
||||||
|
|
||||||
|
private final WebSocketSessionManager sessionManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(JSONObject msg) throws IOException {
|
||||||
|
sessionManager.broadcast(msg.toJSONString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package xin.merlin.myplayerbackend.utils.websocket.command.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.WebSocketSessionManager;
|
||||||
|
import xin.merlin.myplayerbackend.utils.websocket.command.BaseCommandHandler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class Typing implements BaseCommandHandler {
|
||||||
|
|
||||||
|
private final WebSocketSessionManager sessionManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(JSONObject msg) throws IOException {
|
||||||
|
String to = msg.getString("to");
|
||||||
|
sessionManager.sendToUser(Integer.valueOf(to), msg.toJSONString());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user