root d58d53fa3b feat: initial workflow portal - multi-tenant architecture
- Backend: Node.js + Express + TypeScript + Prisma + PostgreSQL
- Frontend: React + TypeScript + Tailwind CSS + Vite
- Multi-tenant with role-based access (SystemAdmin, Technician, Customer)
- Workflow editor with drag-and-drop steps
- JWT authentication with refresh tokens
- German UI throughout
2026-03-20 22:48:04 +00:00

213 lines
7.5 KiB
TypeScript

import { PrismaClient, Role, WorkflowStatus, StepType } from '@prisma/client';
import bcrypt from 'bcryptjs';
const prisma = new PrismaClient();
async function main() {
console.log('Seeding database...');
// Create default tenant "Systemhaus"
const systemhausTenant = await prisma.tenant.upsert({
where: { slug: 'systemhaus' },
update: {},
create: {
name: 'Systemhaus',
slug: 'systemhaus',
active: true,
},
});
console.log('Created tenant:', systemhausTenant.name);
// Create sample tenant "Musterkunde GmbH"
const musterkundeTenant = await prisma.tenant.upsert({
where: { slug: 'musterkunde' },
update: {},
create: {
name: 'Musterkunde GmbH',
slug: 'musterkunde',
active: true,
},
});
console.log('Created tenant:', musterkundeTenant.name);
// Create system admin user
const adminPasswordHash = await bcrypt.hash('admin123', 12);
const systemAdmin = await prisma.user.upsert({
where: { email: 'admin@systemhaus.de' },
update: {},
create: {
email: 'admin@systemhaus.de',
passwordHash: adminPasswordHash,
firstName: 'System',
lastName: 'Administrator',
role: Role.SYSTEM_ADMIN,
tenantId: systemhausTenant.id,
active: true,
},
});
console.log('Created user:', systemAdmin.email, '(SYSTEM_ADMIN)');
// Create technician user
const technicianPasswordHash = await bcrypt.hash('admin123', 12);
const technician = await prisma.user.upsert({
where: { email: 'techniker@systemhaus.de' },
update: {},
create: {
email: 'techniker@systemhaus.de',
passwordHash: technicianPasswordHash,
firstName: 'Max',
lastName: 'Techniker',
role: Role.TECHNICIAN,
tenantId: systemhausTenant.id,
active: true,
},
});
console.log('Created user:', technician.email, '(TECHNICIAN)');
// Create customer admin user
const customerAdminPasswordHash = await bcrypt.hash('admin123', 12);
const customerAdmin = await prisma.user.upsert({
where: { email: 'admin@musterkunde.de' },
update: {},
create: {
email: 'admin@musterkunde.de',
passwordHash: customerAdminPasswordHash,
firstName: 'Maria',
lastName: 'Mustermann',
role: Role.CUSTOMER_ADMIN,
tenantId: musterkundeTenant.id,
active: true,
},
});
console.log('Created user:', customerAdmin.email, '(CUSTOMER_ADMIN)');
// Create customer user
const customerUserPasswordHash = await bcrypt.hash('admin123', 12);
const customerUser = await prisma.user.upsert({
where: { email: 'user@musterkunde.de' },
update: {},
create: {
email: 'user@musterkunde.de',
passwordHash: customerUserPasswordHash,
firstName: 'Hans',
lastName: 'Benutzer',
role: Role.CUSTOMER_USER,
tenantId: musterkundeTenant.id,
active: true,
},
});
console.log('Created user:', customerUser.email, '(CUSTOMER_USER)');
// Create categories (global, no tenant)
const categories = [
{ name: 'Benutzerverwaltung', icon: 'users' },
{ name: 'Netzwerk', icon: 'network' },
{ name: 'VPN', icon: 'shield' },
{ name: 'Backup', icon: 'database' },
{ name: 'Server', icon: 'server' },
];
const createdCategories: Record<string, string> = {};
for (const cat of categories) {
const existing = await prisma.category.findFirst({
where: { name: cat.name, tenantId: null },
});
if (existing) {
createdCategories[cat.name] = existing.id;
console.log('Category already exists:', cat.name);
} else {
const created = await prisma.category.create({
data: {
name: cat.name,
icon: cat.icon,
tenantId: null,
},
});
createdCategories[cat.name] = created.id;
console.log('Created category:', cat.name);
}
}
// Create sample workflow: "Neuen Benutzer anlegen"
const existingWorkflow = await prisma.workflow.findFirst({
where: {
title: 'Neuen Benutzer anlegen',
tenantId: musterkundeTenant.id,
},
});
if (!existingWorkflow) {
const workflow = await prisma.workflow.create({
data: {
title: 'Neuen Benutzer anlegen',
description: 'Schritt-fuer-Schritt Anleitung zum Anlegen eines neuen Benutzers im Active Directory und allen relevanten Systemen.',
tenantId: musterkundeTenant.id,
categoryId: createdCategories['Benutzerverwaltung'],
status: WorkflowStatus.PUBLISHED,
version: 1,
isTemplate: false,
tags: ['benutzer', 'onboarding', 'active-directory'],
createdById: systemAdmin.id,
steps: {
create: [
{
order: 0,
title: 'Anforderung pruefen',
content: 'Pruefen Sie die Benutzeranforderung auf Vollstaendigkeit:\n- Vor- und Nachname\n- Abteilung\n- Vorgesetzter\n- Benoetigte Berechtigungen\n- Startdatum',
type: StepType.CHECKLIST,
isRequired: true,
},
{
order: 1,
title: 'Active Directory Benutzer erstellen',
content: 'Oeffnen Sie die Active Directory Benutzer und Computer Konsole und erstellen Sie einen neuen Benutzer:\n\n```powershell\nNew-ADUser -Name "Vorname Nachname" -GivenName "Vorname" -Surname "Nachname" -SamAccountName "v.nachname" -UserPrincipalName "v.nachname@domain.de" -Path "OU=Users,DC=domain,DC=de" -AccountPassword (ConvertTo-SecureString "TempPasswort123!" -AsPlainText -Force) -Enabled $true -ChangePasswordAtLogon $true\n```',
type: StepType.COMMAND,
isRequired: true,
},
{
order: 2,
title: 'Gruppenmitgliedschaften konfigurieren',
content: 'Fuegen Sie den Benutzer den entsprechenden Sicherheitsgruppen hinzu basierend auf Abteilung und Rolle:\n- Abteilungsgruppe\n- VPN-Zugang (falls erforderlich)\n- Drucker-Gruppen\n- Anwendungs-Gruppen',
type: StepType.INSTRUCTION,
isRequired: true,
},
{
order: 3,
title: 'E-Mail Postfach einrichten',
content: 'WICHTIG: Warten Sie nach der AD-Erstellung mindestens 15 Minuten auf die Exchange-Synchronisation. Pruefen Sie anschliessend, ob das Postfach automatisch erstellt wurde. Falls nicht, erstellen Sie es manuell im Exchange Admin Center.',
type: StepType.WARNING,
isRequired: true,
},
{
order: 4,
title: 'Dokumentation und Uebergabe',
content: 'Dokumentieren Sie die Zugangsdaten und informieren Sie den Vorgesetzten:\n- Benutzername\n- Initiales Passwort (sicher uebermitteln!)\n- E-Mail Adresse\n- VPN-Zugangsdaten (falls zutreffend)\n\nHinweis: Verwenden Sie einen sicheren Kanal fuer die Passwort-Uebermittlung.',
type: StepType.INFO,
isRequired: true,
},
],
},
},
});
console.log('Created workflow:', workflow.title, 'with 5 steps');
} else {
console.log('Workflow already exists:', existingWorkflow.title);
}
console.log('\nSeed complete!');
console.log('\nTest Accounts:');
console.log(' System Admin: admin@systemhaus.de / admin123');
console.log(' Technician: techniker@systemhaus.de / admin123');
console.log(' Customer Admin: admin@musterkunde.de / admin123');
console.log(' Customer User: user@musterkunde.de / admin123');
}
main()
.catch((e) => {
console.error('Seed error:', e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});