Skip to content
Merged
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
64 changes: 44 additions & 20 deletions backend/common/errors/errorHandler.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,82 @@
const logger = require('../../misc/logger')

const logError = (error, request) => {
logger.error({
message: error.message,
error: {
stack: error.stack,
complete: error,
},
request: {
requestBody: request.body,
requestParams: request.params,
requestQuery: request.query,
},
})
}

const errorHandler = (error, request, response, next) => {
logError(error, request)
switch (error.name) {
case 'UnauthorizedError': {
return response.status(401).json({
message: error.message || 'Unauthorized',
status: 401,
})
}
case 'NotFoundError': {
return response.status(404).json({
message: error.message || 'Not found',
status: 404,
})
}
case 'InsufficientPrivilegesError': {
return response.status(401).json({
message: 'Insufficient privileges',
message: error.message || 'Insufficient privileges',
status: 401,
})
}
case 'ForbiddenError': {
case 'EmailVerificationError': {
return response.status(403).json({
message: error.message || 'Forbidden',
message: error.message || 'Email verification required',
status: 403,
})
}
case 'NotFoundError': {
return response.status(404).json({
message: error.message || 'Not found',
status: 404,
})
}
case 'ValidationError': {
return response.status(400).json({
message: error.message,
message: error.message || 'Validation error',
errors: error.errors,
status: 400,
})
}
case 'ForbiddenError': {
return response.status(403).json({
message: error.message || 'Forbidden',
status: 403,
})
}
case 'AlreadyExistsError': {
return response.status(400).json({
message: error.message || 'Already exists',
status: 400,
})
}
case 'MongoError': {
if (error.code === 11000) {
return response.status(400).json({
message: 'Report to tech support',
type: 'unique-violation',
status: 400,
})
}
break
return response.status(400).json({
message: error.message || 'Validation error',
status: 400,
})
}
default:
logger.error({
message: 'Unhandled error',
error: {
message: error.message,
stack: error.stack,
},
})

return response.status(500).json({
message: 'Unexpected error',
message: error.message || 'Unexpected error',
status: 500,
})
}
Expand Down
33 changes: 21 additions & 12 deletions backend/common/errors/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,26 @@ class CustomError extends Error {
}

class NotFoundError extends CustomError {
constructor(message) {
constructor(message, details) {
const name = 'NotFoundError'
const code = 1
super(message, name, code)
super(message, name, code, details)
}
}

class InsufficientPrivilegesError extends CustomError {
constructor(message) {
constructor(message, details) {
const name = 'InsufficientPrivilegesError'
const code = 2
super(message, name, code)
super(message, name, code, details)
}
}

class EmailVerificationError extends CustomError {
constructor(message) {
constructor(message, details) {
const name = 'EmailVerificationError'
const code = 3
super(message, name, code)
super(message, name, code, details)
}
}

Expand All @@ -50,26 +50,34 @@ class ValidationError extends CustomError {
}

class ForbiddenError extends CustomError {
constructor(message) {
constructor(message, details) {
const name = 'ForbiddenError'
const code = 5
super(message, name, code)
super(message, name, code, details)
}
}

class UnauthorizedError extends CustomError {
constructor(message) {
constructor(message, details) {
const name = 'UnauthorizedError'
const code = 6
super(message, name, code)
super(message, name, code, details)
}
}

class AlreadyExistsError extends CustomError {
constructor(message) {
constructor(message, details) {
const name = 'AlreadyExistsError'
const code = 7
super(message, name, code)
super(message, name, code, details)
}
}

class MongoError extends CustomError {
constructor(message, details) {
const name = 'MongoError'
const code = 8
super(message, name, code, details)
}
}

Expand All @@ -81,4 +89,5 @@ module.exports = {
ForbiddenError,
UnauthorizedError,
AlreadyExistsError,
MongoError,
}
72 changes: 47 additions & 25 deletions backend/modules/project_score/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,44 @@ const _ = require('lodash')
const Event = require('../event/model')
const Project = require('../project/model')
const { ProjectScore } = require('./model')
const { NotFoundError } = require('../../common/errors/errors')
const {
NotFoundError,
AlreadyExistsError,
} = require('../../common/errors/errors')

const controller = {}

controller.addProjectScore = async score => {
await Project.findById(score.project).orFail(
controller.addProjectScore = async (projectId, projectScoreByReviewer) => {
const projectScoreFound = await ProjectScore.findOne({ project: projectId })
if (projectScoreFound) {
return controller.updateProjectScoreWithReviewers(
projectScoreFound._id,
projectScoreByReviewer,
)
}
const projectData = await Project.findById(projectId).orFail(
new NotFoundError('The given project does not exist.'),
)
await Event.findById(score.event).orFail(
new NotFoundError('The given event does not exist.'),
)
const projectScore = new ProjectScore({ ...score })
projectScore.averageScore = projectScore.score
const projectScore = new ProjectScore({
reviewers: [projectScoreByReviewer],
project: projectId,
event: projectData.event,
})

if (projectScore.reviewers && projectScore.reviewers.length > 0) {
const averageScore = averageScoreCalculation(
projectScore.reviewers,
projectScore.score,
)
if (!averageScore) {
throw new Error('Score average calculation failed')
throw new Error(
'Score average calculation failed, make sure all criteria are filled in',
)
}
projectScore.averageScore = averageScore
}
return projectScore.save()
projectScore.save()
return projectScore
}

controller.updateProjectScore = async (id, updatedProjectScore) => {
Expand Down Expand Up @@ -112,7 +125,9 @@ const limitDecimals = (number, decimalPlaces) => {

const averageScoreCalculation = (reviewers, globalScore) => {
const allScores = reviewers.map(review => review.score)
allScores.push(globalScore)
if (globalScore) {
allScores.push(globalScore)
}
let scoreCount = allScores.length

const scoreSum = allScores.reduce((acc, current) => {
Expand All @@ -132,17 +147,27 @@ const averageScoreCalculation = (reviewers, globalScore) => {
}

controller.updateProjectScoreWithReviewers = async (
id,
projectScoreId,
updatedProjectScore,
) => {
const projectScore = await ProjectScore.findById(id).orFail(
new NotFoundError('The given ProjectScore does not exist.'),
const projectScore = await ProjectScore.findById(projectScoreId).orFail(
new NotFoundError(
'The given ProjectScore does not exist, refresh and try again.',
),
)
projectScore.status = updatedProjectScore.status
projectScore.track = updatedProjectScore.track
projectScore.challenge = updatedProjectScore.challenge
projectScore.reviewers = updatedProjectScore.reviewers

const reviewerFoundIndex = _.findIndex(projectScore.reviewers, {
userId: updatedProjectScore.userId,
})
if (reviewerFoundIndex !== -1) {
projectScore.reviewers[reviewerFoundIndex].score =
updatedProjectScore.score
projectScore.reviewers[reviewerFoundIndex].scoreCriteria =
updatedProjectScore.scoreCriteria
projectScore.reviewers[reviewerFoundIndex].message =
updatedProjectScore.message
} else {
projectScore.reviewers.push(updatedProjectScore)
}
projectScore.averageScore = projectScore.score

if (projectScore.reviewers && projectScore.reviewers.length > 0) {
Expand All @@ -151,15 +176,12 @@ controller.updateProjectScoreWithReviewers = async (
projectScore.score,
)
if (!averageScore) {
throw new Error('Score average calculation failed')
throw new Error(
'Score average calculation failed, make sure all criteria are filled in',
)
}
projectScore.averageScore = averageScore
}

//scores from reviewers + scores from global, divide by total count of scores

// projectScore.averageScore = projectScore.score +

await projectScore.save()
return projectScore
}
Expand Down
46 changes: 23 additions & 23 deletions backend/modules/project_score/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@ const {
} = require('../../common/middleware/events')

const addProjectScore = asyncHandler(async (req, res) => {
console.log('addProjectScore is running')
const { projectId } = req.params
try {
if (req.params.track) {
req.body.track = req.params.track._id
}
if (req.params.challenge) {
req.body.challenge = req.params.challenge._id
}
const score = await ProjectScoreController.addProjectScore(req.body)
// if (req.params.track) {
// req.body.track = req.params.track._id
// }
// if (req.params.challenge) {
// req.body.challenge = req.params.challenge._id
// }
const score = await ProjectScoreController.addProjectScore(
projectId,
req.body,
)
return res.status(200).json(score)
} catch (e) {
console.error(e)
return res.status(500).json({
message:
'Add project score encountered an unknown error. Please check your request and try again.',
Expand Down Expand Up @@ -86,20 +88,20 @@ const getPublicScores = asyncHandler(async (req, res) => {
})

const updateProjectScoreWithReviewers = asyncHandler(async (req, res) => {
console.log('Received on bcknd')
const { slug, projectScoreId } = req.params
try {
if (req.params.track) {
req.body.track = req.params.track._id
}
if (req.params.challenge) {
req.body.challenge = req.params.challenge._id
}
const score =
// if (req.params.track) {
// req.body.track = req.params.track._id
// }
// if (req.params.challenge) {
// req.body.challenge = req.params.challenge._id
// }
const projectScore =
await ProjectScoreController.updateProjectScoreWithReviewers(
req.params.id,
projectScoreId,
req.body,
)
return res.status(200).json(score)
return res.status(200).json(projectScore)
} catch (e) {
return res.status(500).json({
message:
Expand All @@ -122,7 +124,6 @@ router.get(
'/event/:slug/project/:projectId',
hasToken,
isOrganiserOrCanSubmitProject,
//isEventOrganiser,
getScoreByProjectId,
)

Expand Down Expand Up @@ -160,15 +161,14 @@ router.get(
)

router.post(
'/review/event/:slug/:id',
'/review/event/:slug/:projectId',
hasToken,
isEventPartner,
// getEventFromParams,
addProjectScore,
)

router.put(
'/review/event/:slug/:id',
'/review/event/:slug/:projectScoreId',
hasToken,
isEventPartner,
updateProjectScoreWithReviewers,
Expand Down
Loading