package sys import ( "context" "hotgo/internal/consts" "hotgo/internal/dao" "hotgo/internal/library/contexts" "hotgo/internal/library/imtenant" "hotgo/internal/model/entity" "hotgo/internal/service" "hotgo/utility/simple" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gtime" ) type imAdminScope struct { TenantId int64 OperatorId int64 RoleKey string RequestId string } const ( imAdminOperationAuditTable = "im_admin_operation_audit" ) func resolveImAdminScope(ctx context.Context, selectedTenantId int64) (scope imAdminScope, err error) { return resolveImAdminScopeWithAll(ctx, selectedTenantId, false) } func resolveImAdminScopeWithAll(ctx context.Context, selectedTenantId int64, allowAll bool) (scope imAdminScope, err error) { operatorId := contexts.GetUserId(ctx) scope.OperatorId = operatorId scope.RoleKey = contexts.GetRoleKey(ctx) scope.RequestId = gctx.CtxId(ctx) if isImPlatformAdmin(ctx, operatorId) { if selectedTenantId <= 0 { if allowAll { return scope, nil } return scope, gerror.New("请选择IM租户") } if err = ensureImTenantActive(ctx, selectedTenantId); err != nil { return scope, err } scope.TenantId = selectedTenantId return scope, nil } if !contexts.IsTenantDept(ctx) && !(contexts.IsCompanyDept(ctx) && contexts.GetTenantId(ctx) > 0) { return scope, gerror.New("当前账号无权管理IM租户") } tenantId, err := resolveImAdminBoundTenant(ctx) if err != nil { return scope, err } if err = ensureImTenantActive(ctx, tenantId); err != nil { return scope, err } scope.TenantId = tenantId return scope, nil } func isImPlatformAdmin(ctx context.Context, operatorId int64) bool { if service.AdminMember().VerifySuperId(ctx, operatorId) { return true } return contexts.IsCompanyDept(ctx) && contexts.GetTenantId(ctx) <= 0 } func resolveImAdminBoundTenant(ctx context.Context) (int64, error) { tenantId := contexts.GetTenantId(ctx) if tenantId <= 0 { return 0, gerror.New("当前管理员未关联IM租户") } return tenantId, nil } func ensureImTenantActive(ctx context.Context, tenantId int64) (err error) { var tenant *entity.ImTenant if err = imtenant.RegistryDB().Model(dao.ImTenant.Table()).Safe().Ctx(ctx).WherePri(tenantId).Scan(&tenant); err != nil { return gerror.Wrap(err, "获取IM租户失败") } if tenant == nil || tenant.Id <= 0 { return gerror.New("IM租户不存在") } if tenant.State != consts.ImTenantStateActive { return gerror.New("IM租户未启用") } return nil } func resolveImTenantDB(ctx context.Context, selectedTenantId int64) (db gdb.DB, tenant *entity.ImTenant, err error) { scope, err := resolveImAdminScope(ctx, selectedTenantId) if err != nil { return nil, nil, err } return imtenant.DB(ctx, scope.TenantId) } func writeImAdminAudit(ctx context.Context, tenantId int64, action string, targetType string, targetId int64, result string, detail g.Map) error { operatorId := contexts.GetUserId(ctx) request := ghttp.RequestFromCtx(ctx) ip := "" if request != nil { ip = request.GetClientIp() } detailJson := gjson.New(detail) _, err := g.DB().Exec(ctx, "INSERT INTO "+imAdminOperationAuditTable+" (request_id, tenant_id, operator_id, action, target_type, target_id, result, ip, detail_json, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, CAST(? AS JSON), ?)", gctx.CtxId(ctx), tenantId, operatorId, action, targetType, targetId, result, ip, detailJson.String(), gtime.Now(), ) if err != nil && !simple.IsDemo(ctx) { g.Log().Warningf(ctx, "写入IM后台审计失败 action:%s err:%+v", action, err) } return err }