refactor(store): wave B.12 — user repo (#267)#268
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (26)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (25)
📝 WalkthroughWalkthroughThis PR migrates user data access from query-based projections (store.Queries()) to a new repository abstraction (store.Repos().User): adds store.User types and UserRepo interface, implements a Postgres-backed UserRepo, wires it into store.Repos, and updates handlers, SCIM code, system actions, and tests to use the repository methods. ChangesUser Repository Migration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
cmd/control/admin_user.go (1)
23-27:⚠️ Potential issue | 🟠 Major | ⚡ Quick winHandle non-not-found lookup errors before creating the bootstrap admin.
Line 23 currently treats every
GetByEmailerror as “user does not exist” and continues with creation. That can create duplicate bootstrap attempts or mask DB/repo failures. Only proceed on explicit not-found; return other errors.Proposed fix
import ( "context" + "errors" "fmt" "log/slog" urlpkg "net/url" @@ _, err := st.Repos().User.GetByEmail(ctx, email) if err == nil { logger.Info("admin user already exists", "email", email) return nil } + if !errors.Is(err, store.ErrNotFound) { + return fmt.Errorf("lookup admin user by email: %w", err) + } // Create admin user via event sourcing🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@cmd/control/admin_user.go` around lines 23 - 27, The code assumes any error from st.Repos().User.GetByEmail(ctx, email) means the user is missing; change the logic to first check the error and only proceed to create the bootstrap admin when the error is an explicit "not found" case (use the repository's not-found sentinel or errors.Is check against the repo/sql not-found value used in your project); if err != nil and is not a not-found error, return that error immediately instead of continuing to creation; keep the existing logger.Info("admin user already exists", "email", email) path when GetByEmail returns nil and reference GetByEmail and the repo's not-found sentinel in your check.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@cmd/control/admin_user.go`:
- Around line 23-27: The code assumes any error from
st.Repos().User.GetByEmail(ctx, email) means the user is missing; change the
logic to first check the error and only proceed to create the bootstrap admin
when the error is an explicit "not found" case (use the repository's not-found
sentinel or errors.Is check against the repo/sql not-found value used in your
project); if err != nil and is not a not-found error, return that error
immediately instead of continuing to creation; keep the existing
logger.Info("admin user already exists", "email", email) path when GetByEmail
returns nil and reference GetByEmail and the repo's not-found sentinel in your
check.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 1951261d-2b90-4ca4-a848-64c4fbcb73e2
📒 Files selected for processing (26)
cmd/control/admin_user.gointernal/api/assignment_handler.gointernal/api/auth_handler.gointernal/api/identity_link_handler.gointernal/api/settings_handler.gointernal/api/sso_handler.gointernal/api/system_actions.gointernal/api/system_actions_manager_test.gointernal/api/system_actions_params_canary_test.gointernal/api/terminal_handler.gointernal/api/token_handler.gointernal/api/totp_handler.gointernal/api/user_group_handler.gointernal/api/user_handler.gointernal/scim/groups_helpers.gointernal/scim/handler.gointernal/scim/handler_test.gointernal/scim/users.gointernal/scim/users_create.gointernal/scim/users_helpers.gointernal/scim/users_mutate.gointernal/scim/users_translation.gointernal/store/postgres/user.gointernal/store/postgres/wire.gointernal/store/repos.gointernal/store/user.go
UserRepo — the biggest single-domain migration. Covers the core user-projection reads: Get / GetByEmail / SessionInfo / Permissions / NextLinuxUID / List / Count / ListAllNonDeleted The narrow SessionInfo shape (Disabled / SessionVersion / IsDeleted) keeps the hot refresh-token validation path light. Permissions returns the flattened permission list combining direct role permissions + user-group inheritance. Call sites migrated (~70 across 21 files): - api: user_handler (8), auth_handler (3), sso_handler (2), totp_handler (3), settings_handler (2), system_actions (3) + test sites, terminal_handler, token_handler, identity_link_handler, assignment_handler, user_group_handler - scim: users, users_create, users_helpers, users_mutate, users_translation, handler (interface) - idp: linker, linker_test - control: admin_user Signatures shifted: - userToProto: db.UsersProjection -> store.User - userToSCIM: db.UsersProjection -> store.User - SystemActionsCleaner.CleanupDeletedUserActions: db.UsersProjection -> store.User (interface + tests + fake) - 6 system-action helpers (sync/cleanup user / ssh / tty) + systemTtyUserParams Field rename: LinuxUid (sqlc) -> LinuxUID (domain). SshPublicKeys stays as json.RawMessage at the boundary per the JSONB normalize plan in #242. Closes #267.
ecd4beb to
f93af48
Compare
Summary
Biggest single-domain migration in Wave B. `UserRepo` covers the core user-projection reads consumed across 21 files. Branches off main directly.
Methods
Call sites migrated (~70)
Signatures shifted
Field renames
`LinuxUid` → `LinuxUID` at the domain type. `SshPublicKeys` stays as `json.RawMessage` at the boundary per the JSONB normalize plan.
Non-goals
Acceptance
Part of #242. Closes #267.
Summary by CodeRabbit