删除资源组

This commit is contained in:
zhx 2026-07-22 19:36:16 +08:00
parent 6aab34a60a
commit f0e780ae8f
8 changed files with 90 additions and 7 deletions

39
.codex_tat_action.py Normal file
View File

@ -0,0 +1,39 @@
#!/usr/bin/env python3
import csv
import os
import sys
sys.path.insert(0, "/Users/hy/Documents/hy/deploy-platform")
from deploy.tencent_tat.hyapp_tat_deploy import build_tat_client, run_tat_shell
with open(
"/Users/hy/Documents/环境/haiyi腾讯云临时服务器秘钥.csv",
encoding="utf-8-sig",
newline="",
) as handle:
credential = next(csv.DictReader(handle))
os.environ["TENCENTCLOUD_SECRET_ID"] = credential["SecretId"].strip()
os.environ["TENCENTCLOUD_SECRET_KEY"] = credential["SecretKey"].strip()
os.environ["TENCENTCLOUD_REGION"] = "me-saudi-arabia"
client = build_tat_client({"region": "me-saudi-arabia"})
script = r'''set -euo pipefail
hostname
docker system df
du -sh /opt/deploy/sources/hyapp-server /var/lib/docker 2>/dev/null || true
docker images --format '{{.Repository}}:{{.Tag}} {{.ID}} {{.Size}} {{.CreatedSince}}' | grep 'hyapp/admin-server' | head -n 10 || true
'''
result = run_tat_shell(
client,
instance_id="ins-ntmpcd3a",
script=script,
command_name="codex-admin-server-disk-precheck",
timeout_seconds=60,
poll_seconds=2,
)
print(result.get("status"))
print(result.get("output", ""))

View File

@ -484,6 +484,28 @@ func (h *Handler) UpdateResourceGroup(c *gin.Context) {
response.OK(c, group)
}
func (h *Handler) DeleteResourceGroup(c *gin.Context) {
groupID, ok := parseID(c, "group_id")
if !ok {
return
}
// 删除资源组只关闭后续查询与发放入口,历史发放记录和已固化快照仍需保留用于审计与补偿。
resp, err := h.wallet.SetResourceGroupStatus(c.Request.Context(), &walletv1.SetResourceGroupStatusRequest{
RequestId: middleware.CurrentRequestID(c),
AppCode: appctx.FromContext(c.Request.Context()),
GroupId: groupID,
Status: "deleted",
OperatorUserId: actorID(c),
})
if err != nil {
response.BadRequest(c, err.Error())
return
}
group := resourceGroupFromProto(resp.GetGroup())
h.auditLog(c, "delete-resource-group", "resource_groups", fmt.Sprintf("%d", group.GroupID), "success", group.GroupCode)
response.OK(c, group)
}
func (h *Handler) EnableResourceGroup(c *gin.Context) {
h.setResourceGroupStatus(c, "active")
}

View File

