fix: sync account freeze peer visibility
This commit is contained in:
parent
d9875b5caa
commit
eba402946a
26 changed files with 1034 additions and 19 deletions
|
|
@ -33,11 +33,12 @@ func TestAccountFreezeMigrationAndStoreRoundTrip(t *testing.T) {
|
|||
const (
|
||||
frozenUserID = int64(1999999881)
|
||||
activeUserID = int64(1999999882)
|
||||
observerID = int64(1999999883)
|
||||
)
|
||||
for _, user := range []struct {
|
||||
id int64
|
||||
phone string
|
||||
}{{frozenUserID, "1999999881"}, {activeUserID, "1999999882"}} {
|
||||
}{{frozenUserID, "1999999881"}, {activeUserID, "1999999882"}, {observerID, "1999999883"}} {
|
||||
if _, err := tx.Exec(ctx, `
|
||||
INSERT INTO users (id, access_hash, phone, first_name)
|
||||
VALUES ($1, $1, $2, 'Freeze migration test')`, user.id, user.phone); err != nil {
|
||||
|
|
@ -60,10 +61,32 @@ VALUES ($1, true, 'legacy freeze', 'ops', 'legacy-freeze', $2)`, frozenUserID, l
|
|||
t.Fatalf("GetAccountFreeze migrated = %+v found=%v err=%v", migrated, found, err)
|
||||
}
|
||||
if !migrated.Frozen || !migrated.Since.Equal(legacyUpdatedAt) ||
|
||||
!migrated.Until.Equal(legacyUpdatedAt.Add(7*24*time.Hour)) || migrated.AppealURL != "https://t.me/SpamBot" {
|
||||
!migrated.Until.Equal(legacyUpdatedAt.Add(7*24*time.Hour)) || migrated.AppealURL != "https://t.me/SpamBot" || migrated.Version != 1 {
|
||||
t.Fatalf("migrated freeze = %+v", migrated)
|
||||
}
|
||||
|
||||
if _, err := tx.Exec(ctx, `
|
||||
INSERT INTO contacts (user_id, contact_user_id, contact_first_name)
|
||||
VALUES ($1, $2, 'Visible frozen peer')`, observerID, activeUserID); err != nil {
|
||||
t.Fatalf("insert observer contact: %v", err)
|
||||
}
|
||||
if _, err := tx.Exec(ctx, `
|
||||
INSERT INTO dialogs (user_id, peer_type, peer_id, top_message_id, top_message_date)
|
||||
VALUES ($1, 'user', $2, 1, 100)`, observerID, activeUserID); err != nil {
|
||||
t.Fatalf("insert observer dialog: %v", err)
|
||||
}
|
||||
var contactVersionBefore, dialogVersionBefore int64
|
||||
if err := tx.QueryRow(ctx, `
|
||||
SELECT version FROM read_model_versions
|
||||
WHERE model = 'contact_account' AND owner_user_id = $1 AND peer_type = 'user' AND peer_id = $1`, observerID).Scan(&contactVersionBefore); err != nil {
|
||||
t.Fatalf("read initial contact projection version: %v", err)
|
||||
}
|
||||
if err := tx.QueryRow(ctx, `
|
||||
SELECT version FROM read_model_versions
|
||||
WHERE model = 'dialog_light' AND owner_user_id = $1 AND peer_type = 'user' AND peer_id = $2`, observerID, activeUserID).Scan(&dialogVersionBefore); err != nil {
|
||||
t.Fatalf("read initial dialog projection version: %v", err)
|
||||
}
|
||||
|
||||
since := time.Date(2026, 7, 15, 2, 0, 0, 0, time.UTC)
|
||||
want := domain.AccountFreeze{
|
||||
UserID: activeUserID,
|
||||
|
|
@ -75,21 +98,80 @@ VALUES ($1, true, 'legacy freeze', 'ops', 'legacy-freeze', $2)`, frozenUserID, l
|
|||
Actor: "ops",
|
||||
CommandID: "freeze-round-trip",
|
||||
}
|
||||
if _, err := store.SetAccountFreeze(ctx, want); err != nil {
|
||||
updated, err := store.SetAccountFreeze(ctx, want)
|
||||
if err != nil {
|
||||
t.Fatalf("SetAccountFreeze active: %v", err)
|
||||
}
|
||||
if updated.Version != 1 {
|
||||
t.Fatalf("first freeze version = %d, want 1", updated.Version)
|
||||
}
|
||||
got, found, err := store.GetAccountFreeze(ctx, activeUserID)
|
||||
if err != nil || !found || !got.Frozen || !got.Since.Equal(want.Since) ||
|
||||
!got.Until.Equal(want.Until) || got.AppealURL != want.AppealURL {
|
||||
!got.Until.Equal(want.Until) || got.AppealURL != want.AppealURL || got.Version != 1 {
|
||||
t.Fatalf("active round trip = %+v found=%v err=%v", got, found, err)
|
||||
}
|
||||
if _, err := store.SetAccountFreeze(ctx, domain.AccountFreeze{
|
||||
var contactVersionAfter, dialogVersionAfter, visibilityVersion int64
|
||||
if err := tx.QueryRow(ctx, `
|
||||
SELECT version FROM read_model_versions
|
||||
WHERE model = 'contact_account' AND owner_user_id = $1 AND peer_type = 'user' AND peer_id = $1`, observerID).Scan(&contactVersionAfter); err != nil {
|
||||
t.Fatalf("read frozen contact projection version: %v", err)
|
||||
}
|
||||
if err := tx.QueryRow(ctx, `
|
||||
SELECT version FROM read_model_versions
|
||||
WHERE model = 'dialog_light' AND owner_user_id = $1 AND peer_type = 'user' AND peer_id = $2`, observerID, activeUserID).Scan(&dialogVersionAfter); err != nil {
|
||||
t.Fatalf("read frozen dialog projection version: %v", err)
|
||||
}
|
||||
if contactVersionAfter <= contactVersionBefore || dialogVersionAfter <= dialogVersionBefore {
|
||||
t.Fatalf("projection versions contact %d->%d dialog %d->%d, want increments",
|
||||
contactVersionBefore, contactVersionAfter, dialogVersionBefore, dialogVersionAfter)
|
||||
}
|
||||
if err := tx.QueryRow(ctx, `
|
||||
SELECT version FROM read_model_versions
|
||||
WHERE model = 'user_visibility' AND owner_user_id = 0 AND peer_type = 'user' AND peer_id = $1`, activeUserID).Scan(&visibilityVersion); err != nil || visibilityVersion != 1 {
|
||||
t.Fatalf("user visibility version = %d err=%v, want 1", visibilityVersion, err)
|
||||
}
|
||||
|
||||
claimAt := time.Now().UTC().Add(time.Minute)
|
||||
claimed, err := store.ClaimAccountFreezeNotifications(ctx, claimAt, 10, time.Minute)
|
||||
if err != nil || len(claimed) != 1 {
|
||||
t.Fatalf("claim frozen notification = %+v err=%v, want one", claimed, err)
|
||||
}
|
||||
oldNotification := claimed[0]
|
||||
if oldNotification.TargetUserID != observerID || oldNotification.FrozenUserID != activeUserID || !oldNotification.Frozen || oldNotification.Version != 1 {
|
||||
t.Fatalf("frozen notification = %+v", oldNotification)
|
||||
}
|
||||
|
||||
updated, err = store.SetAccountFreeze(ctx, domain.AccountFreeze{
|
||||
UserID: activeUserID, Reason: "appeal accepted", Actor: "ops", CommandID: "unfreeze-round-trip",
|
||||
}); err != nil {
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("SetAccountFreeze inactive: %v", err)
|
||||
}
|
||||
if updated.Version != 2 {
|
||||
t.Fatalf("unfreeze version = %d, want 2", updated.Version)
|
||||
}
|
||||
// A worker that claimed v1 before the unfreeze cannot acknowledge the
|
||||
// coalesced v2 row and suppress its online refresh.
|
||||
if err := store.CompleteAccountFreezeNotification(ctx, oldNotification.ID, oldNotification.Version, claimAt); err != nil {
|
||||
t.Fatalf("complete stale notification: %v", err)
|
||||
}
|
||||
claimed, err = store.ClaimAccountFreezeNotifications(ctx, claimAt.Add(time.Minute), 10, time.Minute)
|
||||
if err != nil || len(claimed) != 1 {
|
||||
t.Fatalf("claim unfreeze notification = %+v err=%v, want one", claimed, err)
|
||||
}
|
||||
newNotification := claimed[0]
|
||||
if newNotification.ID != oldNotification.ID || newNotification.Version != 2 || newNotification.Frozen {
|
||||
t.Fatalf("coalesced unfreeze notification = %+v, previous=%+v", newNotification, oldNotification)
|
||||
}
|
||||
if err := store.CompleteAccountFreezeNotification(ctx, newNotification.ID, newNotification.Version, claimAt.Add(2*time.Minute)); err != nil {
|
||||
t.Fatalf("complete unfreeze notification: %v", err)
|
||||
}
|
||||
var notificationStatus string
|
||||
if err := tx.QueryRow(ctx, `SELECT status FROM account_freeze_notifications WHERE id = $1`, newNotification.ID).Scan(¬ificationStatus); err != nil || notificationStatus != "delivered" {
|
||||
t.Fatalf("notification status = %q err=%v, want delivered", notificationStatus, err)
|
||||
}
|
||||
got, found, err = store.GetAccountFreeze(ctx, activeUserID)
|
||||
if err != nil || !found || got.Frozen || !got.Since.IsZero() || !got.Until.IsZero() || got.AppealURL != "" {
|
||||
if err != nil || !found || got.Frozen || !got.Since.IsZero() || !got.Until.IsZero() || got.AppealURL != "" || got.Version != 2 {
|
||||
t.Fatalf("inactive round trip = %+v found=%v err=%v", got, found, err)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue