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

Week5 #3

Open
wants to merge 4 commits 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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
145 changes: 140 additions & 5 deletions controllers/todo.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const { ToDo, Token } = require("../models");
const { response } = require("express");
const { ToDo, Token, User } = require("../models");

// All the given method require token.
// So be sure to check for it before doing any stuff
Expand All @@ -7,34 +8,168 @@ const { ToDo, Token } = require("../models");
const getAllToDo = async (req, res) => {
// Get the token in header.
// Use the token to get all the ToDo's of a user
try{
let all = await ToDo.find({$or:[{createdBy: req.user._id},{collaborators:req.user._id}]});
var arr = []
for(a of all){
arr.push({id:a._id,title:a.title})
}
res.status(200).json(arr);
}catch(err){
console.log(err)
res.status(500).send("Internal Server Error")
}
};

const createToDo = async (req, res) => {
// Check for the token and create a todo
// or throw error correspondingly
const user = req.user;
const title = req.body.title;

let toDo = new ToDo({
title: title,
createdBy:user._id,
collaborators:[]
});

await toDo.save().then(() => {
return res.status(200).json({id:toDo._id,title:title});
}).catch(err => {
console.log(err);
return res.status(500).send("Internal Server Error");
});
};

const getParticularToDo = async (req, res) => {
// Get the Todo of the logged in user with given id.
try{
const toDo = await ToDo.findOne({$and:[{$or:[{createdBy:req.user._id},{collaborators:req.user._id}]},{_id: req.params.id}]});
if(!toDo){
return res.status(404).send("No ToDo found with that id")
}
else{
return res.status(200).send({id:toDo._id,title:toDo.title});
}
}catch(err){
console.log(err);
return res.status(500).send("Internal Server Error");
}
};

const editToDo = async (req, res) => {
// Change the title of the Todo with given id, and get the new title as response.
};

const editToDoPatch = async (req, res) => {
// Change the title of the Todo with given id, and get the new title as response
try{
const title = req.body.title;
const toDo = await ToDo.findOne({$and:[{_id:req.params.id},{$or:[{createdBy:req.user._id},{collaborators:req.user._id}]}]});
if(!toDo){
return res.status(404).send("ToDo not found")
}
else{
await ToDo.findByIdAndUpdate(req.params.id,{$set:{title:title}});
return res.status(200).send({id:req.params.id,title:title});
}
}catch(err){
console.log(err);
return res.status(500).send("Internal Server Error");
}
};

const editToDoPatch = async (req, res) => {
// Change the title of the Todo with given id, and get the new title as response
try{
const title = req.body.title;
const toDo = await ToDo.findOne({$and:[{_id:req.params.id},{$or:[{createdBy:req.user._id},{collaborators:req.user._id}]}]});
if(!toDo){
return res.status(404).send("ToDo not found")
}
else{
await ToDo.findByIdAndUpdate(req.params.id,{$set:{title:title}});
return res.status(200).send({id:req.params.id,title:title});
}
}catch(err){
console.log(err);
return res.status(500).send("Internal Server Error");
}
};

const deleteToDo = async (req, res) => {
// Delete the todo with given id
try{
const toDo = await ToDo.findOne({$and:[{_id:req.params.id},{$or:[{createdBy:req.user._id},{collaborators:req.user._id}]}]});
if(!toDo){
return res.status(404).send("ToDo not found")
}
else{
await ToDo.findByIdAndDelete(req.params.id);
return res.status(204).send("Deleted successfully");
}
}catch(err){
console.log(err);
return res.status(500).send("Internal Server Error");
}
};

const addCollaborator = async (req, res) => {
try{
const toDo = await ToDo.findOne({$and:[{_id:req.params.id},{createdBy:req.user._id}]});
if(!toDo){
return res.status(404).send("ToDo not found");
}
const user = await User.findOne({username:req.body.username})
if(!user){
return res.status(404).send("No user found with that username");
}
if(req.body.username==req.user.username){
return res.status(400).send("Creator cannot be a collaborator");
}

for(i of toDo.collaborators){
if(user._id.toString() == i.toString()){
return res.send("Given user is already a Collaborator");
}}

await ToDo.findByIdAndUpdate(req.params.id,{$push:{collaborators:user._id}});
return res.status(200).send("User added as Collaborator")
}catch(err){
console.log(err);
return res.status(500).send("Internal Server Error");
}
}

const removeCollaborator = async(req, res) => {
try{
const toDo = await ToDo.findOne({$and:[{_id:req.params.id},{createdBy:req.user._id}]});
if(!toDo){
return res.status(404).send("ToDo not found");
}
const user = await User.findOne({username:req.body.username});
if(!user){
return res.status(404).send("No user found with that username");
}
if(req.body.username==req.user.username){
return res.status(400).send("Creator cannot be a removed");
}
for(i of toDo.collaborators){
if(i.toString()==user._id.toString()){
await ToDo.findByIdAndUpdate(req.params.id,{$pull:{collaborators:i}})
return res.status(200).send("Collaborator removed successfully")
}
}
return res.status(400).send("Given user is not a Collaborator for this todo");
}catch(err){
console.log(err);
return res.status(500).send("Internal Server Error");
}
}

