156 lines
6.3 KiB
Go
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
|
|
}
|