Skip to content

abhijithwinddaa/Fastor-Nodejs-Assignment

Repository files navigation

Fastor Node.js Assignment – CRM Leads API

A secure REST API for a simple CRM focused on lead management. Counselors can register/login, view public (unclaimed) enquiries, claim leads to make them private, and view their own claimed enquiries. Public users can submit enquiries without authentication.

Tech Stack

  • Node.js, Express.js
  • SQLite (via Sequelize ORM)
  • JWT (jsonwebtoken)
  • bcrypt for password hashing
  • dotenv, nodemon

Endpoints (Summary)

  • Employees
    • POST /api/employees/register – register a counselor
    • POST /api/employees/login – login and receive JWT
  • Enquiries
    • POST /api/enquiries/public – submit enquiry (public, no auth)
    • GET /api/enquiries/public – list unclaimed enquiries (auth)
    • PATCH /api/enquiries/:id/claim – claim an unclaimed enquiry (auth)
    • GET /api/enquiries/private – list enquiries claimed by logged-in counselor (auth)

Project Structure

crm-backend/
├── config/
│   └── database.js
├── controllers/
│   ├── employeeController.js
│   └── enquiryController.js
├── middlewares/
│   └── auth.js
├── models/
│   ├── employee.js
│   ├── enquiry.js
│   └── index.js
├── routes/
│   ├── employeeRoutes.js
│   └── enquiryRoutes.js
├── server.js
├── package.json
└── README.md

Setup

  1. Prerequisites
  • Install Node.js 18+
  1. Install dependencies
npm install
  1. Environment variables
  • Create a .env file in the project root:
PORT=3000
JWT_SECRET=CHANGE_ME_SUPER_SECRET
DB_DIALECT=sqlite
DB_STORAGE=./crm_db.sqlite
  1. Run the server
  • Development (auto-reload):
npm run dev
  • Or normal start:
npm start
  • You should see: Server listening on port 3000

Test with Postman (Step-by-step)

Importantly, for all authenticated requests, add a header:

  • Key: Authorization
  • Value: Bearer YOUR_JWT_TOKEN
  1. Register a counselor (no auth)
  • Method: POST
  • URL: http://localhost:3000/api/employees/register
  • Body → raw → JSON:
{
  "name": "Alice",
  "email": "alice@example.com",
  "password": "Password123!"
}
  • Expect 201 Created
  1. Login to get a token
  • Method: POST
  • URL: http://localhost:3000/api/employees/login
  • Body → raw → JSON:
{
  "email": "alice@example.com",
  "password": "Password123!"
}
  • Copy the token from the response
  1. Submit a public enquiry (no auth)
  • Method: POST
  • URL: http://localhost:3000/api/enquiries/public
  • Body → raw → JSON:
{
  "name": "John Doe",
  "email": "john@example.com",
  "courseInterest": "Node.js"
}
  • Expect 201 with { "id": <number> }
  1. See public (unclaimed) enquiries (auth required)
  • Method: GET
  • URL: http://localhost:3000/api/enquiries/public
  • Headers: Authorization: Bearer YOUR_JWT_TOKEN
  • Expect a list with your unclaimed enquiry, note its id
  1. Claim a specific lead (auth required)
  • Method: PATCH
  • URL: http://localhost:3000/api/enquiries/<ID>/claim
    • Replace <ID> with the numeric id from step 3 or 4
  • Headers: Authorization: Bearer YOUR_JWT_TOKEN
  • Expect success with claimed: true and counselorId set
  1. See your private (claimed) enquiries (auth required)
  • Method: GET
  • URL: http://localhost:3000/api/enquiries/private
  • Headers: Authorization: Bearer YOUR_JWT_TOKEN
  • Expect to see the enquiry you just claimed

Troubleshooting

  • secretOrPrivateKey must have a value.env is missing or JWT_SECRET not set; create .env, restart server
  • 401 Not authorized → Missing/expired token; login again and use new token
  • 404 Enquiry not found → Wrong id or different DB; list public enquiries and use a valid id
  • 409 already claimed → The enquiry was claimed; try a different id

Notes

  • SQLite DB file crm_db.sqlite is created automatically on first run
  • Keep your real .env out of version control; share a .env.example instead

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published