@prism-engineer/router
Version:
Type-safe Express.js router with automatic client generation
462 lines • 18.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const createAuthScheme_1 = require("../../createAuthScheme");
(0, vitest_1.describe)('Authentication - Single Auth Validation', () => {
(0, vitest_1.beforeEach)(() => {
vitest_1.vi.clearAllMocks();
});
(0, vitest_1.it)('should validate bearer token authentication successfully', async () => {
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'bearer',
validate: async (req) => {
const authHeader = req.headers.authorization;
if (!authHeader?.startsWith('Bearer ')) {
throw new Error('Invalid authorization header');
}
const token = authHeader.slice(7);
return { user: { id: '1', token } };
}
});
const mockReq = {
headers: { authorization: 'Bearer valid-token' },
body: {},
query: {},
params: {}
};
const result = await authScheme.validate(mockReq);
(0, vitest_1.expect)(result).toEqual({
user: { id: '1', token: 'valid-token' }
});
});
(0, vitest_1.it)('should validate API key authentication successfully', async () => {
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'apiKey',
validate: async (req) => {
const apiKey = req.headers['x-api-key'];
if (!apiKey) {
throw new Error('API key required');
}
if (apiKey !== 'valid-api-key') {
throw new Error('Invalid API key');
}
return { client: { id: '1', apiKey } };
}
});
const mockReq = {
headers: { 'x-api-key': 'valid-api-key' },
body: {},
query: {},
params: {}
};
const result = await authScheme.validate(mockReq);
(0, vitest_1.expect)(result).toEqual({
client: { id: '1', apiKey: 'valid-api-key' }
});
});
(0, vitest_1.it)('should validate session authentication successfully', async () => {
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'session',
validate: async (req) => {
const sessionId = req.headers.cookie?.match(/sessionId=([^;]+)/)?.[1];
if (!sessionId) {
throw new Error('Session required');
}
return { session: { id: sessionId, userId: '1' } };
}
});
const mockReq = {
headers: { cookie: 'sessionId=abc123; otherCookie=value' },
body: {},
query: {},
params: {}
};
const result = await authScheme.validate(mockReq);
(0, vitest_1.expect)(result).toEqual({
session: { id: 'abc123', userId: '1' }
});
});
(0, vitest_1.it)('should validate custom authentication scheme', async () => {
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'custom',
validate: async (req) => {
const signature = req.headers['x-signature'];
const timestamp = req.headers['x-timestamp'];
if (!signature || !timestamp) {
throw new Error('Missing authentication headers');
}
if (signature !== 'valid-signature') {
throw new Error('Invalid signature');
}
return {
client: {
id: '1',
verified: true,
timestamp: parseInt(timestamp)
}
};
}
});
const mockReq = {
headers: {
'x-signature': 'valid-signature',
'x-timestamp': '1234567890'
},
body: {},
query: {},
params: {}
};
const result = await authScheme.validate(mockReq);
(0, vitest_1.expect)(result).toEqual({
client: {
id: '1',
verified: true,
timestamp: 1234567890
}
});
});
(0, vitest_1.it)('should handle successful validation with minimal context', async () => {
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'minimal',
validate: async () => ({ authenticated: true })
});
const result = await authScheme.validate();
(0, vitest_1.expect)(result).toEqual({ authenticated: true });
});
(0, vitest_1.it)('should handle validation with complex user context', async () => {
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'complex',
validate: async (req) => {
const role = req.headers['x-user-role'];
return {
user: {
id: '1',
name: 'John Doe',
email: 'john@example.com',
role: role || 'user',
permissions: ['read', 'write'],
metadata: {
lastLogin: new Date().toISOString(),
loginCount: 5
}
}
};
}
});
const mockReq = {
headers: { 'x-user-role': 'admin' },
body: {},
query: {},
params: {}
};
const result = await authScheme.validate(mockReq);
(0, vitest_1.expect)(result.user.id).toBe('1');
(0, vitest_1.expect)(result.user.role).toBe('admin');
(0, vitest_1.expect)(result.user.permissions).toEqual(['read', 'write']);
(0, vitest_1.expect)(result.user.metadata.loginCount).toBe(5);
});
(0, vitest_1.it)('should handle async validation with external service simulation', async () => {
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'external',
validate: async (req) => {
const token = req.headers.authorization?.replace('Bearer ', '');
// Simulate async external service call
await new Promise(resolve => setTimeout(resolve, 1));
if (token === 'external-valid-token') {
return {
user: {
id: 'ext-1',
provider: 'external-service',
verified: true
}
};
}
throw new Error('External validation failed');
}
});
const mockReq = {
headers: { authorization: 'Bearer external-valid-token' },
body: {},
query: {},
params: {}
};
const result = await authScheme.validate(mockReq);
(0, vitest_1.expect)(result).toEqual({
user: {
id: 'ext-1',
provider: 'external-service',
verified: true
}
});
});
(0, vitest_1.it)('should handle validation with request context analysis', async () => {
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'context-aware',
validate: async (req) => {
const userAgent = req.headers['user-agent'];
const clientIp = req.ip || '127.0.0.1';
return {
user: { id: '1' },
context: {
userAgent,
clientIp,
timestamp: Date.now(),
secure: req.headers['x-forwarded-proto'] === 'https'
}
};
}
});
const mockReq = {
headers: {
'user-agent': 'Mozilla/5.0',
'x-forwarded-proto': 'https'
},
ip: '192.168.1.1',
body: {},
query: {},
params: {}
};
const result = await authScheme.validate(mockReq);
(0, vitest_1.expect)(result.user.id).toBe('1');
(0, vitest_1.expect)(result.context.userAgent).toBe('Mozilla/5.0');
(0, vitest_1.expect)(result.context.clientIp).toBe('192.168.1.1');
(0, vitest_1.expect)(result.context.secure).toBe(true);
});
(0, vitest_1.it)('should handle validation with role-based permissions', async () => {
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'role-based',
validate: async (req) => {
const token = req.headers.authorization?.replace('Bearer ', '');
const roleMapping = {
'admin-token': { role: 'admin', permissions: ['read', 'write', 'delete', 'manage'] },
'editor-token': { role: 'editor', permissions: ['read', 'write'] },
'viewer-token': { role: 'viewer', permissions: ['read'] }
};
const mapping = roleMapping[token];
if (!mapping) {
throw new Error('Invalid token');
}
return {
user: {
id: '1',
role: mapping.role,
permissions: mapping.permissions
}
};
}
});
const mockReq = {
headers: { authorization: 'Bearer admin-token' },
body: {},
query: {},
params: {}
};
const result = await authScheme.validate(mockReq);
(0, vitest_1.expect)(result.user.role).toBe('admin');
(0, vitest_1.expect)(result.user.permissions).toEqual(['read', 'write', 'delete', 'manage']);
});
(0, vitest_1.it)('should handle validation with caching mechanism', async () => {
const cache = new Map();
let validationCount = 0;
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'cached',
validate: async (req) => {
const token = req.headers.authorization;
// Check cache first
if (cache.has(token)) {
return cache.get(token);
}
// Increment validation count for testing
validationCount++;
// Simulate expensive validation
await new Promise(resolve => setTimeout(resolve, 1));
const context = {
user: { id: '1', validationCount },
cached: true
};
// Cache result with TTL simulation
cache.set(token, context);
setTimeout(() => cache.delete(token), 100); // 100ms TTL
return context;
}
});
const mockReq = {
headers: { authorization: 'Bearer cache-token' },
body: {},
query: {},
params: {}
};
// First validation - should hit validation logic
const result1 = await authScheme.validate(mockReq);
(0, vitest_1.expect)(result1.user.validationCount).toBe(1);
(0, vitest_1.expect)(validationCount).toBe(1);
// Second validation - should hit cache
const result2 = await authScheme.validate(mockReq);
(0, vitest_1.expect)(result2.user.validationCount).toBe(1); // Same as cached
(0, vitest_1.expect)(validationCount).toBe(1); // No additional validation
});
(0, vitest_1.it)('should handle validation with environment-specific logic', async () => {
const originalEnv = process.env.NODE_ENV;
process.env.NODE_ENV = 'development';
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'env-aware',
validate: async (req) => {
const isDevelopment = process.env.NODE_ENV === 'development';
if (isDevelopment) {
// Relaxed validation for development
return {
user: {
id: 'dev-user',
role: 'developer',
environment: 'development'
}
};
}
// Strict validation for production
const token = req.headers.authorization;
if (!token?.startsWith('Bearer ')) {
throw new Error('Valid bearer token required in production');
}
return {
user: {
id: '1',
role: 'user',
environment: 'production'
}
};
}
});
const mockReq = {
headers: {},
body: {},
query: {},
params: {}
};
const result = await authScheme.validate(mockReq);
(0, vitest_1.expect)(result.user.environment).toBe('development');
(0, vitest_1.expect)(result.user.role).toBe('developer');
// Restore original environment
process.env.NODE_ENV = originalEnv;
});
(0, vitest_1.it)('should handle validation with multi-step verification', async () => {
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'multi-step',
validate: async (req) => {
// Step 1: Check basic auth header
const authHeader = req.headers.authorization;
if (!authHeader) {
throw new Error('Authorization header required');
}
// Step 2: Validate format
if (!authHeader.startsWith('Bearer ')) {
throw new Error('Bearer token required');
}
// Step 3: Extract token
const token = authHeader.slice(7);
if (token.length < 10) {
throw new Error('Token too short');
}
// Step 4: Validate token format (simple check)
if (!/^[a-zA-Z0-9-_]+$/.test(token)) {
throw new Error('Invalid token format');
}
// Step 5: Simulate token verification
if (!token.includes('valid')) {
throw new Error('Invalid token');
}
return {
user: {
id: '1',
token,
validated: true,
steps: 5
}
};
}
});
const mockReq = {
headers: { authorization: 'Bearer valid-token-123' },
body: {},
query: {},
params: {}
};
const result = await authScheme.validate(mockReq);
(0, vitest_1.expect)(result.user.validated).toBe(true);
(0, vitest_1.expect)(result.user.steps).toBe(5);
(0, vitest_1.expect)(result.user.token).toBe('valid-token-123');
});
(0, vitest_1.it)('should handle validation with conditional requirements', async () => {
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'conditional',
validate: async (req) => {
const method = req.method;
const path = req.path;
// Different auth requirements based on request
if (method === 'GET' && path?.startsWith('/public')) {
return { user: { id: 'anonymous', level: 'public' } };
}
if (method === 'POST' || method === 'PUT' || method === 'DELETE') {
const token = req.headers.authorization;
if (!token) {
throw new Error('Authentication required for write operations');
}
return { user: { id: '1', level: 'authenticated' } };
}
return { user: { id: 'guest', level: 'guest' } };
}
});
// Test public GET request
const publicReq = {
method: 'GET',
path: '/public/data',
headers: {},
body: {},
query: {},
params: {}
};
const publicResult = await authScheme.validate(publicReq);
(0, vitest_1.expect)(publicResult.user.level).toBe('public');
// Test authenticated POST request
const postReq = {
method: 'POST',
path: '/api/data',
headers: { authorization: 'Bearer token' },
body: {},
query: {},
params: {}
};
const postResult = await authScheme.validate(postReq);
(0, vitest_1.expect)(postResult.user.level).toBe('authenticated');
});
(0, vitest_1.it)('should handle validation with retry logic', async () => {
let attemptCount = 0;
const authScheme = (0, createAuthScheme_1.createAuthScheme)({
name: 'retry',
validate: async (req) => {
attemptCount++;
// Simulate intermittent failure
if (attemptCount === 1) {
throw new Error('Temporary service unavailable');
}
return {
user: {
id: '1',
attempts: attemptCount
}
};
}
});
const mockReq = {
headers: { authorization: 'Bearer token' },
body: {},
query: {},
params: {}
};
// First attempt should fail
await (0, vitest_1.expect)(authScheme.validate(mockReq)).rejects.toThrow('Temporary service unavailable');
// Second attempt should succeed
const result = await authScheme.validate(mockReq);
(0, vitest_1.expect)(result.user.attempts).toBe(2);
});
});
//# sourceMappingURL=single-auth-validation.test.js.map