Files
im_manager/server/internal/logic/sys/im_login_audit.go
T

156 lines
6.3 KiB
Go

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/encoding/gjson"
"github.com/gogf/gf/v2/os/gctx"
)
type sSysImUserLoginHistory struct{}
type sSysImLoginFailureLog struct{}
func NewSysImUserLoginHistory() *sSysImUserLoginHistory { return &sSysImUserLoginHistory{} }
func NewSysImLoginFailureLog() *sSysImLoginFailureLog { return &sSysImLoginFailureLog{} }
func init() {
service.RegisterSysImUserLoginHistory(NewSysImUserLoginHistory())
service.RegisterSysImLoginFailureLog(NewSysImLoginFailureLog())
}
func (s *sSysImUserLoginHistory) List(ctx context.Context, in *sysin.ImUserLoginHistoryListInp) ([]*sysin.ImUserLoginHistoryModel, int, error) {
if err := in.Filter(ctx); err != nil {
return nil, 0, err
}
tenant, err := resolveImAdminTenant(ctx, in.TenantId)
if err != nil {
return nil, 0, err
}
values := addPageQuery(url.Values{}, in.Page, in.PerPage)
setQuery(values, "user_id", in.UserId)
setQuery(values, "account", in.Account)
setQuery(values, "login_type", in.LoginType)
setQuery(values, "event_type", in.EventType)
setQuery(values, "platform", in.Platform)
setQuery(values, "ip", in.Ip)
addTimeRangeQuery(values, "login_at", in.LoginAt)
return imAdminQueryList[sysin.ImUserLoginHistoryModel](ctx, tenant,
"/internal/admin-query/tenants/"+url.PathEscape(tenant.Code)+"/user-login-logs", values, nil)
}
func (s *sSysImUserLoginHistory) Export(ctx context.Context, in *sysin.ImUserLoginHistoryListInp) error {
list, total, err := s.List(ctx, in)
if err != nil {
return err
}
exports := make([]sysin.ImLoginAuditExportModel, 0, len(list))
for _, item := range list {
exports = append(exports, sysin.ImLoginAuditExportModel{Id: item.Id, UserId: item.UserId, AccountMask: item.AccountMask, EventType: item.EventType, Platform: item.Platform, Ip: item.Ip, Region: item.Region, RiskLevel: item.RiskLevel, OccurredAt: item.LoginAt})
}
return exportLoginAudit(ctx, exports, total, in.Page, in.PerPage, "用户登录历史")
}
func (s *sSysImLoginFailureLog) List(ctx context.Context, in *sysin.ImLoginFailureLogListInp) ([]*sysin.ImLoginFailureLogModel, int, error) {
if err := in.Filter(ctx); err != nil {
return nil, 0, err
}
tenant, err := resolveImAdminTenant(ctx, in.TenantId)
if err != nil {
return nil, 0, err
}
values := addPageQuery(url.Values{}, in.Page, in.PerPage)
setQuery(values, "user_id", in.UserId)
setQuery(values, "account", in.Account)
setQuery(values, "failure_type", in.FailureType)
setQuery(values, "platform", in.Platform)
setQuery(values, "ip", in.Ip)
addTimeRangeQuery(values, "attempt_at", in.AttemptAt)
return imAdminQueryList[sysin.ImLoginFailureLogModel](ctx, tenant,
"/internal/admin-query/tenants/"+url.PathEscape(tenant.Code)+"/login-failure-logs", values, nil)
}
func (s *sSysImLoginFailureLog) View(ctx context.Context, in *sysin.ImLoginFailureViewInp) (*sysin.ImLoginFailureLogModel, error) {
if err := in.Filter(ctx); err != nil {
return nil, err
}
tenant, err := resolveImAdminTenant(ctx, in.TenantId)
if err != nil {
return nil, err
}
return imAdminQueryOne[sysin.ImLoginFailureLogModel](ctx, tenant,
"/internal/admin-query/tenants/"+url.PathEscape(tenant.Code)+"/login-failure-logs/"+strconv.FormatInt(in.Id, 10), nil)
}
func (s *sSysImLoginFailureLog) Export(ctx context.Context, in *sysin.ImLoginFailureLogListInp) error {
list, total, err := s.List(ctx, in)
if err != nil {
return err
}
exports := make([]sysin.ImLoginAuditExportModel, 0, len(list))
for _, item := range list {
exports = append(exports, sysin.ImLoginAuditExportModel{Id: item.Id, UserId: item.UserId, AccountMask: item.AccountMask, EventType: item.FailureType, Platform: item.Platform, Ip: item.Ip, Region: item.Region, RiskLevel: item.RiskLevel, Reason: item.Reason, OccurredAt: item.AttemptAt})
}
return exportLoginAudit(ctx, exports, total, in.Page, in.PerPage, "登录失败日志")
}
func exportLoginAudit(ctx context.Context, exports []sysin.ImLoginAuditExportModel, total int, page int, perPage int, label string) error {
tags, err := convert.GetEntityDescTags(sysin.ImLoginAuditExportModel{})
if err != nil {
return err
}
fileName := "导出" + label + "-" + gctx.CtxId(ctx)
sheetName := fmt.Sprintf("索引条件共%v行,共%v页,当前导出是第%v页,本页共%v行", total, form.CalPageCount(total, perPage), page, len(exports))
return excel.ExportByStructs(ctx, tags, exports, fileName, sheetName)
}
func (s *sSysImLoginFailureLog) AddBlacklist(ctx context.Context, in *sysin.ImLoginFailureAddBlacklistInp) error {
if err := in.Filter(ctx); err != nil {
return err
}
remark := in.Remark
if remark == "" {
remark = "由登录失败日志加入"
}
return service.SysImSecurityPolicy().IPRuleEdit(ctx, &sysin.ImSecurityIPRuleEditInp{
TenantId: in.TenantId, RuleType: "blacklist", IpCidr: in.Ip, Action: "deny",
SceneJson: gjson.New([]string{"login"}), RiskLevel: "high", Status: consts.StatusEnabled, Remark: remark,
})
}
func (s *sSysImLoginFailureLog) BanUser(ctx context.Context, in *sysin.ImLoginFailureBanUserInp) (*sysin.ImUserCommandModel, 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
}
command, err := imkafka.PublishAdminCommand(ctx, imkafka.AdminCommandInput{
TenantID: tenant.Id, TenantCode: tenant.Code, EventType: consts.ImAdminCommandUserBan,
BizType: "user", BizID: strconv.FormatInt(in.UserId, 10),
Actor: &imkafka.Actor{Type: "admin", ID: strconv.FormatInt(contexts.GetUserId(ctx), 10), DisplayName: actorName},
Payload: map[string]any{"user_id": strconv.FormatInt(in.UserId, 10), "target_user_id": strconv.FormatInt(in.UserId, 10), "reason": in.Reason},
CreatedBy: contexts.GetUserId(ctx),
})
if err != nil {
return nil, err
}
return &sysin.ImUserCommandModel{CommandID: command.CommandID, EventID: command.EventID, Status: command.Status, TenantID: command.TenantID, TenantCode: command.TenantCode, EventType: command.EventType, IdempotencyKey: command.IdempotencyKey}, nil
}