Commit Graph

64 Commits

Author SHA1 Message Date
Ho Ngoc Hai
8705a2d9a8 fix: resolve all ESLint errors across API and web packages
Fix 19+ lint errors: unused imports (Phone, DuplicateCandidate, listingDetailsSchema),
import ordering violations, consistent-type-imports, and constant binary expression
in test file.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 16:29:44 +07:00
Ho Ngoc Hai
23bb380d34 feat(auth): implement Google and Zalo OAuth backend strategies
Add complete OAuth2 authentication flow for Google and Zalo providers:
- OAuthService: handles account linking (by email/phone), new user
  creation for OAuth-only accounts, and JWT token generation
- GoogleOAuthStrategy: passport-google-oauth20 integration
- ZaloOAuthStrategy: custom OAuth2 implementation using Zalo's API
  (authorization URL generation, code exchange, user info fetch)
- OAuthController: redirect and callback endpoints for both providers
  with httpOnly cookie-based token management
- Unit tests for OAuthService (7 tests), GoogleOAuthStrategy (4 tests),
  and ZaloOAuthStrategy (7 tests)
- OAuth env vars added to .env.example and env-validation warnings

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 14:14:02 +07:00
Ho Ngoc Hai
bac3313873 test(auth,payments,subs): add 58 unit tests for critical auth, payment, and subscription paths
Cover auth handlers (RegisterUser, LoginUser, RefreshToken), TokenService
(token rotation, reuse attack detection), payment callback edge cases
(duplicate/concurrent callbacks, multi-provider), subscription lifecycle
transitions (expire, pastDue, renew), and throttler proxy guard.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 13:49:19 +07:00
Ho Ngoc Hai
cc5c81904b fix(lint): resolve all 49 lint warnings and errors across codebase
- Remove unused imports/variables in seed scripts and test files
- Replace console.log with console.warn in seed/utility scripts
- Replace `as any` with proper Prisma types (InputJsonValue, PaymentStatus, Plan, UserWhereInput)
- Fix import-x/no-named-as-default-member warnings in logger, mapbox, eslint config
- Prefix unused callback params with underscore in e2e tests

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 13:22:07 +07:00
Ho Ngoc Hai
2502aa69b7 fix: production readiness — resolve build, lint, and code quality issues
- Fix Next.js build failure: remove duplicate route at (dashboard)/listings/[id]
  that conflicted with (public)/listings/[id] (same URL path in two route groups)
- Fix 772 ESLint errors: auto-fix import ordering (import-x/order), remove unused
  imports/variables, convert empty interfaces to type aliases, replace require()
  with ESM imports, fix consistent-type-imports violations
- Add CLAUDE.md for developer onboarding documentation
- All checks pass: 0 lint errors, typecheck clean, 230 tests passing, build success

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 07:15:06 +07:00
Ho Ngoc Hai
e9889539ea fix: eliminate untyped repository returns and standardize DomainException usage across all handlers
- Create typed DTOs (ListingDetailData, ListingSearchItem, ListingSellerItem) for repository read methods
- Replace all Promise<any> and PaginatedResult<any> with concrete types in repository interface and implementation
- Remove `as any` casts in search params by using Prisma enum types (TransactionType, PropertyType)
- Migrate all 16 handlers from NestJS built-in exceptions to domain exceptions (NotFoundException, ValidationException, etc.)
- Add CONTRIBUTING.md documenting error handling convention
- All 230 tests pass, typecheck clean

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 06:25:44 +07:00
Ho Ngoc Hai
6389dcf78e fix(auth): migrate tokens from localStorage to httpOnly cookies + CSRF hardening
Backend:
- Auth controller sets httpOnly secure cookies (access_token, refresh_token, goodgo_authenticated) on login/register/refresh
- JWT strategy reads token from cookie first, falls back to Authorization header
- Added POST /auth/logout to clear auth cookies
- Added POST /auth/exchange-token for OAuth callback token-to-cookie exchange
- Refresh endpoint reads refresh_token from cookie (body fallback for backwards compat)
- CSRF middleware excludes auth endpoints (login, register, refresh, exchange-token, logout)

Frontend:
- Removed all localStorage token storage (goodgo_tokens key)
- Removed authGet/authPost/authPatch helpers from api-client (tokens sent via cookies)
- All API calls use credentials:'include' for cookie-based auth
- Updated auth-store: no more token state, uses isAuthenticated flag from cookie
- Updated admin-api, listings-api to remove explicit token parameters
- Updated all pages (admin dashboard, users, KYC, moderation, listings) to remove token passing
- OAuth callbacks use exchange-token endpoint to convert URL tokens to cookies
- Auth provider simplified (no client-side cookie management needed)

