删除资源组
This commit is contained in:
parent
6aab34a60a
commit
f0e780ae8f
39
.codex_tat_action.py
Normal file
39
.codex_tat_action.py
Normal 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", ""))
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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",
|
||||
}
|
||||
|
||||
@ -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"},
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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';
|
||||
@ -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'`
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user