RESTful API in Express with jwt authentication
This project is the API-only backend for The Odin Project Blog API assignment. It is a REST API designed to be consumed by two React frontends for blog authoring + viewing.
- Routes should use RESTful organization
- Users, posts, and comments should be stored in MongoDB and modelled in Mongoose
- JSON Web Tokens should authenticate users for protected routes
HTTP Verb | Endpoints | Action |
---|---|---|
POST | /users | Sign up a new user account |
POST | /auth/login | Login an existing user account |
PUT | /users/permissions | Update user permissions (admin) |
GET | /users/:user_id | Get user information (self/admin) |
DELETE | /users/:user_id | Delete user account (self/admin) |
GET | /users | Get all users (admin) |
HTTP Verb | Endpoints | Action |
---|---|---|
GET | /posts | Get all published posts |
GET | /posts/unpublished | Get unpublished posts (admin) |
POST | /posts | Create new post (author) |
GET | /:post_slug | Get a single blog post |
PUT | /:post_slug | Update post content (post author) |
PUT | /:post_slug/publish | Publish post (post author) |
PUT | /:post_slug/unpublish | Unpublish post (post author) |
DELETE | /:post_slug | Delete post (post author) |
HTTP Verb | Endpoints | Action |
---|---|---|
GET | /:post_slug/comments | Get all post comments |
POST | /:post_slug/comments | Create a new comment (users) |
POST | /:post_slug/comments/:comment_id | Reply to a comment (users) |
GET | /:post_slug/comments/:comment_id | Get a single comment |
PUT | /:post_slug/comments/:comment_id | Update comment (comment author) |
DELETE | /:post_slug/comments/:comment_id | Delete comment (comment author) |
HTTP Verb | Endpoints | Action |
---|---|---|
GET | /authors | Get list of all authors |
GET | /authors/:author_slug | Get all posts by author |
To run locally:
git clone git@github.com:kathyavini/blog-api.git
cd blog-api
npm install
# Will listen on port 3000 if available
npm run start
# OR
npm run serverstart # run in development mode with nodemon
You will need to supply the following environmental variables in your .env
file at the package root:
# Connect string from MongoDB
MONGO_URI
JWT_SECRET # for jwt.sign(); any string
# For Cloudinary
CLOUD_NAME
API_KEY
API_SECRET
- Express
- MongoDB
- Mongoose MongoDB ODM for Node.js
- express-validator Express middleware for validation and sanitization
- PassportJS Simple, unobtrusive authentication for Node.js
- jsonwebtokens JSON Web Token implementation for Node.js
- bcrypt.js Optimized bcrypt in JavaScript with zero dependencies
- Cyclic Serverless hosting - simple AWS deployment from GitHub
- Supertest Super-agent driven library for testing node.js HTTP servers
- Postman API platform for building and using APIs
- mongodb-memory-server Spinning up mongod in memory for fast tests
Testing with Supertest
I enjoyed using familiar Jest syntax with Supertest. However, after testing a few controllers, I found that it could take another 30-60 minutes of coding to produce a working, passing test in Supertest after the endpoint would already return the correct response in Postman. For instance it took a lot more code (relative to Postman) to store and use jwts, and required awkward nested matchers to test uncomplicated JSON:
expect(response.body).toEqual(
expect.arrayContaining([
expect.objectContaining({ username: 'adminuser' }),
])
);
Although I appreciated the documentation provided by the Supertest testing files, I ended up using only Postman for the remainder of development.
Reduce data returned from endpoints
The API endpoints currently return more information than is necessary (generally the entire database query result) because I wasn't sure exactly what I would like to use on the frontend. After finishing the two frontends these will be trimmed down.