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 Optional ENV vars
|
||||
@REM MVNW_REPOURL - repo url base for downloading maven distribution
|
||||
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
|
||||
@REM MVNW_USERNAME/MVNW_PASSWORD - userinfo and password for downloading maven
|
||||
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
65
pom.xml
65
pom.xml
@@ -13,19 +13,6 @@
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>myplayer-backend</name>
|
||||
<description>myplayer-backend</description>
|
||||
<url/>
|
||||
<licenses>
|
||||
<license/>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer/>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection/>
|
||||
<developerConnection/>
|
||||
<tag/>
|
||||
<url/>
|
||||
</scm>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
@@ -51,9 +38,14 @@
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.kafka</groupId>
|
||||
<artifactId>spring-kafka</artifactId>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -64,18 +56,13 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.kafka</groupId>
|
||||
<artifactId>spring-kafka-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
@@ -105,11 +92,27 @@
|
||||
<artifactId>mybatis-plus-jsqlparser</artifactId>
|
||||
<version>3.5.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-spring</artifactId>
|
||||
<version>3.0.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt</artifactId>
|
||||
<version>0.12.6</version>
|
||||
</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>
|
||||
|
||||
<build>
|
||||
@@ -122,29 +125,9 @@
|
||||
</resource>
|
||||
</resources>
|
||||
<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>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
@@ -2,8 +2,11 @@ package xin.merlin.myplayerbackend;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import xin.merlin.myplayerbackend.config.security.JwtProperties;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableConfigurationProperties(JwtProperties.class)
|
||||
public class MyplayerBackendApplication {
|
||||
|
||||
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 {
|
||||
if (!jwtUtil.isTokenExpired(token)) {
|
||||
System.out.println(token);
|
||||
String username = jwtUtil.getUAccount(token);
|
||||
// System.out.println("token expired: " + token);
|
||||
String account = jwtUtil.getAccount(token);
|
||||
|
||||
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
if (account != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
UsernamePasswordAuthenticationToken authenticationToken =
|
||||
new UsernamePasswordAuthenticationToken(username, null, Collections.emptyList());
|
||||
new UsernamePasswordAuthenticationToken(account, null, Collections.emptyList());
|
||||
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package xin.merlin.myplayerbackend.config.security;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
@@ -22,21 +21,24 @@ public class SecurityConfig {
|
||||
private final JWTAuthenticationFilter jwtAuthenticationFilter;
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
public SecurityFilterChain filterChain(HttpSecurity http,CustomAuthenticationEntryPoint entryPoint) throws Exception {
|
||||
http
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.authorizeHttpRequests(authz -> authz
|
||||
.requestMatchers(
|
||||
"/login",
|
||||
"/register",
|
||||
"/error",
|
||||
"/shadow/**",
|
||||
"/health",
|
||||
"/code/**",
|
||||
"/blog/**"
|
||||
"/v3/api-docs/**",
|
||||
"/account/mail/verify/**",
|
||||
"/ws/**"
|
||||
).permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
.exceptionHandling(ex -> ex.authenticationEntryPoint(entryPoint));
|
||||
|
||||
return http.build();
|
||||
}
|
||||
@@ -48,7 +50,7 @@ public class SecurityConfig {
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOriginPatterns("*") // 开发阶段允许所有来源
|
||||
.allowedOriginPatterns("*")
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||
.allowedHeaders("*")
|
||||
.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.security.Keys;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import xin.merlin.myplayerbackend.config.security.JwtProperties;
|
||||
import xin.merlin.myplayerbackend.entity.Account;
|
||||
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
@@ -13,6 +16,8 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
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
|
||||
*/
|
||||
public String generateToken(String uAccount, Integer uId) {
|
||||
public String generateToken(Account account) {
|
||||
Date now = new Date();
|
||||
Date expireDate = new Date(now.getTime() + jwtProperties.getExpire() * 1000L);
|
||||
|
||||
return Jwts.builder()
|
||||
.subject(uAccount)
|
||||
.claim("id", uId)
|
||||
.claim("account", uAccount)
|
||||
.subject(account.getAccount())
|
||||
.claim("id", account.getId())
|
||||
.claim("account", account.getAccount())
|
||||
.claim("character", account.getCharacter())
|
||||
.id(UUID.randomUUID().toString())
|
||||
.issuedAt(now)
|
||||
.expiration(expireDate)
|
||||
@@ -57,10 +73,10 @@ public class JwtUtil {
|
||||
/**
|
||||
* 解析 Token 获取 Claims
|
||||
*/
|
||||
public Claims getClaims(String token) {
|
||||
private Claims getClaims(String token) {
|
||||
try {
|
||||
Jws<Claims> jws = jwtParser.parseSignedClaims(token);
|
||||
System.out.println(jws.getPayload());
|
||||
// System.out.println(jws.getPayload());
|
||||
return jws.getPayload();
|
||||
} catch (ExpiredJwtException 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);
|
||||
return claims.getSubject();
|
||||
}
|
||||
@@ -90,9 +106,19 @@ public class JwtUtil {
|
||||
/**
|
||||
* 获取用户ID
|
||||
*/
|
||||
public String getUId(String token) {
|
||||
public Integer getId(String 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
|
||||
@AllArgsConstructor
|
||||
public class Response<T> {
|
||||
private int code;
|
||||
private String code;
|
||||
private String message;
|
||||
private 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
// 请求失败
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,29 +8,64 @@ import lombok.Getter;
|
||||
@Getter
|
||||
public enum ResultCode {
|
||||
|
||||
SUCCESS(200, "成功"),
|
||||
BAD_REQUEST(400, "请求参数错误"),
|
||||
UNAUTHORIZED(401, "未认证或登录已过期"),
|
||||
FORBIDDEN(403, "无权限访问"),
|
||||
NOT_FOUND(404, "资源不存在"),
|
||||
SERVER_ERROR(500, "服务器内部错误"),
|
||||
SUCCESS("200", "成功"),
|
||||
BAD_REQUEST("400", "请求参数错误"),
|
||||
UNAUTHORIZED("401", "未认证或登录已过期"),
|
||||
FORBIDDEN("403", "无权限访问"),
|
||||
NOT_FOUND("404", "资源不存在"),
|
||||
SERVER_ERROR("500", "服务器内部错误"),
|
||||
|
||||
|
||||
// 自定义业务错误码
|
||||
USER_BANNED(1000,"用户被封禁"),
|
||||
USER_NOT_FOUND(1001, "用户不存在"),
|
||||
USER_EXIST(1003,"用户已存在"),
|
||||
USER_PASSWORD_ERROR(1004,"用户密码错误"),
|
||||
USER_VERIFICATION_ERROR(1005,"验证码不存在或错误"),
|
||||
USER_SEND_TOO_FAST(1006,"用户请求过快"),
|
||||
USER_SEND_TOO_OFTEN(1007,"请求次数过多,已被限制"),
|
||||
ORDER_NOT_FOUND(2000, "订单不存在");
|
||||
|
||||
//账户相关
|
||||
ACCOUNT_EXIST("3001","账户已存在"),
|
||||
ACCOUNT_NOT_INIT("3002","账户未初始化"),
|
||||
ACCOUNT_PWD_ERROR("3003","账户密码错误"),
|
||||
ACCOUNT_INFO_LOST("3004","账户信息丢失"),
|
||||
ACCOUNT_ILLEGAL_CHANGE("3005","账户非法篡改"),
|
||||
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;
|
||||
|
||||
ResultCode(int code, String message) {
|
||||
ResultCode(String code, String message) {
|
||||
this.code = code;
|
||||
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