mirror of
https://github.com/xfarrow/blink
synced 2025-03-25 12:50:07 +01:00
322 lines
8.4 KiB
JavaScript
322 lines
8.4 KiB
JavaScript
/*
|
|
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.
|
|
*/
|
|
|
|
require('dotenv').config();
|
|
const bcrypt = require('bcrypt');
|
|
const crypto = require('crypto');
|
|
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');
|
|
|
|
// ======== API ENDPOINTS ========
|
|
|
|
// POST
|
|
async function registerPerson(req, res){
|
|
|
|
if (process.env.ALLOW_USER_REGISTRATION === 'false'){
|
|
return res.status(403).json({error : "Users cannot register on this server"});
|
|
}
|
|
|
|
// Ensure that the required fields are present before proceeding
|
|
if (!req.body.display_name || !req.body.email || !req.body.password) {
|
|
return res.status(400).json("Invalid request.");
|
|
}
|
|
|
|
// Generate activation link token
|
|
const activationLink = crypto.randomBytes(16).toString('hex');
|
|
|
|
// Hash provided password
|
|
const hashPasswordPromise = bcrypt.hash(req.body.password, 10);
|
|
|
|
try{
|
|
// Begin transaction
|
|
await knex.transaction(async (tr) => {
|
|
|
|
const personIdResult = await tr('Person')
|
|
.insert({
|
|
email: req.body.email,
|
|
password: await hashPasswordPromise,
|
|
display_name: req.body.display_name,
|
|
date_of_birth: req.body.date_of_birth,
|
|
available: req.body.available,
|
|
enabled: true,
|
|
place_of_living: req.body.place_of_living
|
|
})
|
|
.returning("id");
|
|
|
|
await tr('ActivationLink')
|
|
.insert({
|
|
person_id: personIdResult[0].id,
|
|
identifier: activationLink
|
|
});
|
|
});
|
|
return res.status(200).json({ activationLink: activationLink });
|
|
}
|
|
catch (error){
|
|
console.error('Error inserting data:', error);
|
|
res.status(500).json("Internal server error");
|
|
}
|
|
}
|
|
|
|
// POST
|
|
async function login(req, res){
|
|
// Ensure that the required fields are present before proceeding
|
|
if (!req.body.email || !req.body.password) {
|
|
return res.status(400).json("Invalid request");
|
|
}
|
|
|
|
const person = await checkUserCredentials(req.body.email, req.body.password);
|
|
|
|
if (person){
|
|
const token = generateToken(person.id);
|
|
res.status(200).json({ token });
|
|
}
|
|
else{
|
|
res.status(401).json("Unauthorized");
|
|
}
|
|
}
|
|
|
|
// GET
|
|
async function getPerson(req, res){
|
|
try {
|
|
const user = await knex('Person')
|
|
.select('*')
|
|
.where({ id: req.params.id, enabled: true })
|
|
.first();
|
|
|
|
if(user){
|
|
if(user.id == req.jwt.person_id || user.enabled){
|
|
return res.status(200).send(user);
|
|
}
|
|
}
|
|
return res.status(403).json("Forbidden");
|
|
}
|
|
catch (error) {
|
|
console.log(error);
|
|
return res.status(500).json("Internal server error");
|
|
}
|
|
}
|
|
|
|
// POST
|
|
async function createOrganization(req, res){
|
|
|
|
// Ensure that the required fields are present before proceeding
|
|
if (!req.body.name) {
|
|
return res.status(400).json("Invalid request.");
|
|
}
|
|
|
|
try{
|
|
knex.transaction(async (trx) => {
|
|
const organizationResult = await trx('Organization')
|
|
.insert({
|
|
name: req.body.name,
|
|
location: req.body.location,
|
|
description: req.body.description,
|
|
is_hiring: req.body.is_hiring,
|
|
})
|
|
.returning('*');
|
|
|
|
// Inserting in the "OrganizationAdministrator" table
|
|
await trx('OrganizationAdministrator')
|
|
.insert({
|
|
id_person: req.jwt.person_id,
|
|
id_organization: organizationResult[0].id,
|
|
});
|
|
|
|
await trx.commit();
|
|
|
|
return res.status(200).json({ Organization: organizationResult[0] });
|
|
});
|
|
}
|
|
catch (error){
|
|
console.error('Error inserting data:', error);
|
|
res.status(500).json("Internal server error");
|
|
}
|
|
}
|
|
|
|
// DELETE
|
|
async function deleteOrganization(req, res){
|
|
const organizationIdToDelete = req.params.id;
|
|
|
|
try {
|
|
if(await isPersonOrganizationAdmin(req.jwt.person_id, organizationIdToDelete)){
|
|
await knex('Organization')
|
|
.where({ id: organizationIdToDelete })
|
|
.del();
|
|
return res.status(200).json("Ok");
|
|
}
|
|
return res.status(403).json("Forbidden");
|
|
}
|
|
catch (error) {
|
|
console.error(error);
|
|
return res.status(500).json("Internal server error");
|
|
}
|
|
}
|
|
|
|
// POST
|
|
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("Invalid request.");
|
|
}
|
|
|
|
try {
|
|
if (await isPersonOrganizationAdmin(req.jwt.person_id, req.body.organization_id)){
|
|
const organizationPost = await knex('OrganizationPost')
|
|
.insert({
|
|
organization_id: req.body.organization_id,
|
|
content: req.body.content,
|
|
})
|
|
.returning('*');
|
|
return res.status(200).json(organizationPost[0]);
|
|
}
|
|
else{
|
|
return res.status(401).json("Forbidden");
|
|
}
|
|
}
|
|
catch (error) {
|
|
console.log(error);
|
|
return res.status(500).json("Internal server error");
|
|
}
|
|
}
|
|
|
|
// DELETE
|
|
async function deleteOrganizationPost(req, res){
|
|
const organizationPostIdToDelete = req.params.id;
|
|
try{
|
|
knex.transaction(async (trx) => {
|
|
// Check if user is allowed to delete the post
|
|
const result = await trx('OrganizationPost')
|
|
.join('OrganizationAdministrator', 'OrganizationPost.organization_id', 'OrganizationAdministrator.id_organization')
|
|
.where('OrganizationPost.id', organizationPostIdToDelete)
|
|
.where('OrganizationAdministrator.id_person', req.jwt.person_id)
|
|
.select('*')
|
|
.first();
|
|
|
|
if (result) {
|
|
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) {
|
|
console.log(error);
|
|
res.status(500).json("Internal server error");
|
|
}
|
|
}
|
|
|
|
// POST [NOT COMPLETE]
|
|
async function makeAdmin(req, res){
|
|
|
|
}
|
|
|
|
// ======== END API ENDPOINTS ========
|
|
|
|
async function checkUserCredentials(email, password){
|
|
try {
|
|
const user = await knex('Person')
|
|
.where('email', email)
|
|
.where('enabled', true)
|
|
.select('*')
|
|
.first();
|
|
|
|
if(user){
|
|
const passwordMatches = await bcrypt.compare(password, user.password);
|
|
if (passwordMatches) {
|
|
return user;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
catch (error) {
|
|
console.log(error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async function isPersonOrganizationAdmin(personId, organizationId){
|
|
try {
|
|
const organizationAdministrator = await knex('OrganizationAdministrator')
|
|
.where('id_person', personId)
|
|
.where('id_organization', organizationId)
|
|
.select('*')
|
|
.first();
|
|
|
|
if (organizationAdministrator) {
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
catch (error) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function generateToken(person_id) {
|
|
const payload = {
|
|
person_id: person_id
|
|
};
|
|
|
|
const token = jwt.sign(payload, 'your-secret-key', { expiresIn: '1h' });
|
|
return token;
|
|
}
|
|
|
|
// Middlware
|
|
function verifyToken(req, res, next) {
|
|
const token = req.headers.authorization;
|
|
|
|
if (!token) {
|
|
return res.status(403).send('No token provided');
|
|
}
|
|
|
|
jwt.verify(token, 'your-secret-key', (err, decoded) => {
|
|
if (err) {
|
|
return res.status(401).send('Failed to authenticate token');
|
|
}
|
|
|
|
// If the token is valid, store the decoded data in the request object
|
|
req.jwt = decoded;
|
|
next();
|
|
});
|
|
}
|
|
|
|
// Exporting a function
|
|
// means making a JavaScript function defined in one
|
|
// module available for use in another module.
|
|
module.exports = {
|
|
registerPerson,
|
|
login,
|
|
getPerson,
|
|
verifyToken,
|
|
createOrganization,
|
|
deleteOrganization,
|
|
createOrganizationPost,
|
|
deleteOrganizationPost,
|
|
makeAdmin
|
|
}; |