@ -31,6 +31,7 @@ func RegisterRoutes(protected *gin.RouterGroup, h *Handler) {
protected.PUT("/admin/resource-groups/identity-auto-grant-config", middleware.RequirePermission("resource-group:update"), h.UpdateResourceIdentityAutoGrantConfig)
protected.GET("/admin/resource-groups/:group_id", middleware.RequirePermission("resource-group:view"), h.GetResourceGroup)
protected.PUT("/admin/resource-groups/:group_id", middleware.RequirePermission("resource-group:update"), h.UpdateResourceGroup)
protected.DELETE("/admin/resource-groups/:group_id", middleware.RequirePermission("resource-group:delete"), h.DeleteResourceGroup)
protected.PUT("/admin/resource-groups/:group_id/items", middleware.RequirePermission("resource-group:update"), h.UpdateResourceGroup)
protected.POST("/admin/resource-groups/:group_id/enable", middleware.RequirePermission("resource-group:update"), h.EnableResourceGroup)
protected.POST("/admin/resource-groups/:group_id/disable", middleware.RequirePermission("resource-group:update"), h.DisableResourceGroup)

View File

@ -96,7 +96,7 @@ var (
}
resourceManage = []string{
"resource:create", "resource:update", "resource:delete", "upload:create",
"resource-shop:update", "resource-group:create", "resource-group:update",
"resource-shop:update", "resource-group:create", "resource-group:update", "resource-group:delete",
"gift:create", "gift:update", "gift:status", "gift:delete",
"resource-grant:create", "resource-grant:revoke", "emoji-pack:create",
}

View File

@ -69,6 +69,7 @@ var defaultPermissions = []model.Permission{
{Name: "资源组查看", Code: "resource-group:view", Kind: "menu"},
{Name: "资源组创建", Code: "resource-group:create", Kind: "button"},
{Name: "资源组更新", Code: "resource-group:update", Kind: "button"},
{Name: "资源组删除", Code: "resource-group:delete", Kind: "button"},
{Name: "资源赠送查看", Code: "resource-grant:view", Kind: "menu"},
{Name: "资源赠送创建", Code: "resource-grant:create", Kind: "button"},
{Name: "资源赠送撤销", Code: "resource-grant:revoke", Kind: "button"},

View File

@ -112,7 +112,7 @@ WHERE role.code = 'ops-admin'
'room-robot:view', 'room-robot:create', 'room-robot:update',
'app-config:view', 'app-config:update', 'full-server-notice:send',
'resource:view', 'resource:create', 'resource:update', 'resource:delete', 'upload:create',
'resource-shop:view', 'resource-shop:update', 'resource-group:view', 'resource-group:create', 'resource-group:update',
'resource-shop:view', 'resource-shop:update', 'resource-group:view', 'resource-group:create', 'resource-group:update', 'resource-group:delete',
'gift:view', 'gift:create', 'gift:update', 'gift:status', 'gift:delete',
'resource-grant:view', 'resource-grant:create', 'resource-grant:revoke', 'emoji-pack:view', 'emoji-pack:create',
'coin-ledger:view', 'coin-seller-ledger:view', 'coin-adjustment:view', 'coin-adjustment:create', 'report:view',
@ -159,7 +159,7 @@ WHERE role.code = 'operations-specialist'
'room-robot:view', 'room-robot:create', 'room-robot:update',
'app-config:view', 'app-config:update', 'full-server-notice:send',
'resource:view', 'resource:create', 'resource:update', 'resource:delete', 'upload:create',
'resource-shop:view', 'resource-shop:update', 'resource-group:view', 'resource-group:create', 'resource-group:update',
'resource-shop:view', 'resource-shop:update', 'resource-group:view', 'resource-group:create', 'resource-group:update', 'resource-group:delete',
'gift:view', 'gift:create', 'gift:update', 'gift:status', 'gift:delete',
'resource-grant:view', 'resource-grant:create', 'resource-grant:revoke', 'emoji-pack:view', 'emoji-pack:create',
'coin-ledger:view', 'coin-seller-ledger:view', 'report:view',
@ -191,7 +191,7 @@ WHERE role.code = 'product-lead'
'app-config:view', 'app-config:update', 'app-version:view', 'app-version:create', 'app-version:update', 'app-version:delete',
'full-server-notice:view', 'full-server-notice:send',
'resource:view', 'resource:create', 'resource:update', 'resource:delete', 'upload:create',
'resource-shop:view', 'resource-shop:update', 'resource-group:view', 'resource-group:create', 'resource-group:update',
'resource-shop:view', 'resource-shop:update', 'resource-group:view', 'resource-group:create', 'resource-group:update', 'resource-group:delete',
'gift:view', 'gift:create', 'gift:update', 'gift:status', 'gift:delete',
'resource-grant:view', 'resource-grant:create', 'resource-grant:revoke', 'emoji-pack:view', 'emoji-pack:create',
'coin-ledger:view', 'coin-seller-ledger:view', 'report:view', 'gift-diamond:view', 'gift-diamond:update',
@ -224,7 +224,7 @@ WHERE role.code = 'product-specialist'
'room:view', 'room-pin:view', 'room-config:view', 'room-whitelist:view', 'room-robot:view', 'room-robot:create', 'room-robot:update',
'app-config:view', 'app-version:view', 'full-server-notice:view',
'resource:view', 'resource:create', 'resource:update', 'resource:delete', 'upload:create',
'resource-shop:view', 'resource-shop:update', 'resource-group:view', 'resource-group:create', 'resource-group:update',
'resource-shop:view', 'resource-shop:update', 'resource-group:view', 'resource-group:create', 'resource-group:update', 'resource-group:delete',
'gift:view', 'gift:create', 'gift:update', 'gift:status', 'gift:delete',
'resource-grant:view', 'resource-grant:create', 'resource-grant:revoke', 'emoji-pack:view', 'emoji-pack:create',
'coin-ledger:view', 'coin-seller-ledger:view', 'report:view',

View File

@ -0,0 +1,18 @@
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
SET @now_ms = CAST(UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000 AS UNSIGNED);
INSERT INTO admin_permissions (name, code, kind, description, created_at_ms, updated_at_ms) VALUES
('资源组删除', 'resource-group:delete', 'button', '', @now_ms, @now_ms)
ON DUPLICATE KEY UPDATE
name = VALUES(name),
kind = VALUES(kind),
description = VALUES(description),
updated_at_ms = @now_ms;
INSERT IGNORE INTO admin_role_permissions (role_id, permission_id)
SELECT admin_role.id, admin_permission.id
FROM admin_roles admin_role
JOIN admin_permissions admin_permission
WHERE admin_role.code IN ('platform-admin', 'ops-admin', 'operations-specialist', 'product-lead', 'product-specialist')
AND admin_permission.code = 'resource-group:delete';

View File

@ -183,7 +183,8 @@ func (r *Repository) SetResourceGroupStatus(ctx context.Context, command resourc
}
ctx = contextWithCommandApp(ctx, command.AppCode)
command.Status = resourcedomain.NormalizeStatus(command.Status)
if !resourcedomain.ValidStatus(command.Status) {
// deleted 仅供受独立删除权限保护的管理端入口使用;创建、编辑仍只接受 active/disabled。
if !resourcedomain.ValidStatus(command.Status) && command.Status != resourcedomain.StatusDeleted {
return resourcedomain.ResourceGroup{}, xerr.New(xerr.InvalidArgument, "status is invalid")
}
tx, err := r.db.BeginTx(ctx, nil)
@ -468,7 +469,8 @@ func scanResourceGroupItem(scanner scanTarget) (resourcedomain.ResourceGroupItem
}
func resourceGroupWhereSQL(query resourcedomain.ListResourceGroupsQuery) (string, []any) {
where := `WHERE app_code = ?`
// 软删除行保留给历史发放、快照和审计链路,任何资源组列表都不能重新暴露这些行。
where := `WHERE app_code = ? AND status <> 'deleted'`
args := []any{query.AppCode}
if query.ActiveOnly {
where += ` AND status = 'active'`