person ok

This commit is contained in:
xfarrow
2024-10-17 15:37:34 +02:00
parent 9fe5879554
commit 5835bfbc16
7 changed files with 117 additions and 360 deletions

View File

@ -1,110 +0,0 @@
/*
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.
*/
/******************************************************************************
* ⚠ WARNING ⚠
*
*
* Posts are now scheduled to be developed at a later stage in the development
* process, with the possibility that it may not be developed at all.
* I am unsure whether it is a good thing or it'll only be used to
* flood timelines with low-effort content, like other competing platforms.
*
*
*
******************************************************************************/
const knex = require('../utils/knex_config');
/**
* Create OrganizationPost object
* @param {*} organizationId
* @param {*} content
* @param {*} originalAuthor
*/
function createOrganizationPost(organizationId, content, originalAuthor) {
const organizationPost = {
organization_id: organizationId,
content,
original_author: originalAuthor
};
return organizationPost;
}
/**
* Insert an OrganizationPost if and only if the author is
* one of the Organization's administrators.
* @param {*} organization
* @returns the inserted OrganizationPost
*/
async function insertOrganizationPost(organization) {
const isOrganizationAdmin = await knex('OrganizationAdministrator')
.where('id_person', organization.original_author)
.where('id_organization', organization.organization_id)
.select('*')
.first();
// 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
if (!isOrganizationAdmin) {
return false;
}
const organizationPost = await knex('OrganizationPost')
.insert({
organization_id: organization.organization_id,
content: organization.content,
original_author: organization.original_author
})
.returning('*');
return organizationPost[0];
}
/**
* Checks whether the specified Person is an Organization Administrator
* of the Organization the Post belongs to.
* @param {*} postId
* @param {*} personId
* @returns true or false
*/
async function isPersonPostAdministrator(postId, personId) {
return await knex('OrganizationPost')
.join('OrganizationAdministrator', 'OrganizationPost.organization_id', 'OrganizationAdministrator.id_organization')
.where('OrganizationPost.id', postId)
.where('OrganizationAdministrator.id_person', personId)
.select('*')
.first();
}
/**
* Deletes the specified OrganizationPost if the requester is one
* of the Administrators of the Organization the Post belongs to
* @param {*} postId Id of the Post to delete
* @param {*} requester Id of the Person requesting the deletion
*/
async function deleteOrganizationPost(postId, requester) {
if (await isPersonPostAdministrator(postId, requester)) {
return await knex('OrganizationPost')
.where('id', postId)
.del() == 1;
}
return false;
}
module.exports = {
createOrganizationPost,
insertOrganizationPost,
isPersonPostAdministrator,
deleteOrganizationPost
};

View File