Security improvements:
- JWT no longer accessible via JavaScript (XSS-safe)
- Refresh token scoped to /auth path only
- Server-side goodgo_authenticated cookie with SameSite=Lax
- Access token cookie with SameSite=Strict

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 06:25:11 +07:00
Ho Ngoc Hai
be0deddeed fix(security): harden auth — rate limiting, admin audit logging, JWT aud/iss
- Add @Throttle (5 req/hour per IP) on register, login, refresh endpoints
- Add audit logging in RolesGuard for failed admin access attempts (userId, role, IP, action)
- Add audience ('goodgo-api') and issuer ('goodgo-platform') claims to JWT tokens
- Validate aud/iss in JwtStrategy to prevent cross-service token reuse

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 06:17:02 +07:00
Ho Ngoc Hai
271ad76e6f fix: resolve E2E test failures and API runtime issues for Docker dev environment
- Fix DI issues: circular MCP module dependency, EventBus type import,
  SearchModule provider, CacheService metric counters placement
- Fix Express 5 readonly req.query in SanitizeInputMiddleware
- Fix Typesense client lazy initialization (getter instead of constructor)
- Fix MinIO bucket init error handling (non-fatal on 403)
- Fix missing class-validator decorators on bigint DTO fields (priceVND, amountVND)
- Fix subscription plan 404 (was returning 500 for invalid tier)
- Disable CSRF and raise rate limits in test environment
- Update E2E tests to match actual API response shapes
- Update CI workflow with Redis, Typesense, MinIO services and env vars

All 101 API E2E tests now pass against Docker dev environment.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 05:44:00 +07:00
Ho Ngoc Hai
2a392525a2 feat(cache): implement Redis caching layer for hot-read endpoints
Add cache-aside pattern for listing detail, search results, market
analytics (4 endpoints), and user profile queries. Cache invalidation
on all write mutations. Prometheus cache_hit_total/cache_miss_total
metrics with resource labels.

- CacheService: getOrSet, invalidate, invalidateByPrefix (SCAN-based)
- TTLs: listing 5m, search 1m, market 30m, profile 10m
- All 230 tests passing (13 new cache tests + 6 updated handler tests)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 04:14:06 +07:00
Ho Ngoc Hai
8e7672694b feat(api): add OpenAPI/Swagger documentation for all API endpoints
Install @nestjs/swagger, configure Swagger UI at /api/docs with JWT bearer
auth, and add ApiTags/ApiOperation/ApiResponse/ApiProperty decorators to
all 8 controllers (50+ endpoints) and 31 DTOs across auth, listings,
search, payments, subscriptions, admin, notifications, and analytics modules.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 04:08:11 +07:00
Ho Ngoc Hai
402b5b6810 fix(auth): remove hardcoded JWT fallback secret — fail fast on missing env var
The auth module fell back to a publicly-known secret string when JWT_SECRET
was unset, creating a critical authentication bypass risk. Both jwt.strategy.ts
and auth.module.ts now throw at startup if JWT_SECRET is missing.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 04:01:21 +07:00
Ho Ngoc Hai
dafed32e11 feat(admin): add Admin module with moderation, user mgmt, and dashboard
- Commands: ApproveListing, RejectListing, BanUser, AdjustSubscription
- Queries: GetModerationQueue, GetDashboardStats, GetRevenueStats
- Admin-only guards via @Roles('ADMIN') on all endpoints
- Prisma-based admin query repository for dashboard aggregations
- 14 unit tests covering all command handlers and query handlers
- Added activate() method to UserEntity for unban support

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 02:17:09 +07:00
Ho Ngoc Hai
391c040100 feat(auth): implement Auth module with register, login, JWT, guards, and CQRS
- Add RefreshToken and OAuthAccount models to Prisma schema
- Implement clean architecture: domain (entities, VOs, events, repo interfaces),
  infrastructure (Prisma repos, Passport strategies, token service),
  application (CQRS command/query handlers), presentation (controller, guards, DTOs)
- Endpoints: POST /auth/register, /auth/login, /auth/refresh, GET /auth/profile,
  GET /auth/profile/agent, PATCH /auth/kyc
- JWT access + refresh token rotation with family-based revocation
- Role-based guards (BUYER, SELLER, AGENT, ADMIN)
- 16 unit tests (value objects, entity) + integration test suite
- All 80 tests passing, clean TypeScript build

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 00:24:42 +07:00