Skip to content

feat(users): add listOrgUsers, createUser, updateUser, deleteUser repository functions#791

Merged
aaight merged 1 commit intodevfrom
feature/users-repository-crud
Mar 14, 2026
Merged

feat(users): add listOrgUsers, createUser, updateUser, deleteUser repository functions#791
aaight merged 1 commit intodevfrom
feature/users-repository-crud

Conversation

@aaight
Copy link
Copy Markdown
Collaborator

@aaight aaight commented Mar 14, 2026

Summary

  • Extends src/db/repositories/usersRepository.ts with four new CRUD functions: listOrgUsers, createUser, updateUser, deleteUser
  • Mirrors the existing credentialsRepository.ts pattern — standalone async functions using getDb(), org-scoped queries
  • listOrgUsers selects id, orgId, email, name, role, createdAt, updatedAt and intentionally omits passwordHash
  • createUser accepts a pre-hashed password (bcrypt hashing is the caller's responsibility) and returns { id }
  • updateUser performs a sparse update (only provided fields), always sets updatedAt
  • deleteUser deletes by id; sessions auto-cascade via existing ON DELETE CASCADE FK constraint
  • All existing functions (getUserByEmail, getUserById, createSession, etc.) remain unchanged

Test plan

  • 19 unit tests covering all new and existing functions pass
  • TypeScript type checking passes (zero errors)
  • Biome linting passes (zero errors)
  • Tests verify listOrgUsers does not include passwordHash in results
  • Tests verify updateUser sets updatedAt on every call
  • Tests verify createUser stores pre-hashed password as-is

Trello card: https://trello.com/c/42kHRzay/320-as-an-admin-i-want-users-repository-crud-functions-so-that-the-data-layer-supports-user-management

🤖 Generated with Claude Code

Copy link
Copy Markdown
Collaborator

@nhopeatall nhopeatall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Clean implementation of CRUD repository functions following the established credentialsRepository pattern. All CI checks pass. The code is correct, consistent with existing patterns, and ready to merge.

Should Fix (non-blocking)

OrgUser.role typed as string instead of the domain union

src/db/repositories/usersRepository.ts:19OrgUser.role is typed as string, while the existing DashboardUser.role uses the union type 'member' | 'admin' | 'superadmin'. The same loose typing applies to createUser (line 118) and updateUser (line 138) params.

getUserById already validates roles at runtime with VALID_ROLES. The new functions skip that validation, which means callers can pass (or receive) arbitrary role strings without any type-level or runtime guard.

This isn't blocking — the schema column is text with no DB constraint, and the callers don't exist yet. But when the service/API layer is built on top, consider:

  • Extracting a shared UserRole type (e.g., type UserRole = 'member' | 'admin' | 'superadmin')
  • Using it for OrgUser.role, createUser.role, and updateUser.role
  • This gives compile-time safety and makes the valid values discoverable

Everything else looks good — sparse update pattern matches credentialsRepository.updateCredential, passwordHash is correctly excluded from listOrgUsers select, createUser properly delegates hashing to the caller, and delete/update-by-id without org-scoping is consistent with the existing credential CRUD pattern. Tests are well-structured using the shared mockDb helper.

@aaight aaight merged commit ab1c6ad into dev Mar 14, 2026
6 checks passed
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