Skip to content

Fix GET /reputation/me — unreachable route and missing auth guard#122

Open
BrayanMQ wants to merge 2 commits into
TrustUp-app:mainfrom
BrayanMQ:fix/issue-115-reputation-me-route
Open

Fix GET /reputation/me — unreachable route and missing auth guard#122
BrayanMQ wants to merge 2 commits into
TrustUp-app:mainfrom
BrayanMQ:fix/issue-115-reputation-me-route

Conversation

@BrayanMQ

Copy link
Copy Markdown
Contributor

🔗 Related Issue

Closes #115


🔖 Title

Fix GET /reputation/me — unreachable route and missing auth guard


📝 Description

GET /reputation/me was permanently unreachable and would not have worked even if reached, due to two separate bugs:

  1. Route ordering@Get(':wallet') was declared before @Get('me'), so Fastify matched /reputation/me against the :wallet handler first. The wallet regex rejects "me", so the endpoint always 400'd.
  2. Missing auth guard — the handler read req.user?.wallet directly with no @UseGuards(JwtAuthGuard), so req.user was always undefined and the endpoint always threw UnauthorizedException.

🔄 Changes Made

  • Moved @Get('me') above @Get(':wallet') in reputation.controller.ts
  • Added @UseGuards(JwtAuthGuard) + @ApiBearerAuth() to GET /reputation/me
  • Replaced raw @Request() req with @CurrentUser() user, matching the GET /users/me pattern
  • Imported PassportModule and JwtModule in reputation.module.ts
  • Updated reputation.controller.spec.ts: authenticated call returns score, guard-mocked, errors propagate
  • Updated reputation.e2e-spec.ts: valid token → 200, no token → 401, malformed header → 401, route precedence (/me not swallowed by :wallet)

📸 Screenshots (if applicable)

N/A — backend-only change, no UI impact.


✅ Test Evidence

Unit tests (npx jest) — full suite, no regressions:

Test Suites: 18 passed, 18 total
Tests:       228 passed, 228 total
Time:        13.368 s

Reputation unit tests (npx jest reputation):

PASS test/unit/modules/reputation/reputation.controller.spec.ts
PASS test/unit/modules/reputation/reputation.service.spec.ts
Test Suites: 2 passed, 2 total
Tests:       19 passed, 19 total

Reputation e2e tests (npx jest --config ./test/jest-e2e.json reputation):

GET /reputation/:wallet
  × should return 200 with reputation data for a valid wallet
  × should return 200 with default score when wallet has no on-chain data
  √ should return 400 for an invalid wallet address
  √ should return 400 for a wallet that does not start with G
  × should return 500 when the blockchain RPC is unavailable
GET /reputation/me
  √ should return 200 with reputation data when a valid token is provided
  √ should return 401 when no token is provided
  √ should return 401 when Authorization header is malformed
  √ should not be captured by the :wallet route (route precedence)

Tests: 3 failed, 6 passed, 9 total

All 6 /reputation/me cases (the scope of this issue) pass. The 3 failures under GET /reputation/:wallet are pre-existing on main — the test file mocks ReputationContractClient/SorobanService, but ReputationService.getReputationScore actually derives the score from an internal deterministic hash and never calls those clients. Confirmed by running the same suite against main before this branch's changes — identical 3 failures. Out of scope for this issue; left untouched to avoid scope creep.


🗒️ Additional Notes

  • PassportModule/JwtModule were added to reputation.module.ts per the issue checklist. Functionally, AuthGuard('jwt') already works without them (the 'jwt' Passport strategy registers globally once AuthModule loads in AppModule — this is why UsersModule works without importing them), but they're included explicitly per the issue's acceptance criteria and for clarity/robustness.
  • No changes made to lint config — npm run lint currently fails on main itself (ESLint couldn't find a configuration file), unrelated to this PR.

BrayanMQ added 2 commits July 16, 2026 23:45
Move the me route above :wallet so it is no longer swallowed by the
wallet param matcher, and add JwtAuthGuard + CurrentUser so the
handler actually receives an authenticated wallet instead of always
throwing UnauthorizedException.
Update unit and e2e specs to mock JwtAuthGuard the same way
users.controller does, and assert that GET /reputation/me returns
score for an authenticated caller, 401 without a token, and is never
captured by the :wallet route.
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.

fix(security): GET /reputation/me unreachable due to route order and missing JwtAuthGuard

1 participant