diff --git a/docker-compose-v4.yml b/docker-compose-v4.yml index 8bf8af2..7449ab2 100644 --- a/docker-compose-v4.yml +++ b/docker-compose-v4.yml @@ -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: diff --git a/docker-compose-v6.yml b/docker-compose-v6.yml index 6b8b2a7..91d707c 100644 --- a/docker-compose-v6.yml +++ b/docker-compose-v6.yml @@ -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: diff --git a/panel_install.sh b/panel_install.sh index da082bb..0590ea0 100755 --- a/panel_install.sh +++ b/panel_install.sh @@ -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' "$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")" diff --git a/springboot-backend/src/main/java/com/admin/service/impl/GroupServiceImpl.java b/springboot-backend/src/main/java/com/admin/service/impl/GroupServiceImpl.java index c1d088b..fd70de8 100644 --- a/springboot-backend/src/main/java/com/admin/service/impl/GroupServiceImpl.java +++ b/springboot-backend/src/main/java/com/admin/service/impl/GroupServiceImpl.java @@ -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() + .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() .eq("user_group_id", userGroupId) @@ -556,7 +583,7 @@ public class GroupServiceImpl implements GroupService { private Set buildGroupManagedUserTunnelIds(Set userTunnelIds) { if (userTunnelIds.isEmpty()) { - return Collections.emptySet(); + return new HashSet<>(); } return groupPermissionGrantMapper.selectList(new QueryWrapper()