diff --git a/backend/README.md b/backend/README.md index b0b729b..f37b14e 100755 --- a/backend/README.md +++ b/backend/README.md @@ -75,10 +75,10 @@ O endpoint `/jobs` suporta filtros avançados via query params: | Método | Endpoint | Roles | Descrição | |--------|----------|-------|-----------| -| `GET` | `/api/v1/users` | `superadmin`, `companyAdmin` | Listar usuários | -| `POST` | `/api/v1/users` | `superadmin`, `companyAdmin` | Criar usuário | +| `GET` | `/api/v1/users` | `superadmin`, `admin` | Listar usuários | +| `POST` | `/api/v1/users` | `superadmin`, `admin` | Criar usuário | | `DELETE` | `/api/v1/users/{id}` | `superadmin` | Deletar usuário | -| `POST` | `/jobs` | `companyAdmin`, `recruiter` | Criar vaga | +| `POST` | `/jobs` | `admin`, `recruiter` | Criar vaga | --- diff --git a/backend/internal/core/domain/entity/user.go b/backend/internal/core/domain/entity/user.go index 8940bac..2d4e871 100644 --- a/backend/internal/core/domain/entity/user.go +++ b/backend/internal/core/domain/entity/user.go @@ -2,6 +2,20 @@ package entity import "time" +// Role type alias +type RoleString string + +const ( + // RoleSuperAdmin is the platform administrator + RoleSuperAdmin = "superadmin" + // RoleAdmin is the company administrator (formerly admin) + RoleAdmin = "admin" + // RoleRecruiter is a recruiter within a company + RoleRecruiter = "recruiter" + // RoleCandidate is a job seeker (formerly candidate) + RoleCandidate = "candidate" +) + // User represents a user within a specific Tenant (Company). type User struct { ID string `json:"id"` diff --git a/backend/internal/dto/auth.go b/backend/internal/dto/auth.go index 9823156..33cfad2 100755 --- a/backend/internal/dto/auth.go +++ b/backend/internal/dto/auth.go @@ -31,7 +31,7 @@ type UserInfo struct { type CompanyInfo struct { ID int `json:"id"` Name string `json:"name"` - Role string `json:"role"` // Role in this company (companyAdmin or recruiter) + Role string `json:"role"` // Role in this company (admin or recruiter) } // RegisterRequest represents user registration @@ -44,7 +44,7 @@ type RegisterRequest struct { LineID *string `json:"lineId,omitempty"` Instagram *string `json:"instagram,omitempty"` Language string `json:"language" validate:"required,oneof=pt en es ja"` - Role string `json:"role" validate:"required,oneof=jobSeeker recruiter companyAdmin"` + Role string `json:"role" validate:"required,oneof=candidate recruiter admin"` } // User represents a generic user profile diff --git a/backend/internal/dto/requests.go b/backend/internal/dto/requests.go index 5bba8f0..53e75b0 100755 --- a/backend/internal/dto/requests.go +++ b/backend/internal/dto/requests.go @@ -99,7 +99,7 @@ type UpdateCompanyRequest struct { type AssignUserToCompanyRequest struct { UserID string `json:"userId" validate:"required"` CompanyID string `json:"companyId" validate:"required"` - Role string `json:"role" validate:"required,oneof=companyAdmin recruiter"` + Role string `json:"role" validate:"required,oneof=admin recruiter"` Permissions map[string]interface{} `json:"permissions,omitempty"` } diff --git a/backend/internal/infrastructure/persistence/postgres/user_repository.go b/backend/internal/infrastructure/persistence/postgres/user_repository.go index 7876f31..f0ad53c 100644 --- a/backend/internal/infrastructure/persistence/postgres/user_repository.go +++ b/backend/internal/infrastructure/persistence/postgres/user_repository.go @@ -37,8 +37,8 @@ func (r *UserRepository) Save(ctx context.Context, user *entity.User) (*entity.U ` var id string - // Map the first role to the role column, default to 'jobSeeker' - role := "jobSeeker" + // Map the first role to the role column, default to 'candidate' + role := "candidate" if len(user.Roles) > 0 { role = user.Roles[0].Name } diff --git a/backend/internal/middleware/README.md b/backend/internal/middleware/README.md index f00abfd..28ad909 100644 --- a/backend/internal/middleware/README.md +++ b/backend/internal/middleware/README.md @@ -20,7 +20,7 @@ mux.Handle("/admin", AuthMiddleware(RequireRole("superadmin")(handler))) **Claims extraídas:** - `UserID` - ID do usuário -- `Role` - Papel (superadmin, companyAdmin, recruiter, jobSeeker) +- `Role` - Papel (superadmin, admin, recruiter, candidate) - `CompanyID` - ID da empresa (se aplicável) --- diff --git a/backend/internal/models/user.go b/backend/internal/models/user.go index 01fdbc0..e30e669 100755 --- a/backend/internal/models/user.go +++ b/backend/internal/models/user.go @@ -7,7 +7,7 @@ type User struct { ID string `json:"id" db:"id"` Identifier string `json:"identifier" db:"identifier"` PasswordHash string `json:"-" db:"password_hash"` // Never expose password hash in JSON - Role string `json:"role" db:"role"` // superadmin, companyAdmin, recruiter, jobSeeker + Role string `json:"role" db:"role"` // superadmin, admin, recruiter, candidate // Personal Info FullName string `json:"fullName" db:"full_name"` diff --git a/backend/internal/models/user_company.go b/backend/internal/models/user_company.go index 4ab1e87..2c71aec 100755 --- a/backend/internal/models/user_company.go +++ b/backend/internal/models/user_company.go @@ -11,7 +11,7 @@ type UserCompany struct { ID string `json:"id" db:"id"` UserID string `json:"userId" db:"user_id"` CompanyID string `json:"companyId" db:"company_id"` - Role string `json:"role" db:"role"` // companyAdmin, recruiter + Role string `json:"role" db:"role"` // admin, recruiter Permissions JSONMap `json:"permissions,omitempty" db:"permissions"` CreatedAt time.Time `json:"createdAt" db:"created_at"` } diff --git a/backend/internal/services/admin_service.go b/backend/internal/services/admin_service.go index 645ed2e..bd31833 100644 --- a/backend/internal/services/admin_service.go +++ b/backend/internal/services/admin_service.go @@ -276,7 +276,7 @@ func (s *AdminService) ListCandidates(ctx context.Context) ([]dto.Candidate, dto query := ` SELECT id, full_name, email, phone, city, state, title, experience, bio, skills, avatar_url, created_at FROM users - WHERE role = 'jobSeeker' + WHERE role = 'candidate' ORDER BY created_at DESC ` diff --git a/backend/migrations/001_create_users_table.sql b/backend/migrations/001_create_users_table.sql index 9f26a72..81f71ae 100755 --- a/backend/migrations/001_create_users_table.sql +++ b/backend/migrations/001_create_users_table.sql @@ -5,7 +5,7 @@ CREATE TABLE IF NOT EXISTS users ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), identifier VARCHAR(100) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, - role VARCHAR(20) NOT NULL CHECK (role IN ('superadmin', 'companyAdmin', 'recruiter', 'jobSeeker')), + role VARCHAR(20) NOT NULL CHECK (role IN ('superadmin', 'admin', 'recruiter', 'candidate')), -- Personal Info full_name VARCHAR(255), @@ -32,4 +32,4 @@ CREATE INDEX idx_users_active ON users(active); -- Comments for documentation COMMENT ON TABLE users IS 'Stores all system users across all roles'; COMMENT ON COLUMN users.identifier IS 'Username for login (NOT email)'; -COMMENT ON COLUMN users.role IS 'User role: superadmin, companyAdmin, recruiter, or jobSeeker'; +COMMENT ON COLUMN users.role IS 'User role: superadmin, admin, recruiter, or candidate'; diff --git a/backend/migrations/003_create_user_companies_table.sql b/backend/migrations/003_create_user_companies_table.sql index ddb90d8..d992fd2 100755 --- a/backend/migrations/003_create_user_companies_table.sql +++ b/backend/migrations/003_create_user_companies_table.sql @@ -5,7 +5,7 @@ CREATE TABLE IF NOT EXISTS user_companies ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), user_id UUID NOT NULL, company_id UUID NOT NULL, - role VARCHAR(20) NOT NULL CHECK (role IN ('companyAdmin', 'recruiter')), + role VARCHAR(20) NOT NULL CHECK (role IN ('admin', 'recruiter')), permissions JSONB, -- Optional granular permissions created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, @@ -25,5 +25,5 @@ CREATE INDEX idx_user_companies_role ON user_companies(role); -- Comments COMMENT ON TABLE user_companies IS 'Multi-tenant pivot: links users to companies with specific roles'; -COMMENT ON COLUMN user_companies.role IS 'Role within this company: companyAdmin or recruiter'; +COMMENT ON COLUMN user_companies.role IS 'Role within this company: admin or recruiter'; COMMENT ON COLUMN user_companies.permissions IS 'Optional JSON object for granular permissions per company'; diff --git a/backend/migrations/008_create_password_resets_table.sql b/backend/migrations/008_create_password_resets_table.sql index 5561c24..d822c8a 100755 --- a/backend/migrations/008_create_password_resets_table.sql +++ b/backend/migrations/008_create_password_resets_table.sql @@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS password_resets ( id SERIAL PRIMARY KEY, - user_id INT NOT NULL, + user_id UUID NOT NULL, token VARCHAR(255) UNIQUE NOT NULL, expires_at TIMESTAMP NOT NULL, used BOOLEAN DEFAULT false, diff --git a/backend/migrations/017_create_tickets_table.sql b/backend/migrations/017_create_tickets_table.sql index 2f8de9c..cf1ae9a 100644 --- a/backend/migrations/017_create_tickets_table.sql +++ b/backend/migrations/017_create_tickets_table.sql @@ -1,6 +1,3 @@ -DROP TABLE IF EXISTS ticket_messages; -DROP TABLE IF EXISTS tickets; - CREATE TABLE tickets ( id UUID PRIMARY KEY DEFAULT uuid_generate_v7(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, diff --git a/docs/API.md b/docs/API.md index 23d2e39..ed72a12 100644 --- a/docs/API.md +++ b/docs/API.md @@ -18,9 +18,9 @@ Complete API reference with routes, permissions, and modules. | Role | Code | Level | Description | |------|------|-------|-------------| | **SuperAdmin** | `superadmin` | 0 | Platform administrator | -| **CompanyAdmin** | `companyAdmin` | 1 | Company administrator | +| **Admin** | `admin` | 1 | Company administrator | | **Recruiter** | `recruiter` | 2 | Job poster | -| **JobSeeker** | `jobSeeker` | 3 | Candidate | +| **Candidate** | `candidate` | 3 | Candidate | | **Guest** | - | - | No authentication | --- @@ -124,7 +124,7 @@ POST /api/v1/users ``` | Field | Auth | Roles | Description | |-------|------|-------|-------------| -| Protected | ✅ | superadmin, companyAdmin | Create new user | +| Protected | ✅ | superadmin, admin | Create new user | ### Update User ```http @@ -186,7 +186,7 @@ POST /api/v1/jobs ``` | Field | Auth | Roles | Description | |-------|------|-------|-------------| -| Public* | ❌ | companyAdmin, recruiter | Create new job posting | +| Public* | ❌ | admin, recruiter | Create new job posting | ### Update Job ```http @@ -194,7 +194,7 @@ PUT /api/v1/jobs/{id} ``` | Field | Auth | Roles | Description | |-------|------|-------|-------------| -| Public* | ❌ | companyAdmin, recruiter | Update job posting | +| Public* | ❌ | admin, recruiter | Update job posting | ### Delete Job ```http @@ -202,7 +202,7 @@ DELETE /api/v1/jobs/{id} ``` | Field | Auth | Roles | Description | |-------|------|-------|-------------| -| Public* | ❌ | companyAdmin, recruiter | Delete job posting | +| Public* | ❌ | admin, recruiter | Delete job posting | ### List Jobs for Moderation ```http @@ -258,7 +258,7 @@ GET /api/v1/applications ``` | Field | Auth | Roles | Description | |-------|------|-------|-------------| -| Public | ❌ | companyAdmin, recruiter | List applications | +| Public | ❌ | admin, recruiter | List applications | ### Get Application by ID ```http @@ -266,7 +266,7 @@ GET /api/v1/applications/{id} ``` | Field | Auth | Roles | Description | |-------|------|-------|-------------| -| Public | ❌ | companyAdmin, recruiter | Get application details | +| Public | ❌ | admin, recruiter | Get application details | ### Update Application Status ```http @@ -274,7 +274,7 @@ PUT /api/v1/applications/{id}/status ``` | Field | Auth | Roles | Description | |-------|------|-------|-------------| -| Public | ❌ | companyAdmin, recruiter | Update application status | +| Public | ❌ | admin, recruiter | Update application status | **Request:** ```json diff --git a/docs/API_SECURITY.md b/docs/API_SECURITY.md index 847c7e0..ddcc067 100644 --- a/docs/API_SECURITY.md +++ b/docs/API_SECURITY.md @@ -27,8 +27,8 @@ This document details the security layers, authentication methods, and role-base | Method | Route | Description | Notes | | :--- | :--- | :--- | :--- | | `POST` | `/api/v1/auth/login` | User Login | Returns JWT + Cookie | -| `POST` | `/api/v1/auth/register` | Candidate Register | Creates `jobSeeker` user | -| `POST` | `/api/v1/companies` | Company Register | Creates company + `companyAdmin` | +| `POST` | `/api/v1/auth/register` | Candidate Register | Creates `candidate` user | +| `POST` | `/api/v1/companies` | Company Register | Creates company + `admin` | | `GET` | `/api/v1/jobs` | List Jobs | Public search/list | | `GET` | `/api/v1/jobs/{id}` | Get Job | Public details | | `GET` | `/docs/*` | Swagger UI | API Documentation | @@ -47,7 +47,7 @@ This document details the security layers, authentication methods, and role-base | `DELETE` | `/api/v1/storage/files` | Delete S3 File | ### 🟠 Recruiter / CompanyAdmin Routes -**Requirement**: Role `companyAdmin` OR `recruiter`. +**Requirement**: Role `admin` OR `recruiter`. | Method | Route | Description | | :--- | :--- | :--- | diff --git a/docs/DATABASE.md b/docs/DATABASE.md index fff252b..10c3fc5 100644 --- a/docs/DATABASE.md +++ b/docs/DATABASE.md @@ -156,7 +156,7 @@ CREATE TABLE users ( id SERIAL PRIMARY KEY, identifier VARCHAR(100) UNIQUE NOT NULL, -- Login (username/email) password_hash VARCHAR(255) NOT NULL, - role VARCHAR(20) NOT NULL, -- 'superadmin'|'companyAdmin'|'recruiter'|'jobSeeker' + role VARCHAR(20) NOT NULL, -- 'superadmin'|'admin'|'recruiter'|'candidate' -- Profile full_name VARCHAR(255), @@ -190,9 +190,9 @@ CREATE TABLE users ( **Roles:** - `superadmin` - Platform administrator -- `companyAdmin` - Company administrator +- `admin` - Company administrator - `recruiter` - Job poster/recruiter -- `jobSeeker` - Candidate/job seeker +- `candidate` - Candidate/job seeker --- @@ -544,7 +544,7 @@ CREATE TABLE user_companies ( id SERIAL PRIMARY KEY, user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE, company_id INT NOT NULL REFERENCES companies(id) ON DELETE CASCADE, - role VARCHAR(30) DEFAULT 'recruiter', -- 'companyAdmin'|'recruiter' + role VARCHAR(30) DEFAULT 'recruiter', -- 'admin'|'recruiter' permissions JSONB, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(user_id, company_id) diff --git a/frontend/src/app/dashboard/page.tsx b/frontend/src/app/dashboard/page.tsx index 72392ad..661d258 100644 --- a/frontend/src/app/dashboard/page.tsx +++ b/frontend/src/app/dashboard/page.tsx @@ -33,11 +33,11 @@ export default function DashboardPage() { return } - if (user.role === "company" || user.roles?.includes("companyAdmin")) { + if (user.role === "company" || user.roles?.includes("admin")) { return } - if (user.role === "candidate" || user.roles?.includes("jobSeeker")) { + if (user.role === "candidate" || user.roles?.includes("candidate")) { return } diff --git a/frontend/src/app/dashboard/users/page.tsx b/frontend/src/app/dashboard/users/page.tsx index 97dab94..d8d2505 100644 --- a/frontend/src/app/dashboard/users/page.tsx +++ b/frontend/src/app/dashboard/users/page.tsx @@ -45,7 +45,7 @@ export default function AdminUsersPage() { name: "", email: "", password: "", - role: "jobSeeker", + role: "candidate", }) const [editFormData, setEditFormData] = useState({ name: "", @@ -85,7 +85,7 @@ export default function AdminUsersPage() { await usersApi.create(formData) toast.success("User created successfully!") setIsDialogOpen(false) - setFormData({ name: "", email: "", password: "", role: "jobSeeker" }) + setFormData({ name: "", email: "", password: "", role: "candidate" }) setPage(1) loadUsers(1) } catch (error) { @@ -158,18 +158,16 @@ export default function AdminUsersPage() { const getRoleBadge = (role: string) => { const labels: Record = { superadmin: "Super Admin", - companyAdmin: "Company admin", + admin: "Company Admin", recruiter: "Recruiter", - jobSeeker: "Candidate", - admin: "Admin", + candidate: "Candidate", company: "Company" } const colors: Record = { superadmin: "destructive", - companyAdmin: "default", + admin: "default", recruiter: "secondary", - jobSeeker: "outline", - admin: "destructive", + candidate: "outline", company: "default" } const label = labels[role] || role || "User" @@ -239,9 +237,9 @@ export default function AdminUsersPage() { Super Admin - Company admin + Company admin Recruiter - Candidate + Candidate @@ -307,7 +305,7 @@ export default function AdminUsersPage() { Admins (page) - {users.filter((u) => u.role === "superadmin" || u.role === "companyAdmin").length} + {users.filter((u) => u.role === "superadmin" || u.role === "admin" || u.role === "admin").length} @@ -320,7 +318,7 @@ export default function AdminUsersPage() { Candidates (page) - {users.filter((u) => u.role === "jobSeeker").length} + {users.filter((u) => u.role === "candidate" || u.role === "candidate").length} diff --git a/frontend/src/lib/auth.ts b/frontend/src/lib/auth.ts index 8645e31..5037ff1 100644 --- a/frontend/src/lib/auth.ts +++ b/frontend/src/lib/auth.ts @@ -44,9 +44,11 @@ export async function login( // Note: The backend returns roles as an array of strings. The frontend expects a single 'role' or we need to adapt. // For now we map the first role or main role to the 'role' field. let userRole: "candidate" | "admin" | "company" = "candidate"; - if (data.user.roles.includes("superadmin") || data.user.roles.includes("admin") || data.user.roles.includes("ADMIN") || data.user.roles.includes("SUPERADMIN")) { + // Check for SuperAdmin (Platform Admin) + if (data.user.roles.includes("superadmin") || data.user.roles.includes("SUPERADMIN")) { userRole = "admin"; - } else if (data.user.roles.includes("companyAdmin") || data.user.roles.includes("recruiter")) { + // Check for Company Admin (now called 'admin') or Recruiter + } else if (data.user.roles.includes("admin") || data.user.roles.includes("recruiter")) { userRole = "company"; } diff --git a/seeder-api/src/index.js b/seeder-api/src/index.js index d55e037..2bd6208 100644 --- a/seeder-api/src/index.js +++ b/seeder-api/src/index.js @@ -14,19 +14,26 @@ async function resetDatabase() { console.log('🗑️ Resetting database...'); try { - // Drop all tables in reverse order (respecting foreign keys) - await pool.query('DROP TABLE IF EXISTS password_resets CASCADE'); - await pool.query('DROP TABLE IF EXISTS favorite_jobs CASCADE'); - await pool.query('DROP TABLE IF EXISTS applications CASCADE'); - await pool.query('DROP TABLE IF EXISTS jobs CASCADE'); - await pool.query('DROP TABLE IF EXISTS user_companies CASCADE'); - await pool.query('DROP TABLE IF EXISTS companies CASCADE'); - await pool.query('DROP TABLE IF EXISTS users CASCADE'); - await pool.query('DROP TABLE IF EXISTS cities CASCADE'); - await pool.query('DROP TABLE IF EXISTS regions CASCADE'); - await pool.query('DROP TABLE IF EXISTS prefectures CASCADE'); // Legacy drop + // Dynamic drop: Fetch all tables in public schema and drop them + // This avoids "must be owner of schema public" error by operating on tables directly + console.log('🔍 Finding tables to drop...'); + const tablesResult = await pool.query(` + SELECT tablename + FROM pg_tables + WHERE schemaname = 'public' + `); - console.log('✅ All tables dropped successfully'); + if (tablesResult.rows.length > 0) { + const tables = tablesResult.rows.map(row => row.tablename); + console.log(`🔥 Dropping ${tables.length} tables: ${tables.join(', ')}`); + + // Construct a single DROP statement for all tables (CASCADE handles dependencies) + const tableList = tables.map(t => `"${t}"`).join(', '); + await pool.query(`DROP TABLE IF EXISTS ${tableList} CASCADE`); + console.log('✅ All public tables dropped successfully.'); + } else { + console.log('ℹ️ No tables found to drop IN public schema.'); + } } catch (error) { console.error('❌ Error resetting database:', error.message); throw error; diff --git a/seeder-api/src/seeders/jobs.js b/seeder-api/src/seeders/jobs.js index 3b226b8..98f64a3 100644 --- a/seeder-api/src/seeders/jobs.js +++ b/seeder-api/src/seeders/jobs.js @@ -80,7 +80,12 @@ export async function seedJobs() { let totalJobs = 0; try { + // Process companies in chunks to avoid overwhelming the DB for (const company of companies) { + const jobValues = []; + const jobParams = []; + let paramCounter = 1; + // Generate 25 jobs per company for (let i = 0; i < 25; i++) { const template = jobTemplates[i % jobTemplates.length]; @@ -98,13 +103,8 @@ export async function seedJobs() { const currency = currencies[i % currencies.length]; const salaryType = salaryTypes[i % salaryTypes.length]; - // jobs.id is SERIAL - let DB auto-generate - await pool.query(` - INSERT INTO jobs (company_id, created_by, title, description, - salary_min, salary_max, salary_type, currency, employment_type, working_hours, - location, requirements, benefits, visa_support, language_level, status, work_mode) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) - `, [ + // Prepare params for bulk insert + jobParams.push( company.id, seedUserId, title, @@ -122,11 +122,28 @@ export async function seedJobs() { 'beginner', 'open', workMode - ]); + ); + // ($1, $2, $3, ...), ($18, $19, ...) + const placeHolders = []; + for (let k = 0; k < 17; k++) { + placeHolders.push(`$${paramCounter++}`); + } + jobValues.push(`(${placeHolders.join(',')})`); totalJobs++; } + + // Bulk Insert for this company + if (jobValues.length > 0) { + const query = ` + INSERT INTO jobs (company_id, created_by, title, description, + salary_min, salary_max, salary_type, currency, employment_type, working_hours, + location, requirements, benefits, visa_support, language_level, status, work_mode) + VALUES ${jobValues.join(',')} + `; + await pool.query(query, jobParams); + } } console.log(` ✓ ${totalJobs} jobs seeded across ${companies.length} companies`); diff --git a/seeder-api/src/seeders/notifications.js b/seeder-api/src/seeders/notifications.js index 11de134..301e955 100644 --- a/seeder-api/src/seeders/notifications.js +++ b/seeder-api/src/seeders/notifications.js @@ -108,7 +108,7 @@ export async function seedNotifications() { createdAt.setHours(createdAt.getHours() - hoursAgo); await pool.query(` - INSERT INTO notifications (id, user_id, title, message, type, is_read, created_at, updated_at) + INSERT INTO notifications (id, user_id, title, message, type, read_at, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ON CONFLICT (id) DO NOTHING `, [ @@ -117,7 +117,7 @@ export async function seedNotifications() { template.title, template.message, template.type, - template.is_read, + template.is_read ? new Date() : null, createdAt, createdAt ]); diff --git a/seeder-api/src/seeders/users.js b/seeder-api/src/seeders/users.js index 21f8268..3eb7f69 100644 --- a/seeder-api/src/seeders/users.js +++ b/seeder-api/src/seeders/users.js @@ -40,13 +40,13 @@ export async function seedUsers() { console.log(' ✓ SuperAdmin created (superadmin)'); // 2. Create Company Admins - const companyAdmins = [ - { identifier: 'takeshi_yamamoto', fullName: 'Takeshi Yamamoto', company: 'TechCorp', email: 'takeshi@techcorp.com', pass: 'Takeshi@2025', roles: ['companyAdmin'] }, - { identifier: 'kenji', fullName: 'Kenji Tanaka', company: 'AppMakers', email: 'kenji@appmakers.mobile', pass: 'Takeshi@2025', roles: ['companyAdmin'] }, + const admins = [ + { identifier: 'takeshi_yamamoto', fullName: 'Takeshi Yamamoto', company: 'TechCorp', email: 'takeshi@techcorp.com', pass: 'Takeshi@2025', roles: ['admin'] }, + { identifier: 'kenji', fullName: 'Kenji Tanaka', company: 'AppMakers', email: 'kenji@appmakers.mobile', pass: 'Takeshi@2025', roles: ['admin'] }, { identifier: 'maria_santos', fullName: 'Maria Santos', company: 'DesignHub', email: 'maria@designhub.com', pass: 'User@2025', roles: ['recruiter'] } ]; - for (const admin of companyAdmins) { + for (const admin of admins) { const hash = await bcrypt.hash(admin.pass + PASSWORD_PEPPER, 10); const tenantId = companyMap[admin.company]; @@ -86,7 +86,7 @@ export async function seedUsers() { const result = await pool.query(` INSERT INTO users (identifier, password_hash, role, full_name, email, name, status) - VALUES ($1, $2, 'jobSeeker', $3, $4, $5, 'active') + VALUES ($1, $2, 'candidate', $3, $4, $5, 'active') ON CONFLICT (identifier) DO UPDATE SET password_hash = EXCLUDED.password_hash RETURNING id `, [cand.identifier, hash, cand.fullName, cand.email, cand.fullName]); @@ -178,7 +178,7 @@ export async function seedUsers() { INSERT INTO users ( identifier, password_hash, role, full_name, email, name, phone, city, state, title, experience, skills, objective, bio, status - ) VALUES ($1, $2, 'jobSeeker', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, 'active') + ) VALUES ($1, $2, 'candidate', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, 'active') ON CONFLICT (identifier) DO UPDATE SET full_name = EXCLUDED.full_name, email = EXCLUDED.email,