@ -25,17 +25,18 @@ const bcrypt = require('bcrypt');
* @param {*} placeOfLiving
* @returns
*/
function createPerson(email, password, displayName, dateOfBirth, available, enabled, placeOfLiving, aboutMe, qualification) {
function createPerson(email, password, displayName, dateOfBirth, placeOfLiving, aboutMe, qualification, openToWork, enabled) {
const person = {
email: email.toLowerCase(),
password,
display_name: displayName,
date_of_birth: dateOfBirth,
available,
enabled,
open_to_work: openToWork,
place_of_living: placeOfLiving,
about_me: aboutMe,
qualification
qualification,
enabled,
visibility: "EVERYONE"
};
return person;
}
@ -80,12 +81,12 @@ async function insert(person, activationLink) {
const insertedPerson = await tr('Person')
.insert(person)
.returning('*');
if(activationLink != null){
if (activationLink != null) {
await tr('ActivationLink')
.insert({
person_id: insertedPerson[0].id,
identifier: activationLink
});
.insert({
person_id: insertedPerson[0].id,
identifier: activationLink
});
}
return insertedPerson[0];
});

View File

@ -1,106 +0,0 @@
/*
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.
*/
/******************************************************************************
* ⚠ WARNING ⚠
*
*
* Posts are now scheduled to be developed at a later stage in the development
* process, with the possibility that it may not be developed at all.
* I am unsure whether it is a good thing or it'll only be used to
* flood timelines with low-effort content, like other competing platforms.
*
*
*
******************************************************************************/
const organizationPostModel = require('../models/organization_post_model');
const express = require('express');
const jwtUtils = require('../utils/jwt_utils');
/**
* POST Request
*
* Creates a Post belonging to an organization
*
* Required field(s): organization_id, content
* @returns the inserted Post
*/
async function createOrganizationPost(req, res) {
// Ensure that the required fields are present before proceeding
if (!req.params.idOrganization || !req.body.content) {
return res.status(400).json({
error: 'Invalid request'
});
}
const organizationPost = organizationPostModel.createOrganizationPost(
req.params.idOrganization,
req.body.content,
req.jwt.person_id);
try {
const insertedOrganization = await organizationPostModel.insertOrganizationPost(organizationPost);
if(!!insertedOrganization){
return res.status(200).json(insertedOrganization);
}
return res.status(401).json({
error: 'Forbidden'
});
} catch (error) {
console.error(`Error in function ${createOrganizationPost.name}: ${error}`);
return res.status(500).json({
error: 'Internal server error'
});
}
}
/**
* DELETE Request
*
* Deletes a Post belonging to an Organization, only if
* the logged user is an administrator of that Organization.
*
* Required field(s): none.
*/
async function deleteOrganizationPost(req, res) {
try {
const success = await organizationPostModel.deleteOrganizationPost(req.params.id, req.jwt.person_id);
if (success) {
return res.status(200).json({
success: true
});
}
return res.status(401).json({
error: 'Forbidden'
});
} catch (error) {
console.error(`Error in function ${deleteOrganizationPost.name}: ${error}`);
res.status(500).json({
error: 'Internal server error'
});
}
}
const routes = express.Router();
routes.post('/:idOrganization/posts', jwtUtils.extractToken, createOrganizationPost);
routes.delete('/posts/:id', jwtUtils.extractToken, deleteOrganizationPost);
// Exporting a function
// means making a JavaScript function defined in one
// module available for use in another module.
module.exports = {
routes
};

View File

@ -16,7 +16,7 @@ const jwtUtils = require('../utils/jwt_utils');
const bcrypt = require('bcrypt');
const crypto = require('crypto');
const Person = require('../models/person_model');
const activationModel = require('../models/activation_model');
const Activation = require('../models/activation_model');
const express = require('express');
const mailUtils = require('../utils/mail_utils');
@ -66,13 +66,14 @@ async function registerPerson(req, res) {
const personToInsert = Person.createPerson(
req.body.email,
await hashPasswordPromise,
req.body.display_name,
req.body.date_of_birth,
req.body.available,
req.body.displayName,
req.body.dateOfBirth,
req.body.placeOfLiving,
req.body.aboutMe,
req.body.qualification,
req.body.openToWork,
isEnabled,
req.body.place_of_living,
req.body.about_me,
req.body.qualification);
);
const insertedPerson = await Person.insert(personToInsert, activationCode);
delete insertedPerson.password;
@ -190,8 +191,8 @@ async function getMyself(req, res) {
* not present, they shall be ignored. An user can
* only update themselves
*
* Required field(s): At least one. Both old_password and
* new_password if updating the password.
* Required field(s): At least one. Both oldPassword and
* newPassword if updating the password.
*
*/
async function updatePerson(req, res) {
@ -205,46 +206,50 @@ async function updatePerson(req, res) {
const updatePerson = {};
if (req.body.display_name !== undefined) {
updatePerson.display_name = req.body.display_name;
if (req.body.displayName !== undefined) {
updatePerson.display_name = req.body.displayName;
}
if (req.body.date_of_birth !== undefined) {
updatePerson.date_of_birth = req.body.date_of_birth;
if (req.body.dateOfBirth !== undefined) {
updatePerson.date_of_birth = req.body.dateOfBirth;
}
if (req.body.available !== undefined) {
updatePerson.available = req.body.available;
if (req.body.openToWork !== undefined) {
updatePerson.open_to_work = req.body.openToWork;
}
if (req.body.place_of_living !== undefined) {
updatePerson.place_of_living = req.body.place_of_living;
if (req.body.placeOfLiving !== undefined) {
updatePerson.place_of_living = req.body.placeOfLiving;
}
if (req.body.about_me !== undefined) {
updatePerson.about_me = req.body.about_me;
if (req.body.aboutMe !== undefined) {
updatePerson.about_me = req.body.aboutMe;
}
if (req.body.qualification !== undefined) {
updatePerson.qualification = req.body.qualification;
}
if (req.body.visibility !== undefined) {
updatePerson.visibility = req.body.visibility;
}
// If we are tying to change password, the old password must be provided
if (req.body.old_password !== undefined || req.body.new_password !== undefined) {
if (req.body.old_password === undefined) {
if (req.body.oldPassword !== undefined || req.body.newPassword !== undefined) {
if (req.body.oldPassword === undefined) {
return res.status(401).json({
error: 'The old password must be specified'
});
}
if (req.body.new_password === undefined) {
if (req.body.newPassword === undefined) {
return res.status(401).json({
error: 'The new password must be specified'
});
}
const user = await Person.findById(req.jwt.person_id);
const passwordMatches = await bcrypt.compare(req.body.old_password, user.password);
const passwordMatches = await bcrypt.compare(req.body.oldPassword, user.password);
if (passwordMatches) {
updatePerson.password = await bcrypt.hash(req.body.new_password, 10);
updatePerson.password = await bcrypt.hash(req.body.newPassword, 10);
} else {
return res.status(401).json({
error: 'Password verification failed'
@ -306,7 +311,7 @@ async function confirmActivation(req, res) {
errors: errors.array()
});
}
const personId = await activationModel.getPersonIdByIdentifier(req.body.code);
const personId = await Activation.getPersonIdByIdentifier(req.body.code);
if (!personId) {
return res.status(401).json({
error: 'Activation Link either not valid or expired'

View File

@ -17,7 +17,7 @@ const {
} = require("express-validator"); // This is the destructuring part. It specifies which properties of the imported object (express-validator) you want to extract.
const registerValidator = [
check('display_name').trim().notEmpty().escape().isLength({
check('displayName').trim().notEmpty().escape().isLength({
max: 128
}),
check('email').isEmail().normalizeEmail().escape().isLength({
@ -26,12 +26,12 @@ const registerValidator = [
check('password').isLength({
min: 5
}).trim().escape().withMessage('Password must be at least 5 characters'),
check('date_of_birth').optional().isDate().withMessage('Invalid date format. Date must be YYYY-MM-DD'),
check('available').optional().isBoolean(),
check('place_of_living').isLength({
check('dateOfBirth').optional().isDate().withMessage('Invalid date format. Date must be YYYY-MM-DD'),
check('openToWork').optional().isBoolean(),
check('placeOfLiving').isLength({
max: 128
}).escape(),
check('about_me').isLength({
check('aboutMe').isLength({
max: 4096
}).escape(),
check('qualification').isLength({
@ -45,15 +45,15 @@ const getTokenValidator = [
];
const updatePersonValidator = [
check('display_name').trim().escape().isLength({
check('displayName').trim().escape().isLength({
max: 128
}),
check('date_of_birth').optional().isDate().withMessage('Invalid date format. Date must be YYYY-MM-DD'),
check('available').optional().isBoolean(),
check('place_of_living').isLength({
check('dateOfBirth').optional().isDate().withMessage('Invalid date format. Date must be YYYY-MM-DD'),
check('openToWork').optional().isBoolean(),
check('placeOfLiving').isLength({
max: 128
}).escape(),
check('about_me').isLength({
check('aboutMe').isLength({
max: 4096
}).escape(),
check('qualification').isLength({