Skip to content

fix(api): enforce account status per request, rate-limit auth, run tests in CI#48

Merged
aykhan019 merged 1 commit into
aykhan019:mainfrom
endorphin13:fix/api-hardening-and-ci-tests
May 31, 2026
Merged

fix(api): enforce account status per request, rate-limit auth, run tests in CI#48
aykhan019 merged 1 commit into
aykhan019:mainfrom
endorphin13:fix/api-hardening-and-ci-tests

Conversation

@endorphin13

Copy link
Copy Markdown
Contributor

Why

Four related backend/CI gaps surfaced in review.

What changed

  • Banned/deleted access window (BE-1). JwtAuthGuard only verified the JWT signature, so a banned or self-deleted user kept full API access until their access token expired (~15 min); banning/deleting only revoked refresh tokens. The guard now re-loads the account on every request (findUserById, which filters deletedAt/bannedAt) and rejects it if it's gone. Identity — including role — is now read fresh from the DB, so a revoked admin role also takes effect immediately.
  • No auth rate limiting (BE-2). Added @nestjs/throttler (global 100/min, with 5/min register, 10/min login, 30/min refresh) and helmet security headers. This bounds brute-force/credential-stuffing and the unbounded audit_log growth from failed logins.
  • Email conflict 500 (BE-3). findUserByEmail excludes soft-deleted/banned rows, so re-registering (or switching to) a soft-deleted account's email slipped past the existence check and hit the unique constraint as an opaque 500. Now the Prisma P2002 is caught on register and profile update and returned as 409 EMAIL_TAKEN.
  • CI never ran tests (CI-1). The workflow provisioned Postgres and test env vars but only ran typecheck/lint/format/build. Added a Test step running pnpm test.

Verification

  • pnpm typecheck clean across all workspaces.
  • pnpm test295 passing (api 162 incl. a new guard ban-rejection test, web 61, db 72).
  • eslint clean on changed files.

…sts in CI

- Banned/soft-deleted access window (BE-1): JwtAuthGuard now re-loads the
  account on every request and rejects banned or soft-deleted users, so a
  still-valid access token can no longer outlive a ban/delete. Identity
  (including role) is read fresh from the DB rather than the token payload.
- Rate limiting (BE-2): add @nestjs/throttler (global 100/min, with 5/min on
  register, 10/min on login, 30/min on refresh) and helmet security headers.
- Email conflict 500 (BE-3): catch the Prisma unique-email violation (P2002)
  on register and profile update and return 409 EMAIL_TAKEN. findUserByEmail
  filters out soft-deleted/banned rows, so a soft-deleted account's email
  slipped past the pre-check and hit the DB constraint as an opaque 500.
- CI: add a Test step so the vitest suite (~295 tests across api/web/db)
  actually runs; CI provisioned Postgres and test env but never ran tests.
@endorphin13 endorphin13 requested a review from aykhan019 as a code owner May 31, 2026 18:14
@vercel

vercel Bot commented May 31, 2026

Copy link
Copy Markdown

@fateh-mammadli is attempting to deploy a commit to the Aykhan's projects Team on Vercel.

A member of the Team first needs to authorize it.

@aykhan019 aykhan019 merged commit 14c0ed1 into aykhan019:main May 31, 2026
1 of 2 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.

3 participants