mirror of
https://github.com/xfarrow/blink
synced 2025-02-18 08:20:36 +01:00
create organization_model, code refactoring
This commit is contained in:
parent
81dc61fd1f
commit
7fe83ee2e3
147
backend/apis/nodejs/src/models/organization_model.js
Normal file
147
backend/apis/nodejs/src/models/organization_model.js
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
This code is part of Blink
|
||||||
|
licensed under GPLv3
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const knex = require('../utils/knex_config');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create Organization object
|
||||||
|
* @param {*} name
|
||||||
|
* @param {*} location
|
||||||
|
* @param {*} description
|
||||||
|
* @param {*} is_hiring
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function organization(name, location, description, is_hiring){
|
||||||
|
const organization = {
|
||||||
|
name: name,
|
||||||
|
location: location,
|
||||||
|
description: description,
|
||||||
|
is_hiring: is_hiring
|
||||||
|
};
|
||||||
|
return organization;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an Organization by its identifier
|
||||||
|
* @param {*} id
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async function getOrganizationById(id){
|
||||||
|
const organization = await knex('Organization')
|
||||||
|
.where('id', id)
|
||||||
|
.select('*')
|
||||||
|
.first();
|
||||||
|
return organization;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert an Organization and its relative Administrator
|
||||||
|
* @param {*} organization
|
||||||
|
*/
|
||||||
|
async function insertOrganization(organization, organizationAdministratorId){
|
||||||
|
await knex.transaction(async (trx) => {
|
||||||
|
// We have to insert either both in Organization and in OrganizationAdministrator
|
||||||
|
// or in neither
|
||||||
|
const organizationResult = await trx('Organization')
|
||||||
|
.insert(organization, '*');
|
||||||
|
|
||||||
|
// Inserting in the "OrganizationAdministrator" table
|
||||||
|
await trx('OrganizationAdministrator')
|
||||||
|
.insert({
|
||||||
|
id_person: organizationAdministratorId,
|
||||||
|
id_organization: organizationResult[0].id,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates an Organization specified by the OrganizationId, if and
|
||||||
|
* only if the specified personId is one of its Administrator
|
||||||
|
* @param {*} organization
|
||||||
|
* @param {*} organizationId
|
||||||
|
* @param {*} personId
|
||||||
|
* @returns true if the row was updated, false otherwise
|
||||||
|
*/
|
||||||
|
async function updateOrganizationIfAdministrator(organization, organizationId, personId){
|
||||||
|
// // const isOrganizationAdmin = await knex('OrganizationAdministrator')
|
||||||
|
// // .where('id_person', req.jwt.person_id)
|
||||||
|
// // .where('id_organization', req.params.id)
|
||||||
|
// // .select('*')
|
||||||
|
// // .first();
|
||||||
|
|
||||||
|
// // // This introduces a Time of check Time of use weakeness
|
||||||
|
// // // which could'have been fixed by either
|
||||||
|
// // // 1) Using "whereExists", thanks to the "it's easier to ask for
|
||||||
|
// // // forgiveness than for permission" padarigm. Or,
|
||||||
|
// // // 2) Using a serializable transaction.
|
||||||
|
// // //
|
||||||
|
// // // The undersigned chose not to follow these approaches because
|
||||||
|
// // // this does not introduces any serious vulnerability. In this
|
||||||
|
// // // way it seems more readable.
|
||||||
|
|
||||||
|
// // if(!isOrganizationAdmin){
|
||||||
|
// // return res.status(403).json({error : "Forbidden"});
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// // await knex('Organization')
|
||||||
|
// // .where('id', req.params.id)
|
||||||
|
// // .update({
|
||||||
|
// // name: req.body.name,
|
||||||
|
// // location: req.body.location,
|
||||||
|
// // description: req.body.description,
|
||||||
|
// // is_hiring: req.body.is_hiring
|
||||||
|
// // });
|
||||||
|
|
||||||
|
const numberOfUpdatedRows = await knex('Organization')
|
||||||
|
.where('id', organizationId)
|
||||||
|
.whereExists(function(){
|
||||||
|
this.select('*')
|
||||||
|
.from('OrganizationAdministrator')
|
||||||
|
.where('id_person', personId)
|
||||||
|
.where('id_organization', organizationId)
|
||||||
|
})
|
||||||
|
.update(organization);
|
||||||
|
return numberOfUpdatedRows == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes an Organization if the specified PersonId is
|
||||||
|
* one of its administrators
|
||||||
|
* @param {*} organizationId Id of the Organization to delete
|
||||||
|
* @param {*} personId PersonId of the supposedly administrator
|
||||||
|
* @returns true if the Organization was successfully deleted, false otherwise
|
||||||
|
*/
|
||||||
|
async function deleteOrganizationIfAdmin(organizationId, personId){
|
||||||
|
const numberOfDeletedRows = await knex('Organization')
|
||||||
|
.where({ id: organizationId })
|
||||||
|
.whereExists(function(){
|
||||||
|
this.select('*')
|
||||||
|
.from('OrganizationAdministrator')
|
||||||
|
.where('id_person', personId)
|
||||||
|
.where('id_organization', organizationId)
|
||||||
|
})
|
||||||
|
.del();
|
||||||
|
return numberOfDeletedRows == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exporting a function
|
||||||
|
// means making a JavaScript function defined in one
|
||||||
|
// module available for use in another module.
|
||||||
|
module.exports = {
|
||||||
|
getOrganizationById,
|
||||||
|
organization,
|
||||||
|
insertOrganization,
|
||||||
|
updateOrganizationIfAdministrator,
|
||||||
|
updateOrganizationIfAdministrator,
|
||||||
|
deleteOrganizationIfAdmin
|
||||||
|
};
|
@ -25,7 +25,7 @@ const bcrypt = require('bcrypt');
|
|||||||
* @param {*} place_of_living
|
* @param {*} place_of_living
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function createPerson(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: password,
|
||||||
@ -139,7 +139,7 @@ async function deletePerson(person_id){
|
|||||||
// 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 = {
|
||||||
createPerson,
|
person,
|
||||||
getPersonByEmail,
|
getPersonByEmail,
|
||||||
getPersonById,
|
getPersonById,
|
||||||
getPersonByEmailAndPassword,
|
getPersonByEmailAndPassword,
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
IN THE SOFTWARE.
|
IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const knex = require('../utils/knex_config');
|
const organization_model = require('../models/organization_model');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST Request
|
* POST Request
|
||||||
@ -24,198 +24,118 @@ const knex = require('../utils/knex_config');
|
|||||||
*/
|
*/
|
||||||
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{
|
|
||||||
const insertedOrganization = await knex.transaction(async (trx) => {
|
|
||||||
|
|
||||||
// We have to insert either both in Organization and in OrganizationAdministrator
|
|
||||||
// or in neither
|
|
||||||
const organizationResult = await trx('Organization')
|
|
||||||
.insert({
|
|
||||||
name: req.body.name,
|
|
||||||
location: req.body.location,
|
|
||||||
description: req.body.description,
|
|
||||||
is_hiring: req.body.is_hiring,
|
|
||||||
}, '*');
|
|
||||||
|
|
||||||
// Inserting in the "OrganizationAdministrator" table
|
|
||||||
await trx('OrganizationAdministrator')
|
|
||||||
.insert({
|
|
||||||
id_person: req.jwt.person_id,
|
|
||||||
id_organization: organizationResult[0].id,
|
|
||||||
});
|
|
||||||
return organizationResult[0];
|
|
||||||
});
|
|
||||||
return res.status(200).json({ Organization: insertedOrganization });
|
|
||||||
}
|
|
||||||
catch (error){
|
|
||||||
console.error('Error creating Organization:', error);
|
|
||||||
res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
try{
|
||||||
* PUT Request
|
const organization = organization_model.organization(req.body.name, req.body.location, req.body.description, req.body.is_hiring);
|
||||||
* Updates an Organization's details
|
await organization_model.insertOrganization(organization, req.jwt.person_id);
|
||||||
*
|
return res.status(200).json({ Organization: organization });
|
||||||
* Required field(s): none.
|
}
|
||||||
*/
|
catch (error){
|
||||||
async function updateOrganization(req, res){
|
console.error('Error creating Organization:', error);
|
||||||
|
res.status(500).json({error : "Internal server error"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const updateOrganization = {};
|
/**
|
||||||
|
* PUT Request
|
||||||
|
* Updates an Organization's details
|
||||||
|
*
|
||||||
|
* Required field(s): none.
|
||||||
|
*/
|
||||||
|
async function updateOrganization(req, res){
|
||||||
|
|
||||||
if(req.body.name){
|
const updateOrganization = {};
|
||||||
updateOrganization.name = req.body.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(req.body.location){
|
if(req.body.name){
|
||||||
updateOrganization.location = req.body.location;
|
updateOrganization.name = req.body.name;
|
||||||
}
|
|
||||||
|
|
||||||
if(req.body.description){
|
|
||||||
updateOrganization.description = req.body.description;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(req.body.is_hiring){
|
|
||||||
updateOrganization.is_hiring = req.body.is_hiring;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Object.keys(updateOrganization).length === 0) {
|
|
||||||
return res.status(400).json({ error : "Bad request. No data to update"});
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
// // const isOrganizationAdmin = await knex('OrganizationAdministrator')
|
|
||||||
// // .where('id_person', req.jwt.person_id)
|
|
||||||
// // .where('id_organization', req.params.id)
|
|
||||||
// // .select('*')
|
|
||||||
// // .first();
|
|
||||||
|
|
||||||
// // // This introduces a Time of check Time of use weakeness
|
|
||||||
// // // which could'have been fixed by either
|
|
||||||
// // // 1) Using "whereExists", thanks to the "it's easier to ask for
|
|
||||||
// // // forgiveness than for permission" padarigm. Or,
|
|
||||||
// // // 2) Using a serializable transaction.
|
|
||||||
// // //
|
|
||||||
// // // The undersigned chose not to follow these approaches because
|
|
||||||
// // // this does not introduces any serious vulnerability. In this
|
|
||||||
// // // way it seems more readable.
|
|
||||||
|
|
||||||
// // if(!isOrganizationAdmin){
|
|
||||||
// // return res.status(403).json({error : "Forbidden"});
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // await knex('Organization')
|
|
||||||
// // .where('id', req.params.id)
|
|
||||||
// // .update({
|
|
||||||
// // name: req.body.name,
|
|
||||||
// // location: req.body.location,
|
|
||||||
// // description: req.body.description,
|
|
||||||
// // is_hiring: req.body.is_hiring
|
|
||||||
// // });
|
|
||||||
|
|
||||||
const updatedRows = await knex('Organization')
|
|
||||||
.where('id', req.params.id)
|
|
||||||
.whereExists(function(){
|
|
||||||
this.select('*')
|
|
||||||
.from('OrganizationAdministrator')
|
|
||||||
.where('id_person', req.jwt.person_id)
|
|
||||||
.where('id_organization', req.params.id)
|
|
||||||
})
|
|
||||||
.update({
|
|
||||||
name: req.body.name,
|
|
||||||
location: req.body.location,
|
|
||||||
description: req.body.description,
|
|
||||||
is_hiring: req.body.is_hiring
|
|
||||||
});
|
|
||||||
|
|
||||||
if(updatedRows == 1){
|
|
||||||
return res.status(200).json({ success : "true"});
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return res.status(404).json({error : "Organization either not found or insufficient permissions"});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
return res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
if(req.body.location){
|
||||||
* DELETE Request
|
updateOrganization.location = req.body.location;
|
||||||
*
|
|
||||||
* Deletes the specified organization if the logged user is
|
|
||||||
* one of its administrator
|
|
||||||
*/
|
|
||||||
async function deleteOrganization(req, res){
|
|
||||||
const organizationIdToDelete = req.params.id;
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
// Delete organization if admin
|
|
||||||
const deletedRows = await knex('Organization')
|
|
||||||
.where({ id: organizationIdToDelete })
|
|
||||||
.whereExists(function(){
|
|
||||||
this.select('*')
|
|
||||||
.from('OrganizationAdministrator')
|
|
||||||
.where('id_person', req.jwt.person_id)
|
|
||||||
.where('id_organization', organizationIdToDelete)
|
|
||||||
})
|
|
||||||
.del();
|
|
||||||
|
|
||||||
if(deletedRows == 0){
|
|
||||||
return res.status(403).json({error: "Forbidden"});
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return res.status(200).json({success: true});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
return res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
if(req.body.description){
|
||||||
* GET Request
|
updateOrganization.description = req.body.description;
|
||||||
*
|
|
||||||
* Obtains an organization by its identifier.
|
|
||||||
*
|
|
||||||
* Required field(s): none.
|
|
||||||
*
|
|
||||||
* @returns the organization.
|
|
||||||
*/
|
|
||||||
async function getOrganization(req, res){
|
|
||||||
const organizationId = req.params.id;
|
|
||||||
try {
|
|
||||||
const organization = await knex('Organization')
|
|
||||||
.where('id', organizationId)
|
|
||||||
.select('*')
|
|
||||||
.first();
|
|
||||||
if(organization) {
|
|
||||||
return res.status(200).json(organization);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return res.status(404).json({error : "Not found"});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error("Error retrieving an organization: " + error);
|
|
||||||
return res.status(500).json({error : "Internal server error"});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
if(req.body.is_hiring){
|
||||||
createOrganization,
|
updateOrganization.is_hiring = req.body.is_hiring;
|
||||||
getOrganization,
|
}
|
||||||
updateOrganization,
|
|
||||||
deleteOrganization
|
if (Object.keys(updateOrganization).length === 0) {
|
||||||
|
return res.status(400).json({ error : "Bad request. No data to update"});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const isUpdateSuccessful = organization_model.updateOrganizationIfAdministrator(updateOrganization, req.params.id, req.jwt.person_id);
|
||||||
|
if(isUpdateSuccessful){
|
||||||
|
return res.status(200).json({ success : "true"});
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return res.status(404).json({error : "Organization either not found or insufficient permissions"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
return res.status(500).json({error : "Internal server error"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE Request
|
||||||
|
*
|
||||||
|
* Deletes the specified organization if the logged user is
|
||||||
|
* one of its administrator
|
||||||
|
*/
|
||||||
|
async function deleteOrganization(req, res){
|
||||||
|
try {
|
||||||
|
const isDeleteSuccessful = organization_model.deleteOrganizationIfAdmin(req.params.id, req.jwt.person_id);
|
||||||
|
if(isDeleteSuccessful){
|
||||||
|
return res.status(403).json({error: "Forbidden"});
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return res.status(200).json({success: true});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return res.status(500).json({error : "Internal server error"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET Request
|
||||||
|
*
|
||||||
|
* Obtains an organization by its identifier.
|
||||||
|
*
|
||||||
|
* Required field(s): none.
|
||||||
|
*
|
||||||
|
* @returns the organization.
|
||||||
|
*/
|
||||||
|
async function getOrganization(req, res){
|
||||||
|
try {
|
||||||
|
const organization = await organization_model.getOrganizationById(req.params.id);
|
||||||
|
if(organization) {
|
||||||
|
return res.status(200).json(organization);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return res.status(404).json({error : "Not found"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error("Error retrieving an organization: " + error);
|
||||||
|
return res.status(500).json({error : "Internal server error"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
createOrganization,
|
||||||
|
getOrganization,
|
||||||
|
updateOrganization,
|
||||||
|
deleteOrganization
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ async function registerPerson(req, res){
|
|||||||
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.createPerson(
|
const personToInsert = person_model.person(
|
||||||
req.body.email,
|
req.body.email,
|
||||||
await hashPasswordPromise,
|
await hashPasswordPromise,
|
||||||
req.body.display_name,
|
req.body.display_name,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user