fix(admin): close PR review blockers

Keep bot credentials out of durable command results, fail bot deletion closed when session revocation fails, reject invalid scam/fake states at every write boundary, and make direct collectible grants a single replayable PostgreSQL aggregate.

Also lock admin gift sender/message limits and add regression coverage for rollback, replay, moderation constraints, and credential redaction.
This commit is contained in:
iamxvbaba 2026-07-23 13:29:04 +08:00
parent 90792cdfab
commit 234061ef83
30 changed files with 859 additions and 93 deletions

View file

@ -451,9 +451,7 @@ func tgChannel(viewerUserID int64, ch domain.Channel, self *domain.ChannelMember
Creator: ch.CreatorUserID == viewerUserID && viewerUserID != 0,
Verified: ch.Verified,
Scam: ch.Scam,
// scam and fake are mutually exclusive in Telegram; a peer flagged as
// both would render neither badge on clients. scam takes precedence.
Fake: ch.Fake && !ch.Scam,
Fake: ch.Fake,
Gigagroup: ch.Gigagroup,
Broadcast: ch.Broadcast,
Megagroup: ch.Megagroup,

View file

@ -53,9 +53,7 @@ func tgUser(u domain.User) *tg.User {
Phone: u.Phone,
Verified: u.Verified,
Scam: u.Scam,
// scam and fake are mutually exclusive in Telegram; a peer flagged as
// both would render neither badge on clients. scam takes precedence.
Fake: u.Fake && !u.Scam,
Fake: u.Fake,
Support: u.Support,
Contact: u.Contact,
MutualContact: u.Mutual,

View file

@ -7,24 +7,30 @@ import (
"telesrv/internal/domain"
)
type adminUniqueStarGiftGranter interface {
GrantUnique(context.Context, domain.AdminStarGiftGrant) (domain.AdminStarGiftGrantResult, error)
}
// AdminGrantStarGift delivers a catalog gift to a recipient peer on behalf of
// grant.SenderID without charging any Stars. It powers the admin console "Give
// gift" action: the gift is loaded from the catalog and delivered through the
// exact same path a paid send uses (messageActionStarGift service message for
// users, saved-gift + admin log for channels), only the Stars debit is skipped.
//
// When SenderID is zero the official system account (777000, the telesrv
// service account) is used as the sender. When Upgrade is true the granted gift
// is immediately upgraded to a genuine collectible (unique) gift. The optional
// ModelAttributeID / PatternAttributeID / BackdropAttributeID / Num pin specific
// collectible facts (0 => random model/pattern/backdrop, auto sequential
// number); the DB constraints remain the source of truth. Upgraded delivery is
// supported for user recipients only.
// SenderID must be zero or the official system account (777000). When Upgrade
// is true, the store assigns a genuine collectible directly in the same
// transaction as its service message and durable updates. The optional
// ModelAttributeID / PatternAttributeID / BackdropAttributeID pin specific
// collectible facts (0 => random; number is always sequential). Upgraded
// delivery is supported for user recipients only.
func (r *Router) AdminGrantStarGift(ctx context.Context, grant domain.AdminStarGiftGrant) error {
senderID := grant.SenderID
if senderID <= 0 {
senderID = domain.OfficialSystemUserID
}
if senderID != domain.OfficialSystemUserID {
return fmt.Errorf("gift sender must be the official system account")
}
if grant.GiftID <= 0 {
return fmt.Errorf("gift_id is required")
}
@ -56,10 +62,9 @@ func (r *Router) AdminGrantStarGift(ctx context.Context, grant domain.AdminStarG
}
}
// adminGrantUpgradedStarGift grants a base gift carrying a prepaid upgrade
// entitlement and then mints the collectible via the standard zero-charge
// prepaid upgrade path, so the recipient ends up owning a real unique gift with
// the requested (or random) attributes and number.
// adminGrantUpgradedStarGift assigns a collectible through the atomic store
// boundary, so a failure cannot leave a regular gift, partial issuance, pts or
// outbox event behind.
func (r *Router) adminGrantUpgradedStarGift(ctx context.Context, senderID int64, gift domain.StarGift, grant domain.AdminStarGiftGrant) error {
if grant.Recipient.Type != domain.PeerTypeUser {
return fmt.Errorf("upgraded gift delivery is supported for user recipients only")
@ -74,23 +79,18 @@ func (r *Router) adminGrantUpgradedStarGift(ctx context.Context, senderID int64,
if preview.Issued >= preview.SupplyTotal {
return fmt.Errorf("gift %d collectible supply is exhausted", gift.ID)
}
// Grant the base gift with a prepaid-upgrade entitlement so the upgrade
// below runs on the zero-charge RequirePrepaid path.
ref, _, err := r.sendStarGiftToUser(ctx, senderID, grant.Recipient.ID, gift, grant.HideName, grant.Message, preview.UpgradeStars)
granter, ok := r.deps.Gifts.(adminUniqueStarGiftGranter)
if !ok {
return fmt.Errorf("atomic collectible grant is not configured")
}
recipientBlocked, err := r.peerBlocksUser(ctx, senderID, grant.Recipient.ID)
if err != nil {
return err
}
commandKey := fmt.Sprintf("admin-grant-upgrade:%d:%d:%d", grant.Recipient.ID, gift.ID, ref.MsgID)
if _, err := r.deps.Gifts.Upgrade(ctx, domain.StarGiftUpgradeRequest{
UserID: grant.Recipient.ID,
Ref: ref,
RequirePrepaid: true,
CommandKey: commandKey,
Date: int(r.clock.Now().Unix()),
ModelAttributeID: grant.ModelAttributeID,
PatternAttributeID: grant.PatternAttributeID,
BackdropAttributeID: grant.BackdropAttributeID,
}); err != nil {
grant.SenderID = senderID
grant.Date = int(r.clock.Now().Unix())
grant.RecipientBlocked = recipientBlocked
if _, err := granter.GrantUnique(ctx, grant); err != nil {
return err
}
r.invalidateStarGiftOwnerProjection(grant.Recipient)