From 984163231d933ad0b609f145f2f3c1469c6baea6 Mon Sep 17 00:00:00 2001 From: Vishal Reddy Chintham <54095062+vishal-1408@users.noreply.github.com> Date: Wed, 4 Aug 2021 00:03:08 +0530 Subject: [PATCH 01/10] feat: update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2bc1f4c..f9c21ea 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ DSC VIT

WERK BACKEND

-

< Insert Project Description Here >

+

It is a RESTful Backend API for the Werk App.

--- @@ -68,4 +68,4 @@ npm start

Made with :heart: by DSC VIT -

\ No newline at end of file +

From 41bf3657f0b032ba32da02a81092f5bc6e85d169 Mon Sep 17 00:00:00 2001 From: vishal-1408 Date: Wed, 4 Aug 2021 13:22:24 +0530 Subject: [PATCH 02/10] fix: calendar constraints set up --- api/controllers/session.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/api/controllers/session.js b/api/controllers/session.js index 3ad03a7..14c92ae 100644 --- a/api/controllers/session.js +++ b/api/controllers/session.js @@ -15,6 +15,10 @@ exports.createSession = async (req, res) => { // start and end time are in epoch format const { startTime, endTime, taskCreationByAll, taskAssignByAll, participants, name, description } = req.body if (!name || !description || !startTime || !endTime || taskCreationByAll === null || taskAssignByAll === null || !participants.length) throw new BadRequest('All required fields are not provided') + if (startTime >= endTime) throw new BadRequest('End Time cannot be less than or equal to the start time') + + // if (new Date().getTime() > startTime || new Date().getTime() > endTime) throw new BadRequest('Provided timings are not valid!') + const accessCode = crypto.randomBytes(5).toString('hex') const participantsFiltered = participants.filter(p => p !== req.user.email) From b63cb33b96273634ec09577e2673b82a42a6d28e Mon Sep 17 00:00:00 2001 From: vishal-1408 Date: Wed, 4 Aug 2021 13:33:11 +0530 Subject: [PATCH 03/10] fix: task assigned bug --- api/controllers/task.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/controllers/task.js b/api/controllers/task.js index 715c401..51d4b59 100644 --- a/api/controllers/task.js +++ b/api/controllers/task.js @@ -378,7 +378,7 @@ exports.getTask = async (req, res) => { let task = await Task.findOne({ where: { taskId } }) if (!task) throw new BadRequest('task doesn\'t exist') - if (task.assignedTo !== req.user.userId) throw new BadRequest('This task is not assigned to you') + if (task.assignedTo && task.assignedTo !== req.user.userId) throw new BadRequest('This task is not assigned to you') task = task.toJSON() if (task.status === 'started') task.completionDuration += (new Date().getTime() - task.startedTime) res.status(200).json({ ...task, ...changeDurationFormat(task.completionDuration) }) From b24e4cabaf73ba04ee23c56fbeb0bc632dcbd28d Mon Sep 17 00:00:00 2001 From: vishal-1408 Date: Wed, 4 Aug 2021 13:44:12 +0530 Subject: [PATCH 04/10] fix: remove unnecessary task assigned check in getTask controller --- api/controllers/task.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/controllers/task.js b/api/controllers/task.js index 51d4b59..dd14b34 100644 --- a/api/controllers/task.js +++ b/api/controllers/task.js @@ -378,7 +378,7 @@ exports.getTask = async (req, res) => { let task = await Task.findOne({ where: { taskId } }) if (!task) throw new BadRequest('task doesn\'t exist') - if (task.assignedTo && task.assignedTo !== req.user.userId) throw new BadRequest('This task is not assigned to you') + // if (task.assignedTo && task.assignedTo !== req.user.userId) throw new BadRequest('This task is not assigned to you') task = task.toJSON() if (task.status === 'started') task.completionDuration += (new Date().getTime() - task.startedTime) res.status(200).json({ ...task, ...changeDurationFormat(task.completionDuration) }) From 713a2d35f8d4a6a8d68d07943ea7ab800974d888 Mon Sep 17 00:00:00 2001 From: vishal-1408 Date: Wed, 4 Aug 2021 14:09:53 +0530 Subject: [PATCH 05/10] fix: add new constrains in task reassign route --- api/controllers/task.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/api/controllers/task.js b/api/controllers/task.js index dd14b34..b6e422e 100644 --- a/api/controllers/task.js +++ b/api/controllers/task.js @@ -60,7 +60,7 @@ exports.assignTask = async (req, res) => { if (!task) throw new BadRequest('task doesn\'t exist') if (task.assignedTo != null) throw new BadRequest('task is already assigned!') - if (!task.session.taskAssignUniv && req.user.userId !== task.session.createdBy) { throw new BadRequest('Only Session owner can assign the tasks!!') } + if (!task.session.taskAssignUniv && req.user.userId !== task.session.createdBy) { throw new BadRequest('Session creator can only assign the tasks') } const user = await User.findOne({ where: { userId } }) if (!user) throw new BadRequest('Invalid User Id') @@ -223,12 +223,13 @@ exports.taskShifted = async (req, res) => { const task = await Task.findOne({ where: { taskId }, include: { model: Session } }) if (!task) throw new BadRequest('task doesn\'t exist') - if (!task.submittedDate && task.status === 'completed') { throw new BadRequest('Task is already completed!') } + if (task.status === 'completed') { throw new BadRequest('Task is already completed!') } - // if(task.status=='terminated') + if (task.status === 'terminated') throw new BadRequest('task is already terminated') // ONLY TASK CREATOR AND SESSION CREATOR HAS THE POWER TO REASSIGN THE TASK TO SOMEONE ELSE! - if (!task.session.taskAssignUniv && req.user.userId !== task.session.createdBy && task.createdBy !== req.user.userId) { throw new BadRequest('You don\'t have the permission to assign this task to other person') } + if (!task.session.taskAssignUniv && req.user.userId !== task.session.createdBy) throw new BadRequest('Tasks can be assigned only by the session creator!') + // if (task.session.taskAssignUniv && req.user.userId !== task.createdBy && req.user.userId !== task.session.createdBy) { throw new BadRequest('Task creator and session creator can assign the task') } const user = await User.findOne({ where: { userId } }) if (!user) throw BadRequest('Invalid User Id') From 2c01eaca6b46e3c57514248431af7a5c33f08645 Mon Sep 17 00:00:00 2001 From: vishal-1408 Date: Thu, 5 Aug 2021 18:23:01 +0530 Subject: [PATCH 06/10] fix: add new constraints for creating a session --- api/controllers/session.js | 2 +- api/controllers/task.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/api/controllers/session.js b/api/controllers/session.js index 14c92ae..0f69147 100644 --- a/api/controllers/session.js +++ b/api/controllers/session.js @@ -16,7 +16,7 @@ exports.createSession = async (req, res) => { const { startTime, endTime, taskCreationByAll, taskAssignByAll, participants, name, description } = req.body if (!name || !description || !startTime || !endTime || taskCreationByAll === null || taskAssignByAll === null || !participants.length) throw new BadRequest('All required fields are not provided') if (startTime >= endTime) throw new BadRequest('End Time cannot be less than or equal to the start time') - + if (startTime < (new Date().getTime() + (330 * 60 * 60)) || endTime < (new Date().getTime() + (330 * 60 * 60))) throw new BadRequest('Choose only future time and date') // if (new Date().getTime() > startTime || new Date().getTime() > endTime) throw new BadRequest('Provided timings are not valid!') const accessCode = crypto.randomBytes(5).toString('hex') diff --git a/api/controllers/task.js b/api/controllers/task.js index b6e422e..3d9768d 100644 --- a/api/controllers/task.js +++ b/api/controllers/task.js @@ -14,6 +14,10 @@ exports.createTask = async (req, res) => { if (!description || !title || !expectedDuration || !points || !sessionId) { throw new BadRequest('All required fields are not provided') } const session = await Session.findOne({ where: { sessionId } }) + + if ((new Date().getTime() + (330 * 60 * 60) > session.endTime)) throw new BadRequest('Session is completed!') + if ((new Date().getTime() + (330 * 60 * 60) < session.startTime)) throw new BadRequest('Session has not started yet!') + if (!session) throw new BadRequest('Session doesn\'t exist') if (!session.taskCreationUniv && req.user.userId !== session.createdBy) { throw new BadRequest('Task can be created only by the session owner') } From 99bbb82de798390775399926827ef43d39a203e7 Mon Sep 17 00:00:00 2001 From: vishal-1408 Date: Thu, 5 Aug 2021 18:32:33 +0530 Subject: [PATCH 07/10] fix: small change in create session --- api/controllers/session.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/controllers/session.js b/api/controllers/session.js index 0f69147..f644b18 100644 --- a/api/controllers/session.js +++ b/api/controllers/session.js @@ -16,7 +16,11 @@ exports.createSession = async (req, res) => { const { startTime, endTime, taskCreationByAll, taskAssignByAll, participants, name, description } = req.body if (!name || !description || !startTime || !endTime || taskCreationByAll === null || taskAssignByAll === null || !participants.length) throw new BadRequest('All required fields are not provided') if (startTime >= endTime) throw new BadRequest('End Time cannot be less than or equal to the start time') - if (startTime < (new Date().getTime() + (330 * 60 * 60)) || endTime < (new Date().getTime() + (330 * 60 * 60))) throw new BadRequest('Choose only future time and date') + const extraTime = (new Date().getTime() + (330 * 60 * 60)) + if (startTime < extraTime || endTime < extraTime) { + console.log(startTime, extraTime) + throw new BadRequest('Choose only future time and date') + } // if (new Date().getTime() > startTime || new Date().getTime() > endTime) throw new BadRequest('Provided timings are not valid!') const accessCode = crypto.randomBytes(5).toString('hex') From 14c39ceaa947057398d906f8cda3656be6061059 Mon Sep 17 00:00:00 2001 From: vishal-1408 Date: Thu, 5 Aug 2021 18:37:13 +0530 Subject: [PATCH 08/10] fix: future time bad request bug --- api/controllers/session.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/api/controllers/session.js b/api/controllers/session.js index f644b18..1220eaa 100644 --- a/api/controllers/session.js +++ b/api/controllers/session.js @@ -16,11 +16,8 @@ exports.createSession = async (req, res) => { const { startTime, endTime, taskCreationByAll, taskAssignByAll, participants, name, description } = req.body if (!name || !description || !startTime || !endTime || taskCreationByAll === null || taskAssignByAll === null || !participants.length) throw new BadRequest('All required fields are not provided') if (startTime >= endTime) throw new BadRequest('End Time cannot be less than or equal to the start time') - const extraTime = (new Date().getTime() + (330 * 60 * 60)) - if (startTime < extraTime || endTime < extraTime) { - console.log(startTime, extraTime) - throw new BadRequest('Choose only future time and date') - } + if (startTime < new Date().getTime() || endTime < new Date().getTime()) throw new BadRequest('Choose only future time and date') + // if (new Date().getTime() > startTime || new Date().getTime() > endTime) throw new BadRequest('Provided timings are not valid!') const accessCode = crypto.randomBytes(5).toString('hex') From 4e8f8c2328d9e2f6ae89bf075f9c1cdada3b2a6c Mon Sep 17 00:00:00 2001 From: vishal-1408 Date: Sun, 8 Aug 2021 13:08:42 +0530 Subject: [PATCH 09/10] feat: add new feature, can send emails to users who aren't registered on the app --- api/controllers/auth.js | 44 +++++++++++++++++++++++++++----------- api/controllers/session.js | 27 ++++++++++++++++++++--- api/controllers/task.js | 4 ++-- api/models/user.js | 4 ++++ api/utils/email.js | 8 ++++--- 5 files changed, 67 insertions(+), 20 deletions(-) diff --git a/api/controllers/auth.js b/api/controllers/auth.js index a087c18..ce9de31 100644 --- a/api/controllers/auth.js +++ b/api/controllers/auth.js @@ -21,7 +21,7 @@ exports.googleAuth = async (req, res) => { } }) if (!searchedUser) { - console.log(user) + // console.log(user) const result = await User.create({ name: user.displayName || '', email: user.email, @@ -29,6 +29,12 @@ exports.googleAuth = async (req, res) => { emailVerified: true }) searchedUser = result + } else if (!searchedUser.registered) { + searchedUser.name = user.displayName || '' + searchedUser.avatar = user.photoURL || process.env.DEFAULT_AVATAR + searchedUser.emailVerified = true + searchedUser.registered = true + await searchedUser.save() } const token = generateToken({ userId: searchedUser.userId @@ -63,7 +69,7 @@ exports.register = async (req, res) => { } }) - if (searchedUser.length) { throw new BadRequest('Email is already registered!') } + if (searchedUser.length && searchedUser[0].registered) { throw new BadRequest('Email is already registered!') } const hashedPassword = await hashIt(password) @@ -71,11 +77,20 @@ exports.register = async (req, res) => { if (password.length < 5) throw new BadRequest('Password must have more than 5 chars') - const user = await User.create({ - name, - email, - password: hashedPassword - }) + let user + if (!searchedUser.length) { + user = await User.create({ + name, + email, + password: hashedPassword + }) + } else if (!searchedUser.registered) { + searchedUser[0].name = name + searchedUser[0].registered = true + searchedUser[0].password = hashedPassword + await searchedUser[0].save() + user = searchedUser[0] + } const token = generateToken({ userId: user.userId @@ -106,7 +121,8 @@ exports.login = async (req, res) => { if (!email || !password) throw new BadRequest('Required data is not provided') const searchedUser = await User.findAll({ where: { - email: email + email: email, + registered: true } }) if (!searchedUser.length) throw new Unauthorized('Email is not registered with us!') @@ -147,7 +163,8 @@ exports.sendEmail = async (req, res) => { exclude: ['password'] }, where: { - email: email + email: email, + registered: true } }) if (!searchedUser.length) throw new BadRequest('Email is not registered with us!') @@ -173,7 +190,8 @@ exports.verifyEmail = async (req, res) => { exclude: ['password'] }, where: { - verificationCode + verificationCode, + registered: true } }) if (!searchedUser.length) throw new BadRequest('Email is not registered with us!') @@ -199,7 +217,8 @@ exports.sendResetPasswordLink = async (req, res) => { exclude: ['password'] }, where: { - email: email + email: email, + registered: true } }) if (!searchedUser.length) throw new BadRequest('Email is not registered with us!') @@ -250,7 +269,8 @@ exports.changePassword = async (req, res) => { exclude: ['password'] }, where: { - userId + userId, + registered: true } }) if (!searchedUser.length) throw new BadRequest('Invalid User') diff --git a/api/controllers/session.js b/api/controllers/session.js index 1220eaa..d7a8c88 100644 --- a/api/controllers/session.js +++ b/api/controllers/session.js @@ -7,6 +7,7 @@ const Session = require('../models/session') const Participant = require('../models/participant') const { generateQRCode } = require('../utils') const { deleteFile } = require('../utils/s3Utils') + // const Task = require('../models/task') require('dotenv').config() @@ -27,12 +28,30 @@ exports.createSession = async (req, res) => { if (!participantsFiltered.length) throw new BadRequest('Don\'t give your own email while creation of session') const result = await User.findAll({ - attributes: ['userId', 'email'], + attributes: ['userId', 'email', 'registered'], where: { email: participantsFiltered } }) - if (!result.length) throw new BadRequest('Provided emails are not registered with any of our user') + // if (!result.length) throw new BadRequest('Provided emails are not registered with any of our user') + const newParticipants = [] + let check + for (const x of participantsFiltered) { + check = 0 + for (const y of result) { + if (x === y.email) check = 1 + } + if (!check) { + newParticipants.push({ + name: 'Guest@' + crypto.randomBytes(2).toString('hex'), + email: x, + registered: false + }) + } + } + + result.push(...await User.bulkCreate(newParticipants)) + console.log(result) const data = await generateQRCode(accessCode) @@ -61,7 +80,7 @@ exports.createSession = async (req, res) => { await Participant.bulkCreate(participantsArray) result.forEach(async (p, i) => { - if (i !== 0) await sendAccessCode(accessCode, p.email, req.user.name, data.Location, name, description) + if (i !== 0) await sendAccessCode(accessCode, p.email, req.user.name, data.Location, name, description, p.registered) }) res.status(200).json({ @@ -114,6 +133,7 @@ exports.joinSession = async (req, res) => { check = false } }) + // after the last person entered the session! Delete the qr code file! if (check === true) { await deleteFile(process.env.AWS_BUCKET, session[0].qrCode) } @@ -166,6 +186,7 @@ exports.getSessions = async (req, res) => { exports.getParticipants = async (req, res) => { try { const session = await Session.findByPk(req.params.id) + if (!session) throw new BadRequest('Session doesn\'t exist') const participants = await session.getUsers() let users = participants.map(p => { return { diff --git a/api/controllers/task.js b/api/controllers/task.js index 3d9768d..8eb0dfc 100644 --- a/api/controllers/task.js +++ b/api/controllers/task.js @@ -15,8 +15,8 @@ exports.createTask = async (req, res) => { const session = await Session.findOne({ where: { sessionId } }) - if ((new Date().getTime() + (330 * 60 * 60) > session.endTime)) throw new BadRequest('Session is completed!') - if ((new Date().getTime() + (330 * 60 * 60) < session.startTime)) throw new BadRequest('Session has not started yet!') + // if ((new Date().getTime() + (330 * 60 * 60) > session.endTime)) throw new BadRequest('Session is completed!') + // if ((new Date().getTime() + (330 * 60 * 60) < session.startTime)) throw new BadRequest('Session has not started yet!') if (!session) throw new BadRequest('Session doesn\'t exist') diff --git a/api/models/user.js b/api/models/user.js index 7fc8c0b..2a32556 100644 --- a/api/models/user.js +++ b/api/models/user.js @@ -38,6 +38,10 @@ const User = sequelize.define('user', { }, verificationCode: { type: Sequelize.STRING + }, + registered: { + type: Sequelize.BOOLEAN, + defaultValue: true } }, { timestamps: true diff --git a/api/utils/email.js b/api/utils/email.js index 0c8403b..3dc7852 100644 --- a/api/utils/email.js +++ b/api/utils/email.js @@ -18,12 +18,12 @@ exports.sendVerificationLink = async (user) => { return sendEmail(mailOptions) } -exports.sendAccessCode = async (accessCode, email, sender, location, sessionName, sessionDesc) => { +exports.sendAccessCode = async (accessCode, email, sender, location, sessionName, sessionDesc, registered) => { const mailOptions = { from: process.env.WERK_EMAIL, to: email, subject: 'Invite to join a session of Werk', - html: sendAccessCodeTemplate({ userName: sender, name: sessionName, desc: sessionDesc, code: accessCode, location }) + html: sendAccessCodeTemplate({ userName: sender, name: sessionName, desc: sessionDesc, code: accessCode, location, registered }) } return sendEmail(mailOptions) @@ -107,7 +107,9 @@ const sendAccessCodeTemplate = (data) => {
-

Hola! ${data.userName} has invited you to the session ${data.name}. ${data.desc.length > 0 ? 'The description of the session is "' + data.desc + '"' : ''}

+ ${data.registered === true + ? `

Hola! ${data.userName} has invited you to the session ${data.name}. ${data.desc.length > 0 ? 'The description of the session is "' + data.desc + '"' : ''}

` + : `

Hola! Werk is a productivity app. Your friend ${data.userName} has invited to the session

${data.name} in the app. ${data.desc.length > 0 ? 'The description of the session is ' + data.desc + '.' : ''}`}

You can join the session by entering the access code: ${data.code} in the Werk App. You can also join the session by scanning the given QRCode in the Werk app.

img

From 7025825c02fb93ce7bb4c4d90bb191a201c7d2e7 Mon Sep 17 00:00:00 2001 From: vishal-1408 Date: Sun, 8 Aug 2021 13:48:44 +0530 Subject: [PATCH 10/10] fix: bugs due to previous new feature addition --- api/controllers/session.js | 81 ++++++++++++++++++++++++++++++++++++++ api/middlewares/auth.js | 2 +- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/api/controllers/session.js b/api/controllers/session.js index d7a8c88..fb51232 100644 --- a/api/controllers/session.js +++ b/api/controllers/session.js @@ -217,3 +217,84 @@ exports.getParticipants = async (req, res) => { }) } } + +// exports.addParticipants = async (req, res) => { +// try { +// // start and end time are in epoch format +// const { participants } = req.body +// const sid = req.params.id +// if (!participants.length) throw new BadRequest('All required fields are not provided') + +// const session = await Session.findByPk(sid) + +// if (!session) throw new BadRequest('Session doesn\'t exist') + +// const participantsFiltered = participants.filter(p => p !== req.user.email) + +// if (!participantsFiltered.length) throw new BadRequest('Don\'t give your own email while creation of session') + +// const result = await User.findAll({ +// attributes: ['userId', 'email', 'registered'], +// where: { +// email: participantsFiltered +// } +// }) +// const newParticipants = [] +// let check +// for (const x of participantsFiltered) { +// check = 0 +// for (const y of result) { +// if (x === y.email) check = 1 +// } +// if (!check) { +// newParticipants.push({ +// name: 'Guest@' + crypto.randomBytes(2).toString('hex'), +// email: x, +// registered: false +// }) +// } +// } + +// result.push(...await User.bulkCreate(newParticipants)) +// console.log(result) + +// const data = await generateQRCode(session.accessCode) + +// // const session = await Session.create({ +// // sessionName: name, +// // sessionDescription: description, +// // startTime, +// // endTime, +// // createdBy: req.user.userId, +// // taskCreationUniv: taskCreationByAll, +// // taskAssignUniv: taskAssignByAll, +// // accessCode, +// // qrCode: data.Location +// // }) + +// result.splice(0, 0, req.user) +// const participantsArray = [] +// result.forEach(async (p, i) => { +// participantsArray.push({ +// sId: session.sessionId, +// userId: p.userId, +// joined: i === 0 +// }) +// }) + +// await Participant.bulkCreate(participantsArray) + +// result.forEach(async (p, i) => { +// if (i !== 0) await sendAccessCode(accessCode, p.email, req.user.name, data.Location, name, description, p.registered) +// }) + +// res.status(200).json({ +// session: { ...session.dataValues } +// }) +// } catch (e) { +// console.log(e) +// res.status(e.status || 500).json({ +// error: e.status ? e.message : e.toString() +// }) +// } +// } diff --git a/api/middlewares/auth.js b/api/middlewares/auth.js index 0cc97a5..482f792 100644 --- a/api/middlewares/auth.js +++ b/api/middlewares/auth.js @@ -17,7 +17,7 @@ const authMiddleware = async (req, res, next) => { } }) if (!searchedUser.length) throw new Unauthorized('User is not registered!') - if (!searchedUser[0].emailVerified) throw new Unauthorized('EMail is not verified!') + if (!searchedUser[0].emailVerified) throw new Unauthorized('Email is not verified!') req.user = searchedUser[0] next()