A minimal Node.js backend for BroCode Spot backed by a persistent JSON file database.
npm run backendServer starts at http://localhost:4000 by default.
- Uses a local JSON database file at
backend/data/brocode.json. - You can override the location with
BROCODE_DB_PATH=/custom/path.json npm run backend. - On first start, seed data is inserted for users, spots, catalog items, and a sample order.
- New orders are validated against DB data (known
spotId,userId,productId) and item pricing is always derived from catalog prices in the database.
- Passwords are stored as salted
scrypthashes (not plaintext). - Legacy plaintext user passwords are auto-migrated to hashed values on successful login.
- Login is now rate-limited per
IP + usernamekey. - Defaults: 5 failed attempts within 15 minutes triggers a 15 minute temporary block (
429). - Configure via env vars:
LOGIN_RATE_LIMIT_MAX_ATTEMPTSLOGIN_RATE_LIMIT_WINDOW_MSLOGIN_RATE_LIMIT_BLOCK_MS
- Added optional Redis integration (
REDIS_URL) with automatic in-memory fallback when Redis is unavailable. - Active auth sessions are now stored in cache (token hash), and protected routes require an active session.
- Added cache-backed rate limiting primitives for login attempts (window + temporary block).
- Added short-lived cache for read-heavy endpoints:
GET /api/catalog(cached)GET /api/spots(cached)
- Added real-time presence endpoints:
POST /api/presence/heartbeatGET /api/presence/active?spotId=...
- Added temporary event state endpoints:
PUT|POST /api/events/state/:eventKeyGET /api/events/state/:eventKey
- New env vars:
REDIS_URLREDIS_KEY_PREFIXCACHE_DEFAULT_TTL_SECONDSPRESENCE_TTL_SECONDSEVENT_STATE_DEFAULT_TTL_SECONDS
- Login now returns an HMAC-signed bearer token (replacing predictable demo tokens).
- Tokens include user id, role, and expiry, and are validated with constant-time signature checks.
- Data endpoints now require
Authorization: Bearer <token>and enforce role access:GET /api/orders→ users can only read their own orders; admins can read all.POST /api/orders→ users can create only for themselves; admins can create for any user.GET /api/orders/:id→ users can read only their own order; admins can read any order.GET /api/bills/:spotIdandDELETE /api/users/:userId→ admin only.
- Configure via env vars:
AUTH_TOKEN_SECRETAUTH_TOKEN_TTL_SECONDSCORS_ALLOW_ORIGIN
- The backend initializes BullMQ queues for:
- email notification jobs (
email-notifications) when a new order is created. - scheduled reminder jobs (
spot-reminders) for upcoming spots/events. - recurring cleanup jobs (
expired-spot-cleanup) for expired events.
- email notification jobs (
- Redis connection settings:
REDIS_HOST(default127.0.0.1)REDIS_PORT(default6379)REDIS_PASSWORD(optional)
- Reminder timing:
EVENT_REMINDER_BEFORE_HOURS(default2)
- If BullMQ or Redis dependencies are unavailable, backend continues to run with jobs disabled and logs a warning.
- OpenAPI JSON is available at
GET /api/docs/openapi.json. - Swagger UI is available at
GET /api/docs.
GET /api/healthPOST /api/auth/loginGET /api/docsGET /api/docs/openapi.jsonGET /api/catalogPOST /api/auth/logoutGET /api/catalog(cached)GET /api/catalog/:category(drinks,food,cigarettes)GET /api/spots(cached)GET /api/orders?spotId=...&userId=...(auth required)GET /api/orders/:id(auth required)POST /api/orders(auth required)GET /api/bills/:spotId(admin only)DELETE /api/users/:userId(admin only; removes the user and all related records)POST /api/jobs/reminders/run(admin only; manually queue reminder jobs)POST /api/jobs/cleanup/run(admin only; manually queue expired-event cleanup)POST /api/presence/heartbeat(auth required)GET /api/presence/active?spotId=...(auth required)PUT|POST /api/events/state/:eventKey(auth required)GET /api/events/state/:eventKey(auth required)
{
"username": "brocode",
"password": "changeme"
}