Set up PostgreSQL database configuration and enhance application structure
- Added .env.example with database connection details and JWT configuration. - Introduced docker-compose.yml for PostgreSQL service setup with health checks. - Created drizzle.config.ts for database schema and migration management. - Updated nest-cli.json to include Swagger plugin configuration for API documentation. - Enhanced package.json with new database-related scripts and dependencies. - Implemented initial database migrations for user and token management. - Configured application bootstrap process to load environment variables and set up Swagger. - Added shared application configuration in configure-app.ts for consistent setup. - Included unit tests for application configuration and Swagger setup.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import { UnauthorizedException } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { DateTime } from '../../../common/value-objects/date-time/date-time';
|
||||
import type { User } from '../../users/user';
|
||||
import { UsersService } from '../../users/users.service';
|
||||
import { RevokedAccessTokensRepository } from '../revoked-access-tokens.repository';
|
||||
import { JwtStrategy } from './jwt.strategy';
|
||||
|
||||
describe('JwtStrategy', () => {
|
||||
let strategy: JwtStrategy;
|
||||
let usersService: jest.Mocked<Pick<UsersService, 'findById'>>;
|
||||
let revoked: jest.Mocked<Pick<RevokedAccessTokensRepository, 'exists'>>;
|
||||
|
||||
const now = DateTime.fromUnixMs(1_700_000_000_000);
|
||||
const user: User = {
|
||||
id: 'user-1',
|
||||
username: 'alice',
|
||||
passwordHash: 'hash',
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
usersService = { findById: jest.fn() };
|
||||
revoked = { exists: jest.fn() };
|
||||
|
||||
const moduleRef: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
JwtStrategy,
|
||||
{
|
||||
provide: ConfigService,
|
||||
useValue: {
|
||||
getOrThrow: () => 'test-secret-at-least-32-characters-long!!',
|
||||
},
|
||||
},
|
||||
{ provide: UsersService, useValue: usersService },
|
||||
{ provide: RevokedAccessTokensRepository, useValue: revoked },
|
||||
],
|
||||
}).compile();
|
||||
|
||||
strategy = moduleRef.get(JwtStrategy);
|
||||
});
|
||||
|
||||
it('returns AuthUser for a valid access payload', async () => {
|
||||
revoked.exists.mockResolvedValue(false);
|
||||
usersService.findById.mockResolvedValue(user);
|
||||
|
||||
await expect(
|
||||
strategy.validate({
|
||||
sub: 'user-1',
|
||||
username: 'alice',
|
||||
jti: 'jti-1',
|
||||
typ: 'access',
|
||||
}),
|
||||
).resolves.toEqual({ id: 'user-1', username: 'alice', jti: 'jti-1' });
|
||||
});
|
||||
|
||||
it('rejects revoked access tokens', async () => {
|
||||
revoked.exists.mockResolvedValue(true);
|
||||
|
||||
await expect(
|
||||
strategy.validate({
|
||||
sub: 'user-1',
|
||||
username: 'alice',
|
||||
jti: 'jti-1',
|
||||
typ: 'access',
|
||||
}),
|
||||
).rejects.toBeInstanceOf(UnauthorizedException);
|
||||
});
|
||||
|
||||
it('rejects non-access token types', async () => {
|
||||
await expect(
|
||||
strategy.validate({
|
||||
sub: 'user-1',
|
||||
username: 'alice',
|
||||
jti: 'jti-1',
|
||||
typ: 'refresh' as 'access',
|
||||
}),
|
||||
).rejects.toBeInstanceOf(UnauthorizedException);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user