Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nitesh Yadav: Copy_overflow | batch-2 #46

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions nitesh_yadav/copy_overflow/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/node_modules
package-lock.json
/config
56 changes: 56 additions & 0 deletions nitesh_yadav/copy_overflow/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copy_Overflow

The application (REST APIs) serves as a platform for users to ask and answer questions, and, through membership and active participation, to vote questions and answers up or down similar to Reddit/Stack overflow and edit questions and answers.

---

<b>Tech Stack:</b> NodeJs, MongoDB, Postman, VsCode

### Features:

Every write operation is authenticated by JWT.

- User Registration
- User Login
- All CRUD operations by user on question
- All CRUD operations by user on answer
- Upvote/Downvote the question
- Upvote/Downvote the answer
- Get all the answer of particular question

### Supported APIs

#### User

- router.post("/register", users.register);
- router.post("/login", users.login);

#### Question

- router.post("/ask_question", auth, question.ask_question);

- router.get("/:id/answers", question.answers);
- router.get("/:id", question.get_question);

- router.patch("/:id", auth, question.update_question);
- router.patch("/:id/upvote", auth, question.upvote);
- router.patch("/:id/downvote", auth, question.downvote);

- router.delete("/:id", auth, question.delete_question);

#### Answer

- router.post("/add_answer", auth, answer.add_answer);

- router.get("/:id", answer.get_answer);

- router.patch("/:id", answer.update_answer);
- router.patch("/:id/upvote", auth, answer.upvote);
- router.patch("/:id/downvote", auth, answer.downvote);

- router.delete("/:id", auth, question.delete_question);

----------------------------
<b>Future Work:</b>
- User can receive badges for their valued contributions, which represents a gamification of the traditional Q&A website.
- Users unlock new privileges with an increase in reputation like the ability to vote, comment, and even edit other people's posts.
183 changes: 183 additions & 0 deletions nitesh_yadav/copy_overflow/controllers/answers.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
const db = require("../models");

const AnswerDbObj = db.answers;
const Question = db.questions;

/**
* method to add the answer. Only logged In user is allowed
* for this operation with signed JWT token.
*/
exports.add_answer = async (req, res) => {
const { answer, question_id } = req.body;

// all fields should be filled (answer, question_id)
if (!(answer && question_id)) {
return res.status(400).send({
message: "answer or question_id is missing. all fields are required.",
});
}

//check question is present or not
try {
var currQuestion = await Question.findOne({ _id: question_id });
} catch (err) {
return res
.status(400)
.send({ message: "question not found", error_details: err });
}

if (!currQuestion) {
return res.status(400).send({ message: "question not found" });
}

// create answer doc and save into DB
const answerObj = new AnswerDbObj({
answer: answer,
question_id: question_id,
user_id: currQuestion.user_id,
});
answerObj
.save()
.then((data) => {
res.status(200).send({ message: "answer saved!", answer_id: data.id });
})
.catch((err) => {
res
.status(400)
.send({ message: "answer not saved.", error_details: err });
});
};

/**
* method to get the answer by its id
*/
exports.get_answer = async (req, res) => {
const answer_id = req.params.id;
if (!answer_id) {
return res.status(400).send({ message: "answer id is missing." });
}

// find answer in DB with the id
await AnswerDbObj.findOne({ _id: answer_id })
.then((currAnswer) => {
if (!currAnswer) {
return res.status(400).send({ message: "answer not found" });
}
res.status(200).send({ message: "answer found", answer: currAnswer });
})
.catch((err) => {
res
.status(400)
.send({ message: "error! while fetching answer", error_details: err });
});
};

/**
* method to update the answer. Only logged In user is allowed
* for this operation with signed JWT token.
*/
exports.update_answer = async (req, res) => {
const answer_id = req.params.id;
const { answer, question_id } = req.body;

// check all fields should be filled (answre, question_id)
if (!(answer && question_id)) {
return res.status(400).send({
message: "answer or question_id is missing. all fields are required.",
});
}

// validate the question, whether it is present or not
Question.findOne({ _id: question_id })
.then((data) => {
if (!data) {
return res.status(400).send({ message: "question not found" });
}
})
.catch((err) => {
return res
.status(400)
.send({ message: "question not found", error_details: err });
});

// update the answer
AnswerDbObj.updateOne({ _id: answer_id }, { $set: { answer: answer } })
.then((data) => {
res.status(200).send({ message: "answer updated!", answer_id: data });
})
.catch((err) => {
res
.status(400)
.send({ message: "answer not updated.", error_details: err });
});
};

/**
* method to upvote the answer. Only logged In user is allowed
* for this operation with signed JWT token.
*/
exports.upvote = (req, res) => {
const answer_id = req.params.id;

if (!answer_id) {
return res.status(400).send({ message: "answer id not found" });
}

// increments the votes of particular answer by 1.
AnswerDbObj.updateOne({ _id: answer_id }, { $inc: { "meta.votes": 1 } })
.then((data) => {
res.status(200).send({ message: "answer upvoted" });
})
.catch((err) => {
res
.status(400)
.send({ message: "error, answer not upvoted", error_details: err });
});
};

/**
* method to downvote the answer. Only logged In user is allowed
* for this operation with signed JWT token.
*/
exports.downvote = (req, res) => {
const answer_id = req.params.id;
if (!answer_id) {
return res.status(400).send({ message: "answer id not found" });
}

// decrements the votes of particular answer by 1.
AnswerDbObj.updateOne({ _id: answer_id }, { $inc: { "meta.votes": -1 } })
.then((data) => {
res.status(200).send({ message: "answer downvoted" });
})
.catch((err) => {
res
.status(400)
.send({ message: "error, answer not downvoted", error_details: err });
});
};

/**
* method to delete the answer by id.Only logged In user is allowed
* for this operation with signed JWT token.
*/
exports.delete_answer = (req, res) => {
const answer_id = req.params.id;
if (!answer_id) {
return res.status(400).send({ message: "answer id not found." });
}

// find the delete answer by its id
AnswerDbObj.findByIdAndDelete(answer_id)
.then((data) => {
if (!data) {
return res.status(400).send({ message: "answer not found" });
}
return res.status(200).send({ message: "answer deleted" });
})
.catch((err) => {
res
.status(400)
.send({ message: "error, answer not deleted", error_details: err });
});
};
Loading