├── .gitignore ├── loadEnv.js ├── erd.png ├── db └── conn.js ├── package.json ├── models ├── comments.js ├── users.js └── posts.js ├── index.js ├── routes ├── comments.js ├── posts.js └── users.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /loadEnv.js: -------------------------------------------------------------------------------- 1 | import dotenv from "dotenv"; 2 | dotenv.config(); -------------------------------------------------------------------------------- /erd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mindy-d-tran/blog-app-backend/HEAD/erd.png -------------------------------------------------------------------------------- /db/conn.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | export async function conn() { 4 | try { 5 | await mongoose.connect(process.env.ATLAS_URI); 6 | console.log("connected to MongoDB"); 7 | } catch (error) { 8 | console.log(error.message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backend", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "start": "node index.js", 10 | "dev": "nodemon index.js" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "dependencies": { 16 | "bcrypt": "^5.1.1", 17 | "cors": "^2.8.5", 18 | "dotenv": "^16.4.1", 19 | "express": "^4.18.2", 20 | "mongoose": "^8.1.1", 21 | "morgan": "^1.10.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /models/comments.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const user = new mongoose.Schema( 4 | { 5 | user_id: { 6 | type: mongoose.Schema.ObjectId, 7 | ref: "User", 8 | }, 9 | }, 10 | { _id: false } 11 | ); 12 | 13 | const commentsSchema = new mongoose.Schema( 14 | { 15 | user_id: { 16 | type: mongoose.Schema.ObjectId, 17 | ref: "User", 18 | required: true, 19 | }, 20 | post_id: { 21 | type: mongoose.Schema.ObjectId, 22 | ref: "Post", 23 | required: true, 24 | }, 25 | comment_like: { 26 | type: [user], 27 | }, 28 | comment_content: { 29 | type: String, 30 | required: true 31 | }, 32 | }, 33 | { timestamps: true } 34 | ); 35 | 36 | export default mongoose.model("Comment", commentsSchema); 37 | -------------------------------------------------------------------------------- /models/users.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | import bcrypt from "bcrypt"; 3 | 4 | const SALT_ROUNDS = 8; 5 | 6 | const usersSchema = new mongoose.Schema( 7 | { 8 | username: { 9 | type: String, 10 | unique: true, 11 | }, 12 | email: { 13 | type: String, 14 | required: true, 15 | unique: true, 16 | }, 17 | password: { 18 | type: String, 19 | required: true, 20 | minLength: 8, 21 | maxLength: 30, 22 | }, 23 | }, 24 | { 25 | toJSON: { 26 | transform: function (doc, retDoc) { 27 | delete retDoc.password; 28 | return retDoc; 29 | }, 30 | }, 31 | } 32 | ); 33 | 34 | // encrypting the password 35 | usersSchema.pre("save", async function (next) { 36 | this.password = await bcrypt.hash(this.password, SALT_ROUNDS); 37 | return next(); 38 | }); 39 | 40 | export default mongoose.model("User", usersSchema); 41 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import "./loadEnv.js"; 2 | import { conn } from "./db/conn.js"; conn(); 3 | import express from "express"; 4 | import cors from "cors"; 5 | import morgan from "morgan"; 6 | 7 | // importing routes 8 | import usersRouter from "./routes/users.js"; 9 | import postsRouter from "./routes/posts.js"; 10 | import commentsRouter from "./routes/comments.js"; 11 | 12 | const app = express(); 13 | const PORT = process.env.PORT || 4000; 14 | 15 | // middlewares 16 | app.use(cors()); // allows frontend to connect to backend 17 | app.use(morgan("dev")); // logger to know what requests you are calling 18 | app.use(express.json()); // for data in req.body 19 | app.use(express.urlencoded({ extended: true })); // allow data in url 20 | 21 | app.use("/api/users", usersRouter); 22 | app.use("/api/posts", postsRouter); 23 | app.use("/api/comments", commentsRouter); 24 | 25 | // routes 26 | app.get("/", (req, res) => res.send("welcome to blog app api")); 27 | 28 | app.listen(PORT, () => console.log(`server is running on port ${PORT}`)); 29 | -------------------------------------------------------------------------------- /models/posts.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | // subschema for user 4 | const user = new mongoose.Schema( 5 | { 6 | user_id: { 7 | type: mongoose.Schema.ObjectId, 8 | ref: "User", 9 | }, 10 | }, 11 | { _id: false } 12 | ); 13 | // subschema for comment 14 | const comment = new mongoose.Schema( 15 | { 16 | comment_id: { 17 | type: mongoose.Schema.ObjectId, 18 | ref: "Comment", 19 | }, 20 | }, 21 | { _id: false } 22 | ); 23 | // subschema for post content 24 | const post_content = new mongoose.Schema( 25 | { 26 | text: String, 27 | img: [String], 28 | }, 29 | { _id: false } 30 | ); 31 | 32 | // Schema 33 | const postsSchema = new mongoose.Schema( 34 | { 35 | user_id: { 36 | type: mongoose.Schema.ObjectId, 37 | ref: "User", 38 | required: true, 39 | }, 40 | post_likes: { 41 | type: [user], 42 | }, 43 | post_views: { 44 | type: Number, 45 | default: 0, 46 | }, 47 | post_comments: { 48 | type: [comment], 49 | }, 50 | post_title: { 51 | type: String, 52 | default: "", 53 | }, 54 | post_content: { 55 | type: post_content, 56 | required: true, 57 | }, 58 | post_hashtag: { 59 | type: [String], 60 | }, 61 | }, 62 | { 63 | timestamps: true, 64 | } 65 | ); 66 | 67 | export default mongoose.model("Post", postsSchema); 68 | -------------------------------------------------------------------------------- /routes/comments.js: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | 3 | //importing model 4 | import Comment from "../models/comments.js"; 5 | import Post from "../models/posts.js"; 6 | 7 | const router = new Router(); 8 | 9 | // GET comments 10 | router.get("/", async (req, res) => { 11 | try { 12 | const comments = await Comment.find({}); 13 | res.send(comments); 14 | } catch (error) { 15 | res 16 | .status(404) 17 | .json({ msg: "something went wrong", errormsg: error.message }); 18 | } 19 | }); 20 | 21 | // GET 1 comment 22 | router.get("/:id", async (req, res) => { 23 | try { 24 | const comment = await Comment.findById(req.params.id); 25 | res.send(comment); 26 | } catch (error) { 27 | res 28 | .status(404) 29 | .json({ msg: "something went wrong", errormsg: error.message }); 30 | } 31 | }); 32 | 33 | router.get("/post/:post_id", async (req, res) => { 34 | try { 35 | const postComments = await Comment.find({post_id: req.params.post_id}).populate('user_id'); 36 | res.send(postComments); 37 | } catch (error) { 38 | res 39 | .status(404) 40 | .json({ msg: "something went wrong", errormsg: error.message }); 41 | } 42 | }); 43 | 44 | // POST (create) new comment 45 | router.post("/", async (req, res) => { 46 | try { 47 | const newComment = await Comment.create(req.body); 48 | const post = await Post.findById(req.body.post_id); 49 | if (post) { 50 | post.post_comments.push({ comment_id: newComment._id }); 51 | await post.save(); 52 | } 53 | res.status(201).send(newComment); 54 | } catch (error) { 55 | res 56 | .status(404) 57 | .json({ msg: "something went wrong", errormsg: error.message }); 58 | } 59 | }); 60 | 61 | // PUT add user to like array (so the ui can show differently) 62 | router.put("/:id/like", async (req, res) => { 63 | try { 64 | const comment = await Comment.findById(req.params.id).populate('user_id'); 65 | if (comment) { 66 | comment.comment_like.push(req.body); 67 | await comment.save(); 68 | return res.send({ msg: "user like the comment" , comment}); 69 | } 70 | } catch (error) { 71 | res 72 | .status(404) 73 | .json({ msg: "something went wrong", errormsg: error.message }); 74 | } 75 | }); 76 | // PUT remove user from like array (unlike) 77 | router.put("/:id/unlike", async (req, res) => { 78 | try { 79 | const comment = await Comment.findById(req.params.id).populate('user_id'); 80 | if (comment) { 81 | comment.comment_like.pull(req.body); 82 | await comment.save(); 83 | return res.send({ msg: "user unlike the comment", comment }); 84 | } 85 | } catch (error) { 86 | res 87 | .status(404) 88 | .json({ msg: "something went wrong", errormsg: error.message }); 89 | } 90 | }); 91 | 92 | // DELETE comment 93 | router.delete("/:id", async (req, res) => { 94 | try { 95 | // find comment to find post_id 96 | const comment = await Comment.findById(req.params.id); 97 | 98 | //find post 99 | const post = await Post.findById(comment.post_id); 100 | // delete the comment from the array 101 | post.post_comments.pull({ comment_id: req.params.id }); 102 | await post.save(); 103 | 104 | // delete comment from database 105 | const deleteComment = await Comment.findByIdAndDelete(req.params.id); 106 | res.json({ msg: "comment deleted", deleteComment }); 107 | } catch (error) { 108 | res 109 | .status(404) 110 | .json({ msg: "something went wrong", errormsg: error.message }); 111 | } 112 | }); 113 | export default router; 114 | -------------------------------------------------------------------------------- /routes/posts.js: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | 3 | //importing model 4 | import Post from "../models/posts.js"; 5 | 6 | const router = new Router(); 7 | 8 | // GET all posts 9 | router.get("/", async (req, res) => { 10 | try { 11 | const posts = await Post.find({}).sort({createdAt: -1}).populate("user_id").populate('post_comments.comment_id'); 12 | res.status(200).send(posts); 13 | } catch (error) { 14 | res 15 | .status(404) 16 | .json({ msg: "something went wrong", errormsg: error.message }); 17 | } 18 | }); 19 | 20 | // GET 1 post 21 | router.get("/:id", async (req, res) => { 22 | try { 23 | const post = await Post.findById(req.params.id).populate('user_id').populate('post_comments.comment_id'); 24 | // if get post then increase the view by one 25 | if (!post) return res.send("post not found"); 26 | 27 | post.post_views++; 28 | await post.save(); 29 | res.send(post); 30 | } catch (error) { 31 | res 32 | .status(404) 33 | .json({ msg: "something went wrong", errormsg: error.message }); 34 | } 35 | }); 36 | 37 | // POST (create) a new post 38 | router.post("/", async (req, res) => { 39 | try { 40 | const newPost = await Post.create(req.body); 41 | res.status(201).send(newPost); 42 | } catch (error) { 43 | res 44 | .status(404) 45 | .json({ msg: "something went wrong", errormsg: error.message }); 46 | } 47 | }); 48 | 49 | // PUT (update) post if they are updating more than 1 item in the post 50 | router.put("/:id", async (req, res) => { 51 | try { 52 | const post = await Post.findByIdAndUpdate(req.params.id, req.body, { 53 | new: true, 54 | }); 55 | res.status(200).send(post); 56 | } catch (error) { 57 | res 58 | .status(404) 59 | .json({ msg: "something went wrong", errormsg: error.message }); 60 | } 61 | }); 62 | 63 | // PUT (update) post's content 64 | router.put("/:id/update_content", async (req, res) => { 65 | try { 66 | const post = await Post.findByIdAndUpdate(req.params.id, req.body, { 67 | new: true, 68 | }); 69 | res.status(200).send(post); 70 | } catch (error) { 71 | res 72 | .status(404) 73 | .json({ msg: "something went wrong", errormsg: error.message }); 74 | } 75 | }); 76 | // PUT (update) post's content's text 77 | router.put("/:id/update_content_text", async (req, res) => { 78 | try { 79 | // find post 80 | const post = await Post.findById(req.params.id); 81 | 82 | // update post 83 | post.post_content.text = req.body.text; 84 | post.save(); 85 | 86 | // send final result 87 | res.status(200).send(post); 88 | } catch (error) { 89 | res 90 | .status(404) 91 | .json({ msg: "something went wrong", errormsg: error.message }); 92 | } 93 | }); 94 | 95 | // PUT (update) post's content 96 | router.put("/:id/update_content_img", async (req, res) => { 97 | try { 98 | // find post 99 | const post = await Post.findById(req.params.id); 100 | 101 | // update post 102 | post.post_content.img = req.body.img; 103 | post.save(); 104 | 105 | // send final result 106 | res.status(200).send(post); 107 | } catch (error) { 108 | res 109 | .status(404) 110 | .json({ msg: "something went wrong", errormsg: error.message }); 111 | } 112 | }); 113 | 114 | // PUT (update) post's title 115 | router.put("/:id/update_title", async (req, res) => { 116 | try { 117 | const post = await Post.findByIdAndUpdate(req.params.id, req.body, { 118 | new: true, 119 | }); 120 | res.status(200).send(post); 121 | } catch (error) { 122 | res 123 | .status(404) 124 | .json({ msg: "something went wrong", errormsg: error.message }); 125 | } 126 | }); 127 | 128 | // PUT (update) post's hashtag 129 | router.put("/:id/update_hashtag", async (req, res) => { 130 | try { 131 | const post = await Post.findByIdAndUpdate(req.params.id, req.body, { 132 | new: true, 133 | }); 134 | res.status(200).send(post); 135 | } catch (error) { 136 | res 137 | .status(404) 138 | .json({ msg: "something went wrong", errormsg: error.message }); 139 | } 140 | }); 141 | 142 | // PUT add user to like array (so the ui can show differently) 143 | router.put("/:id/like", async (req, res) => { 144 | try { 145 | const post = await Post.findById(req.params.id).populate('user_id'); 146 | if (post) { 147 | post.post_likes.push(req.body); 148 | await post.save(); 149 | return res.send({ msg: "user like the post", post }); 150 | } 151 | } catch (error) { 152 | res 153 | .status(404) 154 | .json({ msg: "something went wrong", errormsg: error.message }); 155 | } 156 | }); 157 | 158 | // PUT remove user from like array (unlike) 159 | router.put("/:id/unlike", async (req, res) => { 160 | try { 161 | const post = await Post.findById(req.params.id).populate('user_id'); 162 | if (post) { 163 | post.post_likes.pull(req.body); 164 | await post.save(); 165 | return res.send({ msg: "user unlike the post",post }); 166 | } 167 | } catch (error) { 168 | res 169 | .status(404) 170 | .json({ msg: "something went wrong", errormsg: error.message }); 171 | } 172 | }); 173 | // DELETE post 174 | router.delete("/:id/", async (req, res) => { 175 | try { 176 | const deletePost = await Post.findByIdAndDelete(req.params.id); 177 | res.json({ msg: "post deleted", deletePost }); 178 | } catch (error) { 179 | res 180 | .status(404) 181 | .json({ msg: "something went wrong", errormsg: error.message }); 182 | } 183 | }); 184 | export default router; 185 | -------------------------------------------------------------------------------- /routes/users.js: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import bcrypt from "bcrypt"; 3 | 4 | //importing model 5 | import User from "../models/users.js"; 6 | 7 | const SALT_ROUNDS = 8; 8 | 9 | const router = new Router(); 10 | 11 | // GET all users 12 | router.get("/", async (req, res) => { 13 | try { 14 | const users = await User.find({}); 15 | res.status(200).send(users); 16 | } catch (error) { 17 | res 18 | .status(404) 19 | .json({ msg: "something went wrong", errormsg: error.message }); 20 | } 21 | }); 22 | 23 | router.put("/login", async (req, res) => { 24 | try { 25 | // try to find user by email or username 26 | const user = await User.findOne({ 27 | $or: [{ username: req.body.emailOrUsername }, { email: req.body.emailOrUsername }], 28 | }); 29 | 30 | // tell user if the email or username not found in the system 31 | if (!user) return res.status(404).send("Can't find email or username in system"); 32 | 33 | // check if password match with user info 34 | const passwordMatched = await bcrypt.compare( 35 | req.body.password, // plaintext password 36 | user.password // hash password 37 | ); 38 | if (!passwordMatched) { 39 | return res.status(401).send("Password doesn't match"); 40 | } 41 | 42 | // log in if it is success 43 | console.log("password matched!"); 44 | res.json(user); 45 | } catch (error) { 46 | res 47 | .status(404) 48 | .json({ msg: "something went wrong", errormsg: error.message }); 49 | } 50 | }); 51 | 52 | // GET single user 53 | router.get("/:id", async (req, res) => { 54 | try { 55 | const user = await User.findById(req.params.id); 56 | if (!user) return res.send("can't find user"); 57 | res.send(user); 58 | } catch (error) { 59 | res 60 | .status(404) 61 | .json({ msg: "something went wrong", errormsg: error.message }); 62 | } 63 | }); 64 | 65 | // POST (create) new user 66 | router.post("/", async (req, res) => { 67 | try { 68 | if (await User.findOne({ username: req.body.username })) 69 | return res.status(404).send("Username already in use"); 70 | if (await User.findOne({ email: req.body.email })) 71 | return res.status(404).send("Email already in use"); 72 | const user = await User.create(req.body); 73 | res.status(201).json(user); 74 | } catch (error) { 75 | res 76 | .status(404) 77 | .json({ msg: "something went wrong", errormsg: error.message }); 78 | } 79 | }); 80 | 81 | // PUT (update) user's profile pic 82 | router.put("/:id/update-profile-pic", async (req, res) => { 83 | try { 84 | const updateUserProfilePic = await User.findByIdAndUpdate( 85 | req.params.id, 86 | req.body, 87 | { 88 | new: true, 89 | } 90 | ); 91 | res.send(updateUserProfilePic); 92 | } catch (error) { 93 | res 94 | .status(404) 95 | .json({ msg: "something went wrong", errormsg: error.message }); 96 | } 97 | }); 98 | 99 | // PUT (update) user's username 100 | router.put("/:id/update-username/", async (req, res) => { 101 | try { 102 | const updateUserProfilePic = await User.findByIdAndUpdate( 103 | req.params.id, 104 | req.body, 105 | { 106 | new: true, 107 | } 108 | ); 109 | res.send(updateUserProfilePic); 110 | } catch (error) { 111 | res 112 | .status(404) 113 | .json({ msg: "something went wrong", errormsg: error.message }); 114 | } 115 | }); 116 | 117 | // PUT (update) user's email 118 | router.put("/:id/update-email/", async (req, res) => { 119 | try { 120 | const updateUserUsername = await User.findByIdAndUpdate( 121 | req.params.id, 122 | req.body, 123 | { 124 | new: true, 125 | } 126 | ); 127 | res.send(updateUserUsername); 128 | } catch (error) { 129 | res 130 | .status(404) 131 | .json({ msg: "something went wrong", errormsg: error.message }); 132 | } 133 | }); 134 | 135 | // PUT (update) user's password 136 | // code from Abraham Tavarez 137 | // https://github.com/AbeTavarez/cohort107/blob/main/nodejs/mongoose-api/backend/routes/users.js 138 | router.put("/:id/update-password", async (req, res) => { 139 | try { 140 | const { id } = req.params; 141 | const { currentPassword, newPassword } = req.body; 142 | 143 | // find the user to update 144 | const user = await User.findById(id); 145 | if (!user) return res.status(404).json({ msg: "User not found!" }); 146 | 147 | // verify the old password with the password hash in db 148 | const passwordMatched = await bcrypt.compare( 149 | currentPassword, 150 | user.password 151 | ); 152 | if (!passwordMatched) { 153 | return res.status(401).json({ msg: "Authentication Error" }); 154 | } 155 | 156 | console.log("password matched!"); 157 | 158 | // hash the new password 159 | const hashedPassword = await bcrypt.hash(newPassword, SALT_ROUNDS); 160 | 161 | // set the old password hash to the newPassword hash 162 | await User.findByIdAndUpdate(id, { password: hashedPassword }); 163 | 164 | res.json({ msg: "User password updated", user }); 165 | } catch (error) { 166 | console.log(error); 167 | } 168 | }); 169 | 170 | // DELETE user 171 | router.delete("/:id/", async (req, res) => { 172 | try { 173 | const deleteUser = await User.findByIdAndDelete(req.params.id); 174 | res.json({ msg: "user deleted", deleteUser }); 175 | } catch (error) { 176 | res 177 | .status(404) 178 | .json({ msg: "something went wrong", errormsg: error.message }); 179 | } 180 | }); 181 | 182 | export default router; 183 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blog App Backend 2 | 3 | ## About 4 | 5 | A blog api for a blog application where users can post, comment, and like each other's post. 6 | 7 | ## Frontend Repository 8 | 9 | [frontend repository link](https://github.com/mindy-d-tran/blog-app-frontend) 10 | 11 | ## Live Demo 12 | 13 | Deployed on netlify: [blog app live demo](https://main--ps-blog-app.netlify.app/) 14 | 15 | # Approach 16 | 17 | Users can use full CRUD for users, posts, and comments 18 | 19 | ## Technology Used 20 | 21 | ### Backend 22 | 23 | - Nodejs 24 | - Express 25 | - Mongoose 26 | - MongoDB 27 | - Bcrypt (Password encrypting, hashing) 28 | 29 | ## Planning 30 | 31 | ## Trello Board 32 | 33 | [trello board link](https://trello.com/invite/b/xMjVRQSG/ATTI0edbb0da239b30e52dd61d33368ae80f69D00CD7/ps-capstone-project) 34 | 35 | ## Entity Relationship Diagram (ERD) 36 | 37 | [ERD](https://drive.google.com/file/d/14j2IKmw6vyK-PiW4wrSRmKZa3s_J_noH/view) 38 | ![erd](./erd.png) 39 | 40 | # Routes 41 | 42 | ## Users Route 43 | 44 | ### GET /api/users 45 | 46 | Reads all users in the database 47 | 48 | ### PUT /api/users/login 49 | 50 | Returns the user data if the login attempt is a sucess 51 | 52 | #### Body (JSON) 53 | 54 | ``` 55 | { 56 | emailOrUsername: String, 57 | password: String 58 | } 59 | ``` 60 | 61 | ### GET /api/users/:id 62 | 63 | Read a single user's data 64 | 65 | - id = user \_id 66 | 67 | ### POST /api/users 68 | 69 | Create a new user and returns new user data 70 | 71 | #### Body (JSON) 72 | 73 | ``` 74 | { 75 | email: String (required, unique), 76 | username: String (required, unique), 77 | password: String (required) 78 | } 79 | ``` 80 | 81 | ### PUT /api/users/:id/update-profile-pic 82 | 83 | Updates the user's profile picture 84 | 85 | - id = user \_id 86 | 87 | #### Body (JSON) 88 | 89 | ``` 90 | { 91 | profile_pic: String 92 | } 93 | ``` 94 | 95 | ### PUT /api/users/:id/update-username 96 | 97 | Updates the user's username 98 | 99 | - id = user \_id 100 | 101 | #### Body (JSON) 102 | 103 | ``` 104 | { 105 | username: String 106 | } 107 | ``` 108 | 109 | ### PUT /api/users/:id/update-email 110 | 111 | Updates the user's email 112 | 113 | - id = user \_id 114 | 115 | #### Body (JSON) 116 | 117 | ``` 118 | { 119 | email: String 120 | } 121 | ``` 122 | 123 | ### PUT /api/users/:id/update-password 124 | 125 | Updates the user's password. Shout out to Abraham Tavarez for the [code](https://github.com/AbeTavarez/cohort107/blob/main/nodejs/mongoose-api/backend/routes/users.js) 126 | 127 | - id = user \_id 128 | 129 | #### Body (JSON) 130 | 131 | ``` 132 | { 133 | currentPassword: String, 134 | newPassword: String 135 | } 136 | ``` 137 | 138 | ### DELETE /api/users/:id/ 139 | 140 | Delete a user from the database 141 | 142 | - id = user \_id 143 | 144 | ## Posts Route 145 | 146 | ### GET /api/posts 147 | 148 | Reads all posts in the database 149 | 150 | ### GET /api/posts/:id 151 | 152 | Read a single post's data 153 | 154 | - id = post \_id 155 | 156 | ### POST /api/posts 157 | 158 | Create a new post and returns new post data 159 | 160 | #### Body (JSON) 161 | 162 | ``` 163 | { 164 | user_id: String (required, unique), 165 | post_title: String (default ""), 166 | post_content: { 167 | text: String, 168 | img: [String] 169 | } (required), 170 | post_hashtag: [String] 171 | } 172 | ``` 173 | 174 | ### PUT /api/posts/:id 175 | 176 | Create a new post and returns new post data 177 | 178 | - id = post \_id 179 | 180 | #### Body (JSON) 181 | 182 | ``` 183 | { 184 | user_id: String (required, unique), 185 | post_title: String (default ""), 186 | post_content: { 187 | text: String, 188 | img: [String] 189 | } (required), 190 | post_hashtag: [String] 191 | } 192 | ``` 193 | 194 | ### PUT /api/posts/:id/update_content 195 | 196 | Updates the post's content 197 | 198 | - id = post \_id 199 | 200 | #### Body (JSON) 201 | 202 | ``` 203 | { 204 | post_title: String (default ""), 205 | post_content: { 206 | text: String, 207 | img: [String] 208 | }, 209 | post_hashtag: [String] 210 | } 211 | ``` 212 | 213 | ### PUT /api/posts/:id/update_content_text 214 | 215 | Updates the post's content's text 216 | 217 | - id = post \_id 218 | 219 | #### Body (JSON) 220 | 221 | ``` 222 | { 223 | text: String, 224 | } 225 | ``` 226 | 227 | ### PUT /api/posts/:id/update_content_img 228 | 229 | Updates the post's content's image 230 | 231 | - id = post \_id 232 | 233 | #### Body (JSON) 234 | 235 | ``` 236 | { 237 | img: [String] 238 | } 239 | ``` 240 | 241 | ### PUT /api/posts/:id/update_title 242 | 243 | Updates the post's title 244 | 245 | - id = post \_id 246 | 247 | #### Body (JSON) 248 | 249 | ``` 250 | { 251 | post_title: String 252 | } 253 | ``` 254 | 255 | ### PUT /api/posts/:id/update_hashtag 256 | 257 | Updates the post's hashtags 258 | 259 | - id = post \_id 260 | 261 | #### Body (JSON) 262 | 263 | ``` 264 | { 265 | post_hashtag: [String] 266 | } 267 | ``` 268 | 269 | ### PUT /api/posts/:id/like 270 | 271 | Updates the post's like (user like the post) 272 | 273 | - id = post \_id 274 | 275 | ### PUT /api/posts/:id/unlike 276 | 277 | Updates the post's like (user unlike the post) 278 | 279 | - id = post \_id 280 | 281 | ### DELETE /api/posts/:id 282 | 283 | Delete a post 284 | 285 | - id = post \_id 286 | 287 | ## Comments Route 288 | 289 | ### GET /api/comments 290 | 291 | Reads all comments in the database 292 | 293 | ### GET /api/comments/:id 294 | 295 | Read a single comment's data 296 | 297 | - id = comment \_id 298 | 299 | ### GET /api/comments/post/:post_id 300 | 301 | Read all comment's for one post 302 | 303 | - post_id = post \_id 304 | 305 | ### POST /api/comments 306 | 307 | Create new comment 308 | 309 | #### Body (JSON) 310 | 311 | ```{ 312 | user_id: String (required), 313 | post_id: String (required), 314 | comment_content: String (required) 315 | } 316 | ``` 317 | 318 | ### PUT /api/comments/:id/like 319 | 320 | Updates the comment's like (user like the comment) 321 | 322 | - id = comment \_id 323 | 324 | ### PUT /api/comments/:id/unlike 325 | 326 | Updates the comment's like (user unlike the comment) 327 | 328 | - id = comment \_id 329 | 330 | ### DELETE /api/comments/:id/ 331 | 332 | Delete a comment from the database 333 | 334 | - id = comment \_id 335 | 336 | # Future Implementations 337 | 338 | - Create search route so user's can search for posts through query 339 | - Create search router for advance search to give users filters when searching for things on the application 340 | - Create a profile schema so users can learn more about each other in the app 341 | --------------------------------------------------------------------------------