diff --git a/.github/workflows/api-test.yml b/.github/workflows/api-test.yml index 6cb8ca7..d4ab9a1 100644 --- a/.github/workflows/api-test.yml +++ b/.github/workflows/api-test.yml @@ -29,7 +29,7 @@ jobs: env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres - POSTGRES_DB: nginx_waf_test + POSTGRES_DB: nginx_waf ports: - 5432:5432 options: >- @@ -59,8 +59,7 @@ jobs: - name: Setup test environment working-directory: apps/api run: | - cp .env.test .env - echo "DATABASE_URL=postgresql://postgres:postgres@localhost:5432/nginx_waf_test?schema=public" >> .env + cp .env.example .env - name: Generate Prisma Client working-directory: apps/api @@ -70,13 +69,13 @@ jobs: working-directory: apps/api run: pnpm prisma migrate deploy env: - DATABASE_URL: postgresql://postgres:postgres@localhost:5432/nginx_waf_test?schema=public + DATABASE_URL: postgresql://postgres:postgres@localhost:5432/nginx_waf?schema=public - name: Run tests working-directory: apps/api run: pnpm test:coverage env: - DATABASE_URL: postgresql://postgres:postgres@localhost:5432/nginx_waf_test?schema=public + DATABASE_URL: postgresql://postgres:postgres@localhost:5432/nginx_waf?schema=public NODE_ENV: test JWT_ACCESS_SECRET: test-access-secret-key-12345 JWT_REFRESH_SECRET: test-refresh-secret-key-12345 diff --git a/apps/api/src/domains/auth/__tests__/auth.integration.test.ts b/apps/api/src/domains/auth/__tests__/auth.integration.test.ts index 94ac007..5711f95 100644 --- a/apps/api/src/domains/auth/__tests__/auth.integration.test.ts +++ b/apps/api/src/domains/auth/__tests__/auth.integration.test.ts @@ -31,6 +31,7 @@ describe('Auth Integration Tests', () => { fullName: 'Test User', role: 'admin', status: 'active', + isFirstLogin: false, }, }); testUserId = user.id; @@ -286,6 +287,7 @@ describe('Auth Integration Tests', () => { fullName: 'Test User 2FA', role: 'admin', status: 'active', + isFirstLogin: false, }, }); user2FAId = user.id; diff --git a/apps/api/src/domains/auth/__tests__/auth.service.test.ts b/apps/api/src/domains/auth/__tests__/auth.service.test.ts index 34560e1..da4e068 100644 --- a/apps/api/src/domains/auth/__tests__/auth.service.test.ts +++ b/apps/api/src/domains/auth/__tests__/auth.service.test.ts @@ -39,6 +39,7 @@ describe('AuthService', () => { phone: null, timezone: 'Asia/Ho_Chi_Minh', language: 'en', + isFirstLogin: false, lastLogin: null, createdAt: new Date(), updatedAt: new Date(), @@ -336,12 +337,18 @@ describe('AuthService', () => { vi.spyOn(authRepository, 'findRefreshToken').mockResolvedValue(mockTokenRecord); vi.spyOn(authRepository, 'isRefreshTokenValid').mockReturnValue(true); vi.spyOn(jwtUtil, 'generateAccessToken').mockReturnValue(mockAccessToken); + vi.spyOn(jwtUtil, 'generateRefreshToken').mockReturnValue('new-refresh-token'); + vi.spyOn(authRepository, 'saveRefreshToken').mockResolvedValue(undefined); + vi.spyOn(authRepository, 'revokeRefreshToken').mockResolvedValue(undefined); // Act const result = await authService.refreshAccessToken(refreshDto); // Assert - expect(result).toEqual({ accessToken: mockAccessToken }); + expect(result).toEqual({ + accessToken: mockAccessToken, + refreshToken: 'new-refresh-token' + }); }); it('should throw AuthenticationError for non-existent token', async () => { diff --git a/apps/api/src/utils/jwt.ts b/apps/api/src/utils/jwt.ts index 39958f6..8942512 100644 --- a/apps/api/src/utils/jwt.ts +++ b/apps/api/src/utils/jwt.ts @@ -1,4 +1,5 @@ import jwt, { SignOptions } from 'jsonwebtoken'; +import { randomUUID } from 'crypto'; import { config } from '../config'; export interface TokenPayload { @@ -15,7 +16,13 @@ export const generateAccessToken = (payload: TokenPayload): string => { }; export const generateRefreshToken = (payload: TokenPayload): string => { - return jwt.sign(payload, config.jwt.refreshSecret, { + // Add a cryptographically secure random jti (JWT ID) to ensure uniqueness + const payloadWithJti = { + ...payload, + jti: randomUUID(), + }; + + return jwt.sign(payloadWithJti, config.jwt.refreshSecret, { expiresIn: config.jwt.refreshExpiresIn, } as any); }; diff --git a/apps/api/vitest.setup.ts b/apps/api/vitest.setup.ts index de0b381..579b744 100644 --- a/apps/api/vitest.setup.ts +++ b/apps/api/vitest.setup.ts @@ -28,7 +28,7 @@ beforeAll(async () => { } catch (error: any) { console.error('❌ Failed to setup test database:', error.message); console.log('💡 Make sure PostgreSQL is running and test database exists.'); - console.log(' Create test database: createdb nginx_love_test'); + console.log(' Create test database: createdb nginx_waf_test'); // Don't throw - allow tests to run but they may fail } });