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:
Astra 2026-09-16 14:03:15 +01:00
parent 3ca8ef1a16
commit f33e25af8d
32 changed files with 750 additions and 44 deletions

View file

@ -28,13 +28,14 @@ type ProfilePhotoProvider = userprojection.ProfilePhotoProvider
// Service 提供用户查询。
type Service struct {
users store.UserStore
cache store.UserCache
contacts store.ContactStore
photos ProfilePhotoProvider
privacy userprojection.PrivacyEvaluator
freezes userprojection.AccountFreezeProvider
projector *userprojection.Projector
users store.UserStore
cache store.UserCache
contacts store.ContactStore
photos ProfilePhotoProvider
privacy userprojection.PrivacyEvaluator
freezes userprojection.AccountFreezeProvider
restrictions userprojection.AccountRestrictionProvider
projector *userprojection.Projector
// hideThirdPartyVerification mirrors config.HideThirdPartyVerification:
// while true, ResolveUsername never resolves @marksbot
// (domain.VerifierBotUserID), so a client cannot discover it by username.
@ -97,6 +98,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, ResolveUsername treats @marksbot as not found.
func WithHideThirdPartyVerification(hidden bool) Option {
@ -135,6 +141,7 @@ func NewService(users store.UserStore, opts ...Option) *Service {
userprojection.WithPhotoProvider(s.photos),
userprojection.WithPrivacyEvaluator(s.privacy),
userprojection.WithAccountFreezeProvider(s.freezes),
userprojection.WithAccountRestrictionProvider(s.restrictions),
)
return s
}