feat: 完成鸽达达后台安全与审计改造
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
package sys
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/imkafka"
|
||||
"hotgo/internal/model/input/form"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/utility/convert"
|
||||
"hotgo/utility/excel"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
type sSysImPrivateMessage struct{}
|
||||
type sSysImGroupMessage struct{}
|
||||
|
||||
func NewSysImPrivateMessage() *sSysImPrivateMessage { return &sSysImPrivateMessage{} }
|
||||
func NewSysImGroupMessage() *sSysImGroupMessage { return &sSysImGroupMessage{} }
|
||||
|
||||
func init() {
|
||||
service.RegisterSysImPrivateMessage(NewSysImPrivateMessage())
|
||||
service.RegisterSysImGroupMessage(NewSysImGroupMessage())
|
||||
}
|
||||
|
||||
func (s *sSysImPrivateMessage) List(ctx context.Context, in *sysin.ImPrivateMessageListInp) ([]*sysin.ImMessageListModel, int, error) {
|
||||
if err := in.Filter(ctx); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
values := addPageQuery(url.Values{}, in.Page, in.PerPage)
|
||||
setQuery(values, "topic", in.Topic)
|
||||
setQuery(values, "from_user_id", in.FromUserId)
|
||||
setQuery(values, "to_user_id", in.ToUserId)
|
||||
setQuery(values, "content_type", in.ContentType)
|
||||
setQuery(values, "status", in.Status)
|
||||
setQuery(values, "keyword", in.Keyword)
|
||||
addTimeRangeQuery(values, "created_at", in.CreatedAt)
|
||||
return queryImMessages(ctx, in.TenantId, "private-messages", values)
|
||||
}
|
||||
|
||||
func (s *sSysImGroupMessage) List(ctx context.Context, in *sysin.ImGroupMessageListInp) ([]*sysin.ImMessageListModel, int, error) {
|
||||
if err := in.Filter(ctx); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
values := addPageQuery(url.Values{}, in.Page, in.PerPage)
|
||||
setQuery(values, "topic", in.Topic)
|
||||
setQuery(values, "sender_user_id", in.SenderUserId)
|
||||
setQuery(values, "content_type", in.ContentType)
|
||||
setQuery(values, "status", in.Status)
|
||||
setQuery(values, "keyword", in.Keyword)
|
||||
addTimeRangeQuery(values, "created_at", in.CreatedAt)
|
||||
return queryImMessages(ctx, in.TenantId, "group-messages", values)
|
||||
}
|
||||
|
||||
func queryImMessages(ctx context.Context, tenantId int64, resource string, values url.Values) ([]*sysin.ImMessageListModel, int, error) {
|
||||
tenant, err := resolveImAdminTenant(ctx, tenantId)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return imAdminQueryList[sysin.ImMessageListModel](ctx, tenant,
|
||||
"/internal/admin-query/tenants/"+url.PathEscape(tenant.Code)+"/"+resource, values,
|
||||
map[string]string{"sender_user_id": "fromUserId", "sent_at": "createdAt", "message_type": "contentType", "content_summary": "contentExcerpt"})
|
||||
}
|
||||
|
||||
func (s *sSysImPrivateMessage) View(ctx context.Context, in *sysin.ImMessageViewInp) (*sysin.ImMessageViewModel, error) {
|
||||
return viewImMessage(ctx, in)
|
||||
}
|
||||
|
||||
func (s *sSysImGroupMessage) View(ctx context.Context, in *sysin.ImMessageViewInp) (*sysin.ImMessageViewModel, error) {
|
||||
return viewImMessage(ctx, in)
|
||||
}
|
||||
|
||||
func viewImMessage(ctx context.Context, in *sysin.ImMessageViewInp) (*sysin.ImMessageViewModel, error) {
|
||||
if err := in.Filter(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tenant, err := resolveImAdminTenant(ctx, in.TenantId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
path := "/internal/admin-query/tenants/" + url.PathEscape(tenant.Code) + "/messages/" + url.PathEscape(in.Topic) + "/" + strconv.FormatInt(in.SeqId, 10)
|
||||
return imAdminQueryOne[sysin.ImMessageViewModel](ctx, tenant, path,
|
||||
map[string]string{"sender_user_id": "fromUserId", "sent_at": "createdAt", "message_type": "contentType"})
|
||||
}
|
||||
|
||||
func (s *sSysImPrivateMessage) Hide(ctx context.Context, in *sysin.ImMessageActionInp) (*sysin.ImMessageCommandModel, error) {
|
||||
return publishMessageCommand(ctx, in, "private", consts.ImAdminCommandMessageHide)
|
||||
}
|
||||
|
||||
func (s *sSysImPrivateMessage) Delete(ctx context.Context, in *sysin.ImMessageActionInp) (*sysin.ImMessageCommandModel, error) {
|
||||
return publishMessageCommand(ctx, in, "private", consts.ImAdminCommandMessageDelete)
|
||||
}
|
||||
|
||||
func (s *sSysImGroupMessage) Hide(ctx context.Context, in *sysin.ImMessageActionInp) (*sysin.ImMessageCommandModel, error) {
|
||||
return publishMessageCommand(ctx, in, "group", consts.ImAdminCommandMessageHide)
|
||||
}
|
||||
|
||||
func (s *sSysImGroupMessage) Delete(ctx context.Context, in *sysin.ImMessageActionInp) (*sysin.ImMessageCommandModel, error) {
|
||||
return publishMessageCommand(ctx, in, "group", consts.ImAdminCommandMessageDelete)
|
||||
}
|
||||
|
||||
func publishMessageCommand(ctx context.Context, in *sysin.ImMessageActionInp, conversationType string, eventType string) (*sysin.ImMessageCommandModel, error) {
|
||||
if err := in.Filter(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tenant, err := resolveImAdminTenant(ctx, in.TenantId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user := contexts.GetUser(ctx)
|
||||
actorName := ""
|
||||
if user != nil {
|
||||
actorName = user.RealName
|
||||
}
|
||||
bizId := in.Topic + ":" + strconv.FormatInt(in.SeqId, 10)
|
||||
command, err := imkafka.PublishAdminCommand(ctx, imkafka.AdminCommandInput{
|
||||
TenantID: tenant.Id, TenantCode: tenant.Code, EventType: eventType, BizType: "message", BizID: bizId,
|
||||
Actor: &imkafka.Actor{Type: "admin", ID: strconv.FormatInt(contexts.GetUserId(ctx), 10), DisplayName: actorName},
|
||||
Payload: map[string]any{"conversation_type": conversationType, "topic": in.Topic, "seq_id": in.SeqId, "reason": in.Reason},
|
||||
CreatedBy: contexts.GetUserId(ctx),
|
||||
})
|
||||
result := "success"
|
||||
if err != nil {
|
||||
result = "failed"
|
||||
}
|
||||
_ = writeImAdminAudit(ctx, tenant.Id, eventType, "message", in.SeqId, result, map[string]any{"conversation_type": conversationType, "topic": in.Topic, "reason": in.Reason})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &sysin.ImMessageCommandModel{CommandId: command.CommandID, EventId: command.EventID, Status: command.Status}, nil
|
||||
}
|
||||
|
||||
func (s *sSysImPrivateMessage) Export(ctx context.Context, in *sysin.ImPrivateMessageListInp) error {
|
||||
list, total, err := s.List(ctx, in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return exportImMessages(ctx, list, total, in.Page, in.PerPage, "单聊消息")
|
||||
}
|
||||
|
||||
func (s *sSysImGroupMessage) Export(ctx context.Context, in *sysin.ImGroupMessageListInp) error {
|
||||
list, total, err := s.List(ctx, in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return exportImMessages(ctx, list, total, in.Page, in.PerPage, "群聊消息")
|
||||
}
|
||||
|
||||
func exportImMessages(ctx context.Context, list []*sysin.ImMessageListModel, total int, page int, perPage int, label string) error {
|
||||
tags, err := convert.GetEntityDescTags(sysin.ImMessageExportModel{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var exports []sysin.ImMessageExportModel
|
||||
if err = gconv.Scan(list, &exports); err != nil {
|
||||
return err
|
||||
}
|
||||
fileName := "导出" + label + "-" + gctx.CtxId(ctx)
|
||||
sheetName := fmt.Sprintf("索引条件共%v行,共%v页,当前导出是第%v页,本页共%v行", total, form.CalPageCount(total, perPage), page, len(list))
|
||||
return excel.ExportByStructs(ctx, tags, exports, fileName, sheetName)
|
||||
}
|
||||
|
||||
func setQuery(values url.Values, key string, value string) {
|
||||
if value != "" {
|
||||
values.Set(key, value)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user