Skip to content
Open
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<img src="https://user-images.githubusercontent.com/30529572/92081025-fabe6f00-edb1-11ea-9169-4a8a61a5dd45.png" alt="DSC VIT"/>
</a>
<h2 align="center"> WERK BACKEND </h2>
<h4 align="center"> < Insert Project Description Here > <h4>
<h4 align="center"> It is a RESTful Backend API for the Werk App. <h4>
</p>

---
Expand Down Expand Up @@ -68,4 +68,4 @@ npm start

<p align="center">
Made with :heart: by <a href="https://dscvit.com">DSC VIT</a>
</p>
</p>
44 changes: 32 additions & 12 deletions api/controllers/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,20 @@ exports.googleAuth = async (req, res) => {
}
})
if (!searchedUser) {
console.log(user)
// console.log(user)
const result = await User.create({
name: user.displayName || '',
email: user.email,
avatar: user.photoURL || process.env.DEFAULT_AVATAR,
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
Expand Down Expand Up @@ -63,19 +69,28 @@ 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)

if (!validator.isEmail(email)) throw new BadRequest('Email format is incorrect')

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
Expand Down Expand Up @@ -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!')
Expand Down Expand Up @@ -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!')
Expand All @@ -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!')
Expand All @@ -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!')
Expand Down Expand Up @@ -250,7 +269,8 @@ exports.changePassword = async (req, res) => {
exclude: ['password']
},
where: {
userId
userId,
registered: true
}
})
if (!searchedUser.length) throw new BadRequest('Invalid User')
Expand Down
113 changes: 110 additions & 3 deletions api/controllers/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -15,19 +16,42 @@ 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 (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')

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'],
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)

Expand Down Expand Up @@ -56,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({
Expand Down Expand Up @@ -109,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)
}
Expand Down Expand Up @@ -161,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 {
Expand Down Expand Up @@ -191,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()
// })
// }
// }
15 changes: 10 additions & 5 deletions api/controllers/task.js
Original file line number Diff line number Diff line change
Expand Up @@ -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') }
Expand Down Expand Up @@ -60,7 +64,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')
Expand Down Expand Up @@ -223,12 +227,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')
Expand Down Expand Up @@ -378,7 +383,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) })
Expand Down
2 changes: 1 addition & 1 deletion api/middlewares/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
4 changes: 4 additions & 0 deletions api/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ const User = sequelize.define('user', {
},
verificationCode: {
type: Sequelize.STRING
},
registered: {
type: Sequelize.BOOLEAN,
defaultValue: true
}
}, {
timestamps: true
Expand Down
8 changes: 5 additions & 3 deletions api/utils/email.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -107,7 +107,9 @@ const sendAccessCodeTemplate = (data) => {
<a href="https://github.com/GDGVIT/werk-backend" ><img src="https://user-images.githubusercontent.com/30529572/92081025-fabe6f00-edb1-11ea-9169-4a8a61a5dd45.png" width="400" height="100"></a>
</div>
<div style="margin-left: 15px;">
<p>Hola! <strong style="text-transform:capitalize;">${data.userName}</strong> has invited you to the session <strong>${data.name}</strong>. ${data.desc.length > 0 ? 'The description of the session is "' + data.desc + '"' : ''}</p>
${data.registered === true
? ` <p>Hola! <strong style="text-transform:capitalize;">${data.userName}</strong> has invited you to the session <strong>${data.name}</strong>. ${data.desc.length > 0 ? 'The description of the session is "' + data.desc + '"' : ''}</p>`
: ` <p>Hola! Werk is a productivity app. Your friend <strong style="text-transform:capitalize;">${data.userName}</strong> has invited to the session </p> <strong>${data.name}</strong> in the app. ${data.desc.length > 0 ? 'The description of the session is ' + data.desc + '.' : ''}`}
<p>You can join the session by entering the access code: <strong>${data.code}</strong> in the Werk App. You can also join the session by scanning the given QRCode in the Werk app.</p>
<div style="text-align:center"> <img src="${data.location}" alt="img" width="200" height="200"/></div>
<br>
Expand Down