Private
Public Access
1
0
Files
Kanban/prisma/seed.ts
T
Catherine Renelle d418c367cb Security hardening and fix all compile warnings
Security fixes:
- Validate theme background image URLs against whitelist pattern
- Add board permission check to Socket.IO join-board handler
- Disable raw HTML passthrough in markdown parser (XSS prevention)
- Add UUID validation on avatar and branding route params (path traversal)
- Add security headers (X-Frame-Options, X-Content-Type-Options, Referrer-Policy)
- Validate webhook URLs (HTTPS only, block internal addresses)
- Add import payload size limit (5MB)
- Remove server uptime from health endpoint
- Make seed password configurable via SEED_ADMIN_PASSWORD env var
- Patch DOMPurify dependency vulnerability via npm audit fix

Warning fixes:
- Convert $state(prop) to $effect.pre sync pattern (state_referenced_locally)
- Add for/id pairings to form labels (a11y_label_has_associated_control)
- Add svelte-ignore for intentional autofocus usage (a11y_autofocus)
- Add ARIA roles to interactive/overlay divs (a11y_no_static_element_interactions)
- Add aria-label to icon-only buttons (a11y_consider_explicit_label)
- Add keyboard handler alongside click events (a11y_click_events_have_key_events)
- Fix non-reactive fileInput declaration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:36:47 -05:00

105 lines
2.4 KiB
TypeScript

import { PrismaClient } from '@prisma/client';
import bcrypt from 'bcrypt';
const prisma = new PrismaClient();
async function main() {
console.log('Seeding database...');
// The app auto-creates a tenant on first request,
// but the seed ensures an admin user exists.
let tenant = await prisma.tenant.findFirst();
if (!tenant) {
tenant = await prisma.tenant.create({
data: {
name: 'Pounce',
slug: 'default'
}
});
console.log(` Created tenant: ${tenant.name} (${tenant.id})`);
} else {
console.log(` Existing tenant: ${tenant.name} (${tenant.id})`);
}
// Create admin user
const seedPassword = process.env.SEED_ADMIN_PASSWORD || 'admin123';
const passwordHash = await bcrypt.hash(seedPassword, 12);
await prisma.user.upsert({
where: { tenantId_email: { tenantId: tenant.id, email: 'admin@example.com' } },
update: {},
create: {
tenantId: tenant.id,
email: 'admin@example.com',
name: 'Admin',
passwordHash,
globalRole: 'SITE_ADMIN',
tenantRole: 'ADMIN'
}
});
// Seed system templates (tenantId: null)
const systemTemplates = [
{
name: 'Basic Kanban',
description: 'Simple three-column workflow',
template: { columns: [{ title: 'To Do' }, { title: 'In Progress' }, { title: 'Done' }] }
},
{
name: 'Scrum Sprint',
description: 'Sprint-based agile workflow',
template: {
columns: [
{ title: 'Backlog' },
{ title: 'Sprint' },
{ title: 'In Review' },
{ title: 'Done' }
]
}
},
{
name: 'Bug Tracker',
description: 'Issue lifecycle tracking',
template: {
columns: [
{ title: 'New' },
{ title: 'Confirmed' },
{ title: 'In Progress' },
{ title: 'Resolved' },
{ title: 'Closed' }
]
}
}
];
for (const tpl of systemTemplates) {
const existing = await prisma.boardTemplate.findFirst({
where: { tenantId: null, name: tpl.name }
});
if (!existing) {
await prisma.boardTemplate.create({
data: {
tenantId: null,
name: tpl.name,
description: tpl.description,
template: tpl.template
}
});
console.log(` Created system template: ${tpl.name}`);
} else {
console.log(` System template exists: ${tpl.name}`);
}
}
console.log('Seed complete.');
console.log(' Admin: admin@example.com (password set via SEED_ADMIN_PASSWORD env var)');
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});