spark-server/internal/module/user/logic/account_send.go
2026-09-29 16:37:36 +08:00

73 lines
1.9 KiB
Go

package logic
import (
"context"
"time"
"spark-server/internal/module/user/entity"
"spark-server/internal/pkg/errs"
)
// AccountModeration is implemented by user persistence for send gates and bans.
type AccountModeration interface {
SetUserStatus(ctx context.Context, userID int64, status entity.Status) error
ExtendSendMutedUntil(ctx context.Context, userID int64, until time.Time) error
}
type BannedKicker interface {
KickUserBanned(userID int64)
}
// AssertCanSend is the AccountGate for message send (all content types).
func (s *Service) AssertCanSend(ctx context.Context, userID int64) error {
if !s.ready() || userID <= 0 {
return errs.ErrUnauthorized
}
u, err := s.repo.GetByID(ctx, userID)
if err != nil {
return err
}
if u.Status != entity.StatusActive {
return errs.ErrForbidden
}
if !u.SendMutedUntil.IsZero() && u.SendMutedUntil.After(time.Now()) {
return errs.ErrSendMuted
}
return nil
}
// ExtendSendMutedUntil implements moderation.UserModeration.
func (s *Service) ExtendSendMutedUntil(ctx context.Context, userID int64, until time.Time) error {
mod, ok := s.repo.(AccountModeration)
if !ok || mod == nil {
return errs.ErrAvailable
}
return mod.ExtendSendMutedUntil(ctx, userID, until)
}
// DisableAccount disables the user and revokes live sessions (moderation / admin ban).
func (s *Service) DisableAccount(ctx context.Context, userID int64) error {
mod, ok := s.repo.(AccountModeration)
if !ok || mod == nil {
return errs.ErrAvailable
}
if err := mod.SetUserStatus(ctx, userID, entity.StatusDisabled); err != nil {
return err
}
s.revokeAccessBanned(ctx, userID)
return nil
}
func (s *Service) revokeAccessBanned(ctx context.Context, userID int64) {
if s.tokens != nil {
_ = s.tokens.LogoutAll(ctx, userID)
}
if bk, ok := s.sessions.(BannedKicker); ok && bk != nil {
bk.KickUserBanned(userID)
return
}
if s.sessions != nil {
s.sessions.KickUser(userID)
}
}