Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
sambaran-singh committed Jul 26, 2023
0 parents commit 2cd6904
Show file tree
Hide file tree
Showing 16 changed files with 3,975 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/node_modules
.env
16 changes: 16 additions & 0 deletions connectMongoDb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import mongoose from "mongoose";

const connectDB = async () => {
try {
const conn = await mongoose.connect(process.env.CONNECTION_URL, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
console.log(`MongoDB connected: ${conn.connection.host}`);
} catch (error) {
console.error(error);
process.exit(1);
}
};

export default connectDB;
53 changes: 53 additions & 0 deletions controllers/Answers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import mongoose from "mongoose";
import Questions from "../models/Questions.js";

export const postAnswer = async (req, res) => {
const { id: _id } = req.params;
const { noOfAnswers, answerBody, userAnswered } = req.body;
const userId = req.userId;
if (!mongoose.Types.ObjectId.isValid(_id)) {
return res.status(404).send("question unavailable...");
}

updateNoOfQuestions(_id, noOfAnswers);
try {
const updatedQuestion = await Questions.findByIdAndUpdate(_id, {
$addToSet: { answer: [{ answerBody, userAnswered, userId }] },
});
res.status(200).json(updatedQuestion);
} catch (error) {
res.status(400).json("error in updating");
}
};

const updateNoOfQuestions = async (_id, noOfAnswers) => {
try {
await Questions.findByIdAndUpdate(_id, {
$set: { noOfAnswers: noOfAnswers },
});
} catch (error) {
console.log(error);
}
};

export const deleteAnswer = async (req, res) => {
const { id: _id } = req.params;
const { answerId, noOfAnswers } = req.body;

if (!mongoose.Types.ObjectId.isValid(_id)) {
return res.status(404).send("Question unavailable...");
}
if (!mongoose.Types.ObjectId.isValid(answerId)) {
return res.status(404).send("Answer unavailable...");
}
updateNoOfQuestions(_id, noOfAnswers);
try {
await Questions.updateOne(
{ _id },
{ $pull: { answer: { _id: answerId } } }
);
res.status(200).json({ message: "Successfully deleted..." });
} catch (error) {
res.status(405).json(error);
}
};
85 changes: 85 additions & 0 deletions controllers/Questions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import Questions from "../models/Questions.js";
import mongoose from "mongoose";

export const AskQuestion = async (req, res) => {
const postQuestionData = req.body;
const userId = req.userId;
const postQuestion = new Questions({ ...postQuestionData, userId });
try {
await postQuestion.save();
res.status(200).json("Posted a question successfully");
} catch (error) {
console.log(error);
res.status(409).json("Couldn't post a new question");
}
};

export const getAllQuestions = async (req, res) => {
try {
const questionList = await Questions.find().sort({ askedOn: -1 });
res.status(200).json(questionList);
} catch (error) {
res.status(404).json({ message: error.message });
}
};

export const deleteQuestion = async (req, res) => {
const { id: _id } = req.params;

if (!mongoose.Types.ObjectId.isValid(_id)) {
return res.status(404).send("question unavailable...");
}

try {
await Questions.findByIdAndRemove(_id);
res.status(200).json({ message: "successfully deleted..." });
} catch (error) {
res.status(404).json({ message: error.message });
}
};

export const voteQuestion = async (req, res) => {
const { id: _id } = req.params;
const { value } = req.body;
const userId = req.userId;

if (!mongoose.Types.ObjectId.isValid(_id)) {
return res.status(404).send("question unavailable...");
}

try {
const question = await Questions.findById(_id);
const upIndex = question.upVote.findIndex((id) => id === String(userId));
const downIndex = question.downVote.findIndex(
(id) => id === String(userId)
);

if (value === "upVote") {
if (downIndex !== -1) {
question.downVote = question.downVote.filter(
(id) => id !== String(userId)
);
}
if (upIndex === -1) {
question.upVote.push(userId);
} else {
question.upVote = question.upVote.filter((id) => id !== String(userId));
}
} else if (value === "downVote") {
if (upIndex !== -1) {
question.upVote = question.upVote.filter((id) => id !== String(userId));
}
if (downIndex === -1) {
question.downVote.push(userId);
} else {
question.downVote = question.downVote.filter(
(id) => id !== String(userId)
);
}
}
await Questions.findByIdAndUpdate(_id, question);
res.status(200).json({ message: "voted successfully..." });
} catch (error) {
res.status(404).json({ message: "id not found" });
}
};
51 changes: 51 additions & 0 deletions controllers/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import jwt from "jsonwebtoken";
import bcrypt from "bcryptjs";

import users from "../models/auth.js";

export const signup = async (req, res) => {
const { name, email, password } = req.body;
try {
const existinguser = await users.findOne({ email });
if (existinguser) {
return res.status(404).json({ message: "User already Exist." });
}

const hashedPassword = await bcrypt.hash(password, 12);
const newUser = await users.create({
name,
email,
password: hashedPassword,
});
const token = jwt.sign(
{ email: newUser.email, id: newUser._id },
process.env.JWT_SECRET,
{ expiresIn: "1h" }
);
res.status(200).json({ result: newUser, token });
} catch (error) {
res.status(500).json("Something went worng...");
}
};

export const login = async (req, res) => {
const { email, password } = req.body;
try {
const existinguser = await users.findOne({ email });
if (!existinguser) {
return res.status(404).json({ message: "User don't Exist." });
}
const isPasswordCrt = await bcrypt.compare(password, existinguser.password);
if (!isPasswordCrt) {
return res.status(400).json({ message: "Invalid credentials" });
}
const token = jwt.sign(
{ email: existinguser.email, id: existinguser._id },
process.env.JWT_SECRET,
{ expiresIn: "1h" }
);
res.status(200).json({ result: existinguser, token });
} catch (error) {
res.status(500).json("Something went worng...");
}
};
41 changes: 41 additions & 0 deletions controllers/users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import mongoose from "mongoose";
import users from "../models/auth.js";

export const getAllUsers = async (req, res) => {
try {
const allUsers = await users.find();
const allUserDetails = [];
allUsers.forEach((user) => {
allUserDetails.push({
_id: user._id,
name: user.name,
about: user.about,
tags: user.tags,
joinedOn: user.joinedOn,
});
});
res.status(200).json(allUserDetails);
} catch (error) {
res.status(404).json({ message: error.message });
}
};

export const updateProfile = async (req, res) => {
const { id: _id } = req.params;
const { name, about, tags } = req.body;

if (!mongoose.Types.ObjectId.isValid(_id)) {
return res.status(404).send("question unavailable...");
}

try {
const updatedProfile = await users.findByIdAndUpdate(
_id,
{ $set: { name: name, about: about, tags: tags } },
{ new: true }
);
res.status(200).json(updatedProfile);
} catch (error) {
res.status(405).json({ message: error.message });
}
};
29 changes: 29 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import express from "express";
import cors from "cors";
import dotenv from "dotenv";

import userRoutes from "./routes/users.js";
import questionRoutes from "./routes/Questions.js";
import answerRoutes from "./routes/Answers.js";
import connectDB from "./connectMongoDb.js";

dotenv.config();
connectDB();
const app = express();
app.use(express.json({ limit: "30mb", extended: true }));
app.use(express.urlencoded({ limit: "30mb", extended: true }));
app.use(cors());

// app.use('/',(req, res) => {
// res.send("This is a stack overflow clone API")
// })

app.use("/user", userRoutes);
app.use("/questions", questionRoutes);
app.use("/answer", answerRoutes);

const PORT = process.env.PORT || 5000;

app.listen(PORT, () => {
console.log(`server running on port ${PORT}`);
});
16 changes: 16 additions & 0 deletions middleware/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import jwt from "jsonwebtoken";

const auth = (req, res, next) => {
try {
const token = req.headers.authorization.split(" ")[1];

let decodeData = jwt.verify(token, process.env.JWT_SECRET);
req.userId = decodeData?.id;

next();
} catch (error) {
console.log(error);
}
};

export default auth;
23 changes: 23 additions & 0 deletions models/Questions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import mongoose from "mongoose";

const QuestionSchema = mongoose.Schema({
questionTitle: { type: String, required: "Question must have a title" },
questionBody: { type: String, required: "Question must have a body" },
questionTags: { type: [String], required: "Question must have a tags" },
noOfAnswers: { type: Number, default: 0 },
upVote: { type: [String], default: [] },
downVote: { type: [String], default: [] },
userPosted: { type: String, required: "Question must have an author" },
userId: { type: String },
askedOn: { type: Date, default: Date.now },
answer: [
{
answerBody: String,
userAnswered: String,
userId: String,
answeredOn: { type: Date, default: Date.now },
},
],
});

export default mongoose.model("Question", QuestionSchema);
12 changes: 12 additions & 0 deletions models/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import mongoose from "mongoose";

const userSchema = mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
about: { type: String },
tags: { type: [String] },
joinedOn: { type: Date, default: Date.now },
});

export default mongoose.model("User", userSchema);
Loading

0 comments on commit 2cd6904

Please sign in to comment.