create organization_routes and organization_admin_routes

This commit is contained in:
Alessandro Ferro 2024-02-20 22:59:53 +01:00
parent 091c59d97a
commit 93baed4b0a
3 changed files with 122 additions and 107 deletions

View File

@ -12,14 +12,17 @@
*/
// Importing modules
// TODO: clean up
require('dotenv').config();
const express = require('express');
const cors = require('cors');
const rateLimit = require('express-rate-limit');
const apiController = require('./controllers/api_controller.js'); // todo refactor
const personRoutes = require('./routes/person_routes.js');
const organizationRoutes = require('./routes/organization_routes.js');
const organizationAdminRoutes = require('./routes/organization_admin_routes.js');
const organizationPostRoutes = require('./routes/organization_post_routes.js')
const jwt_utils = require('./utils/jwt_utils.js');
require('dotenv').config();
// Application configuration
const app = express();
@ -41,14 +44,14 @@ protectedRoutes.get('/person/myself', personRoutes.getMyself);
protectedRoutes.get('/person/:id', personRoutes.getPerson);
protectedRoutes.put('/person/:id', personRoutes.updatePerson);
protectedRoutes.delete('/person/delete', personRoutes.deletePerson);
protectedRoutes.post('/organization/admin', apiController.addOrganizationAdmin);
protectedRoutes.delete('/organization/removeadmin', apiController.removeOrganizationAdmin);
protectedRoutes.post('/organization/admin', organizationAdminRoutes.addOrganizationAdmin);
protectedRoutes.delete('/organization/removeadmin', organizationAdminRoutes.removeOrganizationAdmin);
protectedRoutes.post('/organization', organizationRoutes.createOrganization);
protectedRoutes.get('/organization/:id', organizationRoutes.getOrganization);
protectedRoutes.put('/organization/:id', organizationRoutes.updateOrganization);
protectedRoutes.delete('/organization/:id', organizationRoutes.deleteOrganization);
protectedRoutes.post('/organization/post', apiController.createOrganizationPost);
protectedRoutes.delete('/organization/post/:id', apiController.deleteOrganizationPost);
protectedRoutes.post('/organization/post', organizationPostRoutes.createOrganizationPost);
protectedRoutes.delete('/organization/post/:id', organizationPostRoutes.deleteOrganizationPost);
// Mounting routes
app.use('/api', publicRoutes); // Routes not requiring token

View File

@ -0,0 +1,107 @@
/*
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');
/**
* POST Method
*
* Add an Administrator to an Organization. Allowed only if the
* logged user is an Administrator themselves.
*
* Required field(s): organization_id, person_id
*/
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"});
}
try {
const isPersonAdmin = await knex('OrganizationAdministrator')
.where('id_person', req.jwt.person_id)
.where('id_organization', req.body.organization_id)
.select('*')
.first();
if(!isPersonAdmin){
return res.status(401).json({error : "Forbidden"});
}
await knex('OrganizationAdministrator')
.insert({
id_person: req.body.person_id,
id_organization: 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
*
* Deletes a Person from the list of Administrators of an Organization.
* The logged user can only remove themselves. If no more Administrators
* are left, the Organization is removed.
*
* Required field(s): organization_id
*/
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"});
}
try{
const transaction = await knex.transaction();
// We lock the table to ensure that we won't have concurrency issues
// while checking remainingAdministrators.
// TODO: Understand whether a lock on the table is necessary
await transaction.raw('LOCK TABLE "OrganizationAdministrator" IN SHARE MODE');
await transaction('OrganizationAdministrator')
.where('id_person', req.jwt.person_id)
.where('id_organization', req.body.organization_id)
.del();
// TODO: If the user instead deletes their entire profile, the organization will not be deleted. Fix. (database schema)
const remainingAdministrators = await transaction('OrganizationAdministrator')
.where({ id_organization: req.body.organization_id });
if (remainingAdministrators.length === 0) {
// If no more users, delete the organization
await transaction('Organization')
.where('id', req.body.organization_id)
.del();
}
await transaction.commit();
return res.status(200).json({success : true});
}
catch (error){
console.error(error);
return res.status(500).json({ error: "Internal server error"});
}
}
module.exports = {
addOrganizationAdmin,
removeOrganizationAdmin
};

View File

@ -10,13 +10,10 @@
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
// todo this file shall be deleted
require('dotenv').config();
const knex = require('../utils/knex_config');
// ======== BEGIN API ENDPOINTS ========
/**
/**
* POST Request
*
* Creates a Post belonging to an organization
@ -24,8 +21,8 @@ const knex = require('../utils/knex_config');
* Required field(s): organization_id, content
* @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"});
@ -55,7 +52,7 @@ const knex = require('../utils/knex_config');
return res.status(200).json(organizationPost[0]);
}
catch (error) {
console.log(error);
console.log("Error while creating Organization Post: " + error);
return res.status(500).json({error : "Internal server error"});
}
}
@ -97,102 +94,10 @@ async function deleteOrganizationPost(req, res){
}
}
/**
* POST Method
*
* Add an Administrator to an Organization. Allowed only if the
* logged user is an Administrator themselves.
*
* Required field(s): organization_id, person_id
*/
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"});
}
try {
const isPersonAdmin = await knex('OrganizationAdministrator')
.where('id_person', req.jwt.person_id)
.where('id_organization', req.body.organization_id)
.select('*')
.first();
if(!isPersonAdmin){
return res.status(401).json({error : "Forbidden"});
}
await knex('OrganizationAdministrator')
.insert({
id_person: req.body.person_id,
id_organization: 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
*
* Deletes a Person from the list of Administrators of an Organization.
* The logged user can only remove themselves. If no more Administrators
* are left, the Organization is removed.
*
* Required field(s): organization_id
*/
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"});
}
try{
const transaction = await knex.transaction();
// We lock the table to ensure that we won't have concurrency issues
// while checking remainingAdministrators.
// TODO: Understand whether a lock on the table is necessary
await transaction.raw('LOCK TABLE "OrganizationAdministrator" IN SHARE MODE');
await transaction('OrganizationAdministrator')
.where('id_person', req.jwt.person_id)
.where('id_organization', req.body.organization_id)
.del();
// TODO: If the user instead deletes their entire profile, the organization will not be deleted. Fix. (database schema)
const remainingAdministrators = await transaction('OrganizationAdministrator')
.where({ id_organization: req.body.organization_id });
if (remainingAdministrators.length === 0) {
// If no more users, delete the organization
await transaction('Organization')
.where('id', req.body.organization_id)
.del();
}
await transaction.commit();
return res.status(200).json({success : true});
}
catch (error){
console.error(error);
return res.status(500).json({ error: "Internal server error"});
}
}
// ======== END API ENDPOINTS ========
// Exporting a function
// means making a JavaScript function defined in one
// module available for use in another module.
module.exports = {
createOrganizationPost,
deleteOrganizationPost,
addOrganizationAdmin,
removeOrganizationAdmin
deleteOrganizationPost
};