mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-09-29 16:06:36 +08:00
修复bug
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
package com.admin.common.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PageDto {
|
||||
|
||||
/**
|
||||
* 当前页码,默认为1
|
||||
*/
|
||||
private Long current = 1L;
|
||||
|
||||
/**
|
||||
* 每页显示条数,默认为10
|
||||
*/
|
||||
private Long size = 10L;
|
||||
|
||||
/**
|
||||
* 搜索关键字(可选)
|
||||
*/
|
||||
private String keyword;
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public class TunnelDto {
|
||||
@DecimalMax(value = "100.0", message = "流量倍率不能大于100.0")
|
||||
private BigDecimal trafficRatio = new BigDecimal("1.0");
|
||||
|
||||
// 协议类型(隧道转发时使用:tls、tcp、mtls),默认为tls
|
||||
// 协议类型,默认为tls
|
||||
private String protocol;
|
||||
|
||||
// TCP监听地址,默认为0.0.0.0
|
||||
|
||||
@@ -26,9 +26,14 @@ public class TunnelUpdateDto {
|
||||
@DecimalMax(value = "100.0", message = "流量倍率不能大于100.0")
|
||||
private BigDecimal trafficRatio;
|
||||
|
||||
@NotBlank
|
||||
private String protocol;
|
||||
|
||||
// TCP监听地址
|
||||
@NotBlank
|
||||
private String tcpListenAddr;
|
||||
|
||||
// UDP监听地址
|
||||
@NotBlank
|
||||
private String udpListenAddr;
|
||||
}
|
||||
@@ -181,6 +181,15 @@ public class GostUtil {
|
||||
public static GostDto AddChains(Long node_id, String name, String remoteAddr, String protocol) {
|
||||
JSONObject dialer = new JSONObject();
|
||||
dialer.put("type", protocol);
|
||||
if (Objects.equals(protocol, "quic")){
|
||||
JSONObject metadata = new JSONObject();
|
||||
metadata.put("keepAlive", true);
|
||||
metadata.put("ttl", "10s");
|
||||
dialer.put("metadata", metadata);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
JSONObject connector = new JSONObject();
|
||||
connector.put("type", "relay");
|
||||
@@ -212,6 +221,14 @@ public class GostUtil {
|
||||
JSONObject dialer = new JSONObject();
|
||||
dialer.put("type", protocol);
|
||||
|
||||
if (Objects.equals(protocol, "quic")){
|
||||
JSONObject metadata = new JSONObject();
|
||||
metadata.put("keepAlive", true);
|
||||
metadata.put("ttl", "10s");
|
||||
dialer.put("metadata", metadata);
|
||||
}
|
||||
|
||||
|
||||
JSONObject connector = new JSONObject();
|
||||
connector.put("type", "relay");
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.admin.common.aop.LogAnnotation;
|
||||
import com.admin.common.annotation.RequireRole;
|
||||
import com.admin.common.dto.ForwardDto;
|
||||
import com.admin.common.dto.ForwardUpdateDto;
|
||||
import com.admin.common.dto.PageDto;
|
||||
import com.admin.common.lang.R;
|
||||
import com.admin.service.ForwardService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.admin.common.annotation.RequireRole;
|
||||
import com.admin.common.aop.LogAnnotation;
|
||||
import com.admin.common.dto.NodeDto;
|
||||
import com.admin.common.dto.NodeUpdateDto;
|
||||
import com.admin.common.dto.PageDto;
|
||||
import com.admin.common.lang.R;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.admin.controller;
|
||||
|
||||
import com.admin.common.aop.LogAnnotation;
|
||||
import com.admin.common.annotation.RequireRole;
|
||||
import com.admin.common.dto.PageDto;
|
||||
import com.admin.common.dto.TunnelDto;
|
||||
import com.admin.common.dto.TunnelUpdateDto;
|
||||
|
||||
@@ -47,7 +46,7 @@ public class TunnelController extends BaseController {
|
||||
@LogAnnotation
|
||||
@RequireRole
|
||||
@PostMapping("/list")
|
||||
public R readAll(@RequestBody(required = false) PageDto pageDto) {
|
||||
public R readAll() {
|
||||
return tunnelService.getAllTunnels();
|
||||
}
|
||||
|
||||
|
||||
@@ -40,12 +40,8 @@ public class UserController extends BaseController {
|
||||
@LogAnnotation
|
||||
@RequireRole
|
||||
@PostMapping("/list")
|
||||
public R readAll(@RequestBody(required = false) PageDto pageDto) {
|
||||
// 如果没有传分页参数,使用默认值
|
||||
if (pageDto == null) {
|
||||
pageDto = new PageDto();
|
||||
}
|
||||
return userService.getAllUsers(pageDto);
|
||||
public R readAll() {
|
||||
return userService.getAllUsers();
|
||||
}
|
||||
|
||||
@LogAnnotation
|
||||
|
||||
@@ -55,7 +55,7 @@ public class Tunnel extends BaseEntity {
|
||||
private int flow;
|
||||
|
||||
/**
|
||||
* 协议类型(隧道转发时使用:tls、tcp、mtls)
|
||||
* 协议类型
|
||||
*/
|
||||
private String protocol;
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.admin.service;
|
||||
|
||||
import com.admin.common.dto.NodeDto;
|
||||
import com.admin.common.dto.NodeUpdateDto;
|
||||
import com.admin.common.dto.PageDto;
|
||||
import com.admin.common.lang.R;
|
||||
import com.admin.entity.Node;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.admin.service;
|
||||
|
||||
import com.admin.common.dto.PageDto;
|
||||
import com.admin.common.dto.TunnelDto;
|
||||
import com.admin.common.dto.TunnelUpdateDto;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public interface UserService extends IService<User> {
|
||||
|
||||
R createUser(UserDto userDto);
|
||||
|
||||
R getAllUsers(PageDto pageDto);
|
||||
R getAllUsers();
|
||||
|
||||
R updateUser(UserUpdateDto userUpdateDto);
|
||||
|
||||
|
||||
@@ -147,13 +147,42 @@ public class ForwardServiceImpl extends ServiceImpl<ForwardMapper, Forward> impl
|
||||
if (tunnel.getStatus() != TUNNEL_STATUS_ACTIVE) {
|
||||
return R.err("隧道已禁用,无法更新转发");
|
||||
}
|
||||
|
||||
boolean tunnelChanged = isTunnelChanged(existForward, forwardUpdateDto);
|
||||
// 4. 检查权限和限制
|
||||
UserPermissionResult permissionResult = null;
|
||||
if (isTunnelChanged(existForward, forwardUpdateDto)) {
|
||||
permissionResult = checkUserPermissions(currentUser, tunnel, forwardUpdateDto.getId());
|
||||
if (permissionResult.isHasError()) {
|
||||
return R.err(permissionResult.getErrorMessage());
|
||||
if (tunnelChanged) {
|
||||
// 管理员操作用户转发时,需要检查原用户是否有新隧道权限
|
||||
if (currentUser.getRoleId() == ADMIN_ROLE_ID) {
|
||||
// 获取原转发用户的信息
|
||||
User originalUser = userService.getById(existForward.getUserId());
|
||||
if (originalUser == null) {
|
||||
return R.err("用户不存在");
|
||||
}
|
||||
|
||||
// 检查原用户是否有新隧道权限
|
||||
UserTunnel userTunnel = getUserTunnel(existForward.getUserId(), tunnel.getId().intValue());
|
||||
if (userTunnel == null) {
|
||||
return R.err("用户没有该隧道权限");
|
||||
}
|
||||
|
||||
// 检查隧道权限到期时间
|
||||
if (userTunnel.getExpTime() != null && userTunnel.getExpTime() <= System.currentTimeMillis()) {
|
||||
return R.err("用户的该隧道权限已到期");
|
||||
}
|
||||
|
||||
// 检查原用户的流量和转发数量限制
|
||||
R quotaCheckResult = checkForwardQuota(existForward.getUserId(), tunnel.getId().intValue(), userTunnel, originalUser, forwardUpdateDto.getId());
|
||||
if (quotaCheckResult.getCode() != 0) {
|
||||
return R.err("用户" + quotaCheckResult.getMsg());
|
||||
}
|
||||
|
||||
permissionResult = UserPermissionResult.success(userTunnel.getSpeedId(), userTunnel);
|
||||
} else {
|
||||
// 普通用户检查自己的权限
|
||||
permissionResult = checkUserPermissions(currentUser, tunnel, forwardUpdateDto.getId());
|
||||
if (permissionResult.isHasError()) {
|
||||
return R.err(permissionResult.getErrorMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,16 +210,12 @@ public class ForwardServiceImpl extends ServiceImpl<ForwardMapper, Forward> impl
|
||||
|
||||
// 8. 调用Gost服务更新转发
|
||||
R gostResult;
|
||||
if (isTunnelChanged(existForward, forwardUpdateDto)) {
|
||||
if (tunnelChanged) {
|
||||
// 隧道变化时:先删除原配置,再创建新配置
|
||||
gostResult = updateGostServicesWithTunnelChange(existForward, updatedForward, tunnel,
|
||||
permissionResult != null ? permissionResult.getLimiter() : null,
|
||||
nodeInfo, userTunnel);
|
||||
gostResult = updateGostServicesWithTunnelChange(existForward, updatedForward, tunnel, permissionResult != null ? permissionResult.getLimiter() : null, nodeInfo, userTunnel);
|
||||
} else {
|
||||
// 隧道未变化时:直接更新配置
|
||||
gostResult = updateGostServices(updatedForward, tunnel,
|
||||
permissionResult != null ? permissionResult.getLimiter() : null,
|
||||
nodeInfo, userTunnel);
|
||||
gostResult = updateGostServices(updatedForward, tunnel, permissionResult != null ? permissionResult.getLimiter() : null, nodeInfo, userTunnel);
|
||||
}
|
||||
|
||||
if (gostResult.getCode() != 0) {
|
||||
|
||||
@@ -4,7 +4,6 @@ import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.admin.common.dto.NodeDto;
|
||||
import com.admin.common.dto.NodeUpdateDto;
|
||||
import com.admin.common.dto.PageDto;
|
||||
import com.admin.common.lang.R;
|
||||
import com.admin.entity.Node;
|
||||
import com.admin.entity.Tunnel;
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package com.admin.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.admin.common.dto.GostDto;
|
||||
import com.admin.common.dto.TunnelDto;
|
||||
import com.admin.common.dto.TunnelListDto;
|
||||
import com.admin.common.dto.TunnelUpdateDto;
|
||||
import com.admin.common.dto.*;
|
||||
|
||||
import com.admin.common.lang.R;
|
||||
import com.admin.common.utils.GostUtil;
|
||||
@@ -30,10 +27,7 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -175,35 +169,50 @@ public class TunnelServiceImpl extends ServiceImpl<TunnelMapper, Tunnel> impleme
|
||||
}
|
||||
|
||||
// 2. 验证隧道名称唯一性(排除自身)
|
||||
R nameValidationResult = validateTunnelNameUniquenessForUpdate(
|
||||
tunnelUpdateDto.getName(), tunnelUpdateDto.getId());
|
||||
R nameValidationResult = validateTunnelNameUniquenessForUpdate(tunnelUpdateDto.getName(), tunnelUpdateDto.getId());
|
||||
if (nameValidationResult.getCode() != 0) {
|
||||
return nameValidationResult;
|
||||
}
|
||||
|
||||
|
||||
int up = 0;
|
||||
if (!Objects.equals(existingTunnel.getTcpListenAddr(), tunnelUpdateDto.getTcpListenAddr()) ||
|
||||
!Objects.equals(existingTunnel.getUdpListenAddr(), tunnelUpdateDto.getUdpListenAddr()) ||
|
||||
!Objects.equals(existingTunnel.getProtocol(), tunnelUpdateDto.getProtocol())) {
|
||||
up++;
|
||||
}
|
||||
|
||||
// 5. 更新允许修改的字段
|
||||
existingTunnel.setName(tunnelUpdateDto.getName());
|
||||
existingTunnel.setFlow(tunnelUpdateDto.getFlow());
|
||||
|
||||
// 更新流量倍率
|
||||
if (tunnelUpdateDto.getTrafficRatio() != null) {
|
||||
existingTunnel.setTrafficRatio(tunnelUpdateDto.getTrafficRatio());
|
||||
}
|
||||
|
||||
// 更新TCP和UDP监听地址
|
||||
if (StrUtil.isNotBlank(tunnelUpdateDto.getTcpListenAddr())) {
|
||||
existingTunnel.setTcpListenAddr(tunnelUpdateDto.getTcpListenAddr());
|
||||
}
|
||||
if (StrUtil.isNotBlank(tunnelUpdateDto.getUdpListenAddr())) {
|
||||
existingTunnel.setUdpListenAddr(tunnelUpdateDto.getUdpListenAddr());
|
||||
existingTunnel.setTcpListenAddr(tunnelUpdateDto.getTcpListenAddr());
|
||||
existingTunnel.setUdpListenAddr(tunnelUpdateDto.getUdpListenAddr());
|
||||
existingTunnel.setTrafficRatio(tunnelUpdateDto.getTrafficRatio());
|
||||
existingTunnel.setProtocol(tunnelUpdateDto.getProtocol());
|
||||
this.updateById(existingTunnel);
|
||||
int err = 0;
|
||||
if (up == 1){
|
||||
List<Forward> tunnel = forwardService.list(new QueryWrapper<Forward>().eq("tunnel_id", tunnelUpdateDto.getId()));
|
||||
if (!tunnel.isEmpty()) {
|
||||
for (Forward forward : tunnel) {
|
||||
ForwardUpdateDto forwardUpdateDto = new ForwardUpdateDto();
|
||||
forwardUpdateDto.setId(forward.getId());
|
||||
forwardUpdateDto.setUserId(forward.getUserId());
|
||||
forwardUpdateDto.setName(forward.getName());
|
||||
forwardUpdateDto.setTunnelId(forward.getTunnelId());
|
||||
forwardUpdateDto.setRemoteAddr(forward.getRemoteAddr());
|
||||
forwardUpdateDto.setStrategy(forward.getStrategy());
|
||||
forwardUpdateDto.setInPort(forward.getInPort());
|
||||
R r = forwardService.updateForward(forwardUpdateDto);
|
||||
if (r.getCode() != 0){
|
||||
err++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 6. 保存更新
|
||||
boolean result = this.updateById(existingTunnel);
|
||||
return result ? R.ok("隧道更新成功") : R.err("隧道更新失败");
|
||||
if (err != 0) {
|
||||
return R.err("隧道信息更新成功,但部分转发同步更新失败");
|
||||
}
|
||||
return R.ok("隧道更新成功");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -425,9 +434,8 @@ public class TunnelServiceImpl extends ServiceImpl<TunnelMapper, Tunnel> impleme
|
||||
|
||||
// 验证协议类型
|
||||
String protocol = tunnelDto.getProtocol();
|
||||
if (StrUtil.isNotBlank(protocol) &&
|
||||
!protocol.equals("tls") && !protocol.equals("tcp") && !protocol.equals("mtls") && !protocol.equals("wss")) {
|
||||
return R.err("协议类型只能为tls、tcp、wss或mtls");
|
||||
if (StrUtil.isBlank(protocol)) {
|
||||
return R.err("协议类型必选");
|
||||
}
|
||||
|
||||
// 验证出口节点是否存在
|
||||
|
||||
@@ -183,21 +183,12 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
||||
/**
|
||||
* 获取所有用户(分页)
|
||||
* 支持关键字搜索,排除管理员用户,清除密码信息
|
||||
*
|
||||
* @param pageDto 分页查询数据传输对象
|
||||
*
|
||||
* @return 分页用户列表响应
|
||||
*/
|
||||
@Override
|
||||
public R getAllUsers(PageDto pageDto) {
|
||||
// 1. 构建分页查询
|
||||
Page<User> page = new Page<>(pageDto.getCurrent(), pageDto.getSize());
|
||||
QueryWrapper<User> queryWrapper = buildUserQueryWrapper(pageDto);
|
||||
|
||||
// 2. 执行查询并处理结果
|
||||
Page<User> userPage = this.page(page, queryWrapper);
|
||||
clearUserPasswords(userPage.getRecords());
|
||||
|
||||
return R.ok(userPage);
|
||||
public R getAllUsers() {
|
||||
return R.ok(this.list(new QueryWrapper<User>().ne("role_id", ADMIN_ROLE_ID)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -446,39 +437,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建用户查询条件
|
||||
*
|
||||
* @param pageDto 分页查询DTO
|
||||
* @return 查询条件包装器
|
||||
*/
|
||||
private QueryWrapper<User> buildUserQueryWrapper(PageDto pageDto) {
|
||||
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
|
||||
|
||||
// 关键字搜索
|
||||
if (StrUtil.isNotBlank(pageDto.getKeyword())) {
|
||||
queryWrapper.and(wrapper -> wrapper
|
||||
.like("user", pageDto.getKeyword())
|
||||
);
|
||||
}
|
||||
|
||||
// 排除管理员用户
|
||||
queryWrapper.ne("id", ADMIN_USER_ID);
|
||||
|
||||
// 按更新时间降序排列
|
||||
queryWrapper.orderByDesc("updated_time");
|
||||
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除用户列表中的密码信息
|
||||
*
|
||||
* @param users 用户列表
|
||||
*/
|
||||
private void clearUserPasswords(List<User> users) {
|
||||
users.forEach(user -> user.setPwd(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户是否存在
|
||||
|
||||
Reference in New Issue
Block a user