TypeScript/Express + MongoDB REST API for posts, products, categories, orders, and users. JWT auth, role-based access, file uploads, rate limiting, and structured logging. Suitable for Docker and optional Cloudflare Tunnel exposure.
- Auth: JWT access + refresh, role checks (Admin, Editor)
- Product Management CRUD, category population, stock delta updates, image upload/replace
- Category Management CRUD with “in use” protection
- Post Management Simple CRUD
- Order System Stock validation & atomic updates, owner/role-based access
- CORS: Strict allowlist for production; dev-friendly options
- Logging: Request/event logs with client IP (behind proxies)
- Rate limits: Login throttling
- Docker-ready: Compose setup; optional Cloudflare Tunnel
- Backend: Node.js, Express.js, TypeScript
- Database: MongoDB (Mongoose)
- Authentication:: JWT (access & refresh tokens)
- Uploads:: Multer (2 MB limit; JPEG/PNG/GIF/WebP)
- Environment Configuration:: dotenv
mist-server/
├── src/
│ ├── config/ # env/config/constants (roles, shipping, statuses, regex, cors
│ ├── controllers/ # route handlers (auth, users, products, posts, categories, orders)
│ ├── middleware/ # verifyJWT, verifyRoles, rate limiter, credentials, error handler
│ ├── models/ # Mongoose schemas & TS types
│ ├── routes/ # Express routers
│ ├── services/ # business logic (DB ops, auth helpers)
│ ├── utils/ # helpers (order number, validation, etc.)
│ └── server.ts # app bootstrap
├── public/uploads/images/ # uploaded images (gitignored)
├── logs/ # request/error logs (created at runtime)
├── .env # Environment variables
├── .gitignore # Git ignored files
├── package.json
├── tsconfig.json
├── .gitignore
└── README.md # Project documentation
- Node.js ≥ 18 (LTS recommended)
- MongoDB (local or cloud)
- npm ≥ 9
-
Clone & install
git clone https://github.com/Aztaban/mist-server.git <your-repo-folder> cd <your-repo-folder> npm ci
-
Set up environment variables: Create a
.envfile in the root directory and add the following:PORT=3500 DATABASE_URI=<your-database-uri> ACCESS_TOKEN_SECRET=<your-jwt-secret> REFRESH_TOKEN_SECRET=<your-refresh-token-secret> CORS_ORIGINS=<your-allowed-cors-origins> STRIPE_API_SECRET=<your-stripe-api-secret> COOKIE_SECURE=<true|false> TRUST_PROXY=<true|false> UPLOAD_DIR:=<your-upload-directory>
-
Run in development mode:
npm run dev
-
Run in production mode:
npm run build npm start
Base paths have no /api prefix (e.g., /auth, /products, …).
Protect admin/editor routes in the router with verifyJWT then verifyRoles(...).
POST /auth/register- Register (password policy enforced)POST /auth/login- Issue access + refresh tokensGET /auth/refresh- Rotate access token (if enabled)POST /auth/logout- Invalidate refresh tokenPUT /user/password- Change password (current + new)
GET /users– Get all users (Admin,Editor)GET /users/:id– Get a specific user by ID (Admin)PATCH /users/:id/toggle-status– Enable/disable user account (Admin)PATCH /users/:id/toggle-editor– Grant/revoke editor role (Admin)
GET /users– Get logged-in user's profileGET /users/orders– Get user's own ordersPATCH /users/address– Update addressPATCH /users/phone– Update phone numberPATCH /users/email– Update emailPUT /users/password– Change password
GET /categories– Retrieve all categories
POST /categories– Create a new category (Admin,Editor)PATCH /categories/:id– Update an existing category (Admin,Editor)DELETE /categories/:id– Delete a category (Admin,Editor)
GET /posts– Get all postsGET /posts/:id– Get a specific post by ID
POST /posts– Create a new post (Admin,Editor)PUT /posts/:id– Update a post (Admin,Editor)DELETE /posts/:id– Delete a post (Admin)
GET /– Get all productsGET /:id– Get product by ID
POST /products– Create a new product (Admin,Editor)PATCH /products/:id– Update a product (Admin,Editor)POST /products/imageUpload– Upload a new product image (Admin,Editor)PUT /products/:id/image– Replace an existing product image (Admin,Editor)DELETE /products– Delete a single product by ID (passed in request body) (Admin)
POST /orders– Create a new orderGET /orders/:id– Get a specific order by IDPUT /orders/:id/mark-paid– Mark an order as paid (used after payment)
GET /orders– Get all orders (Admin,Editor)PATCH /orders/:id– Update an order status (e.g., shipped, delivered) (Admin,Editor)DELETE /orders/:id– Delete an order (Admin)
POST /orders/:id/payment-intent– Create a Stripe payment intent for the order
- Prod: allow only your FE origins (e.g., https://mist-gate.vercel.app).
- Dev: http://localhost:5173, etc.
- CORS uses Origin (the site), not visitor IPs.
- Set trust proxy behind Cloudflare/reverse proxies; log client IP from CF-Connecting-IP/X-Forwarded-For.
- Rate limit sensitive routes (login).
- Validate ObjectIds and request bodies (done in controllers/services).
- Logs are written to logs/ with timestamp + UUID.
- Request logger includes method, origin, path, and client IP (when proxied).
- Controllers call next(error); a global error handler maps err.status or defaults to 500.
- Common client errors: 400 Invalid ... id, 409 Category has products, 400 Stock cannot be negative, 401/403 auth failures.
This project is licensed under the MIT License. See the LICENSE file for details.