import bcrypt from 'bcrypt'; import crypto from 'crypto'; import { pool } from '../db.js'; export async function seedUsers() { console.log('👤 Seeding users (Core Architecture)...'); try { // Fetch core companies to map users const companiesResult = await pool.query('SELECT id, name FROM core_companies'); const companyMap = {}; // name -> id companiesResult.rows.forEach(c => companyMap[c.name] = c.id); const systemTenantId = '00000000-0000-0000-0000-000000000000'; // 1. Create SuperAdmin (Requested: superadmin / Admin@2025!) const superAdminPassword = await bcrypt.hash('Admin@2025!', 10); const superAdminId = crypto.randomUUID(); // User requested identifier 'superadmin' const superAdminIdentifier = 'superadmin'; const result = await pool.query(` INSERT INTO core_users (id, tenant_id, name, email, password_hash, status) VALUES ($1, $2, $3, $4, $5, 'ACTIVE') ON CONFLICT (tenant_id, email) DO UPDATE SET password_hash = EXCLUDED.password_hash RETURNING id `, [superAdminId, systemTenantId, 'System Administrator', superAdminIdentifier, superAdminPassword]); const actualSuperAdminId = result.rows[0].id; // Role await pool.query(` INSERT INTO core_user_roles (user_id, role) VALUES ($1, 'superadmin') ON CONFLICT (user_id, role) DO NOTHING `, [actualSuperAdminId]); console.log(' ✓ SuperAdmin created (superadmin)'); // 2. Create Company Admins const companyAdmins = [ // Requested: takeshi_yamamoto / Takeshi@2025 (Company Admin) { identifier: 'takeshi_yamamoto', fullName: 'Takeshi Yamamoto', company: 'TechCorp', email: 'takeshi_yamamoto', pass: 'Takeshi@2025', roles: ['admin', 'company'] }, { identifier: 'kenji', fullName: 'Kenji Tanaka', company: 'AppMakers', email: 'kenji@appmakers.mobile', pass: 'Takeshi@2025', roles: ['admin', 'company'] }, // Requested: maria_santos / User@2025 (Recruiter) - Placing in DesignHub { identifier: 'maria_santos', fullName: 'Maria Santos', company: 'DesignHub', email: 'maria_santos', pass: 'User@2025', roles: ['recruiter', 'company'] } ]; for (const admin of companyAdmins) { const hash = await bcrypt.hash(admin.pass, 10); const userId = crypto.randomUUID(); const tenantId = companyMap[admin.company]; if (!tenantId) { console.warn(`Original company ${admin.company} not found for user ${admin.fullName}, skipping.`); continue; } const result = await pool.query(` INSERT INTO core_users (id, tenant_id, name, email, password_hash, status) VALUES ($1, $2, $3, $4, $5, 'ACTIVE') ON CONFLICT (tenant_id, email) DO UPDATE SET password_hash = EXCLUDED.password_hash RETURNING id `, [userId, tenantId, admin.fullName, admin.email, hash]); const actualUserId = result.rows[0].id; for (const role of admin.roles) { await pool.query(` INSERT INTO core_user_roles (user_id, role) VALUES ($1, $2) ON CONFLICT (user_id, role) DO NOTHING `, [actualUserId, role]); } console.log(` ✓ User created: ${admin.email}`); } // 3. Create Candidates (Job Seekers) // Requested: paulo_santos / User@2025 const candidates = [ { fullName: 'Paulo Santos', email: 'paulo_santos', pass: 'User@2025' }, { fullName: 'Maria Reyes', email: 'maria@email.com', pass: 'User@2025' } ]; for (const cand of candidates) { const hash = await bcrypt.hash(cand.pass, 10); const userId = crypto.randomUUID(); const result = await pool.query(` INSERT INTO core_users (id, tenant_id, name, email, password_hash, status) VALUES ($1, $2, $3, $4, $5, 'ACTIVE') ON CONFLICT (tenant_id, email) DO UPDATE SET password_hash = EXCLUDED.password_hash RETURNING id `, [userId, systemTenantId, cand.fullName, cand.email, hash]); const actualUserId = result.rows[0].id; await pool.query(` INSERT INTO core_user_roles (user_id, role) VALUES ($1, 'candidate') ON CONFLICT (user_id, role) DO NOTHING `, [actualUserId]); console.log(` ✓ Candidate created: ${cand.email}`); } console.log('👤 Seeding legacy candidates...'); const legacyCandidates = [ { identifier: 'ana_silva', fullName: 'Ana Silva', email: 'ana.silva@example.com', phone: '+55 11 98765-4321', city: 'São Paulo', state: 'SP', title: 'Full Stack Developer', experience: '5 years of experience', skills: ['React', 'Node.js', 'TypeScript', 'AWS', 'Docker'], bio: 'Developer passionate about building innovative solutions. Experience in React, Node.js, and cloud computing.', objective: 'Grow as a full stack developer building scalable products.' }, { identifier: 'carlos_santos', fullName: 'Carlos Santos', email: 'carlos.santos@example.com', phone: '+55 11 91234-5678', city: 'Rio de Janeiro', state: 'RJ', title: 'UX/UI Designer', experience: '3 years of experience', skills: ['Figma', 'Adobe XD', 'UI Design', 'Prototyping', 'Design Systems'], bio: 'Designer focused on creating memorable experiences. Specialist in design systems and prototyping.', objective: 'Design intuitive experiences for web and mobile products.' }, { identifier: 'maria_oliveira', fullName: 'Maria Oliveira', email: 'maria.oliveira@example.com', phone: '+55 21 99876-5432', city: 'Belo Horizonte', state: 'MG', title: 'Data Engineer', experience: '7 years of experience', skills: ['Python', 'SQL', 'Spark', 'Machine Learning', 'Data Visualization'], bio: 'Data engineer with a strong background in machine learning and big data. Passionate about turning data into insights.', objective: 'Build robust data pipelines and analytics products.' }, { identifier: 'pedro_costa', fullName: 'Pedro Costa', email: 'pedro.costa@example.com', phone: '+55 31 98765-1234', city: 'Curitiba', state: 'PR', title: 'Product Manager', experience: '6 years of experience', skills: ['Product Management', 'Agile', 'Scrum', 'Data Analysis', 'User Research'], bio: 'Product Manager with experience in digital products and agile methodologies. Focused on delivering user value.', objective: 'Lead cross-functional teams to deliver customer-centric products.' }, { identifier: 'juliana_ferreira', fullName: 'Juliana Ferreira', email: 'juliana.ferreira@example.com', phone: '+55 41 91234-8765', city: 'Porto Alegre', state: 'RS', title: 'DevOps Engineer', experience: '4 years of experience', skills: ['Docker', 'Kubernetes', 'AWS', 'Terraform', 'CI/CD'], bio: 'DevOps engineer specialized in automation and cloud infrastructure. Experience with Kubernetes and CI/CD.', objective: 'Improve delivery pipelines and cloud reliability.' } ]; for (const cand of legacyCandidates) { const hash = await bcrypt.hash('User@2025', 10); await pool.query(` INSERT INTO users ( identifier, password_hash, role, full_name, email, phone, city, state, title, experience, skills, objective, bio ) VALUES ($1, $2, 'jobSeeker', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) ON CONFLICT (identifier) DO UPDATE SET full_name = EXCLUDED.full_name, email = EXCLUDED.email, phone = EXCLUDED.phone, city = EXCLUDED.city, state = EXCLUDED.state, title = EXCLUDED.title, experience = EXCLUDED.experience, skills = EXCLUDED.skills, objective = EXCLUDED.objective, bio = EXCLUDED.bio `, [ cand.identifier, hash, cand.fullName, cand.email, cand.phone, cand.city, cand.state, cand.title, cand.experience, cand.skills, cand.objective, cand.bio ]); console.log(` ✓ Legacy candidate created: ${cand.email}`); } } catch (error) { console.error(' ❌ Error seeding users:', error.message); throw error; } }