INSIGHT-MVP/packages/crm-service/scripts/generate-token.ts
Thomas Reitz 094db465cb feat(crm): add standalone dev environment and test token generator
- docker-compose.crm-dev.yml: isolierte Testumgebung (PostgreSQL + Redis + CRM)
- scripts/generate-token.ts: generiert Test-JWTs fuer curl-basiertes API-Testing
- scripts/init-schema.sql: erstellt app_crm Schema beim DB-Start
- keys/: Test-RSA-Schluessel (nur fuer lokale Entwicklung!)
- Fix: multiSchema previewFeature entfernt (deprecated)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 16:03:59 +01:00

93 lines
3.1 KiB
TypeScript

/**
* Test-Token-Generator fuer CRM-Service Entwicklung.
*
* Generiert ein gueltiges JWT mit konfigurierbaren Claims.
*
* Verwendung:
* npx ts-node scripts/generate-token.ts
* npx ts-node scripts/generate-token.ts --role TENANT_ADMIN
* npx ts-node scripts/generate-token.ts --expiry 60 (60 Minuten)
*/
import * as crypto from 'crypto';
import * as fs from 'fs';
import * as path from 'path';
function base64url(data: Buffer | string): string {
const buf = typeof data === 'string' ? Buffer.from(data) : data;
return buf.toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
}
function generateToken(options: {
role?: string;
tenantId?: string;
tenantSlug?: string;
userId?: string;
email?: string;
expiryMinutes?: number;
}): string {
const privateKeyPath = path.join(__dirname, '..', 'keys', 'jwt-private.pem');
const privateKey = fs.readFileSync(privateKeyPath, 'utf8');
const now = Math.floor(Date.now() / 1000);
const expiryMinutes = options.expiryMinutes ?? 60;
const header = {
alg: 'RS256',
typ: 'JWT',
};
const payload = {
sub: options.userId ?? 'test-user-00000000-0000-0000-0000-000000000001',
email: options.email ?? 'testuser@insight.local',
role: options.role ?? 'TENANT_ADMIN',
tenantId: options.tenantId ?? 'test-tenant-00000000-0000-0000-0000-000000000001',
tenantSlug: options.tenantSlug ?? 'test_tenant',
jti: crypto.randomUUID(),
iss: 'insight-platform',
iat: now,
exp: now + expiryMinutes * 60,
};
const headerB64 = base64url(JSON.stringify(header));
const payloadB64 = base64url(JSON.stringify(payload));
const signingInput = `${headerB64}.${payloadB64}`;
const sign = crypto.createSign('RSA-SHA256');
sign.update(signingInput);
const signature = sign.sign(privateKey);
const signatureB64 = base64url(signature);
return `${signingInput}.${signatureB64}`;
}
// CLI args parsen
const args = process.argv.slice(2);
const getArg = (name: string): string | undefined => {
const idx = args.indexOf(`--${name}`);
return idx >= 0 && idx + 1 < args.length ? args[idx + 1] : undefined;
};
const token = generateToken({
role: getArg('role'),
tenantId: getArg('tenantId'),
tenantSlug: getArg('tenantSlug'),
userId: getArg('userId'),
email: getArg('email'),
expiryMinutes: getArg('expiry') ? parseInt(getArg('expiry')!, 10) : undefined,
});
console.log('\n=== INSIGHT CRM Test-Token ===\n');
console.log('Token:');
console.log(token);
console.log('\n--- Verwendung mit curl ---\n');
console.log(`export CRM_TOKEN="${token}"\n`);
console.log('# Kontakte auflisten:');
console.log('curl -s http://localhost:3100/api/v1/crm/contacts -H "Authorization: Bearer $CRM_TOKEN" | jq\n');
console.log('# Kontakt erstellen:');
console.log(`curl -s -X POST http://localhost:3100/api/v1/crm/contacts \\
-H "Authorization: Bearer $CRM_TOKEN" \\
-H "Content-Type: application/json" \\
-d '{"type":"PERSON","firstName":"Max","lastName":"Mustermann","email":"max@firma.de","companyName":"Firma GmbH"}' | jq\n`);
console.log('# Health-Check (kein Token noetig):');
console.log('curl -s http://localhost:3100/health | jq\n');