220 lines
11 KiB
TypeScript
220 lines
11 KiB
TypeScript
|
|
/**
|
||
|
|
* Seed script for Port Nimara CRM.
|
||
|
|
*
|
||
|
|
* Seeds:
|
||
|
|
* - 1 Port: Port Nimara
|
||
|
|
* - 5 System roles with full permission maps
|
||
|
|
* - 1 Super admin user profile (matt@portnimara.com)
|
||
|
|
*
|
||
|
|
* Run with: npm run db:seed
|
||
|
|
*/
|
||
|
|
|
||
|
|
import 'dotenv/config';
|
||
|
|
import { db } from './index';
|
||
|
|
import { ports } from './schema/ports';
|
||
|
|
import { roles, userProfiles } from './schema/users';
|
||
|
|
import type { RolePermissions } from './schema/users';
|
||
|
|
|
||
|
|
// ─── Permission Maps ─────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
const ALL_PERMISSIONS: RolePermissions = {
|
||
|
|
clients: { view: true, create: true, edit: true, delete: true, merge: true, export: true },
|
||
|
|
interests: { view: true, create: true, edit: true, delete: true, change_stage: true, generate_eoi: true, export: true },
|
||
|
|
berths: { view: true, edit: true, import: true, manage_waiting_list: true },
|
||
|
|
documents: { view: true, create: true, send_for_signing: true, upload_signed: true, delete: true },
|
||
|
|
expenses: { view: true, create: true, edit: true, delete: true, export: true, scan_receipt: true },
|
||
|
|
invoices: { view: true, create: true, edit: true, delete: true, send: true, record_payment: true, export: true },
|
||
|
|
files: { view: true, upload: true, delete: true, manage_folders: true },
|
||
|
|
email: { view: true, send: true, configure_account: true },
|
||
|
|
reminders: { view_own: true, view_all: true, create: true, edit_own: true, edit_all: true, assign_others: true },
|
||
|
|
calendar: { connect: true, view_events: true },
|
||
|
|
reports: { view_dashboard: true, view_analytics: true, export: true },
|
||
|
|
document_templates: { view: true, generate: true, manage: true },
|
||
|
|
admin: { manage_users: true, view_audit_log: true, manage_settings: true, manage_webhooks: true, manage_reports: true, manage_custom_fields: true, manage_forms: true, manage_tags: true, system_backup: true },
|
||
|
|
};
|
||
|
|
|
||
|
|
const DIRECTOR_PERMISSIONS: RolePermissions = {
|
||
|
|
clients: { view: true, create: true, edit: true, delete: true, merge: true, export: true },
|
||
|
|
interests: { view: true, create: true, edit: true, delete: true, change_stage: true, generate_eoi: true, export: true },
|
||
|
|
berths: { view: true, edit: true, import: true, manage_waiting_list: true },
|
||
|
|
documents: { view: true, create: true, send_for_signing: true, upload_signed: true, delete: true },
|
||
|
|
expenses: { view: true, create: true, edit: true, delete: true, export: true, scan_receipt: true },
|
||
|
|
invoices: { view: true, create: true, edit: true, delete: true, send: true, record_payment: true, export: true },
|
||
|
|
files: { view: true, upload: true, delete: true, manage_folders: true },
|
||
|
|
email: { view: true, send: true, configure_account: true },
|
||
|
|
reminders: { view_own: true, view_all: true, create: true, edit_own: true, edit_all: true, assign_others: true },
|
||
|
|
calendar: { connect: true, view_events: true },
|
||
|
|
reports: { view_dashboard: true, view_analytics: true, export: true },
|
||
|
|
document_templates: { view: true, generate: true, manage: true },
|
||
|
|
admin: { manage_users: true, view_audit_log: true, manage_settings: true, manage_webhooks: true, manage_reports: true, manage_custom_fields: true, manage_forms: true, manage_tags: true, system_backup: false },
|
||
|
|
};
|
||
|
|
|
||
|
|
const SALES_MANAGER_PERMISSIONS: RolePermissions = {
|
||
|
|
clients: { view: true, create: true, edit: true, delete: false, merge: true, export: true },
|
||
|
|
interests: { view: true, create: true, edit: true, delete: false, change_stage: true, generate_eoi: true, export: true },
|
||
|
|
berths: { view: true, edit: false, import: false, manage_waiting_list: true },
|
||
|
|
documents: { view: true, create: true, send_for_signing: true, upload_signed: true, delete: false },
|
||
|
|
expenses: { view: true, create: true, edit: true, delete: false, export: true, scan_receipt: true },
|
||
|
|
invoices: { view: true, create: true, edit: true, delete: false, send: true, record_payment: true, export: true },
|
||
|
|
files: { view: true, upload: true, delete: false, manage_folders: true },
|
||
|
|
email: { view: true, send: true, configure_account: true },
|
||
|
|
reminders: { view_own: true, view_all: true, create: true, edit_own: true, edit_all: true, assign_others: true },
|
||
|
|
calendar: { connect: true, view_events: true },
|
||
|
|
reports: { view_dashboard: true, view_analytics: true, export: true },
|
||
|
|
document_templates: { view: true, generate: true, manage: false },
|
||
|
|
admin: { manage_users: false, view_audit_log: false, manage_settings: false, manage_webhooks: false, manage_reports: false, manage_custom_fields: false, manage_forms: false, manage_tags: true, system_backup: false },
|
||
|
|
};
|
||
|
|
|
||
|
|
const SALES_AGENT_PERMISSIONS: RolePermissions = {
|
||
|
|
clients: { view: true, create: true, edit: true, delete: false, merge: false, export: true },
|
||
|
|
interests: { view: true, create: true, edit: true, delete: false, change_stage: true, generate_eoi: true, export: true },
|
||
|
|
berths: { view: true, edit: false, import: false, manage_waiting_list: true },
|
||
|
|
documents: { view: true, create: true, send_for_signing: true, upload_signed: true, delete: false },
|
||
|
|
expenses: { view: true, create: true, edit: true, delete: false, export: true, scan_receipt: true },
|
||
|
|
invoices: { view: true, create: true, edit: true, delete: false, send: true, record_payment: true, export: true },
|
||
|
|
files: { view: true, upload: true, delete: false, manage_folders: false },
|
||
|
|
email: { view: true, send: true, configure_account: true },
|
||
|
|
reminders: { view_own: true, view_all: false, create: true, edit_own: true, edit_all: false, assign_others: false },
|
||
|
|
calendar: { connect: true, view_events: true },
|
||
|
|
reports: { view_dashboard: true, view_analytics: true, export: true },
|
||
|
|
document_templates: { view: true, generate: true, manage: false },
|
||
|
|
admin: { manage_users: false, view_audit_log: false, manage_settings: false, manage_webhooks: false, manage_reports: false, manage_custom_fields: false, manage_forms: false, manage_tags: true, system_backup: false },
|
||
|
|
};
|
||
|
|
|
||
|
|
const VIEWER_PERMISSIONS: RolePermissions = {
|
||
|
|
clients: { view: true, create: false, edit: false, delete: false, merge: false, export: false },
|
||
|
|
interests: { view: true, create: false, edit: false, delete: false, change_stage: false, generate_eoi: false, export: false },
|
||
|
|
berths: { view: true, edit: false, import: false, manage_waiting_list: false },
|
||
|
|
documents: { view: true, create: false, send_for_signing: false, upload_signed: false, delete: false },
|
||
|
|
expenses: { view: true, create: false, edit: false, delete: false, export: false, scan_receipt: false },
|
||
|
|
invoices: { view: true, create: false, edit: false, delete: false, send: false, record_payment: false, export: false },
|
||
|
|
files: { view: true, upload: false, delete: false, manage_folders: false },
|
||
|
|
email: { view: true, send: false, configure_account: false },
|
||
|
|
reminders: { view_own: true, view_all: false, create: false, edit_own: false, edit_all: false, assign_others: false },
|
||
|
|
calendar: { connect: false, view_events: true },
|
||
|
|
reports: { view_dashboard: true, view_analytics: false, export: false },
|
||
|
|
document_templates: { view: true, generate: false, manage: false },
|
||
|
|
admin: { manage_users: false, view_audit_log: false, manage_settings: false, manage_webhooks: false, manage_reports: false, manage_custom_fields: false, manage_forms: false, manage_tags: false, system_backup: false },
|
||
|
|
};
|
||
|
|
|
||
|
|
// ─── Seed Function ────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
async function seed() {
|
||
|
|
console.log('Seeding Port Nimara CRM...');
|
||
|
|
|
||
|
|
// ── 1. Port ─────────────────────────────────────────────────────────────────
|
||
|
|
console.log('Creating Port Nimara...');
|
||
|
|
const [port] = await db
|
||
|
|
.insert(ports)
|
||
|
|
.values({
|
||
|
|
id: crypto.randomUUID(),
|
||
|
|
name: 'Port Nimara',
|
||
|
|
slug: 'port-nimara',
|
||
|
|
logoUrl: null,
|
||
|
|
primaryColor: '#0F4C81',
|
||
|
|
defaultCurrency: 'USD',
|
||
|
|
timezone: 'America/Anguilla',
|
||
|
|
settings: {},
|
||
|
|
isActive: true,
|
||
|
|
})
|
||
|
|
.onConflictDoNothing()
|
||
|
|
.returning();
|
||
|
|
|
||
|
|
const portId = port?.id;
|
||
|
|
if (!portId) {
|
||
|
|
console.log('Port already exists, skipping...');
|
||
|
|
} else {
|
||
|
|
console.log(`Port created: ${portId}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ── 2. System Roles ─────────────────────────────────────────────────────────
|
||
|
|
console.log('Creating system roles...');
|
||
|
|
|
||
|
|
const systemRoles = [
|
||
|
|
{
|
||
|
|
id: crypto.randomUUID(),
|
||
|
|
name: 'super_admin',
|
||
|
|
description: 'Full system access. Bypasses all permission checks.',
|
||
|
|
permissions: ALL_PERMISSIONS,
|
||
|
|
isGlobal: true,
|
||
|
|
isSystem: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id: crypto.randomUUID(),
|
||
|
|
name: 'director',
|
||
|
|
description: 'Operational admin within assigned port(s). Can manage users and settings.',
|
||
|
|
permissions: DIRECTOR_PERMISSIONS,
|
||
|
|
isGlobal: true,
|
||
|
|
isSystem: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id: crypto.randomUUID(),
|
||
|
|
name: 'sales_manager',
|
||
|
|
description: 'Full sales access. Can view all reminders, assign tasks, and export reports.',
|
||
|
|
permissions: SALES_MANAGER_PERMISSIONS,
|
||
|
|
isGlobal: true,
|
||
|
|
isSystem: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id: crypto.randomUUID(),
|
||
|
|
name: 'sales_agent',
|
||
|
|
description: 'Standard sales role. View/create/edit clients and interests, manage own reminders.',
|
||
|
|
permissions: SALES_AGENT_PERMISSIONS,
|
||
|
|
isGlobal: true,
|
||
|
|
isSystem: true,
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id: crypto.randomUUID(),
|
||
|
|
name: 'viewer',
|
||
|
|
description: 'Read-only access to all records.',
|
||
|
|
permissions: VIEWER_PERMISSIONS,
|
||
|
|
isGlobal: true,
|
||
|
|
isSystem: true,
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
for (const role of systemRoles) {
|
||
|
|
await db.insert(roles).values(role).onConflictDoNothing();
|
||
|
|
console.log(`Role created: ${role.name}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ── 3. Super Admin User Profile ─────────────────────────────────────────────
|
||
|
|
// Note: Better Auth creates the actual `user` record on first login.
|
||
|
|
// We create the profile extension now, linked to a known user_id.
|
||
|
|
// The Better Auth user_id for matt@portnimara.com must match this value
|
||
|
|
// once Better Auth is configured. Use a stable placeholder ID here.
|
||
|
|
console.log('Creating super admin user profile...');
|
||
|
|
|
||
|
|
const superAdminUserId = 'super-admin-matt-portnimara';
|
||
|
|
|
||
|
|
await db
|
||
|
|
.insert(userProfiles)
|
||
|
|
.values({
|
||
|
|
id: crypto.randomUUID(),
|
||
|
|
userId: superAdminUserId,
|
||
|
|
displayName: 'Matt',
|
||
|
|
avatarUrl: null,
|
||
|
|
phone: null,
|
||
|
|
isSuperAdmin: true,
|
||
|
|
isActive: true,
|
||
|
|
lastLoginAt: null,
|
||
|
|
preferences: {},
|
||
|
|
})
|
||
|
|
.onConflictDoNothing();
|
||
|
|
|
||
|
|
console.log(`Super admin profile created for user_id: ${superAdminUserId}`);
|
||
|
|
console.log('');
|
||
|
|
console.log('Seed complete!');
|
||
|
|
console.log('');
|
||
|
|
console.log('NOTE: The Better Auth user for matt@portnimara.com must be created');
|
||
|
|
console.log(`separately. Once created, update user_profiles.user_id to match`);
|
||
|
|
console.log(`the actual Better Auth user ID (currently placeholder: ${superAdminUserId})`);
|
||
|
|
|
||
|
|
process.exit(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
seed().catch((err) => {
|
||
|
|
console.error('Seed failed:', err);
|
||
|
|
process.exit(1);
|
||
|
|
});
|