mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-09-30 08:16:37 +08:00
merge: sync origin/main and resolve compose backend conflicts
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
backend:
|
||||
image: ghcr.io/sagit-chu/go-backend:2.0.7-beta
|
||||
image: ghcr.io/sagit-chu/go-backend:${FLUX_VERSION:-latest}
|
||||
container_name: go-backend
|
||||
restart: unless-stopped
|
||||
logging:
|
||||
@@ -29,7 +29,7 @@ services:
|
||||
start_period: 30s
|
||||
|
||||
frontend:
|
||||
image: ghcr.io/sagit-chu/vite-frontend:2.0.7-beta
|
||||
image: ghcr.io/sagit-chu/vite-frontend:${FLUX_VERSION:-latest}
|
||||
container_name: vite-frontend
|
||||
restart: unless-stopped
|
||||
logging:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
backend:
|
||||
image: ghcr.io/sagit-chu/go-backend:2.0.7-beta
|
||||
image: ghcr.io/sagit-chu/go-backend:${FLUX_VERSION:-latest}
|
||||
container_name: go-backend
|
||||
restart: unless-stopped
|
||||
logging:
|
||||
@@ -29,7 +29,7 @@ services:
|
||||
start_period: 30s
|
||||
|
||||
frontend:
|
||||
image: ghcr.io/sagit-chu/vite-frontend:2.0.7-beta
|
||||
image: ghcr.io/sagit-chu/vite-frontend:${FLUX_VERSION:-latest}
|
||||
container_name: vite-frontend
|
||||
restart: unless-stopped
|
||||
logging:
|
||||
|
||||
+39
-3
@@ -78,11 +78,16 @@ resolve_version() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# 根据版本号设置 compose 下载地址
|
||||
set_compose_urls_by_version() {
|
||||
local version="$1"
|
||||
DOCKER_COMPOSEV4_URL=$(maybe_proxy_url "https://github.com/${REPO}/releases/download/${version}/docker-compose-v4.yml")
|
||||
DOCKER_COMPOSEV6_URL=$(maybe_proxy_url "https://github.com/${REPO}/releases/download/${version}/docker-compose-v6.yml")
|
||||
}
|
||||
|
||||
# 全局下载地址配置(默认获取最新版本;也可用 VERSION=... 覆盖)
|
||||
RESOLVED_VERSION=$(resolve_version) || exit 1
|
||||
|
||||
DOCKER_COMPOSEV4_URL=$(maybe_proxy_url "https://github.com/${REPO}/releases/download/${RESOLVED_VERSION}/docker-compose-v4.yml")
|
||||
DOCKER_COMPOSEV6_URL=$(maybe_proxy_url "https://github.com/${REPO}/releases/download/${RESOLVED_VERSION}/docker-compose-v6.yml")
|
||||
set_compose_urls_by_version "$RESOLVED_VERSION"
|
||||
|
||||
|
||||
|
||||
@@ -221,6 +226,27 @@ generate_random() {
|
||||
LC_ALL=C tr -dc 'A-Za-z0-9' </dev/urandom | head -c16
|
||||
}
|
||||
|
||||
upsert_env_var() {
|
||||
local file="$1"
|
||||
local key="$2"
|
||||
local value="$3"
|
||||
local tmp_file
|
||||
|
||||
tmp_file=$(mktemp)
|
||||
if [ -f "$file" ]; then
|
||||
awk -v k="$key" -v v="$value" '
|
||||
BEGIN { found=0 }
|
||||
$0 ~ ("^" k "=") { print k "=" v; found=1; next }
|
||||
{ print }
|
||||
END { if (!found) print k "=" v }
|
||||
' "$file" > "$tmp_file"
|
||||
else
|
||||
printf '%s=%s\n' "$key" "$value" > "$tmp_file"
|
||||
fi
|
||||
|
||||
mv "$tmp_file" "$file"
|
||||
}
|
||||
|
||||
# 删除脚本自身
|
||||
delete_self() {
|
||||
echo ""
|
||||
@@ -268,6 +294,7 @@ install_panel() {
|
||||
JWT_SECRET=$JWT_SECRET
|
||||
FRONTEND_PORT=$FRONTEND_PORT
|
||||
BACKEND_PORT=$BACKEND_PORT
|
||||
FLUX_VERSION=$RESOLVED_VERSION
|
||||
EOF
|
||||
|
||||
echo "🚀 启动 docker 服务..."
|
||||
@@ -288,6 +315,15 @@ update_panel() {
|
||||
echo "🔄 开始更新面板..."
|
||||
check_docker
|
||||
|
||||
echo "🔍 获取最新版本号..."
|
||||
LATEST_VERSION=$(resolve_latest_release_tag) || {
|
||||
echo "❌ 无法获取最新版本号,更新终止"
|
||||
return 1
|
||||
}
|
||||
echo "🆕 最新版本:$LATEST_VERSION"
|
||||
set_compose_urls_by_version "$LATEST_VERSION"
|
||||
upsert_env_var ".env" "FLUX_VERSION" "$LATEST_VERSION"
|
||||
|
||||
echo "🔽 下载最新配置文件..."
|
||||
DOCKER_COMPOSE_URL=$(get_docker_compose_url)
|
||||
echo "📡 选择配置文件:$(basename "$DOCKER_COMPOSE_URL")"
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.admin.service.UserService;
|
||||
import com.admin.service.UserTunnelService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
@@ -158,6 +159,7 @@ public class GroupServiceImpl implements GroupService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R assignTunnelsToGroup(TunnelGroupAssignTunnelsDto dto) {
|
||||
TunnelGroup group = tunnelGroupMapper.selectById(dto.getGroupId());
|
||||
if (group == null) {
|
||||
@@ -274,6 +276,7 @@ public class GroupServiceImpl implements GroupService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R assignUsersToGroup(UserGroupAssignUsersDto dto) {
|
||||
UserGroup group = userGroupMapper.selectById(dto.getGroupId());
|
||||
if (group == null) {
|
||||
@@ -336,6 +339,7 @@ public class GroupServiceImpl implements GroupService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R assignGroupPermission(GroupPermissionAssignDto dto) {
|
||||
UserGroup userGroup = userGroupMapper.selectById(dto.getUserGroupId());
|
||||
if (userGroup == null) {
|
||||
@@ -448,11 +452,12 @@ public class GroupServiceImpl implements GroupService {
|
||||
UserTunnel userTunnel = pairUserTunnelMap.get(pairKey);
|
||||
if (userTunnel == null) {
|
||||
userTunnel = createGroupManagedUserTunnel(userId, tunnelId, user);
|
||||
Long userTunnelId = resolveUserTunnelId(userTunnel, userId, tunnelId);
|
||||
pairUserTunnelMap.put(pairKey, userTunnel);
|
||||
createGrant(userGroupId, tunnelGroupId, userTunnel.getId().longValue(), true, now);
|
||||
currentGrantUserTunnelIds.add(userTunnel.getId().longValue());
|
||||
totalGrantCountMap.put(userTunnel.getId().longValue(), 1L);
|
||||
groupManagedUserTunnelIds.add(userTunnel.getId().longValue());
|
||||
createGrant(userGroupId, tunnelGroupId, userTunnelId, true, now);
|
||||
currentGrantUserTunnelIds.add(userTunnelId);
|
||||
totalGrantCountMap.put(userTunnelId, 1L);
|
||||
groupManagedUserTunnelIds.add(userTunnelId);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -497,10 +502,32 @@ public class GroupServiceImpl implements GroupService {
|
||||
userTunnel.setNum(user.getNum());
|
||||
userTunnel.setFlowResetTime(user.getFlowResetTime());
|
||||
userTunnel.setExpTime(user.getExpTime());
|
||||
userTunnelService.save(userTunnel);
|
||||
boolean saved = userTunnelService.save(userTunnel);
|
||||
if (!saved) {
|
||||
throw new IllegalStateException("创建用户隧道权限失败: userId=" + userId + ", tunnelId=" + tunnelId);
|
||||
}
|
||||
return userTunnel;
|
||||
}
|
||||
|
||||
private Long resolveUserTunnelId(UserTunnel userTunnel, Long userId, Long tunnelId) {
|
||||
if (userTunnel.getId() != null) {
|
||||
return userTunnel.getId().longValue();
|
||||
}
|
||||
|
||||
UserTunnel persisted = userTunnelService.getOne(
|
||||
new QueryWrapper<UserTunnel>()
|
||||
.eq("user_id", userId.intValue())
|
||||
.eq("tunnel_id", tunnelId.intValue())
|
||||
.orderByDesc("id")
|
||||
.last("LIMIT 1")
|
||||
);
|
||||
if (persisted == null || persisted.getId() == null) {
|
||||
throw new IllegalStateException("获取用户隧道权限ID失败: userId=" + userId + ", tunnelId=" + tunnelId);
|
||||
}
|
||||
userTunnel.setId(persisted.getId());
|
||||
return persisted.getId().longValue();
|
||||
}
|
||||
|
||||
private void createGrant(Long userGroupId, Long tunnelGroupId, Long userTunnelId, boolean createdByGroup, long createdTime) {
|
||||
int exists = groupPermissionGrantMapper.selectCount(new QueryWrapper<GroupPermissionGrant>()
|
||||
.eq("user_group_id", userGroupId)
|
||||
@@ -556,7 +583,7 @@ public class GroupServiceImpl implements GroupService {
|
||||
|
||||
private Set<Long> buildGroupManagedUserTunnelIds(Set<Long> userTunnelIds) {
|
||||
if (userTunnelIds.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
return groupPermissionGrantMapper.selectList(new QueryWrapper<GroupPermissionGrant>()
|
||||
|
||||
Reference in New Issue
Block a user