admin: add account spam restriction (join/message gate)
Adds a narrower spam sanction alongside the existing account freeze: a restricted account keeps every existing membership and conversation, but cannot join new channels/groups (public join or invite link) and cannot start a new conversation with a non-contact. Reachable both as a standalone admin action and as a decision on a reported user's moderation case, with the same idempotent-supersession and appeal wiring freeze already has.
This commit is contained in:
parent
3ca8ef1a16
commit
f33e25af8d
32 changed files with 750 additions and 44 deletions
|
|
@ -28,14 +28,15 @@ type phonePrivacyService interface {
|
|||
|
||||
// Service 提供通讯录查询。
|
||||
type Service struct {
|
||||
contacts store.ContactStore
|
||||
users store.UserStore
|
||||
photos userprojection.ProfilePhotoProvider
|
||||
privacy phonePrivacyService
|
||||
freezes userprojection.AccountFreezeProvider
|
||||
projector *userprojection.Projector
|
||||
versions store.ReadModelVersionStore
|
||||
cache *contactListReadModelCache
|
||||
contacts store.ContactStore
|
||||
users store.UserStore
|
||||
photos userprojection.ProfilePhotoProvider
|
||||
privacy phonePrivacyService
|
||||
freezes userprojection.AccountFreezeProvider
|
||||
restrictions userprojection.AccountRestrictionProvider
|
||||
projector *userprojection.Projector
|
||||
versions store.ReadModelVersionStore
|
||||
cache *contactListReadModelCache
|
||||
// hideThirdPartyVerification mirrors config.HideThirdPartyVerification:
|
||||
// while true, Search never returns @marksbot (domain.VerifierBotUserID),
|
||||
// so the account is unreachable for a client that doesn't already know it.
|
||||
|
|
@ -59,6 +60,11 @@ func WithAccountFreezeProvider(p userprojection.AccountFreezeProvider) Option {
|
|||
return func(s *Service) { s.freezes = p }
|
||||
}
|
||||
|
||||
// WithAccountRestrictionProvider injects the account spam-restriction reader.
|
||||
func WithAccountRestrictionProvider(p userprojection.AccountRestrictionProvider) Option {
|
||||
return func(s *Service) { s.restrictions = p }
|
||||
}
|
||||
|
||||
// WithHideThirdPartyVerification mirrors config.HideThirdPartyVerification:
|
||||
// while true, Search filters @marksbot out of every result set.
|
||||
func WithHideThirdPartyVerification(hidden bool) Option {
|
||||
|
|
@ -101,6 +107,7 @@ func (s *Service) rebuildProjector() {
|
|||
userprojection.WithPhotoProvider(s.photos),
|
||||
userprojection.WithPrivacyEvaluator(s.privacy),
|
||||
userprojection.WithAccountFreezeProvider(s.freezes),
|
||||
userprojection.WithAccountRestrictionProvider(s.restrictions),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -126,6 +133,15 @@ func (s *Service) GetContacts(ctx context.Context, userID int64, hash int64) (do
|
|||
return list, false, nil
|
||||
}
|
||||
|
||||
// IsContact reports whether contactUserID is in userID's own contact list.
|
||||
func (s *Service) IsContact(ctx context.Context, userID, contactUserID int64) (bool, error) {
|
||||
if s == nil || s.contacts == nil || userID == 0 || contactUserID == 0 {
|
||||
return false, nil
|
||||
}
|
||||
_, found, err := s.contacts.Get(ctx, userID, contactUserID)
|
||||
return found, err
|
||||
}
|
||||
|
||||
func (s *Service) AddContact(ctx context.Context, userID int64, input domain.ContactInput) (domain.Contact, error) {
|
||||
if s == nil || s.contacts == nil || userID == 0 || input.ContactUserID == 0 || input.ContactUserID == userID {
|
||||
return domain.Contact{}, ErrContactIDInvalid
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue