feat: 添加日志管理和敏感词过滤功能
- 新增日志管理模块:操作日志、登录日志、数据变更日志 - 新增敏感词过滤器 (sanitizer) - 新增日志异步写入管理器 - 新增日志定时清理服务 - 优化帖子相关服务和上传服务
This commit is contained in:
@@ -44,8 +44,8 @@ type UserService interface {
|
||||
// 关注相关
|
||||
GetFollowers(ctx context.Context, userID string, page, pageSize int) ([]*model.User, int64, error)
|
||||
GetFollowing(ctx context.Context, userID string, page, pageSize int) ([]*model.User, int64, error)
|
||||
GetFollowingList(ctx context.Context, userID, page, pageSize string) ([]*model.User, error)
|
||||
GetFollowersList(ctx context.Context, userID, page, pageSize string) ([]*model.User, error)
|
||||
GetFollowingList(ctx context.Context, userID string, page, pageSize string) ([]*model.User, error)
|
||||
GetFollowersList(ctx context.Context, userID string, page, pageSize string) ([]*model.User, error)
|
||||
FollowUser(ctx context.Context, followerID, followeeID string) error
|
||||
UnfollowUser(ctx context.Context, followerID, followeeID string) error
|
||||
GetMutualFollowStatus(ctx context.Context, currentUserID string, targetUserIDs []string) (map[string][2]bool, error)
|
||||
@@ -55,6 +55,9 @@ type UserService interface {
|
||||
UnblockUser(ctx context.Context, blockerID, blockedID string) error
|
||||
GetBlockedUsers(ctx context.Context, blockerID string, page, pageSize int) ([]*model.User, int64, error)
|
||||
IsBlocked(ctx context.Context, blockerID, blockedID string) (bool, error)
|
||||
|
||||
// 日志服务设置
|
||||
SetLogService(logService *LogService)
|
||||
}
|
||||
|
||||
// userServiceImpl 用户服务实现
|
||||
@@ -62,6 +65,7 @@ type userServiceImpl struct {
|
||||
userRepo *repository.UserRepository
|
||||
systemMessageService SystemMessageService
|
||||
emailCodeService EmailCodeService
|
||||
logService *LogService
|
||||
}
|
||||
|
||||
// NewUserService 创建用户服务
|
||||
@@ -75,9 +79,15 @@ func NewUserService(
|
||||
userRepo: userRepo,
|
||||
systemMessageService: systemMessageService,
|
||||
emailCodeService: NewEmailCodeService(emailService, cacheBackend),
|
||||
logService: nil,
|
||||
}
|
||||
}
|
||||
|
||||
// SetLogService 设置日志服务
|
||||
func (s *userServiceImpl) SetLogService(logService *LogService) {
|
||||
s.logService = logService
|
||||
}
|
||||
|
||||
// SendRegisterCode 发送注册验证码
|
||||
func (s *userServiceImpl) SendRegisterCode(ctx context.Context, email string) error {
|
||||
user, err := s.userRepo.GetByEmail(email)
|
||||
@@ -241,12 +251,28 @@ func (s *userServiceImpl) Register(ctx context.Context, username, email, passwor
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 记录注册日志
|
||||
if s.logService != nil {
|
||||
s.logService.OperationLog.RecordOperation(&model.OperationLog{
|
||||
UserID: user.ID,
|
||||
UserName: user.Username,
|
||||
NickName: user.Nickname,
|
||||
Operation: string(model.OpUserRegister),
|
||||
Module: "user",
|
||||
TargetType: "user",
|
||||
TargetID: user.ID,
|
||||
IP: "",
|
||||
Status: "success",
|
||||
})
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// Login 用户登录
|
||||
func (s *userServiceImpl) Login(ctx context.Context, account, password string) (*model.User, error) {
|
||||
account = strings.TrimSpace(account)
|
||||
|
||||
var (
|
||||
user *model.User
|
||||
err error
|
||||
@@ -258,18 +284,86 @@ func (s *userServiceImpl) Login(ctx context.Context, account, password string) (
|
||||
} else {
|
||||
user, err = s.userRepo.GetByUsername(account)
|
||||
}
|
||||
|
||||
// 登录失败处理
|
||||
loginResult := string(model.LoginResultSuccess)
|
||||
var failReason string
|
||||
|
||||
if err != nil || user == nil {
|
||||
loginResult = string(model.LoginResultFail)
|
||||
failReason = string(model.FailReasonUserNotFound)
|
||||
|
||||
// 记录失败登录日志
|
||||
if s.logService != nil {
|
||||
s.logService.LoginLog.RecordLogin(&model.LoginLog{
|
||||
UserName: account,
|
||||
Event: string(model.LoginEventFail),
|
||||
IP: "",
|
||||
UserAgent: "",
|
||||
Result: loginResult,
|
||||
FailReason: failReason,
|
||||
})
|
||||
}
|
||||
|
||||
return nil, ErrInvalidCredentials
|
||||
}
|
||||
|
||||
if !utils.CheckPasswordHash(password, user.PasswordHash) {
|
||||
loginResult = string(model.LoginResultFail)
|
||||
failReason = string(model.FailReasonWrongPassword)
|
||||
|
||||
// 记录失败登录日志
|
||||
if s.logService != nil {
|
||||
s.logService.LoginLog.RecordLogin(&model.LoginLog{
|
||||
UserID: user.ID,
|
||||
UserName: user.Username,
|
||||
NickName: user.Nickname,
|
||||
Event: string(model.LoginEventFail),
|
||||
IP: "",
|
||||
UserAgent: "",
|
||||
Result: loginResult,
|
||||
FailReason: failReason,
|
||||
})
|
||||
}
|
||||
|
||||
return nil, ErrInvalidCredentials
|
||||
}
|
||||
|
||||
if user.Status != model.UserStatusActive {
|
||||
loginResult = string(model.LoginResultFail)
|
||||
failReason = string(model.FailReasonAccountBanned)
|
||||
|
||||
// 记录失败登录日志
|
||||
if s.logService != nil {
|
||||
s.logService.LoginLog.RecordLogin(&model.LoginLog{
|
||||
UserID: user.ID,
|
||||
UserName: user.Username,
|
||||
NickName: user.Nickname,
|
||||
Event: string(model.LoginEventFail),
|
||||
IP: "",
|
||||
UserAgent: "",
|
||||
Result: loginResult,
|
||||
FailReason: failReason,
|
||||
})
|
||||
}
|
||||
|
||||
return nil, ErrUserBanned
|
||||
}
|
||||
|
||||
// 记录成功登录日志
|
||||
if s.logService != nil {
|
||||
s.logService.LoginLog.RecordLogin(&model.LoginLog{
|
||||
UserID: user.ID,
|
||||
UserName: user.Username,
|
||||
NickName: user.Nickname,
|
||||
LoginType: string(model.LoginTypePassword),
|
||||
Event: string(model.LoginEventLogin),
|
||||
IP: "",
|
||||
UserAgent: "",
|
||||
Result: string(model.LoginResultSuccess),
|
||||
})
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
@@ -337,7 +431,27 @@ func (s *userServiceImpl) GetUserByIDWithMutualFollowStatus(ctx context.Context,
|
||||
|
||||
// UpdateUser 更新用户
|
||||
func (s *userServiceImpl) UpdateUser(ctx context.Context, user *model.User) error {
|
||||
return s.userRepo.Update(user)
|
||||
err := s.userRepo.Update(user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 记录数据变更日志
|
||||
if s.logService != nil {
|
||||
s.logService.DataChangeLog.RecordDataChange(&model.DataChangeLog{
|
||||
UserID: user.ID,
|
||||
ChangeType: string(model.ChangeProfile),
|
||||
TargetType: "user",
|
||||
TargetID: user.ID,
|
||||
FieldName: "profile",
|
||||
OldValue: "",
|
||||
NewValue: fmt.Sprintf("昵称:%s", user.Nickname),
|
||||
OperatorType: string(model.OperatorTypeSelf),
|
||||
Reason: "用户修改个人资料",
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetFollowers 获取粉丝
|
||||
@@ -542,7 +656,26 @@ func (s *userServiceImpl) ChangePassword(ctx context.Context, userID, oldPasswor
|
||||
|
||||
// 更新密码
|
||||
user.PasswordHash = hashedPassword
|
||||
return s.userRepo.Update(user)
|
||||
if err := s.userRepo.Update(user); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 记录数据变更日志
|
||||
if s.logService != nil {
|
||||
s.logService.DataChangeLog.RecordDataChange(&model.DataChangeLog{
|
||||
UserID: userID,
|
||||
ChangeType: string(model.ChangePassword),
|
||||
TargetType: "user",
|
||||
TargetID: userID,
|
||||
FieldName: "password",
|
||||
OldValue: "***",
|
||||
NewValue: "***",
|
||||
OperatorType: string(model.OperatorTypeSelf),
|
||||
Reason: "用户主动修改密码",
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetPasswordByEmail 通过邮箱重置密码
|
||||
|
||||
Reference in New Issue
Block a user