mirror of https://github.com/xfarrow/blink
ran 'npx standard --fix'
This commit is contained in:
parent
42104ac0f4
commit
0dc67edc9b
|
@ -13,54 +13,53 @@
|
||||||
|
|
||||||
// Importing modules
|
// Importing modules
|
||||||
// TODO: clean up
|
// TODO: clean up
|
||||||
require('dotenv').config();
|
require('dotenv').config()
|
||||||
const express = require('express');
|
const express = require('express')
|
||||||
const cors = require('cors');
|
const cors = require('cors')
|
||||||
const rateLimit = require('express-rate-limit');
|
const rateLimit = require('express-rate-limit')
|
||||||
const personRoutes = require('./routes/person_routes.js');
|
const personRoutes = require('./routes/person_routes.js')
|
||||||
const organizationRoutes = require('./routes/organization_routes.js');
|
const organizationRoutes = require('./routes/organization_routes.js')
|
||||||
const organizationAdminRoutes = require('./routes/organization_admin_routes.js');
|
const organizationAdminRoutes = require('./routes/organization_admin_routes.js')
|
||||||
const organizationPostRoutes = require('./routes/organization_post_routes.js')
|
const organizationPostRoutes = require('./routes/organization_post_routes.js')
|
||||||
const jwt_utils = require('./utils/jwt_utils.js');
|
const jwt_utils = require('./utils/jwt_utils.js')
|
||||||
|
|
||||||
|
|
||||||
// Application configuration
|
// Application configuration
|
||||||
const app = express();
|
const app = express()
|
||||||
app.use(express.json()); // Middleware which parses JSON for POST requests
|
app.use(express.json()) // Middleware which parses JSON for POST requests
|
||||||
app.use(cors()); // Enable CORS for all routes
|
app.use(cors()) // Enable CORS for all routes
|
||||||
app.use(rateLimit({
|
app.use(rateLimit({
|
||||||
windowMs: process.env.LIMITER_WINDOW,
|
windowMs: process.env.LIMITER_WINDOW,
|
||||||
max: process.env.LIMITER_MAXIMUM_PER_WINDOW,
|
max: process.env.LIMITER_MAXIMUM_PER_WINDOW,
|
||||||
message: {error : "Too many requests from this IP, please try again later"}
|
message: { error: 'Too many requests from this IP, please try again later' }
|
||||||
})); // Apply the rate limiter middleware to all routes
|
})) // Apply the rate limiter middleware to all routes
|
||||||
|
|
||||||
const publicRoutes = express.Router();
|
const publicRoutes = express.Router()
|
||||||
publicRoutes.post('/register', personRoutes.registerPerson);
|
publicRoutes.post('/register', personRoutes.registerPerson)
|
||||||
publicRoutes.post('/login', personRoutes.login);
|
publicRoutes.post('/login', personRoutes.login)
|
||||||
|
|
||||||
const protectedRoutes = express.Router();
|
const protectedRoutes = express.Router()
|
||||||
protectedRoutes.use(jwt_utils.verifyToken);
|
protectedRoutes.use(jwt_utils.verifyToken)
|
||||||
protectedRoutes.get('/person/myself', personRoutes.getMyself);
|
protectedRoutes.get('/person/myself', personRoutes.getMyself)
|
||||||
protectedRoutes.get('/person/:id', personRoutes.getPerson);
|
protectedRoutes.get('/person/:id', personRoutes.getPerson)
|
||||||
protectedRoutes.put('/person/:id', personRoutes.updatePerson);
|
protectedRoutes.put('/person/:id', personRoutes.updatePerson)
|
||||||
protectedRoutes.delete('/person/delete', personRoutes.deletePerson);
|
protectedRoutes.delete('/person/delete', personRoutes.deletePerson)
|
||||||
protectedRoutes.post('/organization/admin', organizationAdminRoutes.addOrganizationAdmin);
|
protectedRoutes.post('/organization/admin', organizationAdminRoutes.addOrganizationAdmin)
|
||||||
protectedRoutes.delete('/organization/removeadmin', organizationAdminRoutes.removeOrganizationAdmin);
|
protectedRoutes.delete('/organization/removeadmin', organizationAdminRoutes.removeOrganizationAdmin)
|
||||||
protectedRoutes.post('/organization', organizationRoutes.createOrganization);
|
protectedRoutes.post('/organization', organizationRoutes.createOrganization)
|
||||||
protectedRoutes.get('/organization/:id', organizationRoutes.getOrganization);
|
protectedRoutes.get('/organization/:id', organizationRoutes.getOrganization)
|
||||||
protectedRoutes.put('/organization/:id', organizationRoutes.updateOrganization);
|
protectedRoutes.put('/organization/:id', organizationRoutes.updateOrganization)
|
||||||
protectedRoutes.delete('/organization/:id', organizationRoutes.deleteOrganization);
|
protectedRoutes.delete('/organization/:id', organizationRoutes.deleteOrganization)
|
||||||
protectedRoutes.post('/organization/post', organizationPostRoutes.createOrganizationPost);
|
protectedRoutes.post('/organization/post', organizationPostRoutes.createOrganizationPost)
|
||||||
protectedRoutes.delete('/organization/post/:id', organizationPostRoutes.deleteOrganizationPost);
|
protectedRoutes.delete('/organization/post/:id', organizationPostRoutes.deleteOrganizationPost)
|
||||||
|
|
||||||
// Mounting routes
|
// Mounting routes
|
||||||
app.use('/api', publicRoutes); // Routes not requiring token
|
app.use('/api', publicRoutes) // Routes not requiring token
|
||||||
app.use('/api', protectedRoutes); // Routes requiring token
|
app.use('/api', protectedRoutes) // Routes requiring token
|
||||||
|
|
||||||
// Start the server. Default port is 3000
|
// Start the server. Default port is 3000
|
||||||
const port = process.env.API_SERVER_PORT || 3000;
|
const port = process.env.API_SERVER_PORT || 3000
|
||||||
app.listen(port, () => {
|
app.listen(port, () => {
|
||||||
console.log(`Blink API server is running on port ${port}`);
|
console.log(`Blink API server is running on port ${port}`)
|
||||||
});
|
})
|
||||||
|
|
||||||
module.exports = app;
|
module.exports = app
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
IN THE SOFTWARE.
|
IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const knex = require('../utils/knex_config');
|
const knex = require('../utils/knex_config')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create Organization object
|
* Create Organization object
|
||||||
|
@ -21,14 +21,14 @@ const knex = require('../utils/knex_config');
|
||||||
* @param {*} is_hiring
|
* @param {*} is_hiring
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function organization(name, location, description, is_hiring){
|
function organization (name, location, description, is_hiring) {
|
||||||
const organization = {
|
const organization = {
|
||||||
name: name,
|
name,
|
||||||
location: location,
|
location,
|
||||||
description: description,
|
description,
|
||||||
is_hiring: is_hiring
|
is_hiring
|
||||||
};
|
}
|
||||||
return organization;
|
return organization
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,32 +36,32 @@ function organization(name, location, description, is_hiring){
|
||||||
* @param {*} id
|
* @param {*} id
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async function getOrganizationById(id){
|
async function getOrganizationById (id) {
|
||||||
const organization = await knex('Organization')
|
const organization = await knex('Organization')
|
||||||
.where('id', id)
|
.where('id', id)
|
||||||
.select('*')
|
.select('*')
|
||||||
.first();
|
.first()
|
||||||
return organization;
|
return organization
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert an Organization and its relative Administrator
|
* Insert an Organization and its relative Administrator
|
||||||
* @param {*} organization
|
* @param {*} organization
|
||||||
*/
|
*/
|
||||||
async function insertOrganization(organization, organizationAdministratorId){
|
async function insertOrganization (organization, organizationAdministratorId) {
|
||||||
await knex.transaction(async (trx) => {
|
await knex.transaction(async (trx) => {
|
||||||
// We have to insert either both in Organization and in OrganizationAdministrator
|
// We have to insert either both in Organization and in OrganizationAdministrator
|
||||||
// or in neither
|
// or in neither
|
||||||
const organizationResult = await trx('Organization')
|
const organizationResult = await trx('Organization')
|
||||||
.insert(organization, '*');
|
.insert(organization, '*')
|
||||||
|
|
||||||
// Inserting in the "OrganizationAdministrator" table
|
// Inserting in the "OrganizationAdministrator" table
|
||||||
await trx('OrganizationAdministrator')
|
await trx('OrganizationAdministrator')
|
||||||
.insert({
|
.insert({
|
||||||
id_person: organizationAdministratorId,
|
id_person: organizationAdministratorId,
|
||||||
id_organization: organizationResult[0].id,
|
id_organization: organizationResult[0].id
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,46 +72,46 @@ async function insertOrganization(organization, organizationAdministratorId){
|
||||||
* @param {*} personId
|
* @param {*} personId
|
||||||
* @returns true if the row was updated, false otherwise
|
* @returns true if the row was updated, false otherwise
|
||||||
*/
|
*/
|
||||||
async function updateOrganizationIfAdministrator(organization, organizationId, personId){
|
async function updateOrganizationIfAdministrator (organization, organizationId, personId) {
|
||||||
// // const isOrganizationAdmin = await knex('OrganizationAdministrator')
|
// // const isOrganizationAdmin = await knex('OrganizationAdministrator')
|
||||||
// // .where('id_person', req.jwt.person_id)
|
// // .where('id_person', req.jwt.person_id)
|
||||||
// // .where('id_organization', req.params.id)
|
// // .where('id_organization', req.params.id)
|
||||||
// // .select('*')
|
// // .select('*')
|
||||||
// // .first();
|
// // .first();
|
||||||
|
|
||||||
// // // This introduces a Time of check Time of use weakeness
|
// // // This introduces a Time of check Time of use weakeness
|
||||||
// // // which could'have been fixed by either
|
// // // which could'have been fixed by either
|
||||||
// // // 1) Using "whereExists", thanks to the "it's easier to ask for
|
// // // 1) Using "whereExists", thanks to the "it's easier to ask for
|
||||||
// // // forgiveness than for permission" padarigm. Or,
|
// // // forgiveness than for permission" padarigm. Or,
|
||||||
// // // 2) Using a serializable transaction.
|
// // // 2) Using a serializable transaction.
|
||||||
// // //
|
// // //
|
||||||
// // // The undersigned chose not to follow these approaches because
|
// // // The undersigned chose not to follow these approaches because
|
||||||
// // // this does not introduces any serious vulnerability. In this
|
// // // this does not introduces any serious vulnerability. In this
|
||||||
// // // way it seems more readable.
|
// // // way it seems more readable.
|
||||||
|
|
||||||
// // if(!isOrganizationAdmin){
|
// // if(!isOrganizationAdmin){
|
||||||
// // return res.status(403).json({error : "Forbidden"});
|
// // return res.status(403).json({error : "Forbidden"});
|
||||||
// // }
|
// // }
|
||||||
|
|
||||||
// // await knex('Organization')
|
// // await knex('Organization')
|
||||||
// // .where('id', req.params.id)
|
// // .where('id', req.params.id)
|
||||||
// // .update({
|
// // .update({
|
||||||
// // name: req.body.name,
|
// // name: req.body.name,
|
||||||
// // location: req.body.location,
|
// // location: req.body.location,
|
||||||
// // description: req.body.description,
|
// // description: req.body.description,
|
||||||
// // is_hiring: req.body.is_hiring
|
// // is_hiring: req.body.is_hiring
|
||||||
// // });
|
// // });
|
||||||
|
|
||||||
const numberOfUpdatedRows = await knex('Organization')
|
const numberOfUpdatedRows = await knex('Organization')
|
||||||
.where('id', organizationId)
|
.where('id', organizationId)
|
||||||
.whereExists(function(){
|
.whereExists(function () {
|
||||||
this.select('*')
|
this.select('*')
|
||||||
.from('OrganizationAdministrator')
|
.from('OrganizationAdministrator')
|
||||||
.where('id_person', personId)
|
.where('id_person', personId)
|
||||||
.where('id_organization', organizationId)
|
.where('id_organization', organizationId)
|
||||||
})
|
})
|
||||||
.update(organization);
|
.update(organization)
|
||||||
return numberOfUpdatedRows == 1;
|
return numberOfUpdatedRows == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,17 +121,17 @@ async function updateOrganizationIfAdministrator(organization, organizationId, p
|
||||||
* @param {*} personId PersonId of the supposedly administrator
|
* @param {*} personId PersonId of the supposedly administrator
|
||||||
* @returns true if the Organization was successfully deleted, false otherwise
|
* @returns true if the Organization was successfully deleted, false otherwise
|
||||||
*/
|
*/
|
||||||
async function deleteOrganizationIfAdmin(organizationId, personId){
|
async function deleteOrganizationIfAdmin (organizationId, personId) {
|
||||||
const numberOfDeletedRows = await knex('Organization')
|
const numberOfDeletedRows = await knex('Organization')
|
||||||
.where({ id: organizationId })
|
.where({ id: organizationId })
|
||||||
.whereExists(function(){
|
.whereExists(function () {
|
||||||
this.select('*')
|
this.select('*')
|
||||||
.from('OrganizationAdministrator')
|
.from('OrganizationAdministrator')
|
||||||
.where('id_person', personId)
|
.where('id_person', personId)
|
||||||
.where('id_organization', organizationId)
|
.where('id_organization', organizationId)
|
||||||
})
|
})
|
||||||
.del();
|
.del()
|
||||||
return numberOfDeletedRows == 1;
|
return numberOfDeletedRows == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exporting a function
|
// Exporting a function
|
||||||
|
@ -144,4 +144,4 @@ module.exports = {
|
||||||
updateOrganizationIfAdministrator,
|
updateOrganizationIfAdministrator,
|
||||||
updateOrganizationIfAdministrator,
|
updateOrganizationIfAdministrator,
|
||||||
deleteOrganizationIfAdmin
|
deleteOrganizationIfAdmin
|
||||||
};
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
IN THE SOFTWARE.
|
IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const knex = require('../utils/knex_config');
|
const knex = require('../utils/knex_config')
|
||||||
const bcrypt = require('bcrypt');
|
const bcrypt = require('bcrypt')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates Person object by the specified fields
|
* Creates Person object by the specified fields
|
||||||
|
@ -25,17 +25,17 @@ const bcrypt = require('bcrypt');
|
||||||
* @param {*} place_of_living
|
* @param {*} place_of_living
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function person(email, password, display_name, date_of_birth, available, enabled, place_of_living) {
|
function person (email, password, display_name, date_of_birth, available, enabled, place_of_living) {
|
||||||
const person = {
|
const person = {
|
||||||
email: email.toLowerCase(),
|
email: email.toLowerCase(),
|
||||||
password: password,
|
password,
|
||||||
display_name: display_name,
|
display_name,
|
||||||
date_of_birth: date_of_birth,
|
date_of_birth,
|
||||||
available: available,
|
available,
|
||||||
enabled: enabled,
|
enabled,
|
||||||
place_of_living: place_of_living
|
place_of_living
|
||||||
};
|
}
|
||||||
return person;
|
return person
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,10 +43,10 @@ function person(email, password, display_name, date_of_birth, available, enabled
|
||||||
* @param {*} email email to look the Person for
|
* @param {*} email email to look the Person for
|
||||||
* @returns the Person object
|
* @returns the Person object
|
||||||
*/
|
*/
|
||||||
async function getPersonByEmail(email){
|
async function getPersonByEmail (email) {
|
||||||
return await knex('Person')
|
return await knex('Person')
|
||||||
.where('email', email.toLowerCase())
|
.where('email', email.toLowerCase())
|
||||||
.first();
|
.first()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,11 +54,11 @@ async function getPersonByEmail(email){
|
||||||
* @param {*} id - The id to look the person for
|
* @param {*} id - The id to look the person for
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async function getPersonById(id){
|
async function getPersonById (id) {
|
||||||
return await knex('Person')
|
return await knex('Person')
|
||||||
.select('*')
|
.select('*')
|
||||||
.where({ id: id })
|
.where({ id })
|
||||||
.first();
|
.first()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,27 +67,27 @@ async function getPersonById(id){
|
||||||
* @param {*} person A Person object
|
* @param {*} person A Person object
|
||||||
* @param {*} activationLink the activationLink identifier
|
* @param {*} activationLink the activationLink identifier
|
||||||
*/
|
*/
|
||||||
async function registerPerson(person, activationLink){
|
async function registerPerson (person, activationLink) {
|
||||||
// We need to insert either both in the "Person" table
|
// We need to insert either both in the "Person" table
|
||||||
// and in the "ActivationLink" one, or in neither
|
// and in the "ActivationLink" one, or in neither
|
||||||
await knex.transaction(async (tr) => {
|
await knex.transaction(async (tr) => {
|
||||||
const personIdResult = await tr('Person')
|
const personIdResult = await tr('Person')
|
||||||
.insert({
|
.insert({
|
||||||
email: person.email.toLowerCase(),
|
email: person.email.toLowerCase(),
|
||||||
password: person.password,
|
password: person.password,
|
||||||
display_name: person.display_name,
|
display_name: person.display_name,
|
||||||
date_of_birth: person.date_of_birth,
|
date_of_birth: person.date_of_birth,
|
||||||
available: person.available,
|
available: person.available,
|
||||||
enabled: person.enabled,
|
enabled: person.enabled,
|
||||||
place_of_living: person.place_of_living
|
place_of_living: person.place_of_living
|
||||||
})
|
})
|
||||||
.returning("id");
|
.returning('id')
|
||||||
await tr('ActivationLink')
|
await tr('ActivationLink')
|
||||||
.insert({
|
.insert({
|
||||||
person_id: personIdResult[0].id,
|
person_id: personIdResult[0].id,
|
||||||
identifier: activationLink
|
identifier: activationLink
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,20 +97,20 @@ async function registerPerson(person, activationLink){
|
||||||
* @param {*} password
|
* @param {*} password
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async function getPersonByEmailAndPassword(email, password){
|
async function getPersonByEmailAndPassword (email, password) {
|
||||||
const person = await knex('Person')
|
const person = await knex('Person')
|
||||||
.where('email', email.toLowerCase())
|
.where('email', email.toLowerCase())
|
||||||
.where('enabled', true)
|
.where('enabled', true)
|
||||||
.select('*')
|
.select('*')
|
||||||
.first();
|
.first()
|
||||||
|
|
||||||
if(person){
|
if (person) {
|
||||||
const passwordMatches = await bcrypt.compare(password, person.password);
|
const passwordMatches = await bcrypt.compare(password, person.password)
|
||||||
if (passwordMatches) {
|
if (passwordMatches) {
|
||||||
return person;
|
return person
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -118,32 +118,31 @@ async function getPersonByEmailAndPassword(email, password){
|
||||||
* @param {*} person The Person to update
|
* @param {*} person The Person to update
|
||||||
* @param {*} person_id The database id of the Person to update
|
* @param {*} person_id The database id of the Person to update
|
||||||
*/
|
*/
|
||||||
async function updatePerson(person, person_id){
|
async function updatePerson (person, person_id) {
|
||||||
await knex('Person')
|
await knex('Person')
|
||||||
.where('id', person_id)
|
.where('id', person_id)
|
||||||
.update(person);
|
.update(person)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a Person specified by its database id.
|
* Deletes a Person specified by its database id.
|
||||||
* @param {*} person_id
|
* @param {*} person_id
|
||||||
*/
|
*/
|
||||||
async function deletePerson(person_id){
|
async function deletePerson (person_id) {
|
||||||
await knex('Person')
|
await knex('Person')
|
||||||
.where({id : person_id})
|
.where({ id: person_id })
|
||||||
.del();
|
.del()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Exporting a function
|
// Exporting a function
|
||||||
// means making a JavaScript function defined in one
|
// means making a JavaScript function defined in one
|
||||||
// module available for use in another module.
|
// module available for use in another module.
|
||||||
module.exports = {
|
module.exports = {
|
||||||
person,
|
person,
|
||||||
getPersonByEmail,
|
getPersonByEmail,
|
||||||
getPersonById,
|
getPersonById,
|
||||||
getPersonByEmailAndPassword,
|
getPersonByEmailAndPassword,
|
||||||
registerPerson,
|
registerPerson,
|
||||||
updatePerson,
|
updatePerson,
|
||||||
deletePerson
|
deletePerson
|
||||||
};
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
IN THE SOFTWARE.
|
IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const knex = require('../utils/knex_config');
|
const knex = require('../utils/knex_config')
|
||||||
const organization_admin_model = require('../models/organization_admin_model');
|
const organization_admin_model = require('../models/organization_admin_model')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST Method
|
* POST Method
|
||||||
|
@ -22,29 +22,27 @@ const organization_admin_model = require('../models/organization_admin_model');
|
||||||
*
|
*
|
||||||
* Required field(s): organization_id, person_id
|
* Required field(s): organization_id, person_id
|
||||||
*/
|
*/
|
||||||
async function addOrganizationAdmin(req, res){
|
async function addOrganizationAdmin (req, res) {
|
||||||
|
// Ensure that the required fields are present before proceeding
|
||||||
|
if (!req.body.organization_id || !req.body.person_id) {
|
||||||
|
return res.status(400).json({ error: 'Invalid request' })
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that the required fields are present before proceeding
|
try {
|
||||||
if (!req.body.organization_id || !req.body.person_id) {
|
const isPersonAdmin = await organization_admin_model.isPersonAdmin(req.jwt.person_id, req.body.organization_id)
|
||||||
return res.status(400).json({ error : "Invalid request"});
|
// TOC/TOU
|
||||||
}
|
if (!isPersonAdmin) {
|
||||||
|
return res.status(401).json({ error: 'Forbidden' })
|
||||||
try {
|
|
||||||
const isPersonAdmin = await organization_admin_model.isPersonAdmin(req.jwt.person_id, req.body.organization_id);
|
|
||||||
// TOC/TOU
|
|
||||||
if(!isPersonAdmin){
|
|
||||||
return res.status(401).json({error : "Forbidden"});
|
|
||||||
}
|
|
||||||
await organization_admin_model.addOrganizationAdministrator(req.body.person_id, req.body.organization_id);
|
|
||||||
return res.status(200).json({success : true});
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error('Error while adding organization admin: ' + error);
|
|
||||||
res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
}
|
||||||
|
await organization_admin_model.addOrganizationAdministrator(req.body.person_id, req.body.organization_id)
|
||||||
|
return res.status(200).json({ success: true })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error while adding organization admin: ' + error)
|
||||||
|
res.status(500).json({ error: 'Internal server error' })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DELETE Request
|
* DELETE Request
|
||||||
*
|
*
|
||||||
* Deletes a Person from the list of Administrators of an Organization.
|
* Deletes a Person from the list of Administrators of an Organization.
|
||||||
|
@ -53,24 +51,22 @@ async function addOrganizationAdmin(req, res){
|
||||||
*
|
*
|
||||||
* Required field(s): organization_id
|
* Required field(s): organization_id
|
||||||
*/
|
*/
|
||||||
async function removeOrganizationAdmin(req, res){
|
async function removeOrganizationAdmin (req, res) {
|
||||||
|
// Ensure that the required fields are present before proceeding
|
||||||
|
if (!req.body.organization_id) {
|
||||||
|
return res.status(400).json({ error: 'Invalid request' })
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that the required fields are present before proceeding
|
try {
|
||||||
if (!req.body.organization_id) {
|
await organization_admin_model.removeOrganizationAdmin(req.jwt.person_id, req.body.organization_id)
|
||||||
return res.status(400).json({ error : "Invalid request"});
|
return res.status(200).json({ success: true })
|
||||||
}
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
try{
|
return res.status(500).json({ error: 'Internal server error' })
|
||||||
await organization_admin_model.removeOrganizationAdmin(req.jwt.person_id, req.body.organization_id);
|
}
|
||||||
return res.status(200).json({success : true});
|
|
||||||
}
|
|
||||||
catch (error){
|
|
||||||
console.error(error);
|
|
||||||
return res.status(500).json({ error: "Internal server error"});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
addOrganizationAdmin,
|
addOrganizationAdmin,
|
||||||
removeOrganizationAdmin
|
removeOrganizationAdmin
|
||||||
};
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
IN THE SOFTWARE.
|
IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const knex = require('../utils/knex_config');
|
const knex = require('../utils/knex_config')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST Request
|
* POST Request
|
||||||
|
@ -21,41 +21,39 @@ const knex = require('../utils/knex_config');
|
||||||
* Required field(s): organization_id, content
|
* Required field(s): organization_id, content
|
||||||
* @returns the inserted Post
|
* @returns the inserted Post
|
||||||
*/
|
*/
|
||||||
async function createOrganizationPost(req, res){
|
async function createOrganizationPost (req, res) {
|
||||||
|
// Ensure that the required fields are present before proceeding
|
||||||
|
if (!req.body.organization_id || !req.body.content) {
|
||||||
|
return res.status(400).json({ error: 'Invalid request' })
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that the required fields are present before proceeding
|
try {
|
||||||
if (!req.body.organization_id || !req.body.content) {
|
// Check if the current user is a organization's administrator
|
||||||
return res.status(400).json({ error : "Invalid request"});
|
const isOrganizationAdmin = await knex('OrganizationAdministrator')
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Check if the current user is a organization's administrator
|
|
||||||
const isOrganizationAdmin = await knex('OrganizationAdministrator')
|
|
||||||
.where('id_person', req.jwt.person_id)
|
.where('id_person', req.jwt.person_id)
|
||||||
.where('id_organization', req.body.organization_id)
|
.where('id_organization', req.body.organization_id)
|
||||||
.select('*')
|
.select('*')
|
||||||
.first();
|
.first()
|
||||||
|
|
||||||
// Non-exploitable TOC/TOU weakness
|
// Non-exploitable TOC/TOU weakness
|
||||||
// For more information https://softwareengineering.stackexchange.com/questions/451038/when-should-i-be-worried-of-time-of-check-time-of-use-vulnerabilities-during-dat
|
// For more information https://softwareengineering.stackexchange.com/questions/451038/when-should-i-be-worried-of-time-of-check-time-of-use-vulnerabilities-during-dat
|
||||||
if(!isOrganizationAdmin){
|
if (!isOrganizationAdmin) {
|
||||||
return res.status(403).json({error : "Forbidden"});
|
return res.status(403).json({ error: 'Forbidden' })
|
||||||
}
|
}
|
||||||
|
|
||||||
const organizationPost = await knex('OrganizationPost')
|
const organizationPost = await knex('OrganizationPost')
|
||||||
.insert({
|
.insert({
|
||||||
organization_id: req.body.organization_id,
|
organization_id: req.body.organization_id,
|
||||||
content: req.body.content,
|
content: req.body.content,
|
||||||
original_author: req.jwt.person_id
|
original_author: req.jwt.person_id
|
||||||
})
|
})
|
||||||
.returning('*');
|
.returning('*')
|
||||||
return res.status(200).json(organizationPost[0]);
|
return res.status(200).json(organizationPost[0])
|
||||||
}
|
} catch (error) {
|
||||||
catch (error) {
|
console.log('Error while creating Organization Post: ' + error)
|
||||||
console.log("Error while creating Organization Post: " + error);
|
return res.status(500).json({ error: 'Internal server error' })
|
||||||
return res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DELETE Request
|
* DELETE Request
|
||||||
|
@ -65,32 +63,29 @@ async function createOrganizationPost(req, res){
|
||||||
*
|
*
|
||||||
* Required field(s): none.
|
* Required field(s): none.
|
||||||
*/
|
*/
|
||||||
async function deleteOrganizationPost(req, res){
|
async function deleteOrganizationPost (req, res) {
|
||||||
|
const organizationPostIdToDelete = req.params.id
|
||||||
|
|
||||||
const organizationPostIdToDelete = req.params.id;
|
try {
|
||||||
|
|
||||||
try{
|
|
||||||
const isOrganizationAdmin = await knex('OrganizationPost')
|
const isOrganizationAdmin = await knex('OrganizationPost')
|
||||||
.join('OrganizationAdministrator', 'OrganizationPost.organization_id', 'OrganizationAdministrator.id_organization')
|
.join('OrganizationAdministrator', 'OrganizationPost.organization_id', 'OrganizationAdministrator.id_organization')
|
||||||
.where('OrganizationPost.id', organizationPostIdToDelete)
|
.where('OrganizationPost.id', organizationPostIdToDelete)
|
||||||
.where('OrganizationAdministrator.id_person', req.jwt.person_id)
|
.where('OrganizationAdministrator.id_person', req.jwt.person_id)
|
||||||
.select('*')
|
.select('*')
|
||||||
.first();
|
.first()
|
||||||
|
|
||||||
// Unexploitable TOC/TOU
|
// Unexploitable TOC/TOU
|
||||||
if(isOrganizationAdmin){
|
if (isOrganizationAdmin) {
|
||||||
await knex('OrganizationPost')
|
await knex('OrganizationPost')
|
||||||
.where('id', organizationPostIdToDelete)
|
.where('id', organizationPostIdToDelete)
|
||||||
.del();
|
.del()
|
||||||
return res.status(200).json({success : true});
|
return res.status(200).json({ success: true })
|
||||||
}
|
} else {
|
||||||
else{
|
return res.status(401).json({ error: 'Forbidden' })
|
||||||
return res.status(401).json({error : "Forbidden"});
|
}
|
||||||
}
|
} catch (error) {
|
||||||
}
|
console.log(error)
|
||||||
catch (error) {
|
res.status(500).json({ error: 'Internal server error' })
|
||||||
console.log(error);
|
|
||||||
res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +93,6 @@ async function deleteOrganizationPost(req, res){
|
||||||
// means making a JavaScript function defined in one
|
// means making a JavaScript function defined in one
|
||||||
// module available for use in another module.
|
// module available for use in another module.
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createOrganizationPost,
|
createOrganizationPost,
|
||||||
deleteOrganizationPost
|
deleteOrganizationPost
|
||||||
};
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
IN THE SOFTWARE.
|
IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const organization_model = require('../models/organization_model');
|
const organization_model = require('../models/organization_model')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST Request
|
* POST Request
|
||||||
|
@ -22,21 +22,19 @@ const organization_model = require('../models/organization_model');
|
||||||
*
|
*
|
||||||
* @returns the inserted organization
|
* @returns the inserted organization
|
||||||
*/
|
*/
|
||||||
async function createOrganization(req, res){
|
async function createOrganization (req, res) {
|
||||||
|
|
||||||
// Ensure that the required fields are present before proceeding
|
// Ensure that the required fields are present before proceeding
|
||||||
if (!req.body.name) {
|
if (!req.body.name) {
|
||||||
return res.status(400).json({ error : "Invalid request"});
|
return res.status(400).json({ error: 'Invalid request' })
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try {
|
||||||
const organization = organization_model.organization(req.body.name, req.body.location, req.body.description, req.body.is_hiring);
|
const organization = organization_model.organization(req.body.name, req.body.location, req.body.description, req.body.is_hiring)
|
||||||
await organization_model.insertOrganization(organization, req.jwt.person_id);
|
await organization_model.insertOrganization(organization, req.jwt.person_id)
|
||||||
return res.status(200).json({ Organization: organization });
|
return res.status(200).json({ Organization: organization })
|
||||||
}
|
} catch (error) {
|
||||||
catch (error){
|
console.error('Error creating Organization:', error)
|
||||||
console.error('Error creating Organization:', error);
|
res.status(500).json({ error: 'Internal server error' })
|
||||||
res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,42 +44,39 @@ async function createOrganization(req, res){
|
||||||
*
|
*
|
||||||
* Required field(s): none.
|
* Required field(s): none.
|
||||||
*/
|
*/
|
||||||
async function updateOrganization(req, res){
|
async function updateOrganization (req, res) {
|
||||||
|
const updateOrganization = {}
|
||||||
|
|
||||||
const updateOrganization = {};
|
if (req.body.name) {
|
||||||
|
updateOrganization.name = req.body.name
|
||||||
if(req.body.name){
|
|
||||||
updateOrganization.name = req.body.name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(req.body.location){
|
if (req.body.location) {
|
||||||
updateOrganization.location = req.body.location;
|
updateOrganization.location = req.body.location
|
||||||
}
|
}
|
||||||
|
|
||||||
if(req.body.description){
|
if (req.body.description) {
|
||||||
updateOrganization.description = req.body.description;
|
updateOrganization.description = req.body.description
|
||||||
}
|
}
|
||||||
|
|
||||||
if(req.body.is_hiring){
|
if (req.body.is_hiring) {
|
||||||
updateOrganization.is_hiring = req.body.is_hiring;
|
updateOrganization.is_hiring = req.body.is_hiring
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Object.keys(updateOrganization).length === 0) {
|
if (Object.keys(updateOrganization).length === 0) {
|
||||||
return res.status(400).json({ error : "Bad request. No data to update"});
|
return res.status(400).json({ error: 'Bad request. No data to update' })
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const isUpdateSuccessful = organization_model.updateOrganizationIfAdministrator(updateOrganization, req.params.id, req.jwt.person_id);
|
const isUpdateSuccessful = organization_model.updateOrganizationIfAdministrator(updateOrganization, req.params.id, req.jwt.person_id)
|
||||||
if(isUpdateSuccessful){
|
if (isUpdateSuccessful) {
|
||||||
return res.status(200).json({ success : "true"});
|
return res.status(200).json({ success: 'true' })
|
||||||
|
} else {
|
||||||
|
return res.status(404).json({ error: 'Organization either not found or insufficient permissions' })
|
||||||
}
|
}
|
||||||
else{
|
} catch (error) {
|
||||||
return res.status(404).json({error : "Organization either not found or insufficient permissions"});
|
console.log(error)
|
||||||
}
|
return res.status(500).json({ error: 'Internal server error' })
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
return res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,19 +86,17 @@ async function updateOrganization(req, res){
|
||||||
* Deletes the specified organization if the logged user is
|
* Deletes the specified organization if the logged user is
|
||||||
* one of its administrator
|
* one of its administrator
|
||||||
*/
|
*/
|
||||||
async function deleteOrganization(req, res){
|
async function deleteOrganization (req, res) {
|
||||||
try {
|
try {
|
||||||
const isDeleteSuccessful = organization_model.deleteOrganizationIfAdmin(req.params.id, req.jwt.person_id);
|
const isDeleteSuccessful = organization_model.deleteOrganizationIfAdmin(req.params.id, req.jwt.person_id)
|
||||||
if(isDeleteSuccessful){
|
if (isDeleteSuccessful) {
|
||||||
return res.status(403).json({error: "Forbidden"});
|
return res.status(403).json({ error: 'Forbidden' })
|
||||||
|
} else {
|
||||||
|
return res.status(200).json({ success: true })
|
||||||
}
|
}
|
||||||
else{
|
} catch (error) {
|
||||||
return res.status(200).json({success: true});
|
console.error(error)
|
||||||
}
|
return res.status(500).json({ error: 'Internal server error' })
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,19 +109,17 @@ async function deleteOrganization(req, res){
|
||||||
*
|
*
|
||||||
* @returns the organization.
|
* @returns the organization.
|
||||||
*/
|
*/
|
||||||
async function getOrganization(req, res){
|
async function getOrganization (req, res) {
|
||||||
try {
|
try {
|
||||||
const organization = await organization_model.getOrganizationById(req.params.id);
|
const organization = await organization_model.getOrganizationById(req.params.id)
|
||||||
if(organization) {
|
if (organization) {
|
||||||
return res.status(200).json(organization);
|
return res.status(200).json(organization)
|
||||||
|
} else {
|
||||||
|
return res.status(404).json({ error: 'Not found' })
|
||||||
}
|
}
|
||||||
else{
|
} catch (error) {
|
||||||
return res.status(404).json({error : "Not found"});
|
console.error('Error retrieving an organization: ' + error)
|
||||||
}
|
return res.status(500).json({ error: 'Internal server error' })
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error("Error retrieving an organization: " + error);
|
|
||||||
return res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,5 +128,4 @@ module.exports = {
|
||||||
getOrganization,
|
getOrganization,
|
||||||
updateOrganization,
|
updateOrganization,
|
||||||
deleteOrganization
|
deleteOrganization
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,12 @@
|
||||||
IN THE SOFTWARE.
|
IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const validator = require('../utils/validation');
|
const validator = require('../utils/validation')
|
||||||
const knex = require('../utils/knex_config');
|
const knex = require('../utils/knex_config')
|
||||||
const jwt_utils = require('../utils/jwt_utils');
|
const jwt_utils = require('../utils/jwt_utils')
|
||||||
const bcrypt = require('bcrypt');
|
const bcrypt = require('bcrypt')
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto')
|
||||||
const person_model = require('../models/person_model');
|
const person_model = require('../models/person_model')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST Request
|
* POST Request
|
||||||
|
@ -27,30 +27,29 @@ const person_model = require('../models/person_model');
|
||||||
*
|
*
|
||||||
* @returns The activationlink identifier
|
* @returns The activationlink identifier
|
||||||
*/
|
*/
|
||||||
async function registerPerson(req, res){
|
async function registerPerson (req, res) {
|
||||||
|
|
||||||
// Does this server allow users to register?
|
// Does this server allow users to register?
|
||||||
if (process.env.ALLOW_USER_REGISTRATION === 'false'){
|
if (process.env.ALLOW_USER_REGISTRATION === 'false') {
|
||||||
return res.status(403).json({error : "Users cannot register on this server"});
|
return res.status(403).json({ error: 'Users cannot register on this server' })
|
||||||
}
|
}
|
||||||
// Ensure that the required fields are present before proceeding
|
// Ensure that the required fields are present before proceeding
|
||||||
if (!req.body.display_name || !req.body.email || !req.body.password) {
|
if (!req.body.display_name || !req.body.email || !req.body.password) {
|
||||||
return res.status(400).json({ error : "Some or all required fields are missing"});
|
return res.status(400).json({ error: 'Some or all required fields are missing' })
|
||||||
}
|
}
|
||||||
if(!validator.validateEmail(req.body.email)){
|
if (!validator.validateEmail(req.body.email)) {
|
||||||
return res.status(400).json({ error : "The email is not in a valid format"});
|
return res.status(400).json({ error: 'The email is not in a valid format' })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate activation link token
|
// Generate activation link token
|
||||||
const activationLink = crypto.randomBytes(16).toString('hex');
|
const activationLink = crypto.randomBytes(16).toString('hex')
|
||||||
// Hash provided password
|
// Hash provided password
|
||||||
const hashPasswordPromise = bcrypt.hash(req.body.password, 10);
|
const hashPasswordPromise = bcrypt.hash(req.body.password, 10)
|
||||||
|
|
||||||
try{
|
try {
|
||||||
// Check whether e-mail exists already (enforced by database constraints)
|
// Check whether e-mail exists already (enforced by database constraints)
|
||||||
const existingUser = await person_model.getPersonByEmail(req.body.email);
|
const existingUser = await person_model.getPersonByEmail(req.body.email)
|
||||||
if(existingUser){
|
if (existingUser) {
|
||||||
return res.status(409).json({ error: "E-mail already in use" });
|
return res.status(409).json({ error: 'E-mail already in use' })
|
||||||
}
|
}
|
||||||
const personToInsert = person_model.person(
|
const personToInsert = person_model.person(
|
||||||
req.body.email,
|
req.body.email,
|
||||||
|
@ -59,13 +58,12 @@ async function registerPerson(req, res){
|
||||||
req.body.date_of_birth,
|
req.body.date_of_birth,
|
||||||
req.body.available,
|
req.body.available,
|
||||||
true,
|
true,
|
||||||
req.body.place_of_living);
|
req.body.place_of_living)
|
||||||
await person_model.registerPerson(personToInsert, activationLink);
|
await person_model.registerPerson(personToInsert, activationLink)
|
||||||
return res.status(200).json({ activationLink: activationLink });
|
return res.status(200).json({ activationLink })
|
||||||
}
|
} catch (error) {
|
||||||
catch (error){
|
console.error('Error registering person:', error)
|
||||||
console.error('Error registering person:', error);
|
res.status(500).json({ error: 'Internal server error' })
|
||||||
res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,25 +77,23 @@ async function registerPerson(req, res){
|
||||||
*
|
*
|
||||||
* @returns The token
|
* @returns The token
|
||||||
*/
|
*/
|
||||||
async function login(req, res){
|
async function login (req, res) {
|
||||||
|
|
||||||
// Ensure that the required fields are present before proceeding
|
// Ensure that the required fields are present before proceeding
|
||||||
if (!req.body.email || !req.body.password) {
|
if (!req.body.email || !req.body.password) {
|
||||||
return res.status(400).json({error : "Invalid request"});
|
return res.status(400).json({ error: 'Invalid request' })
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try {
|
||||||
const person = await person_model.getPersonByEmailAndPassword(req.body.email, req.body.password);
|
const person = await person_model.getPersonByEmailAndPassword(req.body.email, req.body.password)
|
||||||
if (person){
|
if (person) {
|
||||||
const token = jwt_utils.generateToken(person.id);
|
const token = jwt_utils.generateToken(person.id)
|
||||||
res.status(200).json({token: token });
|
res.status(200).json({ token })
|
||||||
|
} else {
|
||||||
|
res.status(401).json({ error: 'Unauthorized' })
|
||||||
}
|
}
|
||||||
else{
|
} catch (error) {
|
||||||
res.status(401).json({error : "Unauthorized"});
|
console.error('Error logging in: ', error)
|
||||||
}
|
res.status(500).json({ error: 'Internal server error' })
|
||||||
} catch(error){
|
|
||||||
console.error('Error logging in: ', error);
|
|
||||||
res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,21 +106,20 @@ async function login(req, res){
|
||||||
*
|
*
|
||||||
* @returns The Person
|
* @returns The Person
|
||||||
*/
|
*/
|
||||||
async function getPerson(req, res){
|
async function getPerson (req, res) {
|
||||||
try {
|
try {
|
||||||
const person = await person_model.getPersonById(req.params.id);
|
const person = await person_model.getPersonById(req.params.id)
|
||||||
if(person){
|
if (person) {
|
||||||
// I am retrieving either myself or an enabled user
|
// I am retrieving either myself or an enabled user
|
||||||
if(person.id == req.jwt.person_id || person.enabled){
|
if (person.id == req.jwt.person_id || person.enabled) {
|
||||||
delete person['password']; // remove password field for security reasons
|
delete person.password // remove password field for security reasons
|
||||||
return res.status(200).send(person);
|
return res.status(200).send(person)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res.status(404).json({error: "Not found"});
|
return res.status(404).json({ error: 'Not found' })
|
||||||
}
|
} catch (error) {
|
||||||
catch (error) {
|
console.log('Error while getting person: ' + error)
|
||||||
console.log("Error while getting person: " + error);
|
return res.status(500).json({ error: 'Internal server error' })
|
||||||
return res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,18 +131,17 @@ async function getPerson(req, res){
|
||||||
*
|
*
|
||||||
* @returns Person's details
|
* @returns Person's details
|
||||||
*/
|
*/
|
||||||
async function getMyself(req, res){
|
async function getMyself (req, res) {
|
||||||
try{
|
try {
|
||||||
const person = await person_model.getPersonById(req.jwt.person_id);
|
const person = await person_model.getPersonById(req.jwt.person_id)
|
||||||
if(person){
|
if (person) {
|
||||||
delete person['password'];
|
delete person.password
|
||||||
return res.status(200).send(person);
|
return res.status(200).send(person)
|
||||||
}
|
}
|
||||||
return res.status(404).json({error: "Not found"});
|
return res.status(404).json({ error: 'Not found' })
|
||||||
}
|
} catch (error) {
|
||||||
catch (error){
|
console.log('Error while getting myself: ' + error)
|
||||||
console.log("Error while getting myself: " + error);
|
return res.status(500).json({ error: 'Internal server error' })
|
||||||
return res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,61 +155,57 @@ async function getMyself(req, res){
|
||||||
* new_password if updating the password.
|
* new_password if updating the password.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async function updatePerson(req, res){
|
async function updatePerson (req, res) {
|
||||||
|
if (req.jwt.person_id != req.params.id) {
|
||||||
if (req.jwt.person_id != req.params.id){
|
return res.status(403).json({ error: 'Forbidden' })
|
||||||
return res.status(403).json({ error : "Forbidden"});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatePerson = {};
|
const updatePerson = {}
|
||||||
|
|
||||||
if(req.body.display_name){
|
if (req.body.display_name) {
|
||||||
updatePerson.display_name = req.body.display_name;
|
updatePerson.display_name = req.body.display_name
|
||||||
}
|
}
|
||||||
|
|
||||||
if(req.body.date_of_birth){
|
if (req.body.date_of_birth) {
|
||||||
if(validator.isPostgresDateFormatValid(req.body.date_of_birth)){
|
if (validator.isPostgresDateFormatValid(req.body.date_of_birth)) {
|
||||||
updatePerson.date_of_birth = req.body.date_of_birth;
|
updatePerson.date_of_birth = req.body.date_of_birth
|
||||||
}
|
} else {
|
||||||
else{
|
return res.status(400).json({ error: 'Date of birth format not valid. Please specify a YYYY-MM-DD date' })
|
||||||
return res.status(400).json({ error : "Date of birth format not valid. Please specify a YYYY-MM-DD date"});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(req.body.available){
|
if (req.body.available) {
|
||||||
updatePerson.available = req.body.available;
|
updatePerson.available = req.body.available
|
||||||
}
|
}
|
||||||
|
|
||||||
if(req.body.place_of_living){
|
if (req.body.place_of_living) {
|
||||||
updatePerson.place_of_living = req.body.place_of_living;
|
updatePerson.place_of_living = req.body.place_of_living
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are tying to change password, the old password must be provided
|
// If we are tying to change password, the old password must be provided
|
||||||
if(req.body.old_password && req.body.new_password){
|
if (req.body.old_password && req.body.new_password) {
|
||||||
const user = await knex('Person')
|
const user = await knex('Person')
|
||||||
.select('password')
|
.select('password')
|
||||||
.where({ id: req.jwt.person_id })
|
.where({ id: req.jwt.person_id })
|
||||||
.first();
|
.first()
|
||||||
const passwordMatches = await bcrypt.compare(req.body.old_password, user.password);
|
const passwordMatches = await bcrypt.compare(req.body.old_password, user.password)
|
||||||
if(passwordMatches){
|
if (passwordMatches) {
|
||||||
updatePerson.password = await bcrypt.hash(req.body.new_password, 10);
|
updatePerson.password = await bcrypt.hash(req.body.new_password, 10)
|
||||||
}
|
} else {
|
||||||
else{
|
return res.status(401).json({ error: 'Password verification failed' })
|
||||||
return res.status(401).json({ error : "Password verification failed"});
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Object.keys(updatePerson).length === 0) {
|
if (Object.keys(updatePerson).length === 0) {
|
||||||
return res.status(400).json({ error : "Bad request. No data to update"});
|
return res.status(400).json({ error: 'Bad request. No data to update' })
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await person_model.updatePerson(updatePerson, req.params.id);
|
await person_model.updatePerson(updatePerson, req.params.id)
|
||||||
return res.status(200).json({ success : "true"});
|
return res.status(200).json({ success: 'true' })
|
||||||
}
|
} catch (error) {
|
||||||
catch (error) {
|
console.log('Error while updating a Person: ' + error)
|
||||||
console.log("Error while updating a Person: " + error);
|
return res.status(500).json({ error: 'Internal server error' })
|
||||||
return res.status(500).json({ error : "Internal server error"});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,15 +218,14 @@ async function updatePerson(req, res){
|
||||||
* Required field(s): none
|
* Required field(s): none
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async function deletePerson(req, res) {
|
async function deletePerson (req, res) {
|
||||||
// TODO: Delete Organization if this user was its only administrator
|
// TODO: Delete Organization if this user was its only administrator
|
||||||
try {
|
try {
|
||||||
await person_model.deletePerson(req.jwt.person_id);
|
await person_model.deletePerson(req.jwt.person_id)
|
||||||
return res.status(200).json({success: true});
|
return res.status(200).json({ success: true })
|
||||||
}
|
} catch (error) {
|
||||||
catch (error) {
|
console.log('Error deleting a Person: ' + error)
|
||||||
console.log("Error deleting a Person: " + error);
|
return res.status(500).json({ error: 'Internal server error' })
|
||||||
return res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,10 +233,10 @@ async function deletePerson(req, res) {
|
||||||
// means making a JavaScript function defined in one
|
// means making a JavaScript function defined in one
|
||||||
// module available for use in another module.
|
// module available for use in another module.
|
||||||
module.exports = {
|
module.exports = {
|
||||||
registerPerson,
|
registerPerson,
|
||||||
login,
|
login,
|
||||||
getPerson,
|
getPerson,
|
||||||
getMyself,
|
getMyself,
|
||||||
updatePerson,
|
updatePerson,
|
||||||
deletePerson
|
deletePerson
|
||||||
};
|
}
|
||||||
|
|
|
@ -11,41 +11,41 @@
|
||||||
IN THE SOFTWARE.
|
IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken')
|
||||||
|
|
||||||
function generateToken(person_id) {
|
function generateToken (person_id) {
|
||||||
// The payload the JWT will carry within itself
|
// The payload the JWT will carry within itself
|
||||||
const payload = {
|
const payload = {
|
||||||
person_id: person_id
|
person_id
|
||||||
};
|
|
||||||
|
|
||||||
const token = jwt.sign(payload, process.env.JWT_SECRET_KEY, {
|
|
||||||
expiresIn: '8h'
|
|
||||||
});
|
|
||||||
return token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Middlware
|
const token = jwt.sign(payload, process.env.JWT_SECRET_KEY, {
|
||||||
function verifyToken(req, res, next) {
|
expiresIn: '8h'
|
||||||
const token = req.headers.authorization;
|
})
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|
||||||
if (!token) {
|
// Middlware
|
||||||
return res.status(401).send({error : 'No token provided'});
|
function verifyToken (req, res, next) {
|
||||||
|
const token = req.headers.authorization
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return res.status(401).send({ error: 'No token provided' })
|
||||||
|
}
|
||||||
|
|
||||||
|
jwt.verify(token, process.env.JWT_SECRET_KEY, (err, decoded) => {
|
||||||
|
if (err) {
|
||||||
|
return res.status(401).send({ error: 'Failed to authenticate token' })
|
||||||
}
|
}
|
||||||
|
|
||||||
jwt.verify(token, process.env.JWT_SECRET_KEY, (err, decoded) => {
|
// If the token is valid, store the decoded data in the request object
|
||||||
if (err) {
|
// req.jwt will contain the payload created in generateToken
|
||||||
return res.status(401).send({error : 'Failed to authenticate token'});
|
req.jwt = decoded
|
||||||
}
|
next()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// If the token is valid, store the decoded data in the request object
|
module.exports = {
|
||||||
// req.jwt will contain the payload created in generateToken
|
generateToken,
|
||||||
req.jwt = decoded;
|
verifyToken
|
||||||
next();
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
generateToken,
|
|
||||||
verifyToken
|
|
||||||
};
|
|
||||||
|
|
|
@ -12,14 +12,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const knexInstance = require('knex')({
|
const knexInstance = require('knex')({
|
||||||
client: 'pg',
|
client: 'pg',
|
||||||
connection: {
|
connection: {
|
||||||
host: process.env.POSTGRES_SERVER,
|
host: process.env.POSTGRES_SERVER,
|
||||||
user: process.env.POSTGRES_USERNAME,
|
user: process.env.POSTGRES_USERNAME,
|
||||||
password: process.env.POSTGRES_PASSWORD,
|
password: process.env.POSTGRES_PASSWORD,
|
||||||
port: process.env.POSTGRES_PORT,
|
port: process.env.POSTGRES_PORT,
|
||||||
database: 'Blink'
|
database: 'Blink'
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
module.exports = knexInstance;
|
module.exports = knexInstance
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
* @param {*} email email to validate
|
* @param {*} email email to validate
|
||||||
* @returns true or false
|
* @returns true or false
|
||||||
*/
|
*/
|
||||||
function validateEmail(email) {
|
function validateEmail (email) {
|
||||||
const regex = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/;
|
const regex = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/
|
||||||
return regex.test(email);
|
return regex.test(email)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,12 +27,12 @@ function validateEmail(email) {
|
||||||
* @param {*} dateString the date to validate
|
* @param {*} dateString the date to validate
|
||||||
* @returns true or false
|
* @returns true or false
|
||||||
*/
|
*/
|
||||||
function isPostgresDateFormatValid(dateString) {
|
function isPostgresDateFormatValid (dateString) {
|
||||||
const regex = /^\d{4}-\d{2}-\d{2}$/;
|
const regex = /^\d{4}-\d{2}-\d{2}$/
|
||||||
return regex.test(dateString);
|
return regex.test(dateString)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
validateEmail,
|
validateEmail,
|
||||||
isPostgresDateFormatValid
|
isPostgresDateFormatValid
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
// Run me with "npm test"
|
// Run me with "npm test"
|
||||||
|
|
||||||
const request = require('supertest');
|
const request = require('supertest')
|
||||||
const app = require('../src/app');
|
const app = require('../src/app')
|
||||||
require('dotenv').config({ path: '../src/.env' });
|
require('dotenv').config({ path: '../src/.env' })
|
||||||
|
|
||||||
describe('Person Tests', () => {
|
describe('Person Tests', () => {
|
||||||
test('Correct registration', async () => {
|
test('Correct registration', async () => {
|
||||||
const response = await request(app)
|
const response = await request(app)
|
||||||
.post('/api/register')
|
.post('/api/register')
|
||||||
.send({
|
.send({
|
||||||
email : "johntestdoe@mail.org",
|
email: 'johntestdoe@mail.org',
|
||||||
password : "password",
|
password: 'password',
|
||||||
display_name : "John Doe"
|
display_name: 'John Doe'
|
||||||
})
|
})
|
||||||
expect(response.status).toBe(200);
|
expect(response.status).toBe(200)
|
||||||
expect(response.body).toEqual({ activationLink: expect.any(String) });
|
expect(response.body).toEqual({ activationLink: expect.any(String) })
|
||||||
});
|
})
|
||||||
|
|
||||||
test('Incorrect registration', async () => {
|
test('Incorrect registration', async () => {
|
||||||
const response = await request(app)
|
const response = await request(app)
|
||||||
.post('/api/register')
|
.post('/api/register')
|
||||||
.send({
|
.send({
|
||||||
email : "this is not an email",
|
email: 'this is not an email',
|
||||||
password : "password",
|
password: 'password',
|
||||||
display_name : "John Doe"
|
display_name: 'John Doe'
|
||||||
})
|
})
|
||||||
expect(response.status).toBe(400);
|
expect(response.status).toBe(400)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
const apiUrl = "http://localhost:3000/blinkapi";
|
const apiUrl = 'http://localhost:3000/blinkapi'
|
||||||
|
|
Loading…
Reference in New Issue