Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion server/src/database/database.module.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Test } from '@nestjs/testing';
import { ConfigModule as NestConfigModule } from '@nestjs/config';
import configuration from '../config/configuration';
import { DatabaseModule } from './database.module';
import { DatabaseModule, assertDatabaseUrlAllowed } from './database.module';
import { PrismaClient } from '../../generated/prisma/client';

/**
Expand Down Expand Up @@ -55,4 +55,39 @@ describe('DatabaseModule', () => {
expect(typeof client.$disconnect).toBe('function');
await moduleRef.close();
});

describe('assertDatabaseUrlAllowed', () => {
it('throws when URL is empty or undefined', () => {
expect(() => assertDatabaseUrlAllowed('', 'development')).toThrow(
/DATABASE_URL is not configured/,
);
expect(() => assertDatabaseUrlAllowed(undefined, 'development')).toThrow(
/DATABASE_URL is not configured/,
);
});

it('throws when URL is file: in production', () => {
expect(() =>
assertDatabaseUrlAllowed('file:./dev.db', 'production'),
).toThrow(/not allowed when NODE_ENV=production/);
});

it('does not throw when URL is file: in development or test', () => {
expect(() =>
assertDatabaseUrlAllowed('file:./dev.db', 'development'),
).not.toThrow();
expect(() =>
assertDatabaseUrlAllowed('file:./dev.db', 'test'),
).not.toThrow();
});

it('does not throw for non-file database URL in production', () => {
expect(() =>
assertDatabaseUrlAllowed(
'postgresql://user:pass@localhost:5432/db',
'production',
),
).not.toThrow();
});
});
});
10 changes: 9 additions & 1 deletion server/src/database/database.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@ import { PrismaPg } from '@prisma/adapter-pg';
* production, so a misconfigured deploy fails fast at startup instead of
* silently running against a throwaway local file.
*/
export function assertDatabaseUrlAllowed(url: string, nodeEnv: string): void {
export function assertDatabaseUrlAllowed(
url: string | undefined,
nodeEnv: string,
): void {
if (!url) {
throw new Error(
'DATABASE_URL is not configured or resolved to an empty value.',
);
}
if (nodeEnv === 'production' && url.startsWith('file:')) {
throw new Error(
`DATABASE_URL resolves to a local file ("${url}"), which is not allowed when NODE_ENV=production. Set DATABASE_URL to a real database connection string.`,
Expand Down