Using knex instead of pg-promise

Knex is better
This commit is contained in:
xfarrow 2023-10-16 13:02:47 +02:00
parent 1afae90de1
commit 9742e81023
3 changed files with 113 additions and 108 deletions

View File

@ -1,12 +1,7 @@
# Blink configuration file
# API Server configuration
API_SERVER_PORT = 3000 API_SERVER_PORT = 3000
# Postgres database configuration
POSTGRES_SERVER = localhost POSTGRES_SERVER = localhost
POSTGRES_USERNAME = postgres POSTGRES_USERNAME = postgres
POSTGRES_PASSWORD = postgres POSTGRES_PASSWORD = postgres
POSTGRES_PORT = 5432 POSTGRES_PORT = 5432
# Admin settings

View File

@ -24,7 +24,7 @@ app.post('/blinkapi/organization', api_controller.verifyToken, api_controller.cr
app.delete('/blinkapi/organization/:id', api_controller.verifyToken, api_controller.deleteOrganization); // Delete organization app.delete('/blinkapi/organization/:id', api_controller.verifyToken, api_controller.deleteOrganization); // Delete organization
app.post('/blinkapi/organization/post', api_controller.verifyToken, api_controller.createOrganizationPost); // Create a organization's post app.post('/blinkapi/organization/post', api_controller.verifyToken, api_controller.createOrganizationPost); // Create a organization's post
app.delete('/blinkapi/organization/post/:id', api_controller.verifyToken, api_controller.deleteOrganizationPost); // Delete a organization's post app.delete('/blinkapi/organization/post/:id', api_controller.verifyToken, api_controller.deleteOrganizationPost); // Delete a organization's post
app.post('/blinkapi/organization/admin', api_controller.verifyToken, api_controller.makeAdmin); // Make someone a organization's administrator
// Start the server // Start the server
app.listen(process.env.API_SERVER_PORT, () => { app.listen(process.env.API_SERVER_PORT, () => {
console.log(`Blink API server is running on port ${process.env.API_SERVER_PORT}`); console.log(`Blink API server is running on port ${process.env.API_SERVER_PORT}`);

View File

@ -10,20 +10,21 @@
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE. IN THE SOFTWARE.
*/ */
require('dotenv').config();
const bcrypt = require('bcrypt'); const bcrypt = require('bcrypt');
const crypto = require('crypto'); const crypto = require('crypto');
const pgp = require('pg-promise')(); // In the future I'd like to use knex.js to avoid raw sql const knex = require('knex')({
client: 'pg',
connection: {
host: process.env.POSTGRES_SERVER,
user: process.env.POSTGRES_USERNAME,
password: process.env.POSTGRES_PASSWORD,
port: process.env.POSTGRES_PORT,
database: 'Blink'
}
});
const jwt = require('jsonwebtoken'); const jwt = require('jsonwebtoken');
require('dotenv').config();
const database_configuration = {
host: process.env.POSTGRES_SERVER,
port: process.env.POSTGRES_PORT,
database: "Blink",
user: process.env.POSTGRES_USERNAME,
password: process.env.POSTGRES_PASSWORD
};
const db = pgp(database_configuration);
// ======== API ENDPOINTS ======== // ======== API ENDPOINTS ========
@ -44,40 +45,27 @@ async function registerPerson(req, res){
const hashPasswordPromise = bcrypt.hash(userData.password, 10); const hashPasswordPromise = bcrypt.hash(userData.password, 10);
try{ try{
// Begin transaction // Begin transaction
await db.tx(async (t) => { await knex.transaction(async (tr) => {
// Inserting in the "Person" table const personIdResult = await tr('Person')
const userInsertQuery = ` .insert({
INSERT INTO "Person" (email, password, display_name, date_of_birth, available, enabled, place_of_living) email: userData.email,
VALUES ($1, $2, $3, $4, $5, $6, $7) password: await hashPasswordPromise,
RETURNING id`; display_name: userData.display_name,
date_of_birth: userData.date_of_birth,
available: userData.available,
enabled: true,
place_of_living: userData.place_of_living})
.returning("id");
const userResult = await t.one(userInsertQuery, [ await tr('ActivationLink')
userData.email, .insert({
await hashPasswordPromise, person_id: personIdResult[0].id,
userData.display_name, identifier: activationLink
userData.date_of_birth, });
userData.available,
false,
userData.place_of_living
]);
// Inserting in the "ActivationLink" table
const activationLinkInsertQuery = `
INSERT INTO "ActivationLink" (person_id, identifier)
VALUES ($1, $2)
RETURNING *`;
const activationLinkResult = await t.one(activationLinkInsertQuery, [
userResult.id,
activationLink,
]);
return res.status(200).json({ activationLink: activationLinkResult.identifier });
}); });
return res.status(200).json({ activationLink: activationLink });
} }
catch (error){ catch (error){
console.error('Error inserting data:', error); console.error('Error inserting data:', error);
@ -109,10 +97,13 @@ async function login(req, res){
// GET // GET
async function getPerson(req, res){ async function getPerson(req, res){
try { try {
const user = await db.oneOrNone('SELECT * FROM "Person" WHERE id = $1 and enabled = $2' , [req.params.id, false]); const user = await knex('Person')
.select('*')
.where({ id: req.params.id, enabled: true })
.first();
if(user){ if(user){
if(user.id == req.jwt.person_id || user.active == true){ if(user.id == req.jwt.person_id || user.enabled){
return res.status(200).send(user); return res.status(200).send(user);
} }
} }
@ -134,35 +125,26 @@ async function createOrganization(req, res){
} }
try{ try{
knex.transaction(async (trx) => {
// Begin transaction const organizationResult = await trx('Organization')
await db.tx(async (t) => { .insert({
name: organizationData.name,
// Inserting in the "Organization" table location: organizationData.location,
const OrganizationInsertQuery = ` description: organizationData.description,
INSERT INTO "Organization" (name, location, description, is_hiring) is_hiring: organizationData.is_hiring,
VALUES ($1, $2, $3, $4) })
RETURNING *`; .returning('*');
const organizationResult = await t.one(OrganizationInsertQuery, [
organizationData.name,
organizationData.location,
organizationData.description,
organizationData.is_hiring
]);
// Inserting in the "OrganizationAdministrator" table // Inserting in the "OrganizationAdministrator" table
const OrganizationAdministratorInsertQuery = ` await trx('OrganizationAdministrator')
INSERT INTO "OrganizationAdministrator" (id_person, id_organization) .insert({
VALUES ($1, $2)`; id_person: req.jwt.person_id,
id_organization: organizationResult[0].id,
await t.none(OrganizationAdministratorInsertQuery, [ });
req.jwt.person_id,
organizationResult.id await trx.commit();
]);
return res.status(200).json({ "Organization" : organizationResult});
return res.status(200).json({ Organization: organizationResult[0] });
}); });
} }
catch (error){ catch (error){
@ -177,7 +159,9 @@ async function deleteOrganization(req, res){
try { try {
if(await isPersonOrganizationAdmin(req.jwt.person_id, organizationIdToDelete)){ if(await isPersonOrganizationAdmin(req.jwt.person_id, organizationIdToDelete)){
await db.none('DELETE FROM "Organization" WHERE id = $1', [organizationIdToDelete]); await knex('Organization')
.where({ id: organizationIdToDelete })
.del();
return res.status(200).json("Ok"); return res.status(200).json("Ok");
} }
return res.status(403).json("Forbidden"); return res.status(403).json("Forbidden");
@ -199,19 +183,20 @@ async function createOrganizationPost(req, res){
try { try {
if (await isPersonOrganizationAdmin(req.jwt.person_id, organizationPostData.organization_id)){ if (await isPersonOrganizationAdmin(req.jwt.person_id, organizationPostData.organization_id)){
const organizationPost = await db.one('INSERT INTO "OrganizationPost" (organization_id, content) VALUES ($1, $2) RETURNING *', const organizationPost = await knex('OrganizationPost')
[organizationPostData.organization_id, organizationPostData.content]); .insert({
if(organizationPost){ organization_id: organizationPostData.organization_id,
return res.status(200).json(organizationPost); content: organizationPostData.content,
} })
else{ .returning('*');
return res.status(500).json("Internal server error"); return res.status(200).json(organizationPost[0]);
}
} }
else{ else{
return res.status(401).json("Forbidden"); return res.status(401).json("Forbidden");
} }
} catch (error) { }
catch (error) {
console.log(error);
return res.status(500).json("Internal server error"); return res.status(500).json("Internal server error");
} }
} }
@ -219,32 +204,48 @@ async function createOrganizationPost(req, res){
// DELETE // DELETE
async function deleteOrganizationPost(req, res){ async function deleteOrganizationPost(req, res){
const organizationPostIdToDelete = req.params.id; const organizationPostIdToDelete = req.params.id;
try { try{
if(await db.oneOrNone(' SELECT *' + knex.transaction(async (trx) => {
' FROM "OrganizationPost"' + // Check if user is allowed to delete the post
' JOIN "OrganizationAdministrator"' + const result = await trx('OrganizationPost')
' ON "OrganizationPost".organization_id = "OrganizationAdministrator".id_organization' + .join('OrganizationAdministrator', 'OrganizationPost.organization_id', 'OrganizationAdministrator.id_organization')
' WHERE "OrganizationPost".id = $1 and "OrganizationAdministrator".id_person = $2', .where('OrganizationPost.id', organizationPostIdToDelete)
[organizationPostIdToDelete, req.jwt.person_id])){ .where('OrganizationAdministrator.id_person', req.jwt.person_id)
await db.none('DELETE FROM "OrganizationPost" WHERE id = $1', [organizationPostIdToDelete]); .select('*')
return res.status(200).json("Ok"); .first();
}
else{ if (result) {
return res.status(403).json("Forbidden"); await trx('OrganizationPost')
} .where('id', organizationPostIdToDelete)
.del();
await trx.commit();
return res.status(200).json('Ok');
} else {
return res.status(401).json('Forbidden');
}
});
} }
catch (error) { catch (error) {
console.error(error); console.log(error);
return res.status(500).json("Internal server error"); res.status(500).json("Internal server error");
} }
} }
// POST [NOT COMPLETE]
async function makeAdmin(req, res){
}
// ======== END API ENDPOINTS ======== // ======== END API ENDPOINTS ========
async function checkUserCredentials(email, password){ async function checkUserCredentials(email, password){
try { try {
const user = await db.oneOrNone('SELECT * FROM "Person" WHERE email = $1 and enabled = $2', [email, true]); const user = await knex('Person')
.where('email', email)
.where('enabled', true)
.select('*')
.first();
if(user){ if(user){
const passwordMatches = await bcrypt.compare(password, user.password); const passwordMatches = await bcrypt.compare(password, user.password);
if (passwordMatches) { if (passwordMatches) {
@ -260,11 +261,19 @@ async function checkUserCredentials(email, password){
} }
async function isPersonOrganizationAdmin(personId, organizationId){ async function isPersonOrganizationAdmin(personId, organizationId){
try { try {
if(await db.oneOrNone('SELECT * FROM "OrganizationAdministrator" WHERE id_person = $1 AND id_organization = $2', [personId, organizationId])){ const organizationAdministrator = await knex('OrganizationAdministrator')
.where('id_person', personId)
.where('id_organization', organizationId)
.select('*')
.first(); // Retrieve the first matching row
if (organizationAdministrator) {
return true; return true;
}
else {
return false;
} }
return false;
} }
catch (error) { catch (error) {
return false; return false;
@ -310,5 +319,6 @@ module.exports = {
createOrganization, createOrganization,
deleteOrganization, deleteOrganization,
createOrganizationPost, createOrganizationPost,
deleteOrganizationPost deleteOrganizationPost,
makeAdmin
}; };