Skip to content

feat(store): user delete keeps the row - #2023

Open
AmanGIT07 wants to merge 2 commits into
fix/user-delete-removes-every-policyfrom
feat/user-delete-keeps-the-row
Open

AmanGIT07 wants to merge 2 commits into
fix/user-delete-removes-every-policyfrom
feat/user-delete-keeps-the-row

Conversation

@AmanGIT07

@AmanGIT07 AmanGIT07 commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #2022. Merge #2022 and #2024 first.

Summary

Deleting a user now keeps the user row and sets deleted_at, like the other soft deletes. The user.deleted audit record takes its time from deleted_at. The organization PAT search now lists a PAT only when its owner is live.

Changes

  • internal/store/postgres/user_repository.go: Delete sets deleted_at on the live row instead of deleting it. It still returns the row and writes the user.deleted record in the same transaction, now with occurred_at equal to deleted_at. A second delete answers user.ErrNotExist.
  • internal/store/postgres/org_pats_repository.go: the main query inner joins users on the PAT owner with users.deleted_at IS NULL, instead of a left join. The count and the list both skip a PAT whose owner is deleted.

Technical Details

  • Every read in the user repository already skips deleted rows, so a deleted user answers not found everywhere, as before.
  • The email and name unique indexes cover live rows only, so a new account can use a deleted user's email and name.
  • The organization PAT search was the only query that joined users without the live filter. user_pats.user_id is NOT NULL and references users, so every PAT has an owner row, and the inner join drops exactly the PATs whose owner is deleted. The user delete removes the user's PATs before the user row, so this only matters for a PAT created while a delete runs.

Known gap

sessions.user_id references users with ON DELETE CASCADE, so the hard delete removed the user's sessions with the row. The soft delete does not. Without #2024, a request with a deleted user's session cookie gets not found instead of unauthenticated. #2024 ends the sessions before the user row; merge it before this PR.

Test Plan

  • internal/store/postgres/user_repository_test.go TestDeleteKeepsTheRow: the row stays with deleted_at set, GetByID answers not found, a second delete answers user.ErrNotExist and writes no second record, the record's occurred_at equals deleted_at, and a new user can be created with the same email and name. With the hard delete back, the row check fails; with time.Now() back, the time check fails.
  • internal/store/postgres/org_pats_repository_test.go: the count and data queries contain the inner join with the live filter.
  • internal/store/postgres/org_pats_repository_pg_test.go: with one live and one soft-deleted owner, the list and the count return only the live owner's PAT, and a search for the deleted owner's name finds nothing. Both cases fail with the left join this PR replaces. With the live filter in the condition of a left join, the list case fails.
  • go test ./internal/store/postgres/... passes.
  • go test ./test/e2e/... passes.
  • golangci-lint run ./internal/store/postgres/... reports no issues.

SQL Safety

  • Values flow through goqu expressions: softDelete with goqu.Ex{"id": id}, and the join condition built with goqu.On, goqu.I and the live helper.
  • ToSQL() callers capture and forward params (query, params, err := stmt.ToSQL(); db.…Context(ctx, …, query, params...)). Never query, _, err := ….
  • No ? placeholders inside single-quoted SQL literals in goqu.L.
  • No new //nolint:forbidigo or // #nosec G20x annotations.

The user row gets deleted_at instead of being removed, and the user.deleted audit record takes its occurred_at from deleted_at. A second delete answers not found.
The search inner joins users with the live filter instead of a left join, so the list and the count skip a PAT whose owner is soft-deleted.
@vercel

vercel Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
frontier Ready Ready Preview Oct 25, 2026 7:55am UTC

@coderabbitai

coderabbitai Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 08ae2bc and dc6c8a8.

Files selected for processing: 5
  • internal/store/postgres/org_pats_repository.go
  • internal/store/postgres/org_pats_repository_pg_test.go
  • internal/store/postgres/org_pats_repository_test.go
  • internal/store/postgres/user_repository.go
  • internal/store/postgres/user_repository_test.go

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • Organization PAT searches now exclude tokens belonging to deleted users, and displayed result totals reflect only tokens owned by active users.
    • Deleting a user preserves the record as deleted rather than removing it permanently. Deleted users remain unavailable through lookup and deletion operations, and their name and email can be used to create a new user with a distinct identity.

User deletion now retains the user row as soft-deleted and uses its deletion timestamp in the audit record. Organization PAT searches exclude PATs owned by soft-deleted users from both results and counts.

Changes: User deletion and PAT search

Layer / File(s) Summary
User soft deletion and audit timestamp
internal/store/postgres/user_repository.go, internal/store/postgres/user_repository_test.go
Delete now uses soft deletion and records the row’s DeletedAt.Time. Tests verify row retention, subsequent lookup and deletion behavior, and recreation with the same name and email under a different ID.
Filter PATs by live owner
internal/store/postgres/org_pats_repository.go, internal/store/postgres/org_pats_repository_test.go, internal/store/postgres/org_pats_repository_pg_test.go
The shared PAT query joins only live users. Unit and PostgreSQL tests check that searches exclude PATs of soft-deleted users and return matching totals.

Priority: Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Feature · Severity of issue fixed: Low

Possibly related PRs

  • raystack/frontier#2022: Both changes update the user-deletion lifecycle. #2022 removes user policies before repository deletion, while this PR changes repository deletion to soft deletion and filters PAT search by owner status.

Suggested reviewers: kushsharma, rohanchkrabrty

Merge Risk: Minimal · up to dc6c8

User deletion now keeps the row and marks it deleted, and organization PAT searches omit PATs owned by deleted users. No concrete merge-blocking issue remains. The PR notes that it depends on being merged after #2022.

Pre-merge checks: Passed 2
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 40174593021

Coverage increased (+0.03%) to 55.77%

Details

  • Coverage increased (+0.03%) from the base build.
  • Patch coverage: 4 of 4 lines across 2 files are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 41929
Covered Lines: 23384
Line Coverage: 55.77%
Coverage Strength: 19.45 hits per line

💛 - Coveralls

This branch was successfully deployed

1 active deployment
Preview — dc6c8a85 Deployed Oct 25, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants