This is the Express backend for Instapost Frontend.
- Application skeleton: Express Generator
- RDBMS: Postgresql
- Authentication/validation: bcrypt, JSON Web Token, JSON Schema
- Image file data marshaling: AWS SDK
- Storage engine for AWS S3: Multer S3
- Auto-update utility: Nodemon
- Logger middleware: Morgan
- Cross-origin resource sharing: CORS
- Terminal styling: Colors
- Testing framework: Jest
- HTTP server testing: SuperTest
Install all dependencies with npm i
The project uses PostgreSQL as its RDBMS.
Make sure to create and seed databases with this command:
psql < instapost.sql
To run this project:
nodemon server.js
This will start the API server on localhost:3001/
To run the tests (make sure jest is installed, it is not listed as a dependency):
jest -i
The entirety of this project is a RESTFUL JSON API.
Authorization and authentication is performed using JSON Web Tokens. Send your JWT as bearer tokens in the authorization header of all of your requests sent to the API.
This route is used for creating new users in the database, and is validated with JSON schema. Include the following in the payload of your POST request, all fields are required:
{
"username": "string, max 30 chars",
"password": "string, min 5 chars, max 20 chars",
"fullName": "string, max 30 chars",
"email": "string, email format, min 6 chars, max 60 chars"
}
Other pieces of data like bio and profileImageURL can be updated with the PATCH /:username request.
This will create a new entry in the users table of the database, with a hashed and salted password. The server will respond with the auth token for the newly registered user.
This route is used to get another auth token. Send the username and password of the user you want to authenticate as in your request payload. If the credentials are valid, the server will respond with an auth token.
{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtc2ciOiJjb25ncmF0dWxhdGlvbnMiLCJob3dldmVyIjoibm90IGEgdmVyeSByZXdhcmRpbmcgc2VjcmV0LCBpcyBpdD8ifQ.PpjeIMk-mILsVOG-eLDcgmrmkXyNTnXRt01bFMfbtSU" }
Routes corresponding with user activity in the database.
This endpoint will respond with all the user's info in the database, with the following format:
{
"user":
{
"username": "johnny_doe_",
"fullName": "John Doe",
"email": "john.doe@gmail.com",
"profileImageURL": "https://randomuser.me/api/portraits/lego/3.jpg",
"bio": "One in the hand is worth two in the bush",
"posts": [{
"postId": 23,
"postURL": "https://randomuser.me/api/portraits/lego/3.jpg",
"caption": "Just me",
"watermark": "The John Foe",
"filter": "grayscale(100%)",
"createdAt": "2023-04-02 14:39:38.975684"
}, ... ],
"postLikes": [{
"postId": 6,
"username": "johnny_doe_",
"postURL": "https://randomuser.me/api/portraits/lego/3.jpg",
"caption": "Oh yeah, look at me",
"watermark": null,
"filter": null,
"createdAt": "2023-04-02 14:23:50.695016"
}, ... ],
"following": [{
"username": "shelby_sherlock",
"fullName": "Shelby Sherlock",
"profileImageURL": "https://randomuser.me/api/portraits/lego/3.jpg"
}, ... ],
"followers": [{
"username": "shelby_sherlock",
"fullName": "Shelby Sherlock",
"profileImageURL": "https://randomuser.me/api/portraits/lego/3.jpg"
}, ... ]
}
}
You can filter your results by passing parameters to the query string. The following parameter is available:
- name: User must have this string appearing somewhere in its
username
orfullName
, case insensitive.
E.g. users/user?name=pas
will return a list of all users where "pas"
appears somwhere in their username
or fullName
.
This endpoint will send an image file to an Amazon S3 bucket and send an resultant object with the status of success. This is done with the Multer middleware. E.g. you send a file to this route:
{
"lastModified": 1679602398563,
"lastModifiedDate": "Thu Mar 23 2023 13:13:18 GMT-0700 (Pacific Daylight Time)",
"name": "unnamed2.jpg",
"size": 1357832,
"type": "image/jpeg",
"webkitRelativePath": ""
}
The result:
{
"result": {
"Bucket": "instagram-clone-photo",
"ETag": "\"e7bf6f55e9131832bb8f9051729fe8a3\"",
"Key": "uploads/4e708a55-7d23-46d1-a23d-1bbe9c5a6589-unnamed2.jpg",
"Location": "https://instagram-clone-photo.s3.us-west-1.amazonaws.com/uploads/4e708a55-7d23-46d1-a23d-1bbe9c5a6589-unnamed2.jpg",
"ServerSideEncryption": "AES256",
"key": "uploads/4e708a55-7d23-46d1-a23d-1bbe9c5a6589-unnamed2.jpg",
},
"status": "success"
}
Creates a new entry in the posts table of the database. Include the data matching the following schema in the payload of your request, username
and postURL
are required. caption
, watermark
, watermarkFont
, and filter
are optional:
{
"username": "johnny_doe_",
"caption": "Just me and my girl",
"watermark": "The John Foe",
"watermarkFont": "sans serif",
"filter": null,
"postURL": "https://instagram-clone-photo.s3.us-west-1.amazonaws.com/uploads/4e708a55-7d23-46d1-a23d-1bbe9c5a6589-unnamed2.jpg"
}
Get all the comments for a single post. Include the postId
as a parameter and you'll receive the following:
{
"comments": [
{
"commentId": 3,
"parentId": null,
"message": "Wow! What a great post, John.",
"username": "shelby_sherlock",
"createdAt": "2023-04-02 14:23:50.695016",
"numLikes": "3",
"children": [{"commentId": ...}, ...]
},
...
]
}
If there are replies to a comment and replies to that comment as well, there will be an array of children
for that comment. Each top level comment would have a parentId
of null.
To create a comment on a post, provide the following inputs:
{
"username": "johnny_doe_",
"postId": 5,
"parentId": 2,
"message": "I don't know if that's true, Barbara."
}
To signify that a comment is a reply, enter a parentId
to reference the commentId being replied to. Otherwise, just leave it null.
To either follow another user or unfollow, you must provide the following respectively:
{
"usernameFollowing": "johnny_doe_",
"usernameBeingFollowed": "Shelby_Sherlock"
}
{
"usernameUnfollowing": "johnny_doe_",
"usernameBeingUnfollowed": "Shelby_Sherlock"
}
Will respond with a the posts from users that the provided username
follows:
{
"users": [{
"username": "shelby_sherlock",
"profileImageURL": "https://randomuser.me/api/portraits/lego/3.jpg",
"posts": [{
"postId": 88,
"postURL": "https://instagram-clone-photo.s3.us-west-1.amazonaws.com/uploads/4e708a55-7d23-46d1-a23d-1bbe9c5a6589-unnamed2.jpg",
"caption": "Hallelujah",
"createdAt": "2023-04-02 14:23:50.695016"
}, ...]
}, ...]
}
Must provide username
, commentOrPostId
, and likeType
to like or unlike either a post or a comment. E.g.:
{
"username": "Johnny_Doe_",
"commentOrPostId": 3,
"likeType": "post"
}
Provide any of the following data to be updated:
{
"profileImageURL": "https://randomuser.me/api/portraits/lego/3.jpg",
"fullName": "John Doe",
"username": "theJohnDoe",
"bio": "Oh yeaaaah",
"email": "john.doe@gmail.com"
}