mirror of
				https://github.com/xfarrow/blink
				synced 2025-06-27 09:03:02 +02:00 
			
		
		
		
	create organization_model, code refactoring
This commit is contained in:
		
							
								
								
									
										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 | ||||||
| @@ -30,27 +30,9 @@ async function createOrganization(req, res){ | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   try{ |   try{ | ||||||
|       const insertedOrganization = await knex.transaction(async (trx) => { |     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); | ||||||
|         // We have to insert either both in Organization and in OrganizationAdministrator |     return res.status(200).json({ Organization: organization }); | ||||||
|         // 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){ |   catch (error){ | ||||||
|     console.error('Error creating Organization:', error); |     console.error('Error creating Organization:', error); | ||||||
| @@ -89,52 +71,8 @@ async function createOrganization(req, res){ | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   try { |   try { | ||||||
|    |     const isUpdateSuccessful = organization_model.updateOrganizationIfAdministrator(updateOrganization, req.params.id, req.jwt.person_id); | ||||||
|       // // const isOrganizationAdmin = await knex('OrganizationAdministrator') |     if(isUpdateSuccessful){ | ||||||
|       // // .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"}); |       return res.status(200).json({ success : "true"}); | ||||||
|     } |     } | ||||||
|     else{ |     else{ | ||||||
| @@ -154,28 +92,14 @@ async function createOrganization(req, res){ | |||||||
|  * one of its administrator  |  * one of its administrator  | ||||||
|  */ |  */ | ||||||
| async function deleteOrganization(req, res){ | async function deleteOrganization(req, res){ | ||||||
|     const organizationIdToDelete = req.params.id; |  | ||||||
|    |  | ||||||
|   try { |   try { | ||||||
|    |     const isDeleteSuccessful = organization_model.deleteOrganizationIfAdmin(req.params.id, req.jwt.person_id); | ||||||
|       // Delete organization if admin |     if(isDeleteSuccessful){ | ||||||
|       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"}); |       return res.status(403).json({error: "Forbidden"}); | ||||||
|     } |     } | ||||||
|     else{ |     else{ | ||||||
|       return res.status(200).json({success: true}); |       return res.status(200).json({success: true}); | ||||||
|     } |     } | ||||||
|          |  | ||||||
|   } |   } | ||||||
|   catch (error) { |   catch (error) { | ||||||
|     console.error(error); |     console.error(error); | ||||||
| @@ -193,12 +117,8 @@ async function createOrganization(req, res){ | |||||||
|  * @returns the organization. |  * @returns the organization. | ||||||
|  */ |  */ | ||||||
| async function getOrganization(req, res){ | async function getOrganization(req, res){ | ||||||
|     const organizationId = req.params.id; |  | ||||||
|   try { |   try { | ||||||
|       const organization = await knex('Organization') |     const organization = await organization_model.getOrganizationById(req.params.id); | ||||||
|         .where('id', organizationId) |  | ||||||
|         .select('*') |  | ||||||
|         .first(); |  | ||||||
|     if(organization) { |     if(organization) { | ||||||
|       return res.status(200).json(organization); |       return res.status(200).json(organization); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -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, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user