- Correct all passwords (were wrong/outdated) - Add full table of current seeded users (superadmin, admins, candidates) - Document 3 bugs fixed 2026-02-24: - superadmin placeholder hash (seeder fix) - users.status VARCHAR(20) crash loop (migration fix) - PASSWORD_PEPPER alignment requirement - Add bash ! expansion gotcha for curl testing Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
140 lines
5.4 KiB
Markdown
140 lines
5.4 KiB
Markdown
# 🧪 Test Users & Credentials — GoHorseJobs
|
|
|
|
All accounts below are provisioned by `seeder-api` against the DEV environment (`local.gohorsejobs.com` / `api-local.gohorsejobs.com`).
|
|
|
|
> **Last verified:** 2026-02-24
|
|
> **Environment:** Coolify DEV (Redbull VPS)
|
|
> **Auth endpoint:** `POST https://api-local.gohorsejobs.com/api/v1/auth/login`
|
|
|
|
---
|
|
|
|
## Login Payload Format
|
|
|
|
```json
|
|
{ "email": "<identifier OR email>", "password": "<password>" }
|
|
```
|
|
|
|
The `"email"` JSON key accepts **both** the username (`identifier`) and the actual e-mail address. The backend resolves `WHERE email = $1 OR identifier = $1`.
|
|
|
|
---
|
|
|
|
## 👑 SuperAdmin
|
|
|
|
| Identifier | Email | Password | Role |
|
|
|---|---|---|---|
|
|
| `lol` | `lol@gohorsejobs.com` | `Admin@2025!` | superadmin |
|
|
| `superadmin` | `admin@gohorsejobs.com` | `Admin@2025!` | superadmin |
|
|
|
|
Both identifiers grant full system access. `lol` is the primary dev account; `superadmin` is the alias created by migration 010.
|
|
|
|
---
|
|
|
|
## 🏢 Admins / Recruiters
|
|
|
|
| Identifier | Email | Password | Role | Company |
|
|
|---|---|---|---|---|
|
|
| `takeshi_yamamoto` | `takeshi@techcorp.com` | `Takeshi@2025` | admin | TechCorp |
|
|
| `kenji` | `kenji@appmakers.mobile` | `Takeshi@2025` | admin | AppMakers |
|
|
| `maria_santos` | `maria@designhub.com` | `User@2025` | recruiter | DesignHub |
|
|
| `wile_e_coyote` | `wile@acme.corp` | `MeepMeep@123` | admin | ACME Corporation |
|
|
|
|
---
|
|
|
|
## 🙋 Candidates
|
|
|
|
### Unified Users (identifier-based login)
|
|
|
|
| Identifier | Email | Password | Name |
|
|
|---|---|---|---|
|
|
| `paulo_santos` | `paulo@email.com` | `User@2025` | Paulo Santos |
|
|
| `maria_email` | `maria@email.com` | `User@2025` | Maria Reyes |
|
|
|
|
### Legacy Candidates (email-based login)
|
|
|
|
| Email | Password | Name |
|
|
|---|---|---|
|
|
| `ana.silva@example.com` | `User@2025` | Ana Silva |
|
|
| `carlos.santos@example.com` | `User@2025` | Carlos Santos |
|
|
| `maria.oliveira@example.com` | `User@2025` | Maria Oliveira |
|
|
| `pedro.costa@example.com` | `User@2025` | Pedro Costa |
|
|
| `juliana.ferreira@example.com` | `User@2025` | Juliana Ferreira |
|
|
|
|
---
|
|
|
|
## 🌱 Seeding & Reset
|
|
|
|
```bash
|
|
# Reset all data (drops and recreates all public tables)
|
|
curl -X POST https://s-local.gohorsejobs.com/reset
|
|
|
|
# Re-seed everything (locations, users, companies, jobs, applications)
|
|
curl https://s-local.gohorsejobs.com/seed/stream
|
|
|
|
# After reset+seed, the backend must be reachable so migrations have already run.
|
|
# The seeder does NOT apply Go migrations — they run on backend startup.
|
|
```
|
|
|
|
> **Order matters after a full DB wipe:**
|
|
> 1. Wait for the backend container to finish running migrations (check `GET /api/v1/jobs` returns `[]`)
|
|
> 2. Then run `POST /reset` → `GET /seed/stream`
|
|
|
|
---
|
|
|
|
## ⚠️ Known Issues / Gotchas
|
|
|
|
### 1. `superadmin` login broken after DB reset (FIXED 2026-02-24)
|
|
|
|
**Bug:** Migration `010_seed_super_admin.sql` creates the `superadmin` user with a hardcoded placeholder hash (`$invalid-placeholder-run-seeder$`). The seeder previously only updated `lol`'s hash, leaving `superadmin` permanently unable to log in after a DB reset.
|
|
|
|
**Root cause:** `ON CONFLICT DO NOTHING` in migration 010 means the user exists in the DB but with an unusable hash. The seeder's upsert only covered the `lol` identifier.
|
|
|
|
**Fix (commit `6b1c058`):** `seeder-api/src/seeders/users.js` now also upserts `superadmin` with the same runtime-generated hash as `lol`:
|
|
```js
|
|
// Uses the same bcrypt(pass + PASSWORD_PEPPER) hash already computed for lol
|
|
await pool.query(`
|
|
INSERT INTO users (identifier, password_hash, ...) VALUES ('superadmin', $1, ...)
|
|
ON CONFLICT (identifier) DO UPDATE SET password_hash = EXCLUDED.password_hash, status = 'active'
|
|
`, [superAdminHash]);
|
|
```
|
|
|
|
**Affected versions:** All environments before `6b1c058`. Triggered on every fresh DB seed.
|
|
|
|
---
|
|
|
|
### 2. `users.status` column too short — backend crash loop on startup (FIXED 2026-02-24)
|
|
|
|
**Bug:** Migration `009_unify_schema.sql` defined `status VARCHAR(20)`. Migration `010_seed_super_admin.sql` tried to insert `'force_change_password'` (21 chars), crashing the backend with `pq: value too long for type character varying(20)` on every restart.
|
|
|
|
**Fix (commit `e5e4397`):**
|
|
- `009`: `VARCHAR(20)` → `VARCHAR(30)`
|
|
- `010`: initial status changed from `'force_change_password'` → `'pending'`
|
|
- New migration `046_fix_user_status_varchar.sql`: `ALTER TABLE users ALTER COLUMN status TYPE VARCHAR(30)` for existing deployments
|
|
|
|
---
|
|
|
|
### 3. `PASSWORD_PEPPER` must match between seeder and backend
|
|
|
|
All password hashes are stored as `bcrypt(password + PASSWORD_PEPPER)`. Both the seeder-api and backend must have the **same** `PASSWORD_PEPPER` env var, or all logins return `401 invalid credentials`.
|
|
|
|
**DEV value:** `gohorse-pepper`
|
|
**Confirmed in:** Coolify backend env + Coolify seeder env
|
|
|
|
If logins break after a deploy: check `docker inspect <backend_container> --format '{{.Config.Env}}'` for `PASSWORD_PEPPER`, then re-run the seeder.
|
|
|
|
---
|
|
|
|
### 4. Bash `!` expansion breaks login tests via curl
|
|
|
|
When testing logins from the shell, passwords containing `!` (e.g. `Admin@2025!`) must be in a file or use `$'...'` syntax. Using `"Admin@2025!"` in double-quotes causes bash history expansion (`\!`), producing invalid JSON and a `400 Invalid Request`.
|
|
|
|
```bash
|
|
# WRONG (bash expands !)
|
|
curl ... -d '{"email":"lol","password":"Admin@2025!"}' # OK in single quotes
|
|
curl ... -d "{\"email\":\"lol\",\"password\":\"Admin@2025!\"}" # BROKEN
|
|
|
|
# CORRECT — use a file
|
|
cat > /tmp/login.json << 'EOF'
|
|
{"email":"lol","password":"Admin@2025!"}
|
|
EOF
|
|
curl -X POST .../auth/login -d @/tmp/login.json
|
|
```
|