package postgres import ( "context" "errors" "reflect" "testing" "time" ) func TestChangeOwnPasswordLocksVerifiesUpdatesAndRefreshesSnapshot(t *testing.T) { now := time.Date(2026, 8, 13, 12, 0, 0, 0, time.UTC) hash := nodeCompatibleHash(t, "current-password", "salt") tx := &loginTransaction{queries: []loginQueryResult{ {rows: loginRows([]any{"user-1", "13800138000", "User", "user", "org-1", "active", hash, "salt", 4})}, {rows: loginRows([]any{"user-1", "13800138000", "User", "user", "org-1", "active", 5})}, {rows: loginRows([]any{"org-1", "Acme", "active"})}, }} got, err := loginDatabase(tx).ChangeOwnPassword(context.Background(), "user-1", "current-password", "next-password", now) if err != nil { t.Fatal(err) } if got.Account.SessionVersion != 5 || got.Organization == nil || got.Organization.Name != "Acme" || tx.commits != 1 { t.Fatalf("snapshot=%#v commits=%d", got, tx.commits) } if tx.queriesSeen[0].sql != SelectPasswordChangeAccountSQL || tx.queriesSeen[1].sql != UpdatePasswordChangeAccountSQL || tx.queriesSeen[2].sql != SelectPasswordLoginOrganizationSQL { t.Fatalf("queries=%#v", tx.queriesSeen) } if !reflect.DeepEqual(tx.queriesSeen[0].args, []any{"user-1"}) { t.Fatalf("args=%#v", tx.queriesSeen[0].args) } } func TestChangeOwnPasswordRejectsCurrentPasswordAndRollsBack(t *testing.T) { tx := &loginTransaction{queries: []loginQueryResult{{rows: loginRows([]any{"u", "p", "N", "super_admin", nil, "active", nodeCompatibleHash(t, "right", "salt"), "salt", 1})}}} _, err := loginDatabase(tx).ChangeOwnPassword(context.Background(), "u", "wrong", "next-password", time.Now()) if err == nil || tx.commits != 0 || tx.rollbacks != 1 || len(tx.queriesSeen) != 1 { t.Fatalf("err=%v tx=%#v", err, tx) } } func TestChangeOwnPasswordRollsBackInfrastructureFailure(t *testing.T) { tx := &loginTransaction{queries: []loginQueryResult{{err: errors.New("boom")}}} _, err := loginDatabase(tx).ChangeOwnPassword(context.Background(), "u", "old-password", "next-password", time.Now()) if err == nil || tx.rollbacks != 1 { t.Fatalf("err=%v rollbacks=%d", err, tx.rollbacks) } }