fix(loads): Normalize dates on post and patch (remove time from dates)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
const { getModel } = require( '../../../lib/Models' );
|
const { getModel } = require( '../../../lib/Models' );
|
||||||
const { getPagination, genKey } = require( '../../../lib/Misc.js' );
|
const { getPagination, genKey, normalizeDate } = require( '../../../lib/Misc.js' );
|
||||||
const { GenericHandler } = require( '../../../lib/Handlers/Generic.handler.js' );
|
const { GenericHandler } = require( '../../../lib/Handlers/Generic.handler.js' );
|
||||||
const { onPatchEvent } = require('../../../lib/Handlers/Loads.handler');
|
const { onPatchEvent } = require('../../../lib/Handlers/Loads.handler');
|
||||||
const Model = getModel('loads');
|
const Model = getModel('loads');
|
||||||
@@ -275,6 +275,25 @@ const getById = async(req, res) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function normalizeDatesFromData( data ){
|
||||||
|
let fields2normalize = [
|
||||||
|
"contract_start_date",
|
||||||
|
"contract_end_date",
|
||||||
|
"est_loading_date",
|
||||||
|
"est_unloading_date",
|
||||||
|
"published_date",
|
||||||
|
"loaded_date",
|
||||||
|
"transit_date",
|
||||||
|
"delivered_date",
|
||||||
|
];
|
||||||
|
for( const item of fields2normalize ){
|
||||||
|
if( Object.hasOwn( data, item ) ){
|
||||||
|
data[ item ] = normalizeDate( data[ item ] )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
function getDataToModify( data ){
|
function getDataToModify( data ){
|
||||||
/**
|
/**
|
||||||
* Take the only fields from model that
|
* Take the only fields from model that
|
||||||
@@ -329,7 +348,7 @@ function getDataToModify( data ){
|
|||||||
throw "nothing to change";
|
throw "nothing to change";
|
||||||
}
|
}
|
||||||
|
|
||||||
return filtered_data;
|
return normalizeDatesFromData( filtered_data );
|
||||||
}
|
}
|
||||||
const patchLoad = async(req, res) => {
|
const patchLoad = async(req, res) => {
|
||||||
try{
|
try{
|
||||||
@@ -357,23 +376,92 @@ const patchLoad = async(req, res) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getDataToCreate( data ){
|
||||||
|
/**
|
||||||
|
* Take the only fields from model that
|
||||||
|
* should be modifiable by the client.
|
||||||
|
* The rest are populated on demand by the event handlers.
|
||||||
|
*/
|
||||||
|
let data_fields = {
|
||||||
|
carrier: null,
|
||||||
|
vehicle: null,
|
||||||
|
driver: null,
|
||||||
|
bidder: null,
|
||||||
|
alert_list: null,
|
||||||
|
origin_warehouse: null,
|
||||||
|
destination_warehouse: null,
|
||||||
|
origin: null,
|
||||||
|
origin_geo: null,
|
||||||
|
destination: null,
|
||||||
|
destination_geo: null,
|
||||||
|
categories: null,
|
||||||
|
product: null,
|
||||||
|
truck_type: null,
|
||||||
|
tyre_type: null,
|
||||||
|
weight: null,
|
||||||
|
estimated_cost: null,
|
||||||
|
distance: null,
|
||||||
|
actual_cost: null,
|
||||||
|
status: null,
|
||||||
|
load_status: null,
|
||||||
|
contract_start_date: null,
|
||||||
|
contract_end_date: null,
|
||||||
|
est_loading_date: null,
|
||||||
|
est_unloading_date: null,
|
||||||
|
published_date: null,
|
||||||
|
loaded_date: null,
|
||||||
|
transit_date: null,
|
||||||
|
delivered_date: null,
|
||||||
|
notes: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
let filtered_data = {};
|
||||||
|
|
||||||
|
if( Object.keys( data_fields ).length === 0 ){
|
||||||
|
throw "no data to add";
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( const [key, value] of Object.entries( data_fields ) ) {
|
||||||
|
if( Object.hasOwn( data, key ) ){
|
||||||
|
filtered_data[ key ] = data[ key ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Object.keys( filtered_data ).length === 0 ){
|
||||||
|
throw "no data to add";
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalizeDatesFromData( filtered_data );
|
||||||
|
}
|
||||||
const postLoad = async(req, res) => {
|
const postLoad = async(req, res) => {
|
||||||
try{
|
try{
|
||||||
const companyId = req.context.companyId;
|
const companyId = req.context.companyId;
|
||||||
const userId = req.context.userId;
|
const userId = req.context.userId;
|
||||||
const user_name = req.context.user.first_name;
|
let user_name;
|
||||||
|
|
||||||
|
if( req.context.user.last_name ){
|
||||||
|
user_name = `${req.context.user.first_name} ${req.context.user.last_name}`;
|
||||||
|
}else{
|
||||||
|
user_name = req.context.user.first_name;
|
||||||
|
}
|
||||||
|
|
||||||
const permissions = req.context.permissions;
|
const permissions = req.context.permissions;
|
||||||
const data = req.body;
|
|
||||||
if( !data ){
|
if( !req.body ){
|
||||||
throw "Load data not sent";
|
throw "Load data not sent";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(permissions !== "role_shipper" ){
|
if(permissions !== "role_shipper" ){
|
||||||
throw "You can't create loads";
|
throw "You can't create loads";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const data = getDataToCreate( req.body );
|
||||||
|
|
||||||
data.company = companyId;
|
data.company = companyId;
|
||||||
data.posted_by = userId;
|
data.posted_by = userId;
|
||||||
data.name = user_name;
|
data.posted_by_name = user_name;
|
||||||
const load = new Model( data );/// ToDo, check data content and normalize Dates!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
||||||
|
const load = new Model( data );
|
||||||
await load.save();
|
await load.save();
|
||||||
|
|
||||||
const id = "" + load._id;
|
const id = "" + load._id;
|
||||||
|
|||||||
@@ -16,9 +16,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"version" : {
|
"version" : {
|
||||||
"version" : "1.5.1",
|
"version" : "1.5.2",
|
||||||
"name": "ETA Beta",
|
"name": "ETA Beta",
|
||||||
"date":"06/2025"
|
"date":"21/07/2025"
|
||||||
},
|
},
|
||||||
"S3" : {
|
"S3" : {
|
||||||
"bucket": "etaviaporte",
|
"bucket": "etaviaporte",
|
||||||
|
|||||||
@@ -12,11 +12,18 @@ const proposalsModel = getModel('proposals');
|
|||||||
*/
|
*/
|
||||||
async function onDelivered( userId, elementId ){
|
async function onDelivered( userId, elementId ){
|
||||||
const load = await loadsModel.findById( elementId );
|
const load = await loadsModel.findById( elementId );
|
||||||
|
|
||||||
|
if( !load ){
|
||||||
|
/// Nothing to do, invalid load
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const proposal_list = await proposalsModel.find({
|
const proposal_list = await proposalsModel.find({
|
||||||
load: elementId,
|
load: elementId,
|
||||||
is_accepted: true,
|
is_accepted: true,
|
||||||
is_completed: false
|
is_completed: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const vehicle_list = await vehiclesModel.find({
|
const vehicle_list = await vehiclesModel.find({
|
||||||
active_load: elementId
|
active_load: elementId
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -39,6 +39,19 @@ function genKey( len = 6, key="" ){
|
|||||||
return otp_str.slice(0,len);
|
return otp_str.slice(0,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a datetime input and produces a date only output.
|
||||||
|
* @param {*} date
|
||||||
|
*/
|
||||||
|
function normalizeDate( date ){
|
||||||
|
let in_date = new Date( date );
|
||||||
|
let year = in_date.getFullYear();
|
||||||
|
let monthIndex = in_date.getMonth();
|
||||||
|
let day = in_date.getDate();
|
||||||
|
// new Date(year, monthIndex, day, hours, minutes, seconds, milliseconds);
|
||||||
|
return new Date( year, monthIndex, day, 0, 0, 0, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
function getPagination( query ){
|
function getPagination( query ){
|
||||||
let limit = {
|
let limit = {
|
||||||
page : 0,
|
page : 0,
|
||||||
@@ -101,4 +114,4 @@ async function downloadFile( bucket, key, obj_id ){
|
|||||||
return s3resp;
|
return s3resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { genKey , toSha256, getPagination, getPage, queryPage, downloadFile};
|
module.exports = { genKey , toSha256, normalizeDate, getPagination, getPage, queryPage, downloadFile};
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# Use an official Python runtime as a parent image
|
|
||||||
FROM node:18-alpine
|
|
||||||
|
|
||||||
# Set the working directory to /app
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Copy the current directory contents into the container at /app
|
|
||||||
COPY server /app/server
|
|
||||||
COPY package.json /app
|
|
||||||
COPY dotenv /app/.env
|
|
||||||
|
|
||||||
RUN apk add bash bash-completion vim
|
|
||||||
RUN npm install --include=dev
|
|
||||||
|
|
||||||
EXPOSE 3000
|
|
||||||
|
|
||||||
ENTRYPOINT npm start
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "etaapi",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "ETA API",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"start": "nodemon server/src/",
|
|
||||||
"dev": "nodemon server/src/",
|
|
||||||
"test": "mocha test/lib/handlers/proposals"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://gitlab.com/jcruzbaasworkspace/enruta/etaapi.git"
|
|
||||||
},
|
|
||||||
"author": "Josepablo C.",
|
|
||||||
"license": "ISC",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://gitlab.com/jcruzbaasworkspace/enruta/etaapi/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://gitlab.com/jcruzbaasworkspace/enruta/etaapi#readme",
|
|
||||||
"dependencies": {
|
|
||||||
"@aws-sdk/client-s3": "^3.427.0",
|
|
||||||
"audit": "^0.0.6",
|
|
||||||
"axios": "^1.5.1",
|
|
||||||
"body-parser": "^1.20.2",
|
|
||||||
"compression": "^1.7.4",
|
|
||||||
"cors": "^2.8.5",
|
|
||||||
"crypto-js": "^4.1.1",
|
|
||||||
"dotenv": "^16.3.1",
|
|
||||||
"express": "^4.19.2",
|
|
||||||
"express-fileupload": "^1.4.1",
|
|
||||||
"express-jwt": "^8.4.1",
|
|
||||||
"form-data": "^4.0.0",
|
|
||||||
"graphql": "^16.9.0",
|
|
||||||
"graphql-http": "^1.22.1",
|
|
||||||
"graphql-scalars": "^1.23.0",
|
|
||||||
"helmet": "^7.0.0",
|
|
||||||
"jsonschema": "^1.4.1",
|
|
||||||
"jsonwebtoken": "^9.0.2",
|
|
||||||
"knex": "^2.5.1",
|
|
||||||
"mongodb-core": "^3.2.7",
|
|
||||||
"mongoose": "^7.5.4",
|
|
||||||
"morgan": "^1.10.0",
|
|
||||||
"mysql": "^2.18.1",
|
|
||||||
"nodemailer": "^6.9.5",
|
|
||||||
"nodemailer-sendgrid": "^1.0.3",
|
|
||||||
"nodemon": "^3.0.1",
|
|
||||||
"objection": "^3.1.4",
|
|
||||||
"uuid": "^9.0.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"chai": "^5.1.0",
|
|
||||||
"mocha": "^10.3.0",
|
|
||||||
"sinon": "^17.0.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
#! /bin/bash
|
|
||||||
|
|
||||||
REGISTRY_USER="jcruzbaas@gmail.com"
|
|
||||||
REGISTRY_NAME="registry.gitlab.com/jcruzbaasworkspace/enruta"
|
|
||||||
REGISTRY_SERVER="registry.gitlab.com"
|
|
||||||
CONTAINER_VERSION="2"
|
|
||||||
|
|
||||||
# Requirements
|
|
||||||
# Docker: Node v18-alpine
|
|
||||||
function build_docker(){
|
|
||||||
#Global ENV VAR: REGISTRY_NAME
|
|
||||||
#Global ENV VAR: CONTAINER_NAME
|
|
||||||
if [[ $# -lt 1 ]]; then
|
|
||||||
echo $0 "[conatiner name]"
|
|
||||||
return -1
|
|
||||||
fi
|
|
||||||
CONTAINER_NAME=$1
|
|
||||||
|
|
||||||
set -x
|
|
||||||
docker rmi -f "$REGISTRY_NAME/$CONTAINER_NAME"
|
|
||||||
docker buildx build --no-cache -t $REGISTRY_NAME/$CONTAINER_NAME ./
|
|
||||||
set +x
|
|
||||||
}
|
|
||||||
|
|
||||||
function upload_image(){
|
|
||||||
#Global ENV VAR: REGISTRY_NAME
|
|
||||||
#Global ENV VAR: GITLAB_CICD_REGISTRY_TOKEN
|
|
||||||
#Global ENV VAR: CONTAINER_NAME
|
|
||||||
docker login $REGISTRY_SERVER -u "$REGISTRY_USER" -p "$GITLAB_CICD_REGISTRY_TOKEN"
|
|
||||||
set -x
|
|
||||||
docker push "$REGISTRY_NAME/$CONTAINER_NAME":$CONTAINER_VERSION
|
|
||||||
set +x
|
|
||||||
}
|
|
||||||
|
|
||||||
function deploy_uservice(){
|
|
||||||
# CONTAINER NAME
|
|
||||||
# PUBLIC PORT
|
|
||||||
# PRIVATE PORT
|
|
||||||
# ECR REPO
|
|
||||||
if [[ $# -lt 4 ]]; then
|
|
||||||
echo "$0 [container_name] [public port] [private port] [ecr_repo]"
|
|
||||||
return -1
|
|
||||||
fi
|
|
||||||
container_name=$1
|
|
||||||
public_port=$2
|
|
||||||
private_port=$3
|
|
||||||
ecr_repo=$4
|
|
||||||
|
|
||||||
docker stop $container_name && docker rm $container_name
|
|
||||||
docker run -p"$public_port:$private_port" -d --restart unless-stopped --name $container_name $ecr_repo/$container_name:$CONTAINER_VERSION
|
|
||||||
}
|
|
||||||
|
|
||||||
function deploy_local(){
|
|
||||||
# docker login --username $AWS_ECR_USER --password $DOCKER_PWD $REGISTRY_NAME
|
|
||||||
deploy_uservice $CONTAINER_NAME $PUBLIC_PORT $PRIVATE_PORT $REGISTRY_NAME
|
|
||||||
}
|
|
||||||
|
|
||||||
function deploy(){
|
|
||||||
# Global ENV VAR: GITLAB_CICD_REGISTRY_TOKEN
|
|
||||||
# Global Env Var: REGISTRY_NAME
|
|
||||||
# Global Env Var: REGISTRY_USER
|
|
||||||
# Global Env Var: CONTAINER_NAME
|
|
||||||
# Global Env Var: PUBLIC_PORT
|
|
||||||
# Global Env Var: PRIVATE_PORT
|
|
||||||
# Global Env Var: SYSTEM_HOSTNAME
|
|
||||||
set -x
|
|
||||||
ssh -i ~/.ssh/gitlab_runner gitlab-runner@$SYSTEM_HOSTNAME "docker login $REGISTRY_SERVER --username $REGISTRY_USER --password $GITLAB_CICD_REGISTRY_TOKEN $REGISTRY_NAME && ./deploy_uservice.sh $CONTAINER_NAME $PUBLIC_PORT $PRIVATE_PORT $REGISTRY_NAME && exit"
|
|
||||||
set +x
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# REST API Framework
|
|
||||||
|
|
||||||
## Architecture Design
|
|
||||||
|
|
||||||

|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
{
|
|
||||||
"authentication": {
|
|
||||||
"pwdSecret":"Nx2g_IWo2Zt_LS$+",
|
|
||||||
"jwtSecret":"9o3BBz0EsrwXXiwEJ/SFuywZoN8=",
|
|
||||||
"jwtTimeout":24,
|
|
||||||
"jwtRenewalTimeout":720,
|
|
||||||
"tokenSecret":"9Z'jMt|(h_f(&/S+zv.K",
|
|
||||||
"jwtOptions": {
|
|
||||||
"header": {
|
|
||||||
"typ": "access"
|
|
||||||
},
|
|
||||||
"audience": "https://www.etaviaporte.com",
|
|
||||||
"issuer": "etaviaporte",
|
|
||||||
"algorithm": "HS256",
|
|
||||||
"expiresIn": "1d"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"version" : {
|
|
||||||
"version" : "2.0.0",
|
|
||||||
"name": "ETA Beta",
|
|
||||||
"date":"08/2024"
|
|
||||||
},
|
|
||||||
"S3" : {
|
|
||||||
"accessKeyId": "AKIAXTQEUF6MLCHTUIKW",
|
|
||||||
"secretAccessKey": "QhM8gQ5O3hVDIf41YeO5/A6Wo58D1xQz8pzxBB2W",
|
|
||||||
"bucket": "enruta",
|
|
||||||
"load_attachments_key":"loadattachments",
|
|
||||||
"news_key":"news",
|
|
||||||
"region": "us-west-1"
|
|
||||||
},
|
|
||||||
"sendgrid" : {
|
|
||||||
"HOST": "smtp.sendgrid.net",
|
|
||||||
"PORT": "465",
|
|
||||||
"username": "apikey",
|
|
||||||
"API_KEY": "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",
|
|
||||||
"FROM": "noreply@etaviaporte.com"
|
|
||||||
},
|
|
||||||
"email_standalone" : {
|
|
||||||
"host": "smtp.hostinger.com",
|
|
||||||
"port": "465",
|
|
||||||
"secure": true,
|
|
||||||
"auth": {
|
|
||||||
"user": "noreply@etaviaporte.com",
|
|
||||||
"pass": "-)WJt[oP~P$`76Q4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mongodb": "mongodb+srv://enruta_admin:NeptFx4RUZG8OsfA@enruta.vwofshy.mongodb.net/enrutaviaporte?retryWrites=true&w=majority",
|
|
||||||
"sql":{
|
|
||||||
"host":"srv765.hstgr.io",
|
|
||||||
"port":3306,
|
|
||||||
"user":"u947463964_sysadmin",
|
|
||||||
"password":"3^K/47^h5pP",
|
|
||||||
"database":"u947463964_etaviaporte"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
<mxfile host="app.diagrams.net" modified="2024-04-12T18:18:19.489Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0" etag="IcOi7BUkbZV7L-Fstefg" version="24.2.3" type="device">
|
|
||||||
<diagram name="Page-1" id="TZpYyL79LOodfNr5sDYv">
|
|
||||||
<mxGraphModel dx="1656" dy="1032" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="850" math="0" shadow="0">
|
|
||||||
<root>
|
|
||||||
<mxCell id="0" />
|
|
||||||
<mxCell id="1" parent="0" />
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-5" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="80" y="540" width="720" height="130" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-1" value="<div>Connections</div>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="180" y="590" width="160" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-2" value="Controller (ExpressJS)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="540" y="590" width="160" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-3" value="EventManager" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="360" y="590" width="160" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-6" value="<div>SystemServices</div>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="97.5" y="560" width="100" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-8" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="80" y="400" width="400" height="130" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-10" value="Resources" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="280" y="450" width="180" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-9" value="Shared" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="97.5" y="420" width="87.5" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-11" value="Models" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="97.5" y="450" width="172.5" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-12" value="Controller (Router)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="490" y="400" width="310" height="130" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-14" value="entry_point with safe exit events" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="80" y="680" width="720" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-17" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="pRzEEGsYkG0vH22XolYE-2" target="pRzEEGsYkG0vH22XolYE-12">
|
|
||||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
|
||||||
<mxPoint x="510" y="550" as="sourcePoint" />
|
|
||||||
<mxPoint x="560" y="500" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-18" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="80" y="90" width="720" height="300" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-19" value="Controller" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#333333;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="662.5" y="290" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-20" value="" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="232.5" y="270" width="420" height="100" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-21" value="Domain" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="97.5" y="150" width="690" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-22" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="pRzEEGsYkG0vH22XolYE-12" target="pRzEEGsYkG0vH22XolYE-19">
|
|
||||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
|
||||||
<mxPoint x="510" y="540" as="sourcePoint" />
|
|
||||||
<mxPoint x="560" y="490" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-23" value="Application" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="102.5" y="110" width="80" height="30" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-24" value="Repository" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;fontColor=#333333;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="102.5" y="290" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-25" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="pRzEEGsYkG0vH22XolYE-19" target="pRzEEGsYkG0vH22XolYE-21">
|
|
||||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
|
||||||
<mxPoint x="542.5" y="530" as="sourcePoint" />
|
|
||||||
<mxPoint x="592.5" y="480" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-27" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="pRzEEGsYkG0vH22XolYE-21" target="pRzEEGsYkG0vH22XolYE-20">
|
|
||||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
|
||||||
<mxPoint x="542.5" y="530" as="sourcePoint" />
|
|
||||||
<mxPoint x="592.5" y="480" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-28" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="pRzEEGsYkG0vH22XolYE-21" target="pRzEEGsYkG0vH22XolYE-24">
|
|
||||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
|
||||||
<mxPoint x="542.5" y="530" as="sourcePoint" />
|
|
||||||
<mxPoint x="592.5" y="480" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-29" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="pRzEEGsYkG0vH22XolYE-24" target="pRzEEGsYkG0vH22XolYE-11">
|
|
||||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
|
||||||
<mxPoint x="510" y="530" as="sourcePoint" />
|
|
||||||
<mxPoint x="90" y="340" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-30" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="pRzEEGsYkG0vH22XolYE-3" target="pRzEEGsYkG0vH22XolYE-10">
|
|
||||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
|
||||||
<mxPoint x="510" y="520" as="sourcePoint" />
|
|
||||||
<mxPoint x="560" y="470" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-32" value="Public" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="252.5" y="290" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-33" value="Interfaces" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="382.5" y="290" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-34" value="Events" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;fontColor=#333333;strokeColor=#666666;" vertex="1" parent="1">
|
|
||||||
<mxGeometry x="512.5" y="290" width="120" height="60" as="geometry" />
|
|
||||||
</mxCell>
|
|
||||||
<mxCell id="pRzEEGsYkG0vH22XolYE-35" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="pRzEEGsYkG0vH22XolYE-34" target="pRzEEGsYkG0vH22XolYE-10">
|
|
||||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
|
||||||
<mxPoint x="450" y="480" as="sourcePoint" />
|
|
||||||
<mxPoint x="500" y="430" as="targetPoint" />
|
|
||||||
</mxGeometry>
|
|
||||||
</mxCell>
|
|
||||||
</root>
|
|
||||||
</mxGraphModel>
|
|
||||||
</diagram>
|
|
||||||
</mxfile>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 60 KiB |
@@ -1,169 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const Application = require('../Domain');
|
|
||||||
|
|
||||||
function dummy_middleware( req, res, next ){
|
|
||||||
return res.status(500).send({ error:"Not implemented yet" });
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Block access to the next list of endpoints if JWT is not valid
|
|
||||||
async function access_control_with_jwt( req, res, next){
|
|
||||||
if( ! req.JWT?.isValid ){
|
|
||||||
return res.status(401).send({error:"Unauthorized",code:401});
|
|
||||||
}
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function authorize(req, res, next) {
|
|
||||||
try{
|
|
||||||
const email = req.body.email;
|
|
||||||
const password = req.body.password;
|
|
||||||
const data = await Application.authorize_credentials( email , password );
|
|
||||||
if( data.error ){
|
|
||||||
const error = data.error;
|
|
||||||
return res.status( error.code ).send( { error : error.msg } );
|
|
||||||
}
|
|
||||||
return res.send( data );
|
|
||||||
}catch(error){
|
|
||||||
console.error( error );
|
|
||||||
return res.status( 500 ).send( { error } );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function refresh_session(req, res, next) {
|
|
||||||
try{
|
|
||||||
const session_token = req.params.session_token;
|
|
||||||
const data = await Application.authorize_token( session_token );
|
|
||||||
if( data.error ){
|
|
||||||
const error = data.error;
|
|
||||||
return res.status( error.code ).send( { error : error.msg } );
|
|
||||||
}
|
|
||||||
return res.send( data );
|
|
||||||
}catch(error){
|
|
||||||
console.error( error );
|
|
||||||
return res.status( 500 ).send( { error } );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function check_account(req, res, next){
|
|
||||||
try{
|
|
||||||
const email = req.params.email;
|
|
||||||
const data = await Application.check_account( email );
|
|
||||||
if( data.error ){
|
|
||||||
const error = data.error;
|
|
||||||
return res.status( error.code ).send( { error : error.msg } );
|
|
||||||
}
|
|
||||||
return res.send( data );
|
|
||||||
}catch(error){
|
|
||||||
console.error( error );
|
|
||||||
return res.status( 500 ).send( { error } );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function post_signup(req, res, next) {
|
|
||||||
try{
|
|
||||||
const email = req.body.email;
|
|
||||||
const password = req.body.password;
|
|
||||||
const data = await Application.genOTPChecksum( email, password, "signup" );
|
|
||||||
if( data.error ){
|
|
||||||
const error = data.error;
|
|
||||||
return res.status( error.code ).send( { error : error.msg } );
|
|
||||||
}
|
|
||||||
return res.send( data );
|
|
||||||
}catch(error){
|
|
||||||
console.error( error );
|
|
||||||
return res.status( 500 ).send( { error } );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function patch_signup(req, res, next) {
|
|
||||||
try{
|
|
||||||
const email = req.body.email;
|
|
||||||
const password = req.body.password;
|
|
||||||
const otp = req.body.otp;
|
|
||||||
const checksum = req.body.checksum;
|
|
||||||
const data = await Application.signup( email , password, otp, checksum);
|
|
||||||
if( data.error ){
|
|
||||||
const error = data.error;
|
|
||||||
return res.status( error.code ).send( { error : error.msg } );
|
|
||||||
}
|
|
||||||
return res.send( data );
|
|
||||||
}catch(error){
|
|
||||||
console.error( error );
|
|
||||||
return res.status( 500 ).send( { error } );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function post_recover(req, res, next){
|
|
||||||
try{
|
|
||||||
const email = req.body.email;
|
|
||||||
const password = req.body.password;
|
|
||||||
const data = await Application.genOTPChecksum( email, password, "recover" );
|
|
||||||
if( data.error ){
|
|
||||||
const error = data.error;
|
|
||||||
return res.status( error.code ).send( { error : error.msg } );
|
|
||||||
}
|
|
||||||
return res.send( data );
|
|
||||||
}catch(error){
|
|
||||||
console.error( error );
|
|
||||||
return res.status( 500 ).send( { error } );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function patch_recover(req, res, next){
|
|
||||||
try{
|
|
||||||
const email = req.body.email;
|
|
||||||
const password = req.body.password;
|
|
||||||
const otp = req.body.otp;
|
|
||||||
const checksum = req.body.checksum;
|
|
||||||
const data = await Application.recover( email , password, otp, checksum);
|
|
||||||
if( data.error ){
|
|
||||||
const error = data.error;
|
|
||||||
return res.status( error.code ).send( { error : error.msg } );
|
|
||||||
}
|
|
||||||
return res.send( data );
|
|
||||||
}catch(error){
|
|
||||||
console.error( error );
|
|
||||||
return res.status( 500 ).send( { error } );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function AppInit(){
|
|
||||||
Application.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
AppInit,
|
|
||||||
hooks : {
|
|
||||||
before: {
|
|
||||||
/**Array of middleware functions or objects lile { endpoint, middleware }*/
|
|
||||||
all : [],
|
|
||||||
del : [],
|
|
||||||
get : [],
|
|
||||||
patch : [],
|
|
||||||
post : [],
|
|
||||||
put : []
|
|
||||||
},
|
|
||||||
|
|
||||||
after: {
|
|
||||||
/**Array of middleware functions or objects lile { endpoint, middleware }*/
|
|
||||||
all : [
|
|
||||||
{ '/register': dummy_middleware }
|
|
||||||
],
|
|
||||||
del : [],
|
|
||||||
get : [
|
|
||||||
{ '/check-account/:email' : check_account },
|
|
||||||
{ '/authorize/:session_token': refresh_session }
|
|
||||||
],
|
|
||||||
patch : [
|
|
||||||
{ '/signup' : patch_signup },
|
|
||||||
{ '/recover' : patch_recover }
|
|
||||||
],
|
|
||||||
post : [
|
|
||||||
{ '/authorize' : authorize },
|
|
||||||
{ '/signup' : post_signup },
|
|
||||||
{ '/recover' : post_recover }
|
|
||||||
],
|
|
||||||
put : []
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const { hooks, AppInit } = require( './hooks' );
|
|
||||||
const GenericController = require('../../Lib');
|
|
||||||
|
|
||||||
class Account extends GenericController {
|
|
||||||
init(){
|
|
||||||
super.init();
|
|
||||||
AppInit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new Account( hooks );
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const Repository = require('../Repository');
|
|
||||||
const jsonwebtoken = require('jsonwebtoken');
|
|
||||||
const { ModuleName,
|
|
||||||
toSha256,
|
|
||||||
publishEvent,
|
|
||||||
registerEvent,
|
|
||||||
jwtRenewalTimeout,
|
|
||||||
jwtTimeout,
|
|
||||||
jwtOptions,
|
|
||||||
jwtSecret,
|
|
||||||
tokenSecret,
|
|
||||||
pwdSecret,
|
|
||||||
genErrorResponse } = require('../Interfaces');
|
|
||||||
|
|
||||||
|
|
||||||
class Account {
|
|
||||||
constructor(){
|
|
||||||
this.Events = {
|
|
||||||
/** Event_Id : callback */
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
init(){
|
|
||||||
/// Setup application events
|
|
||||||
const Events = this.Events;
|
|
||||||
for ( const [event, callback] of Object.entries( Events ) ) {
|
|
||||||
const event_id = ModuleName + event
|
|
||||||
Interfaces.registerEvent( event_id , callback );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
genOTP( email ){
|
|
||||||
const len = 5;
|
|
||||||
const shacode = toSha256( email + new Date() + tokenSecret );
|
|
||||||
const otp_hex = shacode.slice(0 , len );
|
|
||||||
const otp_dec = Number.parseInt( otp_hex , 16 );
|
|
||||||
return ""+otp_dec;
|
|
||||||
}
|
|
||||||
|
|
||||||
genSafePassword( password ){
|
|
||||||
return toSha256( password + pwdSecret );
|
|
||||||
}
|
|
||||||
|
|
||||||
async check_account( email ){
|
|
||||||
const projection = ["id","email","password","company_id"];
|
|
||||||
const user = await Repository.getByEmail( email , projection );
|
|
||||||
const retVal = {
|
|
||||||
has_account:false,
|
|
||||||
isVerified:false,
|
|
||||||
has_password:false
|
|
||||||
};
|
|
||||||
|
|
||||||
if( !user ){
|
|
||||||
retVal.has_account = false;
|
|
||||||
retVal.isVerified = false;
|
|
||||||
retVal.has_password = false;
|
|
||||||
}else{
|
|
||||||
retVal.has_account = true;
|
|
||||||
retVal.isVerified = user.isVerified;
|
|
||||||
retVal.has_password = ( !user.password )? false : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
async genOTPChecksum( email, password, reason="signup" ){
|
|
||||||
let event_id = reason;
|
|
||||||
|
|
||||||
if( reason === "signup" ){
|
|
||||||
event_id = "getchecksum:signup";
|
|
||||||
|
|
||||||
const it_exists = await Repository.getByEmail( email );
|
|
||||||
if( it_exists ){
|
|
||||||
return genErrorResponse( "User already registered!" );
|
|
||||||
}
|
|
||||||
|
|
||||||
}else if( reason === "recover" ){
|
|
||||||
event_id = "getchecksum:recover";
|
|
||||||
}else{
|
|
||||||
return genErrorResponse( "OPT Event type not defined" , 500 );
|
|
||||||
}
|
|
||||||
|
|
||||||
const otp = this.genOTP( email );
|
|
||||||
|
|
||||||
const content = { OTP : otp, user_name : email, email };
|
|
||||||
|
|
||||||
const checksum_entry = {
|
|
||||||
email,
|
|
||||||
password,
|
|
||||||
otp
|
|
||||||
};
|
|
||||||
|
|
||||||
const checksum = toSha256( JSON.stringify(checksum_entry)).slice(0, 32);
|
|
||||||
|
|
||||||
publishEvent( event_id , content );
|
|
||||||
|
|
||||||
return { checksum };
|
|
||||||
}
|
|
||||||
|
|
||||||
async signup( email, password, otp, checksum ){
|
|
||||||
const it_exists = await Repository.getByEmail( email );
|
|
||||||
|
|
||||||
if( it_exists ){
|
|
||||||
return genErrorResponse( "User already registered!" );
|
|
||||||
}
|
|
||||||
|
|
||||||
const checksum_entry = {email, password, otp};
|
|
||||||
const recomputed_checksum = toSha256( JSON.stringify(checksum_entry)).slice(0, 32);
|
|
||||||
|
|
||||||
if( recomputed_checksum != checksum ){
|
|
||||||
return genErrorResponse( "Wrong OTP" );
|
|
||||||
}
|
|
||||||
|
|
||||||
await Repository.createOne( email, this.genSafePassword( password ) );
|
|
||||||
|
|
||||||
const content = { user_name : email, email };
|
|
||||||
|
|
||||||
publishEvent( "signupconfirmed" , content );
|
|
||||||
|
|
||||||
return await this.authorize_credentials( email, password );
|
|
||||||
}
|
|
||||||
|
|
||||||
async recover( email, password, otp, checksum ){
|
|
||||||
const user = await Repository.getByEmail( email );
|
|
||||||
|
|
||||||
if( !user ){
|
|
||||||
return genErrorResponse( "Email is not registered!" );
|
|
||||||
}
|
|
||||||
|
|
||||||
const checksum_entry = {email, password, otp};
|
|
||||||
const recomputed_checksum = toSha256( JSON.stringify(checksum_entry)).slice(0, 32);
|
|
||||||
|
|
||||||
if( recomputed_checksum != checksum ){
|
|
||||||
return genErrorResponse( "Wrong OTP" );
|
|
||||||
}
|
|
||||||
|
|
||||||
await Repository.updatePassword( user.id, this.genSafePassword( password ) );
|
|
||||||
|
|
||||||
return await this.authorize_credentials( email, password );
|
|
||||||
}
|
|
||||||
|
|
||||||
async authorize_credentials( email, password ){
|
|
||||||
const user = await Repository.findByEmailPassword( email, this.genSafePassword( password ) );
|
|
||||||
|
|
||||||
if( !user ){
|
|
||||||
return genErrorResponse( "Not able to log in", 401 );
|
|
||||||
}
|
|
||||||
const current_date = new Date();
|
|
||||||
const iat = Math.floor( (current_date.getTime())/1000 );
|
|
||||||
const renewal_exp = ( iat + 3600*jwtRenewalTimeout ) * 1000;
|
|
||||||
/**
|
|
||||||
* Renew session token on every login event.
|
|
||||||
* Previous session token is lost
|
|
||||||
*/
|
|
||||||
const session_token = toSha256( `${new Date()}` );
|
|
||||||
const session_token_exp = new Date( renewal_exp );
|
|
||||||
|
|
||||||
await Repository.addSessionToken( user.id, session_token, session_token_exp );
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
iat: iat,
|
|
||||||
exp: iat + jwtTimeout * 3600,
|
|
||||||
aud: jwtOptions.audience,
|
|
||||||
iss: jwtOptions.audience,
|
|
||||||
sub: user.id,
|
|
||||||
};
|
|
||||||
const jwt = jsonwebtoken.sign( payload , jwtSecret );
|
|
||||||
return {
|
|
||||||
accessToken : jwt,
|
|
||||||
payload : payload,
|
|
||||||
session_token,
|
|
||||||
session_token_exp,
|
|
||||||
user : user
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async authorize_token( token ){
|
|
||||||
const user = await Repository.findBySessionToken( token );
|
|
||||||
|
|
||||||
if( !user ){
|
|
||||||
return genErrorResponse( "Invalid Session Token", 401 );
|
|
||||||
}
|
|
||||||
|
|
||||||
const current_date = new Date();
|
|
||||||
const iat = Math.floor( (current_date.getTime())/1000 );
|
|
||||||
const renewal_exp = ( iat + 3600*jwtRenewalTimeout ) * 1000;
|
|
||||||
/**
|
|
||||||
* Renew session token on every login event.
|
|
||||||
* Previous session token is lost
|
|
||||||
*/
|
|
||||||
const session_token = toSha256( `${new Date()}` );
|
|
||||||
const session_token_exp = new Date( renewal_exp );
|
|
||||||
|
|
||||||
await Repository.addSessionToken( user.id, session_token, session_token_exp );
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
iat: iat,
|
|
||||||
exp: iat + jwtTimeout * 3600,
|
|
||||||
aud: jwtOptions.audience,
|
|
||||||
iss: jwtOptions.audience,
|
|
||||||
sub: user.id,
|
|
||||||
};
|
|
||||||
const jwt = jsonwebtoken.sign( payload , jwtSecret );
|
|
||||||
return {
|
|
||||||
accessToken : jwt,
|
|
||||||
payload : payload,
|
|
||||||
session_token,
|
|
||||||
session_token_exp,
|
|
||||||
user : user
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = new Account();
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const ModuleName = "App:Account:";
|
|
||||||
|
|
||||||
const { toSha256 } = require('../../../Shared/ShaUtils');
|
|
||||||
|
|
||||||
const { authentication } = require('../../../../config/apiConfig.json');
|
|
||||||
|
|
||||||
const { genErrorResponse } = require('../../../Shared/ErrorResponse');
|
|
||||||
|
|
||||||
const SharedResources = require('../../../Shared/Resources');
|
|
||||||
|
|
||||||
function registerEvent( event_id , callback ){
|
|
||||||
console.log(`Loading event ${event_id}`);
|
|
||||||
const EventBus = SharedResources.get("SysS:EventManager");
|
|
||||||
EventBus.addEvent( event_id , callback );
|
|
||||||
}
|
|
||||||
|
|
||||||
function publishEvent( event , data = null ){
|
|
||||||
const EventBus = SharedResources.get("SysS:EventManager");
|
|
||||||
const AppEventDomain = ModuleName;
|
|
||||||
const event_id = AppEventDomain + event;
|
|
||||||
|
|
||||||
console.log( event_id );
|
|
||||||
EventBus.publishEvent( event_id , data );
|
|
||||||
}
|
|
||||||
|
|
||||||
const tokenSecret = authentication.tokenSecret;
|
|
||||||
const jwtRenewalTimeout = authentication.jwtRenewalTimeout;
|
|
||||||
const jwtTimeout = authentication.jwtTimeout;
|
|
||||||
const jwtOptions = authentication.jwtOptions;
|
|
||||||
const jwtSecret = authentication.jwtSecret;
|
|
||||||
|
|
||||||
const pwdSecret = authentication.pwdSecret;
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
toSha256,
|
|
||||||
tokenSecret,
|
|
||||||
jwtRenewalTimeout,
|
|
||||||
jwtTimeout,
|
|
||||||
jwtOptions,
|
|
||||||
jwtSecret,
|
|
||||||
pwdSecret,
|
|
||||||
genErrorResponse,
|
|
||||||
registerEvent,
|
|
||||||
publishEvent
|
|
||||||
};
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const { getModel } = require('../../../../Shared/Models/Objection');
|
|
||||||
const Users = getModel('users');
|
|
||||||
const Sessions = getModel('users_sessions');
|
|
||||||
const Companies = getModel('companies');
|
|
||||||
|
|
||||||
class SpecificModelRepository{
|
|
||||||
constructor(){}
|
|
||||||
|
|
||||||
async populate( user ){
|
|
||||||
if( user.company_id ){
|
|
||||||
const company = await Companies.query().findById( user.company_id );
|
|
||||||
user.company = company;
|
|
||||||
}else{
|
|
||||||
user.company = null;
|
|
||||||
}
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getByEmail( email ){
|
|
||||||
const user = await Users.query()
|
|
||||||
.select( "*" )
|
|
||||||
.where("email","=",email).first();
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
async createOne( email, safe_password ){
|
|
||||||
const user = await Users.query().insert({
|
|
||||||
email,
|
|
||||||
password : safe_password,
|
|
||||||
"name":"No name",
|
|
||||||
"last_name":"No lastname",
|
|
||||||
"createdAt" : new Date().toISOString()
|
|
||||||
});
|
|
||||||
return await this.populate( user );
|
|
||||||
}
|
|
||||||
|
|
||||||
async findByEmailPassword( email, safe_password ){
|
|
||||||
const user = await Users.query().select('*')
|
|
||||||
.where("email","=",email)
|
|
||||||
.where("password","=",safe_password)
|
|
||||||
.first();
|
|
||||||
if( user ){
|
|
||||||
return await this.populate( user );
|
|
||||||
}else{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateSessionToken( old_token, token, expiration ){
|
|
||||||
const entry = await Sessions.query().select('*').where('token','=',old_token).first();
|
|
||||||
const data = {
|
|
||||||
token,
|
|
||||||
expiration,
|
|
||||||
};
|
|
||||||
if( entry ){
|
|
||||||
return await Sessions.query().patch( data ).where('token','=',old_token).first();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
async updatePassword( userId , safe_password ){
|
|
||||||
return await Users.query()
|
|
||||||
.findById( userId )
|
|
||||||
.patch( { password : safe_password } );
|
|
||||||
}
|
|
||||||
|
|
||||||
async addSessionToken( userId , token, expiration ){
|
|
||||||
const entry = await Sessions.query().select('*').where("user_id",'=',userId).first();
|
|
||||||
const data = {
|
|
||||||
token,
|
|
||||||
expiration : expiration.toISOString(),
|
|
||||||
};
|
|
||||||
if( entry ){
|
|
||||||
return await Sessions.query()
|
|
||||||
.findById( entry.id )
|
|
||||||
.patch(data);
|
|
||||||
}else{
|
|
||||||
data.user_id = userId;
|
|
||||||
return await Sessions.query().insert( data );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async findBySessionToken( token ){
|
|
||||||
const session = await Sessions.query().select("*").where("token","=",token).first();
|
|
||||||
const user = await Users.query().findById( session.user_id );
|
|
||||||
if( user ){
|
|
||||||
return await this.populate( user );
|
|
||||||
}else{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new SpecificModelRepository();
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const SpecificModelRepository = require('./Objection');
|
|
||||||
|
|
||||||
module.exports = SpecificModelRepository;
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const Application = require('../Domain');
|
|
||||||
|
|
||||||
function dummy_middleware( req, res, next ){
|
|
||||||
Application.trigger_example_event( {
|
|
||||||
example : "This is an example of event data"
|
|
||||||
} )
|
|
||||||
return res.status(500).send({ error:"Not implemented yet" });
|
|
||||||
}
|
|
||||||
|
|
||||||
function AppInit(){
|
|
||||||
Application.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
AppInit,
|
|
||||||
hooks : {
|
|
||||||
before: {
|
|
||||||
/**Array of middleware functions or objects lile { endpoint, middleware }*/
|
|
||||||
all : [],
|
|
||||||
del : [],
|
|
||||||
get : [],
|
|
||||||
patch : [],
|
|
||||||
post : [],
|
|
||||||
put : []
|
|
||||||
},
|
|
||||||
|
|
||||||
after: {
|
|
||||||
/**Array of middleware functions or objects lile { endpoint, middleware }*/
|
|
||||||
all : [ { "/test" : dummy_middleware } ],
|
|
||||||
del : [],
|
|
||||||
get : [],
|
|
||||||
patch : [],
|
|
||||||
post : [],
|
|
||||||
put : []
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const { hooks, AppInit } = require( './hooks' );
|
|
||||||
const GenericController = require('../../Lib');
|
|
||||||
|
|
||||||
class Company extends GenericController {
|
|
||||||
init(){
|
|
||||||
super.init();
|
|
||||||
AppInit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new Company( hooks );
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const Repository = require('../Repository');
|
|
||||||
const Interfaces = require('../Interfaces');
|
|
||||||
|
|
||||||
class Company {
|
|
||||||
constructor(){
|
|
||||||
this.Events = {
|
|
||||||
/** Event_Id : callback */
|
|
||||||
"Example" : this.event_handler_example
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
init(){
|
|
||||||
/// Setup application events
|
|
||||||
const Events = this.Events;
|
|
||||||
/// Setup application events
|
|
||||||
for ( const [event, callback] of Object.entries( Events ) ) {
|
|
||||||
const event_id = Interfaces.ModuleName + event
|
|
||||||
Interfaces.registerEvent( event_id , callback );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trigger_example_event( data ){
|
|
||||||
Interfaces.publishEvent( "Example", data );
|
|
||||||
}
|
|
||||||
|
|
||||||
event_handler_example( data ){
|
|
||||||
console.log( "CompanyDomain event" );
|
|
||||||
console.log( data );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = new Company();
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const ModuleName = "App:Company:";
|
|
||||||
|
|
||||||
const SharedResources = require('../../../Shared/Resources');
|
|
||||||
|
|
||||||
function registerEvent( event_id , callback ){
|
|
||||||
const EventBus = SharedResources.get("SysS:EventManager");
|
|
||||||
|
|
||||||
console.log(`Loading event ${event_id}`);
|
|
||||||
EventBus.addEvent( event_id , callback );
|
|
||||||
}
|
|
||||||
|
|
||||||
function publishEvent( event , data = null ){
|
|
||||||
const EventBus = SharedResources.get("SysS:EventManager");
|
|
||||||
const AppEventDomain = ModuleName;
|
|
||||||
const event_id = AppEventDomain + event;
|
|
||||||
|
|
||||||
console.log( event_id );
|
|
||||||
EventBus.publishEvent( event_id , data );
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
ModuleName,
|
|
||||||
registerEvent,
|
|
||||||
publishEvent
|
|
||||||
};
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports = {};
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const SpecificModelRepository = require('./Objection');
|
|
||||||
|
|
||||||
module.exports = SpecificModelRepository;
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
class GenericController{
|
|
||||||
constructor( hooks ){
|
|
||||||
this.router = express.Router();
|
|
||||||
this.hooks = hooks;
|
|
||||||
}
|
|
||||||
|
|
||||||
init(){
|
|
||||||
const { before, after } = this.hooks;
|
|
||||||
if( before ){
|
|
||||||
this.populate_hooks( before );
|
|
||||||
}
|
|
||||||
if( after ){
|
|
||||||
this.populate_hooks( after );
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
populate_hooks( hooks ){
|
|
||||||
if( (hooks.all) && (hooks.all.length > 0) ){
|
|
||||||
this.populate_hooks_by_verb( 'all' , hooks.all );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (hooks.delete) && (hooks.delete.length > 0) ){
|
|
||||||
this.populate_hooks_by_verb( 'del', hooks.del );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (hooks.get) && (hooks.get.length > 0) ){
|
|
||||||
this.populate_hooks_by_verb( 'get', hooks.get );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (hooks.patch) && (hooks.patch.length > 0) ){
|
|
||||||
this.populate_hooks_by_verb( 'patch', hooks.patch );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (hooks.post) && (hooks.post.length > 0) ){
|
|
||||||
this.populate_hooks_by_verb( 'post', hooks.post );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (hooks.put) && (hooks.put.length > 0) ){
|
|
||||||
this.populate_hooks_by_verb( 'put', hooks.put );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
add_hook_with_endpoint( http_verb, endpoint, middleware ){
|
|
||||||
switch( http_verb ){
|
|
||||||
case 'all':
|
|
||||||
this.router.use( endpoint , middleware );
|
|
||||||
break;
|
|
||||||
case 'del':
|
|
||||||
this.router.delete(endpoint, middleware);
|
|
||||||
break;
|
|
||||||
case 'get':
|
|
||||||
this.router.get(endpoint, middleware);
|
|
||||||
break;
|
|
||||||
case 'patch':
|
|
||||||
this.router.patch(endpoint, middleware);
|
|
||||||
break;
|
|
||||||
case 'post':
|
|
||||||
this.router.post(endpoint, middleware);
|
|
||||||
break;
|
|
||||||
case 'put':
|
|
||||||
this.router.put(endpoint, middleware);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
add_simple_hook( http_verb, middleware ){
|
|
||||||
switch( http_verb ){
|
|
||||||
case 'all':
|
|
||||||
this.router.use( middleware );
|
|
||||||
break;
|
|
||||||
case 'del':
|
|
||||||
this.router.delete( middleware );
|
|
||||||
break;
|
|
||||||
case 'get':
|
|
||||||
this.router.get( middleware );
|
|
||||||
break;
|
|
||||||
case 'patch':
|
|
||||||
this.router.patch( middleware );
|
|
||||||
break;
|
|
||||||
case 'post':
|
|
||||||
this.router.post( middleware );
|
|
||||||
break;
|
|
||||||
case 'put':
|
|
||||||
this.router.put( middleware );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
populate_hooks_by_verb( http_verb, hook_list ){
|
|
||||||
for (let custom_hook of hook_list ){
|
|
||||||
if( typeof custom_hook === "object" ){
|
|
||||||
for (let entry of Object.entries(custom_hook) ){
|
|
||||||
const endpoint = entry[0];
|
|
||||||
const callback = entry[1];
|
|
||||||
/// Add this hook as an (endpoint, middleware function) pair
|
|
||||||
this.add_hook_with_endpoint( http_verb, endpoint, callback );
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
/// Add this hook as a middleware function
|
|
||||||
this.add_simple_hook( http_verb, custom_hook );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = GenericController;
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { DateResolver, DateTimeResolver } = require('graphql-scalars');
|
|
||||||
const { Account, User, Company, getUserById, getCompanyById, findUsersPage, findCompaniesPage } = require('../../Domain');
|
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
// Queries
|
|
||||||
//////////////////////////////////////////////
|
|
||||||
async function account( args, context ) {
|
|
||||||
const account = new Account( context.requestContext.userId );
|
|
||||||
return account;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function profile( args, context ) {
|
|
||||||
const profile = new User( context.requestContext.userId );
|
|
||||||
return profile;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function company( args, context ) {
|
|
||||||
const company = new Company( context.requestContext.companyId );
|
|
||||||
return company;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function companyById( args, context ) {
|
|
||||||
return getCompanyById( args.id );
|
|
||||||
}
|
|
||||||
|
|
||||||
async function userById( args, context ) {
|
|
||||||
return getUserById( args.id );
|
|
||||||
}
|
|
||||||
|
|
||||||
async function findCompanies( args, context ) {
|
|
||||||
const { filters, elements, page } = args;
|
|
||||||
return findCompaniesPage( filters, elements, page );
|
|
||||||
}
|
|
||||||
|
|
||||||
async function findUsers( args, context ) {
|
|
||||||
const { filters, elements, page } = args;
|
|
||||||
return findUsersPage( filters, elements, page );
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////
|
|
||||||
// Mutations
|
|
||||||
/////////////////////////////////////////////////
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
account,
|
|
||||||
profile,
|
|
||||||
company,
|
|
||||||
companyById,
|
|
||||||
userById,
|
|
||||||
findCompanies,
|
|
||||||
findUsers
|
|
||||||
};
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
type Query {
|
|
||||||
account : Account!
|
|
||||||
profile : User!
|
|
||||||
company : Company!
|
|
||||||
|
|
||||||
companyById( id : Int! ) : PublicCompany
|
|
||||||
userById( id : Int! ) : PublicUser
|
|
||||||
|
|
||||||
findCompanies( filters : FindCompanyFilterInput!, elements: Int!, page: Int! ) : PublicCompanyFound!
|
|
||||||
findUsers( filters : FindUserFilterInput!, elements: Int!, page: Int! ) : PublicUserFound!
|
|
||||||
}
|
|
||||||
|
|
||||||
scalar DateTime
|
|
||||||
|
|
||||||
type Session {
|
|
||||||
token : String!
|
|
||||||
expiration : DateTime!
|
|
||||||
}
|
|
||||||
|
|
||||||
type Account {
|
|
||||||
user : User!
|
|
||||||
|
|
||||||
sessions( limit: Int , offset : Int ) : [Session]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type LocationCategory{
|
|
||||||
id : Int!
|
|
||||||
category : String!
|
|
||||||
}
|
|
||||||
|
|
||||||
type Location{
|
|
||||||
id : Int!
|
|
||||||
company : Company!
|
|
||||||
type : String!
|
|
||||||
state : String!
|
|
||||||
city : String!
|
|
||||||
country : String!
|
|
||||||
zipcode : String!
|
|
||||||
address_line1 : String!
|
|
||||||
address_line2 : String
|
|
||||||
|
|
||||||
categories : [LocationCategory]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type TruckType{
|
|
||||||
id : Int!
|
|
||||||
category : String!
|
|
||||||
}
|
|
||||||
|
|
||||||
type CompanyCategory{
|
|
||||||
id : Int!
|
|
||||||
category : String!
|
|
||||||
}
|
|
||||||
|
|
||||||
type Company {
|
|
||||||
id : Int!
|
|
||||||
owner : User!
|
|
||||||
staff : [User]!
|
|
||||||
|
|
||||||
type : String!
|
|
||||||
is_hidden : Boolean!
|
|
||||||
is_active : Boolean!
|
|
||||||
|
|
||||||
name : String!
|
|
||||||
description : String
|
|
||||||
|
|
||||||
createdAt : DateTime!
|
|
||||||
|
|
||||||
locations : [Location]!
|
|
||||||
categories : [CompanyCategory]!
|
|
||||||
truck_types : [TruckType]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type User {
|
|
||||||
id : Int!
|
|
||||||
company : Company
|
|
||||||
phone : String
|
|
||||||
|
|
||||||
email : String!
|
|
||||||
name : String!
|
|
||||||
last_name : String!
|
|
||||||
job_role : String!
|
|
||||||
permissions : String!
|
|
||||||
createdAt : DateTime!
|
|
||||||
is_active : Boolean!
|
|
||||||
|
|
||||||
locations( limit: Int , offset : Int ) : [Location]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type PublicCompany {
|
|
||||||
id : Int!
|
|
||||||
owner : PublicUser!
|
|
||||||
staff : [PublicUser]!
|
|
||||||
|
|
||||||
type : String!
|
|
||||||
name : String!
|
|
||||||
description : String
|
|
||||||
|
|
||||||
createdAt : DateTime!
|
|
||||||
|
|
||||||
locations : [Location]!
|
|
||||||
categories : [CompanyCategory]!
|
|
||||||
truck_types : [TruckType]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type PublicCompanyFound {
|
|
||||||
count : Int!
|
|
||||||
list : [PublicCompany]!
|
|
||||||
}
|
|
||||||
|
|
||||||
input FindCompanyFilterInput {
|
|
||||||
name : String
|
|
||||||
type : String
|
|
||||||
state : String
|
|
||||||
city : String
|
|
||||||
truck_type : String
|
|
||||||
categories : String
|
|
||||||
}
|
|
||||||
|
|
||||||
type PublicUser {
|
|
||||||
id : Int!
|
|
||||||
company : Company
|
|
||||||
phone : String
|
|
||||||
|
|
||||||
email : String!
|
|
||||||
name : String!
|
|
||||||
last_name : String!
|
|
||||||
job_role : String!
|
|
||||||
createdAt : DateTime!
|
|
||||||
|
|
||||||
locations( limit: Int , offset : Int ) : [Location]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type PublicUserFound {
|
|
||||||
count : Int!
|
|
||||||
list : [PublicUser]!
|
|
||||||
}
|
|
||||||
|
|
||||||
input FindUserFilterInput {
|
|
||||||
email : String
|
|
||||||
name : String
|
|
||||||
last_name : String
|
|
||||||
employee_id : String
|
|
||||||
company_name : String
|
|
||||||
job_role : String
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const fs = require('fs');
|
|
||||||
const { join } = require('path');
|
|
||||||
const { buildSchema } = require('graphql');
|
|
||||||
|
|
||||||
const schema = fs.readFileSync(join(__dirname, './schema.graphql'), 'utf8');
|
|
||||||
|
|
||||||
module.exports = buildSchema( schema );
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const { createHandler } = require("graphql-http/lib/use/express");
|
|
||||||
|
|
||||||
/// Include graphql schema and resolvers
|
|
||||||
const schemaDescription = require('./graphql/schema.js');
|
|
||||||
const schemaResolvers = require('./graphql/resolvers.js');
|
|
||||||
|
|
||||||
const { initEvents } = require('../Domain');
|
|
||||||
|
|
||||||
async function test(req, res, next){
|
|
||||||
console.log( req.requestContext );
|
|
||||||
res.status(200).send({
|
|
||||||
msg : "It is alive!"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
AppInit : initEvents, /// Dummy App Init
|
|
||||||
hooks : {
|
|
||||||
before: {
|
|
||||||
/**Array of middleware functions or objects lile { endpoint, middleware }*/
|
|
||||||
all : [],
|
|
||||||
del : [],
|
|
||||||
get : [ test ],
|
|
||||||
patch : [],
|
|
||||||
post : [],
|
|
||||||
put : []
|
|
||||||
},
|
|
||||||
|
|
||||||
after: {
|
|
||||||
/**Array of middleware functions or objects lile { endpoint, middleware }*/
|
|
||||||
all : [],
|
|
||||||
del : [],
|
|
||||||
get : [],
|
|
||||||
patch : [],
|
|
||||||
post : [
|
|
||||||
{ '/graphql' :
|
|
||||||
createHandler({
|
|
||||||
schema: schemaDescription,
|
|
||||||
rootValue : schemaResolvers,
|
|
||||||
context: async (req, params) => { return { requestContext : req.raw.requestContext }; },
|
|
||||||
graphiql: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
],
|
|
||||||
put : []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const { hooks, AppInit } = require( './hooks' );
|
|
||||||
const GenericController = require('../../Lib');
|
|
||||||
|
|
||||||
class PrivateResources extends GenericController {
|
|
||||||
init(){
|
|
||||||
super.init();
|
|
||||||
AppInit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new PrivateResources( hooks );
|
|
||||||
@@ -1,389 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const Repository = require('../Repository');
|
|
||||||
const Interfaces = require('../Interfaces');
|
|
||||||
|
|
||||||
class TruckType {
|
|
||||||
constructor( category ){
|
|
||||||
this._category = category;
|
|
||||||
}
|
|
||||||
|
|
||||||
async id(){
|
|
||||||
return this._category.id;
|
|
||||||
}
|
|
||||||
async category(){
|
|
||||||
return this._category.category;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Category {
|
|
||||||
constructor( category ){
|
|
||||||
this._category = category;
|
|
||||||
}
|
|
||||||
|
|
||||||
async id(){
|
|
||||||
return this._category.id;
|
|
||||||
}
|
|
||||||
async category(){
|
|
||||||
return this._category.category;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Location {
|
|
||||||
constructor( location ){
|
|
||||||
this._location = location;
|
|
||||||
this._categories = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
async populate_content(){
|
|
||||||
if( !this._categories ){
|
|
||||||
this._categories = await Repository.getCategories( 'location', this._location.id );
|
|
||||||
|
|
||||||
this._categories.map( (element) => {
|
|
||||||
return new Category( element );
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async company_id(){
|
|
||||||
await this.populate_content();
|
|
||||||
this._location.company_id;
|
|
||||||
}
|
|
||||||
async type(){
|
|
||||||
await this.populate_content();
|
|
||||||
this._location.type;
|
|
||||||
}
|
|
||||||
async state(){
|
|
||||||
await this.populate_content();
|
|
||||||
this._location.state;
|
|
||||||
}
|
|
||||||
async city(){
|
|
||||||
await this.populate_content();
|
|
||||||
this._location.city;
|
|
||||||
}
|
|
||||||
async country(){
|
|
||||||
await this.populate_content();
|
|
||||||
this._location.country;
|
|
||||||
}
|
|
||||||
async zipcode(){
|
|
||||||
await this.populate_content();
|
|
||||||
this._location.zipcode;
|
|
||||||
}
|
|
||||||
async address_line1(){
|
|
||||||
await this.populate_content();
|
|
||||||
this._location.address_line1;
|
|
||||||
}
|
|
||||||
async address_line2(){
|
|
||||||
await this.populate_content();
|
|
||||||
this._location.address_line2;
|
|
||||||
}
|
|
||||||
|
|
||||||
async categories(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._categories;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Company {
|
|
||||||
constructor( companyId , owner = null ){
|
|
||||||
this._companyId = companyId;
|
|
||||||
this._company = null;
|
|
||||||
this._owner = owner;
|
|
||||||
this._staff = null;
|
|
||||||
this._locations = null;
|
|
||||||
this._truck_types = null;
|
|
||||||
this._categories = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
setCompany( company ){
|
|
||||||
this._company = company;
|
|
||||||
}
|
|
||||||
|
|
||||||
async populate_content(){
|
|
||||||
if(! this._company ){
|
|
||||||
this._company = await Repository.getCompanyById( this._companyId );
|
|
||||||
}
|
|
||||||
if(! this._owner ){
|
|
||||||
this._owner = new User( this._company.owner_id, this );
|
|
||||||
await this._owner.populate_content();
|
|
||||||
}
|
|
||||||
if( !this._locations ){
|
|
||||||
this._locations = await Repository.getLocations( 'company', this._companyId );
|
|
||||||
|
|
||||||
this._locations.map( (element) => {
|
|
||||||
return new Location( element );
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if( !this._truck_types ){
|
|
||||||
this._truck_types = await Repository.getTruckTypes( 'company', this._companyId );
|
|
||||||
|
|
||||||
this._truck_types.map( (element) => {
|
|
||||||
return new TruckType( element );
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if( !this._categories ){
|
|
||||||
this._categories = await Repository.getCategories( 'company', this._companyId );
|
|
||||||
|
|
||||||
this._categories.map( (element) => {
|
|
||||||
return new Category( element );
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if( !this._staff ){
|
|
||||||
/// ToDo: Populate _staff
|
|
||||||
this._staff = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async id(){
|
|
||||||
return this._companyId;
|
|
||||||
}
|
|
||||||
async owner(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._owner;
|
|
||||||
}
|
|
||||||
async staff(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._staff;
|
|
||||||
}
|
|
||||||
|
|
||||||
async type(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._company.type;
|
|
||||||
}
|
|
||||||
async is_hidden(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._company.is_hidden;
|
|
||||||
}
|
|
||||||
async is_active(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._company.is_active;
|
|
||||||
}
|
|
||||||
async name(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._company.name;
|
|
||||||
}
|
|
||||||
async description(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._company.description;
|
|
||||||
}
|
|
||||||
async createdAt(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._company.createdAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
async locations(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._locations;
|
|
||||||
}
|
|
||||||
async categories(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._categories;
|
|
||||||
}
|
|
||||||
async truck_types(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._truck_types;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class User {
|
|
||||||
constructor( userId, company = null ){
|
|
||||||
this._userId = userId;
|
|
||||||
this._user = null;
|
|
||||||
this._locations = null;
|
|
||||||
|
|
||||||
this._company = company;
|
|
||||||
}
|
|
||||||
|
|
||||||
setUser( user ){
|
|
||||||
this._user = user;
|
|
||||||
}
|
|
||||||
|
|
||||||
async populate_content(){
|
|
||||||
if(! this._user ){
|
|
||||||
this._user = await Repository.getUserById( this._userId );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (!this._company) && (this._user.company_id) ){
|
|
||||||
/// Populate only if company is linked to user
|
|
||||||
this._company = new Company( this._user.company_id, this );
|
|
||||||
await this._company.populate_content();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !this._locations ){
|
|
||||||
this._locations = await Repository.getLocations( 'user', this._userId );
|
|
||||||
|
|
||||||
this._locations.map( (element) => {
|
|
||||||
return new Location( element );
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async id(){
|
|
||||||
return this._userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
async company(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._company;
|
|
||||||
}
|
|
||||||
async phone(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._user.phone;
|
|
||||||
}
|
|
||||||
|
|
||||||
async email(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._user.email;
|
|
||||||
}
|
|
||||||
async name(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._user.name;
|
|
||||||
}
|
|
||||||
async last_name(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._user.last_name;
|
|
||||||
}
|
|
||||||
async job_role(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._user.job_role;
|
|
||||||
}
|
|
||||||
async permissions(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._user.permissions;
|
|
||||||
}
|
|
||||||
async createdAt(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._user.createdAt;
|
|
||||||
}
|
|
||||||
async is_active(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._user.is_active;
|
|
||||||
}
|
|
||||||
|
|
||||||
async locations(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._locations;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Account {
|
|
||||||
constructor( userId ){
|
|
||||||
this._userId = userId;
|
|
||||||
this._sessions = null;
|
|
||||||
this._user = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
setUser( user ){
|
|
||||||
this._user = user;
|
|
||||||
}
|
|
||||||
|
|
||||||
async user(){
|
|
||||||
if( this._user ){
|
|
||||||
return this._user;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._user = new User( this._userId );
|
|
||||||
return this._user;
|
|
||||||
}
|
|
||||||
|
|
||||||
async populate_content(){
|
|
||||||
if( this._sessions ){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._sessions = await Repository.getSessions( this._userId );
|
|
||||||
|
|
||||||
this._sessions.map( (item) => {
|
|
||||||
return {
|
|
||||||
token : item.token,
|
|
||||||
expiration : item.expiration
|
|
||||||
};
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
async sessions(){
|
|
||||||
await this.populate_content();
|
|
||||||
return this._sessions;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async function getUserById( id ) {
|
|
||||||
const user = await Repository.getUserById( id );
|
|
||||||
if( user ){
|
|
||||||
const user_obj = new User( user.id );
|
|
||||||
user_obj.setUser(user);
|
|
||||||
return user_obj;
|
|
||||||
}else{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getCompanyById( id ) {
|
|
||||||
const company = await Repository.getCompanyById( id );
|
|
||||||
if( company ){
|
|
||||||
const company_obj = new Company( user.id );
|
|
||||||
company_obj.setCompany(company);
|
|
||||||
return company_obj;
|
|
||||||
}else{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function findUsersPage( filters, elements, page ) {
|
|
||||||
/// ToDo: Populate find
|
|
||||||
const list = [];
|
|
||||||
list.map( (element) => {
|
|
||||||
const user = new User( element.id );
|
|
||||||
user.setUser( element );
|
|
||||||
return user;
|
|
||||||
} );
|
|
||||||
return {
|
|
||||||
count : list.length,
|
|
||||||
list
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function findCompaniesPage( filters, elements, page ) {
|
|
||||||
/// ToDo: Populate find
|
|
||||||
const list = [];
|
|
||||||
list.map( (element) => {
|
|
||||||
const company = new Company( element.id );
|
|
||||||
company.setCompany( element );
|
|
||||||
return company;
|
|
||||||
} );
|
|
||||||
return {
|
|
||||||
count : list.length,
|
|
||||||
list
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of Events to handle in this App Domain
|
|
||||||
*/
|
|
||||||
const Events = {
|
|
||||||
/** Event_Id : callback */
|
|
||||||
};
|
|
||||||
|
|
||||||
function initEvents(){
|
|
||||||
console.log("Init GraphQL Events");
|
|
||||||
/// Setup application events
|
|
||||||
for ( const [event, callback] of Object.entries( Events ) ) {
|
|
||||||
const event_id = Interfaces.ModuleName + event
|
|
||||||
Interfaces.registerEvent( event_id , callback );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
initEvents,
|
|
||||||
Account,
|
|
||||||
User,
|
|
||||||
Company,
|
|
||||||
Location,
|
|
||||||
Category,
|
|
||||||
TruckType,
|
|
||||||
getUserById,
|
|
||||||
getCompanyById,
|
|
||||||
findUsersPage,
|
|
||||||
findCompaniesPage,
|
|
||||||
};
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const ModuleName = "App:PrivateResources:";
|
|
||||||
|
|
||||||
const SharedResources = require('../../../Shared/Resources');
|
|
||||||
|
|
||||||
function registerEvent( event_id , callback ){
|
|
||||||
const EventBus = SharedResources.get("SysS:EventManager");
|
|
||||||
|
|
||||||
console.log(`Loading event ${event_id}`);
|
|
||||||
EventBus.addEvent( event_id , callback );
|
|
||||||
}
|
|
||||||
|
|
||||||
function publishEvent( event , data = null ){
|
|
||||||
const EventBus = SharedResources.get("SysS:EventManager");
|
|
||||||
const AppEventDomain = ModuleName;
|
|
||||||
const event_id = AppEventDomain + event;
|
|
||||||
|
|
||||||
console.log( event_id );
|
|
||||||
EventBus.publishEvent( event_id , data );
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
ModuleName,
|
|
||||||
registerEvent,
|
|
||||||
publishEvent
|
|
||||||
};
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const { getModel } = require('../../../../Shared/Models/Objection');
|
|
||||||
const Users = getModel('users');
|
|
||||||
const Sessions = getModel('users_sessions');
|
|
||||||
const Companies = getModel('companies');
|
|
||||||
|
|
||||||
const Locations = getModel('locations');
|
|
||||||
const userLocations = getModel('user_locations');
|
|
||||||
const companyTruckTypes = getModel('company_truck_types');
|
|
||||||
const companyCategories = getModel('company_categories');
|
|
||||||
const locationTruckTypes = getModel('location_truck_types');
|
|
||||||
const locationCategories = getModel('location_categories');
|
|
||||||
|
|
||||||
class SpecificModelRepository{
|
|
||||||
constructor(){}
|
|
||||||
|
|
||||||
async getUserById( userId ){
|
|
||||||
return await Users.query().findById( userId );
|
|
||||||
}
|
|
||||||
|
|
||||||
async getCompanyById( companyId ){
|
|
||||||
return await Companies.query().findById( companyId );
|
|
||||||
}
|
|
||||||
|
|
||||||
async getSessions( userId ){
|
|
||||||
return await Sessions.query().where("user_id","=",userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getLocations( location_type, elementId ){
|
|
||||||
switch( location_type ){
|
|
||||||
case 'company':
|
|
||||||
return await Locations.query().where("company_id","=",elementId);
|
|
||||||
case 'user':
|
|
||||||
///ToDo: Implement join on Locations and userLocations
|
|
||||||
return [];
|
|
||||||
default:
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getCategories( category_type, elementId ){
|
|
||||||
switch( category_type ){
|
|
||||||
case 'company':
|
|
||||||
return await companyCategories.query().where("company_id","=",elementId);
|
|
||||||
case 'location':
|
|
||||||
///ToDo: Implement join on companyCategories and locationCategories
|
|
||||||
return [];
|
|
||||||
default:
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getTruckTypes( search_type, elementId ){
|
|
||||||
switch( search_type ){
|
|
||||||
case 'company':
|
|
||||||
return await companyTruckTypes.query().where("company_id","=",elementId);
|
|
||||||
case 'location':
|
|
||||||
///ToDo: Implement join on companyTruckTypes and locationTruckTypes
|
|
||||||
return [];
|
|
||||||
default:
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new SpecificModelRepository();
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const SpecificModelRepository = require('./Objection');
|
|
||||||
|
|
||||||
module.exports = SpecificModelRepository;
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
/**
|
|
||||||
* ExpressJS Controller
|
|
||||||
*/
|
|
||||||
const express = require('express');
|
|
||||||
const SystemService = require('../SysS/Lib');
|
|
||||||
|
|
||||||
const middlewares = require('./middlewares');
|
|
||||||
const Resources = require('./resources');
|
|
||||||
|
|
||||||
class AppLayerController extends SystemService {
|
|
||||||
constructor(){
|
|
||||||
super();
|
|
||||||
this.app = express();
|
|
||||||
this.resources = Resources;
|
|
||||||
}
|
|
||||||
|
|
||||||
async setup(){
|
|
||||||
super.setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
async init(){
|
|
||||||
super.init();
|
|
||||||
|
|
||||||
const app = this.app;
|
|
||||||
|
|
||||||
/// Populate context from JWT payload
|
|
||||||
app.use( middlewares.jwtValidator );
|
|
||||||
app.use( middlewares.contextGenerator );
|
|
||||||
|
|
||||||
for ( const resource of this.resources ){
|
|
||||||
for ( const [endpoint, controller] of Object.entries( resource ) ) {
|
|
||||||
controller.init();
|
|
||||||
app.use( endpoint, controller.router );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
app_controller(){
|
|
||||||
return this.app;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new AppLayerController();
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const apiConfig = require( '../../config/apiConfig.json' );
|
|
||||||
const jwt = require('jsonwebtoken');
|
|
||||||
const jwtSecret = apiConfig.authentication.jwtSecret;
|
|
||||||
|
|
||||||
const { getModel } = require('../Shared/Models/Objection');
|
|
||||||
const Users = getModel('users');
|
|
||||||
|
|
||||||
function jwtValidator(req, res, next){
|
|
||||||
if( req.JWT ){
|
|
||||||
req.JWT.isValid = false;
|
|
||||||
try{
|
|
||||||
req.JWT.payload = jwt.verify( req.JWT.raw, jwtSecret );
|
|
||||||
if( !req.JWT.payload ){
|
|
||||||
return res.status(401).send({error:"Unauthorized",code:401});
|
|
||||||
}else{
|
|
||||||
req.JWT.isValid = true;
|
|
||||||
}
|
|
||||||
}catch( err ){
|
|
||||||
console.error( err );
|
|
||||||
return res.status(401).send({error:"Unauthorized",code:401});
|
|
||||||
}
|
|
||||||
return next();
|
|
||||||
}else{
|
|
||||||
/// If no JWT available, ignore and continue
|
|
||||||
return next();
|
|
||||||
// return res.status(401).send({error:"Unauthorized",code:401});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function contextGenerator( req, res, next ){
|
|
||||||
if( ! req.JWT?.isValid ){
|
|
||||||
/// If no JWT available, ignore and continue
|
|
||||||
return next();
|
|
||||||
// return res.status(401).send({error:"Unauthorized",code:401});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Process only if JWT is valid
|
|
||||||
const userId = req.JWT.payload.sub;
|
|
||||||
const user = await Users.query().findById( userId ).select( "id", "company_id", "phone", "email", "name", "last_name", "job_role", "permissions", "createdAt", "is_active" );
|
|
||||||
const companyId = user.company_id;
|
|
||||||
const job_role = user.job_role;
|
|
||||||
const permissions = user.permissions;
|
|
||||||
|
|
||||||
req.requestContext = {
|
|
||||||
userId,
|
|
||||||
companyId,
|
|
||||||
job_role,
|
|
||||||
permissions,
|
|
||||||
user
|
|
||||||
}
|
|
||||||
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
jwtValidator,
|
|
||||||
contextGenerator
|
|
||||||
};
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
|
|
||||||
const Account = require('../Apps/Account/Controller');
|
|
||||||
const Company = require('../Apps/Company/Controller');
|
|
||||||
const PrivateResources = require('../Apps/PrivateResources/Controller');
|
|
||||||
|
|
||||||
module.exports = [
|
|
||||||
{ "/account": Account },
|
|
||||||
{ "/company": Company },
|
|
||||||
{ "/private": PrivateResources },
|
|
||||||
];
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
function genErrorResponse( msg , code = 400 ){
|
|
||||||
return {
|
|
||||||
error : {
|
|
||||||
code,
|
|
||||||
msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { genErrorResponse };
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class Companies extends Model {
|
|
||||||
static get tableName() { return 'companies'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : ['owner_id','type','is_hidden','is_active','name','description','createdAt'],
|
|
||||||
properties : {
|
|
||||||
owner_id : { type : 'integer', minimum : 0 },
|
|
||||||
type : { type : 'string' , enum : ['carrier', 'shipper'] },
|
|
||||||
is_hidden : { type : 'boolean', default : true },
|
|
||||||
is_active : { type : 'boolean', default : true },
|
|
||||||
name : { type : 'string', maxLength : 100 },
|
|
||||||
description : { type : 'string', maxLength : 256 },
|
|
||||||
createdAt : { type : 'date-time' }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Companies;
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class CompanyCategories extends Model {
|
|
||||||
static get tableName() { return 'company_categories'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : ['company_id','category'],
|
|
||||||
properties : {
|
|
||||||
company_id : { type : 'integer', minimum : 0 },
|
|
||||||
category : { type : 'string', maxLength : 100 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = CompanyCategories;
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class CompanyTruckTypes extends Model {
|
|
||||||
static get tableName() { return 'company_truck_types'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : ['company_id','truck_type'],
|
|
||||||
properties : {
|
|
||||||
company_id : { type : 'integer', minimum : 0 },
|
|
||||||
truck_type : { type : 'string', maxLength : 100 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = CompanyTruckTypes;
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const users = require('./users.model');
|
|
||||||
const user_sessions = require('./user_sessions.model');
|
|
||||||
const companies = require('./companies.model');
|
|
||||||
const locations = require('./locations.model');
|
|
||||||
const user_locations = require('./user_locations.model');
|
|
||||||
const company_truck_types = require('./company_truck_types.model');
|
|
||||||
const company_categories = require('./company_categories.model');
|
|
||||||
const location_categories = require('./location_categories.model');
|
|
||||||
const location_truck_types = require('./location_truck_types.model');
|
|
||||||
|
|
||||||
const metadata_categories = require('./metadata_categories.model');
|
|
||||||
const metadata_cities = require('./metadata_cities.model');
|
|
||||||
const metadata_products = require('./metadata_products.model');
|
|
||||||
const metadata_truck_types = require('./metadata_truck_types.model');
|
|
||||||
|
|
||||||
function getModel( name ){
|
|
||||||
switch( name ){
|
|
||||||
case 'users':
|
|
||||||
return users;
|
|
||||||
case 'users_sessions':
|
|
||||||
return user_sessions;
|
|
||||||
case 'companies':
|
|
||||||
return companies;
|
|
||||||
case 'locations':
|
|
||||||
return locations;
|
|
||||||
|
|
||||||
case 'user_locations':
|
|
||||||
return user_locations;
|
|
||||||
case 'company_truck_types':
|
|
||||||
return company_truck_types;
|
|
||||||
case 'company_categories':
|
|
||||||
return company_categories;
|
|
||||||
case 'location_categories':
|
|
||||||
return location_categories;
|
|
||||||
case 'location_truck_types':
|
|
||||||
return location_truck_types;
|
|
||||||
|
|
||||||
case 'metadata_categories':
|
|
||||||
return metadata_categories;
|
|
||||||
case 'metadata_cities':
|
|
||||||
return metadata_cities;
|
|
||||||
case 'metadata_products':
|
|
||||||
return metadata_products;
|
|
||||||
case 'metadata_truck_types':
|
|
||||||
return metadata_truck_types;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getModel
|
|
||||||
};
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class LoadAttachments extends Model {
|
|
||||||
static get tableName() { return 'load_attachments'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : [
|
|
||||||
'status',
|
|
||||||
'type',
|
|
||||||
'createdAt',
|
|
||||||
'updatedAt',
|
|
||||||
'doneAt'
|
|
||||||
],
|
|
||||||
properties : {
|
|
||||||
load_id : { type : 'integer' , minimum : 0 },
|
|
||||||
shipper_id : { type : 'integer' , minimum : 0 },
|
|
||||||
carrier_id : { type : 'integer' , minimum : 0 },
|
|
||||||
author_id : { type : 'integer' , minimum : 0 },
|
|
||||||
status : { type : 'string' , default : 'Draft', enum: ['Draft', 'Done'] },
|
|
||||||
type : { type : 'string' , enum: ['Draft', 'Done'] },
|
|
||||||
createdAt : { type : 'date-time' },
|
|
||||||
updatedAt : { type : 'date-time' },
|
|
||||||
doneAt : { type : 'date-time' }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = LoadAttachments;
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class LoadCategories extends Model {
|
|
||||||
static get tableName() { return 'load_categories'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : ['load_id','category_id'],
|
|
||||||
properties : {
|
|
||||||
load_id : { type : 'integer', minimum : 0 },
|
|
||||||
category_id : { type : 'integer', minimum : 0 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = LoadCategories;
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class Loads extends Model {
|
|
||||||
static get tableName() { return 'loads'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : [
|
|
||||||
'company_id',
|
|
||||||
'responsible_id',
|
|
||||||
'origin_country',
|
|
||||||
'origin_state',
|
|
||||||
'origin_city',
|
|
||||||
'origin_zipcode',
|
|
||||||
'origin_address_line1',
|
|
||||||
'destination_address_line1',
|
|
||||||
'updatedAt',
|
|
||||||
'createdAt',
|
|
||||||
'publication_status'
|
|
||||||
],
|
|
||||||
properties : {
|
|
||||||
company_id : { type : 'integer' , minimum : 0 },
|
|
||||||
responsible_id : { type : 'integer' , minimum : 0 },
|
|
||||||
truck_type : { type : 'string' , maxLength : 100 },
|
|
||||||
origin_country : { type : 'string' , default : 'Mexico', maxLength : 45 },
|
|
||||||
origin_state : { type : 'string' , maxLength : 45 },
|
|
||||||
origin_city : { type : 'string' , maxLength : 45 },
|
|
||||||
origin_zipcode : { type : 'string' , maxLength : 10 },
|
|
||||||
origin_lat : { type : 'string' , maxLength : 45 },
|
|
||||||
origin_lng : { type : 'string' , maxLength : 45 },
|
|
||||||
origin_address_line1 : { type : 'string' , maxLength : 100 },
|
|
||||||
origin_address_line2 : { type : 'string' , maxLength : 100 },
|
|
||||||
destination_country : { type : 'string' , maxLength : 45 },
|
|
||||||
destination_state : { type : 'string' , maxLength : 45 },
|
|
||||||
destination_city : { type : 'string' , maxLength : 45 },
|
|
||||||
destination_zipcode : { type : 'string' , maxLength : 10 },
|
|
||||||
destination_lat : { type : 'string' , maxLength : 45 },
|
|
||||||
destination_lng : { type : 'string' , maxLength : 45 },
|
|
||||||
destination_address_line1 : { type : 'string' , maxLength : 100 },
|
|
||||||
destination_address_line2 : { type : 'string' , maxLength : 100 },
|
|
||||||
weight : { type : 'number' , minimum : 0.0 },
|
|
||||||
est_loading_date : { type : 'date-time' },
|
|
||||||
est_unloading_date : { type : 'date-time' },
|
|
||||||
notes : { type : 'string', maxLength : 256 },
|
|
||||||
updatedAt : { type : 'date-time' },
|
|
||||||
createdAt : { type : 'date-time' },
|
|
||||||
publishedAt : { type : 'date-time' },
|
|
||||||
loadedAt : { type : 'date-time' },
|
|
||||||
transitAt : { type : 'date-time' },
|
|
||||||
deliveredAt : { type : 'date-time' },
|
|
||||||
publication_status : { type : 'string' , default : 'Draft', enum : ['Draft', 'Published', 'Completed', 'Closed'] },
|
|
||||||
status : { type : 'string', enum : ['Published', 'Loading', 'Transit', 'Downloading', 'Delivered'] }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Loads;
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class LocationCategories extends Model {
|
|
||||||
static get tableName() { return 'location_categories'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : ['location_id','category_id'],
|
|
||||||
properties : {
|
|
||||||
location_id : { type : 'integer', minimum : 0 },
|
|
||||||
category_id : { type : 'integer', minimum : 0 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = LocationCategories;
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class LocationTruckTypes extends Model {
|
|
||||||
static get tableName() { return 'location_truck_types'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : ['location_id','truck_type_id'],
|
|
||||||
properties : {
|
|
||||||
location_id : { type : 'integer', minimum : 0 },
|
|
||||||
truck_type_id : { type : 'integer', minimum : 0 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = LocationTruckTypes;
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class Locations extends Model {
|
|
||||||
static get tableName() { return 'locations'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : ['company_id','type','state','city','country','zipcode','address_line1'],
|
|
||||||
properties : {
|
|
||||||
company_id : { type : 'integer', minimum : 0 },
|
|
||||||
type : { type : 'string' , enum : ['loading', 'unloading', 'both'] },
|
|
||||||
state : { type : 'string', maxLength : 45 },
|
|
||||||
city : { type : 'string', maxLength : 45 },
|
|
||||||
country : { type : 'string', maxLength : 45 },
|
|
||||||
zipcode : { type : 'string', maxLength : 10 },
|
|
||||||
address_line1 : { type : 'string', maxLength : 100 },
|
|
||||||
address_line2 : { type : 'string', maxLength : 100 }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Locations;
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class MetadataCategories extends Model {
|
|
||||||
static get tableName() { return 'metadata_categories'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : ['category'],
|
|
||||||
properties : {
|
|
||||||
category: { type: 'string', maxLength: 100 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = MetadataCategories;
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class MetadataCities extends Model {
|
|
||||||
static get tableName() { return 'metadata_cities'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : ['city','state','country'],
|
|
||||||
properties : {
|
|
||||||
city: { type: 'string', maxLength: 100 },
|
|
||||||
state: { type: 'string', maxLength: 100 },
|
|
||||||
country: { type: 'string', maxLength: 100 },
|
|
||||||
zipcode: { type: 'string', maxLength: 100 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = MetadataCities;
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class MetadataProducts extends Model {
|
|
||||||
static get tableName() { return 'metadata_products'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : ['type'],
|
|
||||||
properties : {
|
|
||||||
product: { type: 'string', maxLength: 100 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = MetadataProducts;
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class MetadataTruckTypes extends Model {
|
|
||||||
static get tableName() { return 'metadata_truck_types'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : ['type'],
|
|
||||||
properties : {
|
|
||||||
truck_type: { type: 'string', maxLength: 100 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = MetadataTruckTypes;
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class Users extends Model {
|
|
||||||
static get tableName() { return 'users'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : [
|
|
||||||
'email',
|
|
||||||
'password',
|
|
||||||
'name',
|
|
||||||
'last_name',
|
|
||||||
'job_role',
|
|
||||||
'permissions',
|
|
||||||
'createdAt',
|
|
||||||
'is_active'
|
|
||||||
],
|
|
||||||
properties : {
|
|
||||||
company_id : { type : 'integer' , minimum : 0 },
|
|
||||||
phone: { type: 'string' , maxLength : 45 },
|
|
||||||
email : { type : 'string' , maxLength : 254 },
|
|
||||||
password : { type : 'string' , maxLength : 64 },
|
|
||||||
name : { type : 'string' , maxLength : 45 },
|
|
||||||
last_name : { type : 'string', maxLength : 100 },
|
|
||||||
job_role: { type: 'string', default : 'limited', enum : ['owner', 'manager', 'staff', 'driver', 'limited'] },
|
|
||||||
permissions: { type: 'string', default: 'limited', enum : ['carrier', 'shipper', 'limited'] },
|
|
||||||
createdAt: { type : 'date-time' },
|
|
||||||
is_active : { type : 'boolean', default : true }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Users;
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class UserSessions extends Model {
|
|
||||||
static get tableName() { return 'user_sessions'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : ['user_id','token','expiration'],
|
|
||||||
properties : {
|
|
||||||
user_id : { type : 'integer' , minimum : 0 },
|
|
||||||
token: { type: 'string' , maxLength : 256 },
|
|
||||||
expiration: { type: 'string' },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = UserSessions;
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class Users extends Model {
|
|
||||||
static get tableName() { return 'users'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : [
|
|
||||||
'email',
|
|
||||||
'password',
|
|
||||||
'name',
|
|
||||||
'last_name',
|
|
||||||
'job_role',
|
|
||||||
'permissions',
|
|
||||||
'createdAt',
|
|
||||||
'is_active'
|
|
||||||
],
|
|
||||||
properties : {
|
|
||||||
company_id : { type : 'integer' , minimum : 0 },
|
|
||||||
phone: { type: 'string' , maxLength : 45 },
|
|
||||||
email : { type : 'string' , maxLength : 254 },
|
|
||||||
password : { type : 'string' , maxLength : 64 },
|
|
||||||
name : { type : 'string' , maxLength : 45 },
|
|
||||||
last_name : { type : 'string', maxLength : 100 },
|
|
||||||
job_role: { type: 'string', default : 'limited', enum : ['owner', 'manager', 'staff', 'driver', 'warehouse', 'limited'] },
|
|
||||||
permissions: { type: 'string', default: 'limited', enum : ['carrier', 'shipper', 'limited'] },
|
|
||||||
createdAt: { type: "string" },
|
|
||||||
is_active : { type : 'boolean', default : true }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Users;
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class VehiclePublications extends Model {
|
|
||||||
static get tableName() { return 'vehicle_publications'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : [
|
|
||||||
'vehicle_id',
|
|
||||||
'published_by',
|
|
||||||
'published_date',
|
|
||||||
'destination',
|
|
||||||
'is_available',
|
|
||||||
'is_hidden',
|
|
||||||
],
|
|
||||||
properties : {
|
|
||||||
vehicle_id : { type : 'integer' , minimum : 0 },
|
|
||||||
published_by : { type : 'integer' , minimum : 0 },
|
|
||||||
published_date : { type : 'date-time' },
|
|
||||||
destination : { type : 'string' , maxLength : 45 },
|
|
||||||
is_available : { type: 'boolean' , default : false },
|
|
||||||
is_hidden : { type: 'boolean' , default : true },
|
|
||||||
available_date : { type : 'date-time' },
|
|
||||||
notes : { type: 'string' , maxLength : 256 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = VehiclePublications;
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class LoadCategories extends Model {
|
|
||||||
static get tableName() { return 'vehicle_categories'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : ['vehicle_id','category_id'],
|
|
||||||
properties : {
|
|
||||||
vehicle_id : { type : 'integer', minimum : 0 },
|
|
||||||
category_id : { type : 'integer', minimum : 0 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = LoadCategories;
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
class Vehicles extends Model {
|
|
||||||
static get tableName() { return 'vehicles'; }
|
|
||||||
static get idColumn() { return 'id'; }
|
|
||||||
static get jsonSchema() {
|
|
||||||
return {
|
|
||||||
type : 'object',
|
|
||||||
required : [
|
|
||||||
'company_id',
|
|
||||||
'background_tracking',
|
|
||||||
'status',
|
|
||||||
'createdAt'
|
|
||||||
],
|
|
||||||
properties : {
|
|
||||||
company_id : { type : 'integer' , minimum : 0 },
|
|
||||||
VIN : { type: 'string', maxLength : 20 },
|
|
||||||
circulation_serial_number : { type: 'string', maxLength : 100 },
|
|
||||||
truck_type : { type: 'string', maxLength : 100 },
|
|
||||||
background_tracking: { type: 'boolean' , default : false },
|
|
||||||
status: { type: 'string', default : 'Free', enum : ['Free', 'Loading', 'Transit', 'Downloading'] },
|
|
||||||
last_location_lat : { type: 'string', maxLength : 45 },
|
|
||||||
last_location_lng : { type: 'string', maxLength : 45 },
|
|
||||||
last_location_time : { type : 'date-time' },
|
|
||||||
active_load : { type : 'integer' , minimum : 0 },
|
|
||||||
active_driver : { type : 'integer' , minimum : 0 },
|
|
||||||
createdAt: { type : 'date-time' },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Vehicles;
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
class SharedResources{
|
|
||||||
constructor(){
|
|
||||||
this.dictionary = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
set( key , val ){
|
|
||||||
this.dictionary[ key ] = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
exists( key ){
|
|
||||||
return ( this.dictionary[ key ] != undefined );
|
|
||||||
}
|
|
||||||
|
|
||||||
get( key ){
|
|
||||||
if( ! this.exists( key ) ){
|
|
||||||
throw new Error( `Key [${key}] not defined!` );
|
|
||||||
}
|
|
||||||
return this.dictionary[ key ];
|
|
||||||
}
|
|
||||||
|
|
||||||
try_get( key ){
|
|
||||||
if( ! this.exists( key ) ){
|
|
||||||
return null;
|
|
||||||
}else{
|
|
||||||
return this.dictionary[ key ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
remove( key ){
|
|
||||||
if( this.exists(key) ){
|
|
||||||
delete this.dictionary[ key ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new SharedResources();
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
const crypto = require('crypto');
|
|
||||||
/**
|
|
||||||
* Convert string to sha256 string in hex
|
|
||||||
* @param {*} text
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function toSha256( text ){
|
|
||||||
return crypto.createHmac( "sha256" , "" ).update( text ).digest( 'hex' );
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { toSha256 };
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const apiConfig = require( '../../../config/apiConfig.json' );
|
|
||||||
const Knex = require('knex');
|
|
||||||
const { Model } = require('objection');
|
|
||||||
|
|
||||||
const UNINIT = 0;
|
|
||||||
const INIT = 1;
|
|
||||||
const ONLINE = 2;
|
|
||||||
const OFFLINE = 3;
|
|
||||||
|
|
||||||
class SystemServices {
|
|
||||||
constructor(){
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async setup(){
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async init(){
|
|
||||||
this.SystemServiceState = INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async connect(){
|
|
||||||
const knex = Knex({
|
|
||||||
client: 'mysql',
|
|
||||||
useNullAsDefault: true,
|
|
||||||
connection: {
|
|
||||||
host: apiConfig.sql.host,
|
|
||||||
port: apiConfig.sql.port,
|
|
||||||
user: apiConfig.sql.user,
|
|
||||||
password: apiConfig.sql.password,
|
|
||||||
database: apiConfig.sql.database,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Model.knex(knex);
|
|
||||||
this.knex = knex;
|
|
||||||
console.log("Connected to SQL");
|
|
||||||
this.SystemServiceState = ONLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
async disconnect(){
|
|
||||||
this.knex.destroy();
|
|
||||||
|
|
||||||
console.log("SQL Disconnected");
|
|
||||||
this.SystemServiceState = OFFLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
async deinit(){
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getState(){
|
|
||||||
switch( this.SystemServiceState ){
|
|
||||||
case UNINIT:
|
|
||||||
return "UNINIT";
|
|
||||||
case INIT:
|
|
||||||
return "INIT";
|
|
||||||
case ONLINE:
|
|
||||||
return "ONLINE";
|
|
||||||
case OFFLINE:
|
|
||||||
return "OFFLINE";
|
|
||||||
default:
|
|
||||||
return "UNINIT";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new SystemServices();
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
/**
|
|
||||||
* ExpressJS Controller
|
|
||||||
*/
|
|
||||||
require('dotenv').config();
|
|
||||||
const express = require('express');
|
|
||||||
const cors = require('cors');
|
|
||||||
const compression = require('compression');
|
|
||||||
const morgan = require('morgan');
|
|
||||||
const helmet = require('helmet');
|
|
||||||
const bodyParser = require('body-parser');
|
|
||||||
const fileUpload = require('express-fileupload');
|
|
||||||
|
|
||||||
/// Import Applications to serve
|
|
||||||
const AppsController = require('../../Controller');
|
|
||||||
const middlewares = require('./middlewares');
|
|
||||||
|
|
||||||
const UNINIT = 0;
|
|
||||||
const INIT = 1;
|
|
||||||
const ONLINE = 2;
|
|
||||||
const OFFLINE = 3;
|
|
||||||
|
|
||||||
class ExpressJSServices {
|
|
||||||
constructor(){
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
this.serverPort = process.env.SERVER_PORT || 3000;
|
|
||||||
this.app = express();
|
|
||||||
}
|
|
||||||
|
|
||||||
async setup(){
|
|
||||||
const app = this.app;
|
|
||||||
|
|
||||||
await AppsController.setup();
|
|
||||||
|
|
||||||
app.use( middlewares.Auth );
|
|
||||||
|
|
||||||
app.use(
|
|
||||||
fileUpload({
|
|
||||||
limits: { fileSize: 4 * 1024 * 1024 },
|
|
||||||
abortOnLimit: true,
|
|
||||||
limitHandler: (req,res,next) => {
|
|
||||||
req.limitSize = true;
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
app.use((req, res, next) => {
|
|
||||||
if (req.limitSize) {
|
|
||||||
res.status(413).send({message:"File size limit has been reached",status:"PAYLOAD_TOO_LARGE"});
|
|
||||||
}else{
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
app.use(bodyParser.urlencoded({ extended: true, limit: '50mb' }));
|
|
||||||
app.use(bodyParser.json({ limit: '50mb' }));
|
|
||||||
app.use(morgan('dev'));
|
|
||||||
|
|
||||||
app.use(helmet({
|
|
||||||
crossOriginResourcePolicy: false
|
|
||||||
}));
|
|
||||||
|
|
||||||
app.use(compression());
|
|
||||||
|
|
||||||
app.use(cors({
|
|
||||||
origin: '*',
|
|
||||||
methods: [
|
|
||||||
'GET',
|
|
||||||
'POST',
|
|
||||||
'PATCH',
|
|
||||||
'PUT',
|
|
||||||
'DELETE'
|
|
||||||
],
|
|
||||||
allowedHeaders: ['Content-Type', 'Authorization']
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async init(){
|
|
||||||
const app = this.app;
|
|
||||||
|
|
||||||
await AppsController.init();
|
|
||||||
|
|
||||||
app.use( middlewares.errorJSON );
|
|
||||||
app.use( AppsController.app_controller() );
|
|
||||||
app.use( middlewares.error404 );
|
|
||||||
|
|
||||||
this.SystemServiceState = INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async connect(){
|
|
||||||
const app = this.app;
|
|
||||||
const serverPort = this.serverPort;
|
|
||||||
|
|
||||||
await AppsController.connect();
|
|
||||||
|
|
||||||
const server = app.listen( serverPort , function(err){
|
|
||||||
if( !err ){
|
|
||||||
console.log('API listen on port', serverPort );
|
|
||||||
}else{
|
|
||||||
console.log( err );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.server = server;
|
|
||||||
|
|
||||||
this.SystemServiceState = ONLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
async disconnect(){
|
|
||||||
await AppsController.disconnect();
|
|
||||||
this.server.close();
|
|
||||||
|
|
||||||
this.SystemServiceState = OFFLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
async deinit(){
|
|
||||||
await AppsController.deinit();
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getState(){
|
|
||||||
switch( this.SystemServiceState ){
|
|
||||||
case UNINIT:
|
|
||||||
return "UNINIT";
|
|
||||||
case INIT:
|
|
||||||
return "INIT";
|
|
||||||
case ONLINE:
|
|
||||||
return "ONLINE";
|
|
||||||
case OFFLINE:
|
|
||||||
return "OFFLINE";
|
|
||||||
default:
|
|
||||||
return "UNINIT";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new ExpressJSServices();
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
/**
|
|
||||||
* HASH
|
|
||||||
*****************************************************
|
|
||||||
* DEPENDENCIES
|
|
||||||
*****************************************************
|
|
||||||
* Based on Express Framework
|
|
||||||
* System
|
|
||||||
*****************************************************
|
|
||||||
* PUBLIC METHODS
|
|
||||||
*****************************************************
|
|
||||||
* Auth( req, res, next)
|
|
||||||
* Extract JWT or BasicAuth data
|
|
||||||
* errorJSON( error , request , response , next )
|
|
||||||
* Generate error response on bad JSON format
|
|
||||||
* error404( request , response , next )
|
|
||||||
* Generate error 404 response
|
|
||||||
* apiKey( request , response , next )
|
|
||||||
* Generate error on invalid apikey
|
|
||||||
**/
|
|
||||||
|
|
||||||
/// Extract JWT or BasicAuth
|
|
||||||
function Auth( req, res , next ){
|
|
||||||
///
|
|
||||||
/// Try to extract the authorization data from headers
|
|
||||||
///
|
|
||||||
let auth;
|
|
||||||
if( req.headers.hasOwnProperty( "authorization" ) ){
|
|
||||||
auth = req.headers.authorization;
|
|
||||||
auth = auth.split(" ")[1];
|
|
||||||
if( !auth ){ console.log( "NO HEADER AUTH available" ); return next(); }
|
|
||||||
//console.log( auth );
|
|
||||||
/// Try BasicAuth {
|
|
||||||
try{
|
|
||||||
let ba = Buffer.from( auth , 'base64' ).toString()
|
|
||||||
//const [user,pass] = ba.split(':');
|
|
||||||
ba = ba.split(':');
|
|
||||||
if( ba.length == 2 ){
|
|
||||||
req.basicAuth = { user : ba[0] , password : ba[1] };
|
|
||||||
}
|
|
||||||
}catch(error){
|
|
||||||
console.log("MIDDLEWARE_AUTH_ERR_BA",error);
|
|
||||||
}
|
|
||||||
/// Try BasicAuth }
|
|
||||||
}else if( req.query.access_token ){
|
|
||||||
auth = req.query.access_token;
|
|
||||||
if( !auth ){ console.log( "NO QUERY AUTH available" ); return next(); }
|
|
||||||
}
|
|
||||||
if( auth ){
|
|
||||||
/// Try JWT {
|
|
||||||
try{
|
|
||||||
let jwt = auth.split(".");
|
|
||||||
if( jwt.length == 3 ){
|
|
||||||
req.JWT = {};
|
|
||||||
req.JWT.raw = auth;
|
|
||||||
}
|
|
||||||
}catch( error ){
|
|
||||||
console.log("MIDDLEWARE_AUTH_ERR_JWT",error);
|
|
||||||
}
|
|
||||||
/// Try JWT }
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
function errorJSON( error , request , response , next ){
|
|
||||||
console.log(error);
|
|
||||||
if( error !== null ){
|
|
||||||
/// For body-parser errors
|
|
||||||
if( error instanceof SyntaxError && error.status === 400 && 'body' in error ){
|
|
||||||
return response.status(400).json({ error : 'Invalid json' , code : 400 });
|
|
||||||
}
|
|
||||||
/// For any error
|
|
||||||
return response.status(500).send( { error: "Internal server error" , code : 500 } );
|
|
||||||
}else{
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function error404( request , response , next ){
|
|
||||||
return response.status(404).send( { error : "Page not found", code : 404 } );
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
Auth,
|
|
||||||
errorJSON,
|
|
||||||
error404,
|
|
||||||
};
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
'user strict';
|
|
||||||
const apiConfig = require( '../../../../config/apiConfig.json' );
|
|
||||||
const nodemailer = require("nodemailer");
|
|
||||||
const SendGrid = require("nodemailer-sendgrid");
|
|
||||||
|
|
||||||
const SiteName = "ETA Viaporte";
|
|
||||||
|
|
||||||
const sendgridConfig = apiConfig.sendgrid;
|
|
||||||
|
|
||||||
const transporter = nodemailer.createTransport(
|
|
||||||
SendGrid({
|
|
||||||
host: sendgridConfig.HOST,
|
|
||||||
apiKey: sendgridConfig.API_KEY
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
async function sendMailTemplate( templateId, receiver, subject, content ){
|
|
||||||
/**TODO: Remove in production */
|
|
||||||
const default_mail_list = [
|
|
||||||
{pattern:"testing@etaviaporte.com",redirect:"testing@etaviaporte.com"},
|
|
||||||
{pattern:"alex@etaviaporte.com",redirect:"alexandro_uribe@outlook.com"},
|
|
||||||
{pattern:"pablo@etaviaporte.com",redirect:"josepablo134@gmail.com"}
|
|
||||||
];
|
|
||||||
for( let i=0; i< default_mail_list.length; i++ ){
|
|
||||||
if( receiver.indexOf( default_mail_list[i].pattern ) >= 0 ){
|
|
||||||
receiver = default_mail_list[i].redirect;
|
|
||||||
break;/** Set only the first match */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return await transporter.sendMail({
|
|
||||||
from: sendgridConfig.FROM,
|
|
||||||
to: receiver,
|
|
||||||
subject: subject,
|
|
||||||
templateId: templateId,
|
|
||||||
dynamic_template_data: content
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function AccountVerifyEmail( receiver , content ){
|
|
||||||
const templateId = "d-e9b7966303694964a64b6e4954e9715d";
|
|
||||||
const subject = "[ETA] Account Verification";
|
|
||||||
const content_to_send = {
|
|
||||||
project_name: SiteName,
|
|
||||||
user_name: content.user_name,
|
|
||||||
user_email: receiver,
|
|
||||||
OTP : content.OTP
|
|
||||||
};
|
|
||||||
return await sendMailTemplate( templateId, receiver, subject, content_to_send );
|
|
||||||
}
|
|
||||||
|
|
||||||
async function AccountConfirmed( receiver, content ){
|
|
||||||
const templateId = "d-4daaab1b85d443ceba38826f606e9931";
|
|
||||||
const subject = "[ETA] Welcome to ETA";
|
|
||||||
const content_to_send = {
|
|
||||||
user_name: content.user_name,
|
|
||||||
};
|
|
||||||
return await sendMailTemplate( templateId, receiver, subject, content_to_send );
|
|
||||||
}
|
|
||||||
|
|
||||||
async function AccountPwdResetEmail( receiver, content ){
|
|
||||||
const templateId = "d-e9b7966303694964a64b6e4954e9715d";
|
|
||||||
const subject = "[ETA] Password Reset";
|
|
||||||
const content_to_send = {
|
|
||||||
project_name: SiteName,
|
|
||||||
user_name: content.user_name,
|
|
||||||
user_email: receiver,
|
|
||||||
OTP : content.OTP
|
|
||||||
};
|
|
||||||
return await sendMailTemplate( templateId, receiver, subject, content_to_send );
|
|
||||||
}
|
|
||||||
|
|
||||||
async function ContactEmail( receiver, content ){
|
|
||||||
const templateId = "d-1090dda1091442f3a75ee8ab39ad0f10";
|
|
||||||
const subject = "[ETA] Contact Email";
|
|
||||||
const content_to_send = {
|
|
||||||
project_name: SiteName,
|
|
||||||
user_name: content.name,
|
|
||||||
user_email: receiver
|
|
||||||
};
|
|
||||||
return await sendMailTemplate( templateId, receiver, subject, content_to_send );
|
|
||||||
}
|
|
||||||
//ContactEmail( "josepablo134@gmail.com", { email : "josepablo134@gmail.com", name:"Josepablo C.", message: "This is an example" } ).then().catch();
|
|
||||||
|
|
||||||
module.exports = { AccountVerifyEmail, AccountConfirmed, AccountPwdResetEmail, ContactEmail };
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
'user strict';
|
|
||||||
const nodemailer = require("nodemailer");
|
|
||||||
const apiConfig = require( '../../../../config/apiConfig.json' );
|
|
||||||
|
|
||||||
const transporter = nodemailer.createTransport(
|
|
||||||
apiConfig.email_standalone
|
|
||||||
);
|
|
||||||
|
|
||||||
async function StandAloneContactEmail( content ){
|
|
||||||
const default_from = apiConfig.email_standalone.auth.user;
|
|
||||||
const receiver = "support@etaviaporte.com";
|
|
||||||
const {name, email, message } = content;
|
|
||||||
return await transporter.sendMail({
|
|
||||||
from: `${name} <${default_from}>`,
|
|
||||||
to: receiver,
|
|
||||||
subject: "Contact Email From Landing Page",
|
|
||||||
text: `\n\n The following is an email from : ${email}\n\n\n` + message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
//StandAloneContactEmail( { email : "josepablo134@gmail.com", name:"Josepablo C.", message: "This is an example" } ).then().catch();
|
|
||||||
|
|
||||||
module.exports = { StandAloneContactEmail };
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const { StandAloneContactEmail } = require('./StandAlone.handler');
|
|
||||||
const { AccountVerifyEmail, AccountConfirmed, AccountPwdResetEmail, ContactEmail } = require('./SendGrid.handler');
|
|
||||||
|
|
||||||
async function onChecksumGeneration( data ){
|
|
||||||
console.log( data );
|
|
||||||
const receiver = data.email;
|
|
||||||
await AccountVerifyEmail( receiver, data );
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onAccountConfirmed( data ){
|
|
||||||
const receiver = data.email;
|
|
||||||
await AccountConfirmed( receiver, data );
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onPasswordReset( data ){
|
|
||||||
const receiver = data.email;
|
|
||||||
await AccountPwdResetEmail( receiver, data );
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onContactFromWebPage( data ){
|
|
||||||
const receiver = data.email;
|
|
||||||
await StandAloneContactEmail( data );
|
|
||||||
await ContactEmail( receiver, data );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dictionary of event ids and handlers
|
|
||||||
*/
|
|
||||||
module.exports = {
|
|
||||||
"App:Account:getchecksum:signup" : onChecksumGeneration,
|
|
||||||
"App:Account:signupconfirmed":onAccountConfirmed,
|
|
||||||
"App:Account:getchecksum:recover":onPasswordReset,
|
|
||||||
"App:ContactEmail:contact":onContactFromWebPage,
|
|
||||||
};
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const events = require('events');
|
|
||||||
const SharedResources = require('../../Shared/Resources');
|
|
||||||
|
|
||||||
const resources_list = require('./resources');
|
|
||||||
|
|
||||||
const UNINIT = 0;
|
|
||||||
const INIT = 1;
|
|
||||||
const ONLINE = 2;
|
|
||||||
const OFFLINE = 3;
|
|
||||||
|
|
||||||
class SystemServices {
|
|
||||||
constructor(){
|
|
||||||
this.resources = resources_list;
|
|
||||||
this.eventEmitter = new events.EventEmitter();
|
|
||||||
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
addEvent( event_id , callback ){
|
|
||||||
this.eventEmitter.on( event_id , callback );
|
|
||||||
}
|
|
||||||
|
|
||||||
publishEvent( event_id , data ){
|
|
||||||
this.eventEmitter.emit( event_id , data );
|
|
||||||
}
|
|
||||||
|
|
||||||
async setup(){
|
|
||||||
for ( const resource of this.resources ){
|
|
||||||
for ( const [key, value] of Object.entries( resource ) ) {
|
|
||||||
this.eventEmitter.on( key , value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async init(){
|
|
||||||
SharedResources.set( "SysS:EventManager" , this );
|
|
||||||
this.SystemServiceState = INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async connect(){
|
|
||||||
this.SystemServiceState = ONLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
async disconnect(){
|
|
||||||
this.SystemServiceState = OFFLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
async deinit(){
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getState(){
|
|
||||||
switch( this.SystemServiceState ){
|
|
||||||
case UNINIT:
|
|
||||||
return "UNINIT";
|
|
||||||
case INIT:
|
|
||||||
return "INIT";
|
|
||||||
case ONLINE:
|
|
||||||
return "ONLINE";
|
|
||||||
case OFFLINE:
|
|
||||||
return "OFFLINE";
|
|
||||||
default:
|
|
||||||
return "UNINIT";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new SystemServices();
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const EmailEvents = require('./EmailEvents');
|
|
||||||
|
|
||||||
module.exports = [
|
|
||||||
EmailEvents,
|
|
||||||
];
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const UNINIT = 0;
|
|
||||||
const INIT = 1;
|
|
||||||
const ONLINE = 2;
|
|
||||||
const OFFLINE = 3;
|
|
||||||
|
|
||||||
class SystemService {
|
|
||||||
constructor(){
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async setup(){
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async init(){
|
|
||||||
this.SystemServiceState = INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async connect(){
|
|
||||||
this.SystemServiceState = ONLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
async disconnect(){
|
|
||||||
this.SystemServiceState = OFFLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
async deinit(){
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = SystemService;
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const EventManager = require('./EventManager');
|
|
||||||
const Connections = require('./Connections');
|
|
||||||
const Controller = require('./Controller');
|
|
||||||
|
|
||||||
const UNINIT = 0;
|
|
||||||
const INIT = 1;
|
|
||||||
const ONLINE = 2;
|
|
||||||
const OFFLINE = 3;
|
|
||||||
|
|
||||||
class SystemServices {
|
|
||||||
constructor(){
|
|
||||||
this.resources = [
|
|
||||||
EventManager,
|
|
||||||
Connections,
|
|
||||||
Controller,
|
|
||||||
];
|
|
||||||
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async setup(){
|
|
||||||
for ( const service of this.resources ){
|
|
||||||
await service.setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async init(){
|
|
||||||
for ( const service of this.resources ){
|
|
||||||
await service.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.SystemServiceState = INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async connect(){
|
|
||||||
for ( const service of this.resources ){
|
|
||||||
await service.connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.SystemServiceState = ONLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
async disconnect(){
|
|
||||||
for ( const service of this.resources ){
|
|
||||||
await service.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.SystemServiceState = OFFLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
async deinit(){
|
|
||||||
for ( const service of this.resources ){
|
|
||||||
await service.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.SystemServiceState = UNINIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getState(){
|
|
||||||
switch( this.SystemServiceState ){
|
|
||||||
case UNINIT:
|
|
||||||
return "UNINIT";
|
|
||||||
case INIT:
|
|
||||||
return "INIT";
|
|
||||||
case ONLINE:
|
|
||||||
return "ONLINE";
|
|
||||||
case OFFLINE:
|
|
||||||
return "OFFLINE";
|
|
||||||
default:
|
|
||||||
return "UNINIT";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new SystemServices();
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const process = require('node:process');
|
|
||||||
const SystemServices = require('./SysS');
|
|
||||||
|
|
||||||
async function main(){
|
|
||||||
await SystemServices.setup();
|
|
||||||
await SystemServices.init();
|
|
||||||
await SystemServices.connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
main()
|
|
||||||
.then( ( out ) => { if( out ){ console.log( out ); } } )
|
|
||||||
.catch( ( error ) => { if( error ){ console.error( error ); } } );
|
|
||||||
|
|
||||||
async function disconnect_server( code ){
|
|
||||||
if( await SystemServices.getState() !== "OFFLINE" ){
|
|
||||||
await SystemServices.disconnect();
|
|
||||||
console.log("Server disconnected with exit code : " , code );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
process.on('SIGINT', () => {
|
|
||||||
disconnect_server( "SIGINT" ).then( ()=>{} ).catch((error)=>{
|
|
||||||
console.error("Shutdown error", error);
|
|
||||||
})
|
|
||||||
} );
|
|
||||||
|
|
||||||
process.on('exit', (code) => {
|
|
||||||
disconnect_server( "exit:"+code ).then( ()=>{} ).catch((error)=>{
|
|
||||||
console.error("Shutdown error", error);
|
|
||||||
})
|
|
||||||
} );
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
/// Unit testing dependences
|
|
||||||
const assert = require("assert");
|
|
||||||
const SharedResources = require('../src/Shared/SharedResources');
|
|
||||||
|
|
||||||
|
|
||||||
describe('Shared Resources' , () => {
|
|
||||||
it('Check key', async () => {
|
|
||||||
assert.equal( SharedResources.exists("test") , false );
|
|
||||||
|
|
||||||
SharedResources.set("test" , "This is a test value ");
|
|
||||||
assert.equal( SharedResources.exists("test") , true );
|
|
||||||
|
|
||||||
SharedResources.remove("test");
|
|
||||||
assert.equal( SharedResources.exists("test") , false );
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user