Renamed errors

This commit is contained in:
Ceferino Patino 2022-12-17 16:37:51 -06:00
commit 2dddd857c1
30 changed files with 104 additions and 98 deletions

View file

@ -1,23 +1,20 @@
{
"errorGeneric": {
"Generic": {
"error": "Oops! Something went wrong. Please try again later."
},
"errorIncomplete": {
"Incomplete": {
"error": "Your request is missing information."
},
"errorUnauthed": {
"Unauthenticated": {
"error": "You are unauthenticated, please log in and try again."
},
"errorForbidden": {
"Forbidden": {
"error": "You are not authorized to do that."
},
"errorNotFound": {
"NotFound": {
"error": "That resource was not found. Please try again."
},
"errorUserNotFound": {
"error": "A user with that email does not exist. Create an account to get started."
},
"errorDuplicateName": {
"DuplicateName": {
"error": "Something already exists with that name. Please try again with a different name."
}
}

View file

@ -1,31 +1,31 @@
const forge = require('node-forge');
const { User } = require('../db/models/index');
const config = require('../config/error.json');
const errors = require('../config/error.json');
async function basicAuth(req, res, next) {
const authHeader = req.get('Authorization');
const b64Encoded = authHeader?.split(' ')[1];
if (!b64Encoded) return res.status(400).send(config.errorIncomplete);
if (!b64Encoded) return res.status(400).send(errors.Incomplete);
// Isolate username and password
const [email, password] = Buffer.from(b64Encoded, 'base64').toString().split(':');
if (!email || !password) return res.status(400).send(config.errorIncomplete);
if (!email || !password) return res.status(400).send(errors.Incomplete);
// Make sure that a user exists with that email
const result = await User.findOne({
where: { email: email },
});
if (!result) {
return res.status(404).send(config.errorNotFound);
return res.status(404).send(errors.NotFound);
}
// Hash the password and verify that the user hash is identical
const hashedPassword = forge.md.sha512.create().update(password).digest().toHex();
if (hashedPassword != result.password) {
return res.status(403).send(config.errorForbidden);
return res.status(403).send(errors.Forbidden);
}
req.user = result;

View file

@ -1,6 +1,6 @@
const { Organization } = require('../db/models/index');
const config = require('../config/error.json');
const errors = require('../config/error.json');
async function checkKnownOrg(req, res, next) {
const user = req.user;
@ -24,12 +24,12 @@ async function checkKnownOrg(req, res, next) {
// Verify that there is an organization that the specified id.
if (!result) {
return res.status(404).send(config.errorNotFound);
return res.status(404).send(errors.NotFound);
}
// Verify that the user who submitted the request exists as an owner or member
if (!result.owner && result.member.length == 0) {
return res.status(403).send(config.errorForbidden);
return res.status(403).send(errors.Forbidden);
}
return next();

View file

@ -1,6 +1,6 @@
const { User } = require('../db/models/index');
const config = require('../config/error.json');
const errors = require('../config/error.json');
async function checkKnownUser(req, res, next) {
const user = req.user;
@ -41,7 +41,7 @@ async function checkKnownUser(req, res, next) {
// Confirm that a user with that ID exists within the database
if (!result) {
return res.status(404).send(config.errorNotFound);
return res.status(404).send(errors.NotFound);
}
// Filter for an organization where the user is a member or an owner
@ -49,7 +49,7 @@ async function checkKnownUser(req, res, next) {
// Error if there is not an organization that includes that user and they are not in an owned organization
if (filteredResult.length == 0 && result.ownedOrg.length == 0) {
return res.status(403).send(config.errorForbidden);
return res.status(403).send(errors.Forbidden);
}
return next();

View file

@ -1,5 +1,5 @@
const { Token } = require('../db/models/index');
const config = require('../config/error.json');
const errors = require('../config/error.json');
async function tokenAuth(req, res, next) {
const authHeader = req.get('Authorization');
@ -7,17 +7,17 @@ async function tokenAuth(req, res, next) {
const token = authHeader?.split(' ')[1];
// Verify token is included in request
if (!token) return res.status(400).send(config.errorIncomplete);
if (!token) return res.status(400).send(errors.Incomplete);
const result = await Token.findOne({ token });
// Verify token expiration
const date = new Date();
if (!result) {
return res.status(401).send(config.errorUnauthed);
return res.status(401).send(errors.Unauthenticated);
} else if (result.expires && date.setDate(date.getDate + 1) > result.createdAt) {
await Token.findOneAndDelete({ token });
return res.status(401).send(config.errorUnauthed);
return res.status(401).send(errors.Unauthenticated);
}
const user = await result.getUser();

View file

@ -1,14 +1,14 @@
const forge = require('node-forge');
const { User, Organization } = require('../../db/models/index');
const config = require('../../config/error.json');
const errors = require('../../config/error.json');
async function Register(req, res, next) {
const body = req.body;
// Verify that the object body contains all SQL required fields
if (!body.firstName || !body.lastName || !body.email || !body.password) {
return res.status(400).send(config.errorIncomplete);
return res.status(400).send(errors.Incomplete);
}
// Make sure that no existing user exists with that email
@ -19,7 +19,7 @@ async function Register(req, res, next) {
});
if (existingUsers > 0) {
return res.status(400).send(config.errorDuplicateName);
return res.status(409).send(errors.DuplicateName);
}
// Hash password for storage into database
@ -51,7 +51,7 @@ async function Register(req, res, next) {
} catch (e) {
console.log(e);
return res.status(500).send(config.errorGeneric);
return res.status(500).send(errors.Generic);
}
} else {
try {
@ -65,7 +65,7 @@ async function Register(req, res, next) {
} catch (e) {
console.log(e);
return res.status(500).send(config.errorGeneric);
return res.status(500).send(errors.Generic);
}
}
}

View file

@ -1,20 +1,20 @@
const { CourierClient } = require('@trycourier/courier');
const { User } = require('../../db/models/index');
const config = require('../../config/error.json');
const errors = require('../../config/error.json');
async function RequestReset(req, res, next) {
try {
// Make sure that the request contains an email
const email = req.body.email;
if (!email) {
return res.status(400).send(config.errorIncomplete);
return res.status(400).send(errors.Incomplete);
}
// Confirm that a user exists with that email
const result = await User.findOne({ where: { email: email } });
if (!result) {
return res.status(404).send(config.errorNotFound);
return res.status(404).send(errors.NotFound);
}
// Create resetRequest instance and send email containing reset information
@ -39,7 +39,7 @@ async function RequestReset(req, res, next) {
return res.sendStatus(200);
} catch (e) {
console.log(e);
return res.status(500).send(config.errorGeneric);
return res.status(500).send(errors.Generic);
}
}

View file

@ -1,7 +1,7 @@
const forge = require('node-forge');
const { ResetRequest } = require('../../db/models/index');
const config = require('../../config/error.json');
const errors = require('../../config/error.json');
async function ResetPassword(req, res, next) {
const reqID = req.params.id;
@ -9,13 +9,13 @@ async function ResetPassword(req, res, next) {
// Verify that the form contains a new password
if (!password) {
return res.status(400).send(config.errorIncomplete);
return res.status(400).send(errors.Incomplete);
}
// Confirm that there is a reset request for the user with that ID
const result = await ResetRequest.findByPk(reqID);
if (!result) {
return res.status(500).send(config.errorGeneric);
return res.status(500).send(errors.Generic);
}
// Hash the submitted password and update model

View file

@ -1,7 +1,7 @@
const { Op } = require('sequelize');
const { User } = require('../../db/models/index');
const config = require('../../config/error.json');
const errors = require('../../config/error.json');
async function UpdateUserDetails(req, res, next) {
const { token, ...body } = req.body;
@ -18,7 +18,7 @@ async function UpdateUserDetails(req, res, next) {
});
if (result) {
return res.status(409).send(config.errorDuplicateName);
return res.status(409).send(errors.DuplicateName);
}
}

View file

@ -1,6 +1,6 @@
const { Organization } = require('../../db/models/index');
const config = require('../../config/error.json');
const errors = require('../../config/error.json');
async function AddOrgMember(req, res, next) {
const user = req.user;
@ -9,7 +9,7 @@ async function AddOrgMember(req, res, next) {
// Verify that an organization exists with the ID provided
const result = await Organization.findByPk(orgID);
if (!result) {
return res.status(404).send(config.errorNotFound);
return res.status(404).send(errors.NotFound);
}
// Add the as a member to the found organization

View file

@ -1,4 +1,4 @@
const config = require('../../config/error.json');
const errors = require('../../config/error.json');
async function CreateOrg(req, res, next) {
const user = req.user;
@ -6,7 +6,7 @@ async function CreateOrg(req, res, next) {
// Error if the form does not contain an organization name
if (!orgName) {
return res.status(400).send(config.errorIncomplete);
return res.status(400).send(errors.Incomplete);
}
// Verify that no owned organizations have the same name
@ -14,7 +14,7 @@ async function CreateOrg(req, res, next) {
where: { name: orgName },
});
if (existing > 0) {
return res.status(500).send(config.errorGeneric);
return res.status(409).send(errors.DuplicateName);
}
await user.createOwnedOrg({

View file

@ -1,6 +1,6 @@
const { Organization } = require('../../db/models/index');
const config = require('../../config/error.json');
const errors = require('../../config/error.json');
async function DeleteOrg(req, res, next) {
const user = req.user;
@ -8,7 +8,7 @@ async function DeleteOrg(req, res, next) {
// Error if an organization id was not provided
if (!orgID) {
return res.status(400).send(config.errorIncomplete);
return res.status(400).send(errors.Incomplete);
}
// Destroy all organizations with that ID

View file

@ -1,6 +1,6 @@
const { Organization } = require('../../db/models/index');
const config = require('../../config/error.json');
const errors = require('../../config/error.json');
async function RemoveOrgMember(req, res, next) {
const user = req.user;
@ -13,7 +13,7 @@ async function RemoveOrgMember(req, res, next) {
});
if (!result) {
return res.status(404).send(config.errorNotFound);
return res.status(404).send(errors.NotFound);
}
// Remove self if doomedUserIDs does not exist, otherwise destroy all users in doomedUserIDs
@ -23,7 +23,7 @@ async function RemoveOrgMember(req, res, next) {
if (user.id == result.owner.id) {
await result.removeMember(doomedUserIDs);
} else {
return res.status(403).send(config.errorForbidden);
return res.status(403).send(errors.Forbidden);
}
}

View file

@ -1,24 +1,33 @@
const config = require('../../config/error.json');
const errors = require('../../config/error.json');
async function UpdateOrgDetails(req, res, next) {
const user = req.user;
const id = req.params.id;
const id = req.params.orgID;
const name = req.body.name;
// Verify that an name and id exist on the form
if (!name) {
return res.status(400).send(config.errorIncomplete);
return res.status(400).send(errors.Incomplete);
}
// Confirm that an organization exists with that ID
const result = await user.getOwnedOrg({ where: { id } });
if (result.length < 1) {
return res.status(404).send(config.errorNotFound);
return res.status(404).send(errors.NotFound);
}
// Verify that no owned organizations have the same name
const existing = await user.countOwnedOrg({
where: { name },
});
if (existing > 0) {
return res.status(409).send(errors.DuplicateName);
}
// Update the name of the organization
result[0].update({ name });
await result[0].update({ name });
return res.sendStatus(200);
}

View file

@ -50,7 +50,7 @@ describe('Get Member Orgs', function () {
.get('/api/auth/orgs/member')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[401] Token was not found', async () => {
@ -59,6 +59,6 @@ describe('Get Member Orgs', function () {
.set('Authorization', 'bearer randomString')
.send()
.expect('Content-Type', /json/)
.expect(401, errors.errorUnauthed);
.expect(401, errors.Unauthenticated);
});
});

View file

@ -46,7 +46,7 @@ describe('Get Owned Orgs', function () {
.get('/api/auth/orgs')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[401] Token was not found', async () => {
@ -55,6 +55,6 @@ describe('Get Owned Orgs', function () {
.set('Authorization', 'bearer randomString')
.send()
.expect('Content-Type', /json/)
.expect(401, errors.errorUnauthed);
.expect(401, errors.Unauthenticated);
});
});

View file

@ -52,7 +52,7 @@ describe('Get User Details', function () {
.set('Authorization', `bearer ${token.id}`)
.send()
.expect('Content-Type', /json/)
.expect(404, errors.errorNotFound);
.expect(404, errors.NotFound);
});
test('[403] No contact with that user', async () => {
@ -68,7 +68,7 @@ describe('Get User Details', function () {
.set('Authorization', `bearer ${token.id}`)
.send()
.expect('Content-Type', /json/)
.expect(403, errors.errorForbidden);
.expect(403, errors.Forbidden);
});
test('[400] Request does not include token', async () => {
@ -76,7 +76,7 @@ describe('Get User Details', function () {
.get(`/api/auth/randomString`)
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[401] Token was not found', async () => {
@ -85,6 +85,6 @@ describe('Get User Details', function () {
.set('Authorization', 'bearer randomString')
.send()
.expect('Content-Type', /json/)
.expect(401, errors.errorUnauthed);
.expect(401, errors.Unauthenticated);
});
});

View file

@ -40,7 +40,7 @@ describe('Login', function () {
.post('/api/auth/login')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[403] Invalid password', async () => {
@ -53,6 +53,6 @@ describe('Login', function () {
.set('Authorization', `basic ${encoded}`)
.send()
.expect('Content-Type', /json/)
.expect(403, errors.errorForbidden);
.expect(403, errors.Forbidden);
});
});

View file

@ -36,7 +36,7 @@ describe('Logout', function () {
.post('/api/auth/logout')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[401] Token was not found', async () => {
@ -45,6 +45,6 @@ describe('Logout', function () {
.set('Authorization', 'bearer randomString')
.send()
.expect('Content-Type', /json/)
.expect(401, errors.errorUnauthed);
.expect(401, errors.Unauthenticated);
});
});

View file

@ -31,7 +31,7 @@ describe('Request Reset', function () {
.post('/api/auth/reset')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[404] No user with email', async () => {
@ -41,6 +41,6 @@ describe('Request Reset', function () {
.post('/api/auth/reset')
.send({ email: 'randomString' })
.expect('Content-Type', /json/)
.expect(404, errors.errorNotFound);
.expect(404, errors.NotFound);
});
});

View file

@ -43,7 +43,7 @@ describe('Reset Password', function () {
.patch(`/api/auth/reset/${resetRequest.reqID}`)
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[500] Reset request does not exist', async () => {
@ -53,6 +53,6 @@ describe('Reset Password', function () {
password: 'newPassword',
})
.expect('Content-Type', /json/)
.expect(500, errors.errorGeneric);
.expect(500, errors.Generic);
});
});

View file

@ -83,7 +83,7 @@ describe('Register', function () {
.post('/api/auth/register')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[409] User already exists', async () => {
@ -100,6 +100,6 @@ describe('Register', function () {
.post('/api/auth/register')
.send(userInfo)
.expect('Content-Type', /json/)
.expect(409, errors.errorDuplicateName);
.expect(409, errors.DuplicateName);
});
});

View file

@ -20,7 +20,7 @@ describe('Set Audio', function () {
.post('/api/auth/audio')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[401] Token was not found', async () => {
@ -29,6 +29,6 @@ describe('Set Audio', function () {
.set('Authorization', 'bearer randomString')
.send()
.expect('Content-Type', /json/)
.expect(401, errors.errorUnauthed);
.expect(401, errors.Unauthenticated);
});
});

View file

@ -50,7 +50,7 @@ describe('Update User Details', function () {
email: 'new.user@test.com',
})
.expect('Content-Type', /json/)
.expect(409, errors.errorDuplicateName);
.expect(409, errors.DuplicateName);
});
test('[400] Request does not include token', async () => {
@ -58,7 +58,7 @@ describe('Update User Details', function () {
.patch('/api/auth/update')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[401] Token was not found', async () => {
@ -67,6 +67,6 @@ describe('Update User Details', function () {
.set('Authorization', 'bearer randomString')
.send()
.expect('Content-Type', /json/)
.expect(401, errors.errorUnauthed);
.expect(401, errors.Unauthenticated);
});
});

View file

@ -45,7 +45,7 @@ describe('Add Org Member', function () {
.set('Authorization', `bearer ${token.id}`)
.send()
.expect('Content-Type', /json/)
.expect(404, errors.errorNotFound);
.expect(404, errors.NotFound);
});
test('[400] Request does not include token', async () => {
@ -53,7 +53,7 @@ describe('Add Org Member', function () {
.post('/api/org/randomString/add')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[401] Token was not found', async () => {
@ -62,6 +62,6 @@ describe('Add Org Member', function () {
.set('Authorization', 'bearer randomString')
.send()
.expect('Content-Type', /json/)
.expect(401, errors.errorUnauthed);
.expect(401, errors.Unauthenticated);
});
});

View file

@ -37,7 +37,7 @@ describe('Create Org', function () {
.set('Authorization', `bearer ${token.id}`)
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[409] Pre-existing organization with that name', async () => {
@ -52,7 +52,7 @@ describe('Create Org', function () {
.set('Authorization', `bearer ${token.id}`)
.send({ orgName: 'Org' })
.expect('Content-Type', /json/)
.expect(409, errors.errorDuplicateName);
.expect(409, errors.DuplicateName);
});
test('[400] Request does not include token', async () => {
@ -60,7 +60,7 @@ describe('Create Org', function () {
.post('/api/org')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[401] Token was not found', async () => {
@ -69,6 +69,6 @@ describe('Create Org', function () {
.set('Authorization', 'bearer randomString')
.send()
.expect('Content-Type', /json/)
.expect(401, errors.errorUnauthed);
.expect(401, errors.Unauthenticated);
});
});

View file

@ -79,7 +79,7 @@ describe('Delete Org', function () {
.delete('/api/org/randomString')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[401] Token was not found', async () => {
@ -88,6 +88,6 @@ describe('Delete Org', function () {
.set('Authorization', 'bearer randomString')
.send()
.expect('Content-Type', /json/)
.expect(401, errors.errorUnauthed);
.expect(401, errors.Unauthenticated);
});
});

View file

@ -61,7 +61,7 @@ describe('Get Org', function () {
.set('Authorization', `bearer ${token.id}`)
.send()
.expect('Content-Type', /json/)
.expect(404, errors.errorNotFound);
.expect(404, errors.NotFound);
});
test('[403] Unknown organization queried', async () => {
@ -78,7 +78,7 @@ describe('Get Org', function () {
.set('Authorization', `bearer ${token.id}`)
.send()
.expect('Content-Type', /json/)
.expect(403, errors.errorForbidden);
.expect(403, errors.Forbidden);
});
test('[400] Request does not include token', async () => {
@ -86,7 +86,7 @@ describe('Get Org', function () {
.get('/api/org/randomString')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[401] Token was not found', async () => {
@ -95,6 +95,6 @@ describe('Get Org', function () {
.set('Authorization', 'bearer randomString')
.send()
.expect('Content-Type', /json/)
.expect(401, errors.errorUnauthed);
.expect(401, errors.Unauthenticated);
});
});

View file

@ -60,7 +60,7 @@ describe('Remove Org Member', function () {
doomedUsers: [newUser.id],
})
.expect('Content-Type', /json/)
.expect(404, errors.errorNotFound);
.expect(404, errors.NotFound);
});
test('[403] Insufficient permissions', async () => {
@ -81,7 +81,7 @@ describe('Remove Org Member', function () {
})
.set('Authorization', `bearer ${token.id}`)
.expect('Content-Type', /json/)
.expect(403, errors.errorForbidden);
.expect(403, errors.Forbidden);
});
test('[400] Request does not include token', async () => {
@ -89,7 +89,7 @@ describe('Remove Org Member', function () {
.post('/api/org/randomString/remove')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[401] Token was not found', async () => {
@ -98,6 +98,6 @@ describe('Remove Org Member', function () {
.set('Authorization', 'bearer randomString')
.send()
.expect('Content-Type', /json/)
.expect(401, errors.errorUnauthed);
.expect(401, errors.Unauthenticated);
});
});

View file

@ -41,7 +41,7 @@ describe('Update Org Details', function () {
.patch('/api/org/update')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[404] No organization exists with that id', async () => {
@ -55,7 +55,7 @@ describe('Update Org Details', function () {
name: 'New Name',
})
.expect('Content-Type', /json/)
.expect(404, errors.errorNotFound);
.expect(404, errors.NotFound);
});
test('[409] Pre-existing organization with that name', async () => {
@ -71,7 +71,7 @@ describe('Update Org Details', function () {
.set('Authorization', `bearer ${token.id}`)
.send({ name: 'Org' })
.expect('Content-Type', /json/)
.expect(409, errors.errorDuplicateName);
.expect(409, errors.DuplicateName);
});
test('[400] Request does not include token', async () => {
@ -79,7 +79,7 @@ describe('Update Org Details', function () {
.patch('/api/org/randomString')
.send()
.expect('Content-Type', /json/)
.expect(400, errors.errorIncomplete);
.expect(400, errors.Incomplete);
});
test('[401] Token was not found', async () => {
@ -88,6 +88,6 @@ describe('Update Org Details', function () {
.set('Authorization', 'bearer randomString')
.send()
.expect('Content-Type', /json/)
.expect(401, errors.errorUnauthed);
.expect(401, errors.Unauthenticated);
});
});