module.exports = {
createToDo,
deleteToDo,
editToDo,
editToDoPatch,
getAllToDo,
getParticularToDo,
addCollaborator,
removeCollaborator
};
73 changes: 73 additions & 0 deletions controllers/user.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
const { User, Token } = require("../models");
const { randomBytes } = require("crypto");
const { validationResult } = require('express-validator');
const bcrypt = require('bcrypt');
const { response } = require("express");

const createToken = (user) => {
return Token({
Expand All @@ -13,20 +16,90 @@ const login = async (req, res) => {
// Check if data is valid
// Return correct status codes: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
// If the user is verified, then return a token along with correct status code
try{
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
var user = await User.findOne({username: req.body.username});

if(user){
var check = await bcrypt.compare(req.body.pwd,user.password);
if(check){
let token = await Token.findOne({user:user._id});

return res.status(200).json({token:token.token});
}
else{
return res.status(401).send("Enter correct username and password!");
}
}
else{
return res.status(401).send("Enter correct username and password!");
}}catch(err){
console.log(err);
return res.status(500).send("Internal Server Error");
}
};

const signup = async (req, res) => {
// TODO: Read username, email, name, pwd from the req object
// Hash the password
// Return with appropriate status code in case of an error
// If successful, return with an appropriate token along with correct status code
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
if (await User.findOne({ $or: [{ username: req.body.username }, { email: req.body.email }] })) {
return res.status(400).json({ error: "User with same username or email already exists" });
}
const salt = await bcrypt.genSalt(10);
const hashPass = await bcrypt.hash(req.body.pwd, salt);

let newUser = new User({
name: req.body.name,
email: req.body.email,
username: req.body.username,
password: hashPass,
})

await newUser.save().then(() => {
let token = createToken(newUser);
token.save();
return res.status(201).json({token:token.token});
}).catch(err => console.error(err));

} catch (err) {
console.log(err);
return res.status(500).send("Internal Server Error")
}
};

const profile = async (req, res) => {
// TODO:
// Implement the functionality to retrieve the details
// of the logged in user.
// Check for the token and then use it to get user details
const authToken = req.header('authorization');
if(!authToken){
return res.status(401).send({error:"No Token"});
}

let token = authToken.split(" ");

if(token.length!==2 || token[0]!=="Token"){
return res.status(401).send({error:"Invalid Syntax. Use 'Token <token>' instead."});
}

let foundUser = await Token.findOne({token: token[1]}).populate('user');
if(!foundUser){
return res.status(401).send({error:"Invalid Token"});
}
else{
return res.status(200).json({id:foundUser.user._id,name:foundUser.user.name,username:foundUser.user.username,email:foundUser.user.email});
}
};

module.exports = { login, signup, profile };
9 changes: 6 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const express = require("express");
const { json, urlencoded } = require("body-parser");
const cors = require("cors");
const mongoose = require("mongoose");
const checkUser = require("./middleware/checkUser");

const { ToDoRoutes, UserRoutes } = require("./routes");

Expand All @@ -14,19 +15,21 @@ app.use(cors());
// disable powered by cookies
app.disable("x-powered-by");


app.use("/api/auth", UserRoutes);
app.use("/api/todo", ToDoRoutes);
app.use("/api/todo",checkUser,ToDoRoutes);

const PORT = process.env.PORT || 8000;
const mongoDB = "mongodb://127.0.0.1/my_database";
const mongoDB = "mongodb://localhost:27017/my_database"; // MongoDB Compass

mongoose.set("useFindAndModify", false);
mongoose.set("useCreateIndex", true);
mongoose
.connect(mongoDB, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
console.log("Mongoose connected")
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
console.log(`http://localhost:${PORT}/`);
});
})
.catch((err) => console.log(err.message));
25 changes: 25 additions & 0 deletions middleware/checkUser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const express = require('express');
const Token = require('../models/token')

const checkUser = async function (req, res, next) {
const authToken = req.header('authorization');

if (!authToken) {
return res.status(401).send({ error: "No Token" });
}

let token = authToken.split(" ");

if (token.length !== 2 || token[0] !== "Token") {
return res.status(401).send({ error: "Invalid Syntax. Use 'Token <token>' instead." });
}

let found = await Token.findOne({token:token[1]}).populate('user');
if(!found)return res.status(401).send({ error: "Invalid Token" });
else{
req.user = found.user;
return next();
}

}
module.exports = checkUser;
1 change: 1 addition & 0 deletions models/todo.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const todoSchema = new Schema(
{
title: { type: String, required: true },
createdBy: { type: Schema.Types.ObjectId, ref: "User" },
collaborators: [{ type: Schema.Types.ObjectId, ref: "User" }]
},
{ timestamps: true }
);
Expand Down
15 changes: 15 additions & 0 deletions node_modules/.bin/color-support

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions node_modules/.bin/color-support.cmd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions node_modules/.bin/is-ci

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions node_modules/.bin/is-ci.cmd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading