newStaffLDB-API (#48)

Merge newStaffLDB-API into main.

Ready to deploy

Reviewed-on: #48
This commit is contained in:
Fred Boniface
2023-10-03 21:35:00 +01:00
parent 5db9d8e52a
commit 0a25ae85f5
61 changed files with 2498 additions and 520705 deletions

View File

@@ -1,6 +1,6 @@
// statusCodes should be a map, not an object
const statusCodes = {
export const statusCodes = {
400: "data not found",
700: "no authentication attempt",
701: "invalid credentials",
@@ -14,5 +14,18 @@ const statusCodes = {
951: "unknown server error",
};
export const msgCodes = new Map<string, string>([
[
"LOC_NOT_FOUND",
"Location not found. If you are sure that the location exists, there may be a fault with the data provider.",
],
[
"USR_NOT_FOUND",
"User is not registered, consider regeristering for access to this resource",
],
["AUTH_ERR", "Authentication Error"],
["OK", "OK"],
]);
module.exports = statusCodes;
export { statusCodes };
//export { statusCodes };

View File

@@ -5,7 +5,7 @@ interface versions {
const version: versions = {
api: ["/api/v1/", "/api/v2"],
app: "2023.8.2",
app: "2023.10.1",
};
module.exports = version;

View File

@@ -52,7 +52,7 @@ async function getStation(req, res, next) {
if (!req.isAuthed) {
const err = new Error("Unauthorized");
err.status = 401;
throw err;
return next(err);
}
res.json(await ldb.get(id, true));
} else {

View File

@@ -1,12 +1,13 @@
const utils = require("../utils/auth.utils");
const log = require("../utils/logs.utils");
const logger = require("../utils/logger.utils");
module.exports = async function authCheck(req, res, next) {
log.out("authMiddlewares: Checking authentication", "dbug");
//log.out("authMiddlewares: Checking authentication", "dbug");
logger.logger.debug("Auth check starting");
try {
var uuid = req.headers.uuid;
} catch (err) {
log.out("authMiddlewares: User !isAuthed", "dbug");
logger.logger.warn("Unable to read UUID header - Not authenticated");
req.isAuthed = false;
return next();
}
@@ -14,14 +15,21 @@ module.exports = async function authCheck(req, res, next) {
var result = (await utils.isAuthed(uuid)) || false;
if (!result) {
req.isAuthed = false;
log.out("authMiddlewares: User !isAuthed", "dbug");
//log.out("authMiddlewares: User !isAuthed", "dbug");
logger.logger.debug("Auth denied");
} else {
req.isAuthed = true;
log.out("authMiddlewares: User isAuthed", "dbug");
//log.out("authMiddlewares: User isAuthed", "dbug");
logger.logger.debug("Auth successful");
}
return next();
} catch (err) {
/*log.out(
"authMiddlewares: Unable to check auth, default to !isAuthed",
"warn"
);*/
logger.logger.error(err, `Auth check failed`);
req.isAuthed = false;
return next();
return next(err);
}
};

View File

@@ -1,8 +0,0 @@
const express = require("express");
const router = express.Router();
// Controller Imports
// Routes
module.exports = router;

View File

@@ -1,28 +0,0 @@
const express = require("express");
const router = express.Router();
/* Controller Imports */
// Live
// Timetable
// Ref
// User
/* Routes */
// Live
router.get("/live/station/:id/:type");
router.get("/live/train/:searchType/:id");
// Timetable
router.get("/timetable/train/:date/:searchType/:id");
// User
router.post("/user");
router.get("/user/:uuid");
router.delete("/user/:uuid");
module.exports = router;

View File

@@ -1,5 +1,4 @@
/* global process */
const log = require("../utils/logs.utils"); // Log Helper
import { logger } from "../utils/logger.utils";
const dbUser = process.env.OWL_DB_USER || "owl";
const dbPass = process.env.OWL_DB_PASS || "twittwoo";
@@ -15,27 +14,27 @@ const db = client.db(dbName);
async function query(collection, query, returnId = false) {
await client.connect();
log.out(`dbAccess.query: Connecting to collection: '${collection}'`, "info");
logger.trace(`dbAccess.query: Connecting to collection: '${collection}'`);
var qcoll = db.collection(collection);
var qcursor = qcoll.find(query);
if (!returnId) {
qcursor.project({ _id: 0 });
}
log.out(`dbAccess.query: Running Query: ${JSON.stringify(query)}`, "info");
logger.trace(query, "dbAccess.query: Runnung Query");
increment(collection);
return await qcursor.toArray();
let result = await qcursor.toArray();
logger.trace(result, "dbAccess.query: Response");
return result;
}
async function queryProject(collection, query, projection) {
await client.connect();
log.out(`dbAccess.queryProject: Connecting to col: '${collection}'`, "info");
logger.debug(`dbAccess.queryProject: Connecting to col: '${collection}'`);
const qcoll = db.collection(collection);
const qcursor = qcoll.find(query).project(projection);
log.out(
`dbAccess.query: Running Query: ${JSON.stringify(
query
)}, Projection: ${JSON.stringify(projection)}`,
"dbug"
logger.debug(
projection,
`dbAccess.query: Running Query: ${JSON.stringify(query)}`
);
increment(collection);
return await qcursor.toArray();
@@ -43,17 +42,14 @@ async function queryProject(collection, query, projection) {
async function queryAggregate(collection, pipeline) {
await client.connect();
log.out(`dbAccess.queryProject: Connecting to col: '${collection}'`, "info");
log.out(
`dbAccess.query: Running Aggregation: ${JSON.stringify(pipeline)}`,
"dbug"
);
logger.debug(`dbAccess.queryProject: Connecting to col: '${collection}'`);
logger.trace(pipeline, "dbAccess.query: Running Aggregation");
increment(collection);
return await db.collection(collection).aggregate(pipeline).toArray();
}
async function increment(target) {
log.out(`dbAccess.increment: Incrementing counter for: ${target}`, "info");
logger.debug(`dbAccess.increment: Incrementing counter for: ${target}`);
await client.connect();
let col = db.collection("meta");
let update = {};
@@ -63,7 +59,7 @@ async function increment(target) {
async function addUser(uuid, domain) {
// Needs testing
log.out("dbAccess.addUser: Adding user to database");
logger.debug("dbAccess.addUser: Adding user to database");
let doc = { uuid: uuid, domain: domain, atime: new Date() };
await client.connect();
let col = db.collection("users");
@@ -76,7 +72,7 @@ async function addUser(uuid, domain) {
async function addRegReq(uuid, domain) {
// Needs testing
log.out("dbAccess.addRegReq: Adding registration request");
logger.debug("dbAccess.addRegReq: Adding registration request");
let doc = { uuid: uuid, time: new Date(), domain: domain };
await client.connect();
let col = db.collection("registrations");
@@ -86,7 +82,7 @@ async function addRegReq(uuid, domain) {
async function userAtime(uuid) {
// Needs testing
log.out("dbAccess.userAtime: Updating access time for user");
logger.debug("dbAccess.userAtime: Updating access time for user");
let q = { uuid: uuid };
let n = { $set: { uuid: uuid, atime: new Date() } };
await client.connect();
@@ -97,7 +93,7 @@ async function userAtime(uuid) {
// Deletes one single registration request entry from the DB
async function delRegReq(uuid) {
log.out("dbAccess.delRegReq: Deleting a Registration Request");
logger.debug("dbAccess.delRegReq: Deleting a Registration Request");
let collection = "registrations";
await client.connect();
let col = db.collection(collection);
@@ -105,11 +101,13 @@ async function delRegReq(uuid) {
}
async function colCount(collection) {
log.out(`dbAccess.colCount: Counting entries in collection: ${collection}`);
logger.debug(
`dbAccess.colCount: Counting entries in collection: ${collection}`
);
await client.connect();
let col = db.collection(collection);
let count = col.countDocuments();
log.out(
logger.debug(
`dbAccess.colCount: Collection: ${collection} contains ${count}` +
" documents"
);
@@ -127,3 +125,15 @@ module.exports = {
delRegReq,
colCount,
};
export {
query,
queryProject,
queryAggregate,
increment,
addUser,
userAtime,
addRegReq,
delRegReq,
colCount,
};

View File

@@ -1,59 +0,0 @@
// Parse and return a find request
const log = require("../utils/logs.utils"); // Log Helper
const db = require("../services/dbAccess.services");
const san = require("../utils/sanitizer.utils");
// DB Query: query(collection, query)
// Define collection as all queries are for the "corpus" collection.
const col = "corpus";
async function name(id) {
log.out(`findServices.name: Finding station name: ${id}`, "info");
var name = san.cleanApiEndpointTxt(id.toUpperCase());
let query = { NLCDESC: name };
//var data = await db.query(col,query)
return await db.query(col, query);
}
async function crs(id) {
log.out(`findServices.crs: Finding crs: ${id}`, "info");
var crs = san.cleanApiEndpointTxt(id.toUpperCase());
let query = { "3ALPHA": crs };
//var data = await db.query(col,query)
return await db.query(col, query);
}
async function nlc(id) {
log.out(`findServices.nlc: Finding nlc: ${id}`, "info");
var nlc = san.cleanApiEndpointNum(id);
let query = { NLC: parseInt(nlc) };
log.out(`findServices.nlc: NLC Converted to int: ${query}`, "info");
//var data = await db.query(col,query)
return await db.query(col, query);
}
async function tiploc(id) {
log.out(`findServices.tiploc: Finding tiploc: ${id}`, "info");
var tiploc = san.cleanApiEndpointTxt(id.toUpperCase());
let query = { TIPLOC: tiploc };
//var data = await db.query(col,query)
return await db.query(col, query);
}
async function stanox(id) {
log.out(`findServices.stanox: Finding stanox: ${id}`, "info");
var stanox = san.cleanApiEndpointNum(id);
let query = { STANOX: String(stanox) };
//var data = await db.query(col,query)
return await db.query(col, query);
}
module.exports = {
name,
crs,
nlc,
tiploc,
stanox,
};

View File

@@ -0,0 +1,55 @@
// Parse and return a find request
import { query } from "../services/dbAccess.services";
import {
cleanApiEndpointTxt,
cleanApiEndpointNum,
} from "../utils/sanitizer.utils";
import { logger } from "../utils/logger.utils";
// Define collection as all queries are for the "corpus" collection.
const col: string = "corpus";
async function name(id: string) {
logger.debug(`findServices.name: Finding station name: ${id}`);
var name = cleanApiEndpointTxt(id.toUpperCase());
let queryObj = { NLCDESC: name };
return await query(col, queryObj);
}
async function crs(id: string) {
logger.debug(`findServices.crs: Finding crs: ${id}`);
var crs = cleanApiEndpointTxt(id.toUpperCase());
let queryObj = { "3ALPHA": crs };
return await query(col, queryObj);
}
async function nlc(id: string) {
logger.debug(`findServices.nlc: Finding nlc: ${id}`);
var nlc = cleanApiEndpointNum(id);
let queryObj = { NLC: parseInt(nlc) };
logger.trace(`findServices.nlc: NLC Converted to int: ${query}`);
return await query(col, queryObj);
}
async function tiploc(id: string) {
logger.debug(`findServices.tiploc: Finding tiploc: ${id}`);
var tiploc = cleanApiEndpointTxt(id.toUpperCase());
let queryObj = { TIPLOC: tiploc };
return await query(col, queryObj);
}
async function stanox(id: string) {
logger.debug(`findServices.stanox: Finding stanox: ${id}`);
var stanox = cleanApiEndpointNum(id);
let queryObj = { STANOX: String(stanox) };
return await query(col, queryObj);
}
module.exports = {
name,
crs,
nlc,
tiploc,
stanox,
};

View File

@@ -1,6 +1,4 @@
/* eslint-disable no-useless-escape */
const axios = require("axios");
const log = require("../utils/logs.utils");
import { logger } from "../utils/logger.utils";
const issueLabels = {
bug: 120,
@@ -11,8 +9,7 @@ const issueLabels = {
};
async function processor(data) {
log.out("issueService.processor: Issue received", "info");
console.log(data); // TEMPORARY MEASURE
logger.debug("issueService.processor: Issue received");
let out = {};
out.labels = [issueLabels[data?.label] || 0, issueLabels["web-user"]];
out.title = data?.subject.replace(/<[^>]+>|[\*\$]/g, "");
@@ -21,22 +18,32 @@ async function processor(data) {
}
async function sendToGitea(body) {
let key = process.env.OWL_GIT_ISSUEBOT;
let url = process.env.OWL_GIT_APIENDPOINT;
let opts = {
headers: {
Authorization: key,
},
};
var res = await axios.post(url, body, opts);
/* Need to read the output from the POST and pass the result upwards to the
client.*/
if (res.status == 201) {
log.out("issueService.sendToGitea: Issue sent to Gitea", "info");
return { status: res.status, message: "issue created" };
} else {
log.out(`issueService.sendToGitea: Fail to send issue: ${res.body}`, "err");
return { status: res.status, message: "issue not created" };
try {
const key = process.env.OWL_GIT_ISSUEBOT;
const url = process.env.OWL_GIT_APIENDPOINT;
const opts = {
method: "POST",
headers: {
Authorization: key,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
};
const res = await fetch(url, opts);
if (res.status === 201) {
logger.debug("issueService.sendToGitea: Issue created");
return { status: res.status, message: "issue created" };
} else {
logger.error(
`issueService.sendtoGitea: Error creating issue RETURN: ${res.status}`
);
return { status: res.status, message: "issue not created" };
}
} catch (err) {
logger.error(err, `issueService.sendToGitea`);
return { status: 500, message: "Internal Server Error" };
}
}

View File

@@ -1,28 +0,0 @@
const testing = require("../services/mail.services");
const log = require("../utils/logs.utils");
async function getAlive() {
log.out("kubeServices.getAlive: alive hook checked", "info");
return { code: 200, state: { state: "alive", noise: "twit-twoo" } };
}
async function getReady() {
log.out("kubeServices.getReady: ready hook checked", "info");
testing.send({
to: "fred@fjla.uk",
subject: "OwlBoard Test",
txt: "This is a test message from OwlBoard (testing)",
});
return "not_implemented";
}
async function getTime() {
var now = new Date();
return { responseGenerated: now };
}
module.exports = {
getAlive,
getReady,
getTime,
};

View File

@@ -0,0 +1,22 @@
import { logger } from "../utils/logger.utils";
async function getAlive() {
logger.trace("kubeServices.getAlive: alive hook checked");
return { code: 200, state: { state: "alive", noise: "twit-twoo" } };
}
async function getReady() {
logger.trace("kubeServices.getReady: ready hook checked");
return "not_implemented";
}
async function getTime() {
var now: Date = new Date();
return { responseGenerated: now };
}
module.exports = {
getAlive,
getReady,
getTime,
};

View File

@@ -1,12 +1,14 @@
// Parse and return an LDB Request
const log = require("../utils/logs.utils"); // Log Helper
const ldb = require("ldbs-json");
const util = require("../utils/ldb.utils");
const san = require("../utils/sanitizer.utils");
const db = require("../services/dbAccess.services");
import { logger } from "../utils/logger.utils";
import { transform as staffStationTransform } from "../utils/translators/ldb/staffStation";
import { msgCodes } from "../configs/errorCodes.configs";
const ldbKey = process.env.OWL_LDB_KEY;
const ldbsvKey = process.env.OWL_LDB_SVKEY;
@@ -16,7 +18,7 @@ async function get(id, staff = false) {
const obj = await util.checkCrs(cleanId);
try {
const crs = obj[0]["3ALPHA"];
log.out(`ldbService.get: Determined CRS for lookup to be: ${crs}`, "info");
logger.debug(`ldbService.get: Determined CRS for lookup to be: ${crs}`);
if (staff) {
const data = arrDepBoardStaff(crs);
db.increment("ldbsvws");
@@ -27,16 +29,16 @@ async function get(id, staff = false) {
return await data;
}
} catch (err) {
log.out(`ldbService.get: Error, Unable to find CRS: ${err}`, "info");
logger.error(err, "ldbService.get: Error, Unable to find CRS");
return {
ERROR: "NOT_FOUND",
description: "The entered station was not found.",
obStatus: "LOC_NOT_FOUND",
obMsg: "UNABLE TO FIND MESSAGE",
};
}
}
async function arrDepBoard(CRS) {
log.out(`ldbService.arrDepBoard: Trying to fetch board for ${CRS}`, "info");
logger.trace(`ldbService.arrDepBoard: Trying to fetch board for ${CRS}`);
try {
const options = {
numRows: 10,
@@ -46,7 +48,7 @@ async function arrDepBoard(CRS) {
let d = await api.call("GetArrDepBoardWithDetails", options, false, false);
return await util.cleanData(d);
} catch (err) {
log.out(`ldbService.arrDepBoard: Lookup Failed for: ${CRS}`, "warn");
logger.error(err, "ldbService.arrDepBoard: Lookup Failed");
return {
GetStationBoardResult: "not available",
Reason: `The CRS code ${CRS} is not valid`,
@@ -55,7 +57,7 @@ async function arrDepBoard(CRS) {
}
async function arrDepBoardStaff(CRS) {
log.out(`ldbService.arrDepBoardStaff: Try to fetch board for ${CRS}`, "dbug");
logger.debug(`ldbService.arrDepBoardStaff: Try to fetch board for ${CRS}`);
try {
const options = {
numRows: 40,
@@ -73,18 +75,24 @@ async function arrDepBoardStaff(CRS) {
false,
false
);
console.log("\n\n\nORIGINAL DATA");
console.log("\n" + JSON.stringify(result) + "\n\n\n");
console.timeEnd(`Fetch Staff LDB for ${CRS.toUpperCase()}`);
try {
const _staffLdb = staffStationTransform(result);
console.log("Transformation Test Successful");
console.log(JSON.stringify(_staffLdb));
logger.debug("StaffLDB Transformed");
logger.trace(_staffLdb, "StaffLDB Transformed");
return {
obStatus: "OK",
obMsg: "OK",
data: _staffLdb,
};
} catch (err) {
console.log("Transformation Test Failed: " + err);
logger.error(err, "Transformation Error");
}
return result;
} catch (err) {
log.out(`ldbService.arrDepBoardStaff: Lookup Failed for: ${CRS}`, "warn");
log.out(`ldbService.arrDepBoardStaff: ${err}`);
logger.error(err, "ldbService.arrDepBoardStaff error");
return {
GetStationBoardResult: "not available",
Reason: `The CRS code ${CRS} is not valid`,
@@ -93,7 +101,7 @@ async function arrDepBoardStaff(CRS) {
}
async function getServiceByRID(rid) {
log.out(`ldbService.getServiceByRID: Finding RID: ${rid}`, "dbug");
logger.debug(`ldbService.getServiceByRID: Finding RID: ${rid}`);
try {
const options = {
rid: String(rid),
@@ -101,12 +109,12 @@ async function getServiceByRID(rid) {
const api = new ldb(ldbsvKey, true);
return await api.call("GetServiceDetailsByRID", options, false, false);
} catch (err) {
log.out(`ldbService.queryService: ${err}`, "EROR");
logger.error(err, `ldbService.queryService`);
}
}
async function getServicesByOther(id) {
log.out(`ldbService.getServiceByOther: Finding services: ${id}`, "dbug");
logger.debug(`ldbService.getServiceByOther: Finding services: ${id}`);
try {
const options = {
serviceID: id,
@@ -115,30 +123,30 @@ async function getServicesByOther(id) {
const api = new ldb(ldbsvKey, true);
return await api.call("QueryServices", options, false, false);
} catch (err) {
log.out(`ldbService.getServiceByOther: Error: ${err}`, "EROR");
logger.error(err, "ldbService.getServiceByOther");
return false;
}
}
async function getReasonCodeList() {
log.out("ldbService.getReasonCodeList: Fetching reason code list", "eror");
logger.debug("ldbService.getReasonCodeList: Fetching reason code list");
try {
const dbFilter = {};
return await db.query("reasonCodes", dbFilter, false);
} catch (err) {
log.out(`ldbService.getReasonCodeList: ${err}`, "eror");
logger.error(err, "ldbService.getReasonCodeList");
}
}
async function getReasonCode(code) {
log.out(`ldbService.getReasonCode: Fetching reason code ${code}`, "dbug");
logger.debug(`ldbService.getReasonCode: Fetching reason code ${code}`);
try {
const dbFilter = {
code: code,
};
return await db.query("reasonCodes", dbFilter, false);
} catch (err) {
log.out(`ldbService.getReasonCode: ${err}`, "eror");
logger.error(err, "ldbService.getReasonCode");
}
}

View File

@@ -1,19 +0,0 @@
const log = require("../utils/logs.utils"); // Log Helper
const db = require("../services/dbAccess.services");
async function getStations() {
var out = db.query("stations");
log.out("listServices.getStations: Fetching stations list", "info");
return await out;
}
async function getCorpus() {
var out = db.query("corpus");
log.out("listServices.getCorpus: Fetching CORPUS list", "info");
return await out;
}
module.exports = {
getStations,
getCorpus,
};

View File

@@ -0,0 +1,19 @@
import { query } from "./dbAccess.services";
import { logger } from "../utils/logger.utils";
async function getStations() {
var out = query("stations");
logger.debug("listServices.getStations: Fetching stations list");
return await out;
}
async function getCorpus() {
var out = query("corpus");
logger.debug("listServices.getCorpus: Fetching CORPUS list");
return await out;
}
module.exports = {
getStations,
getCorpus,
};

View File

@@ -1,37 +0,0 @@
const log = require("../utils/logs.utils");
const mail = require("nodemailer"); //>> Probs wrong
const fromAddr = process.env.OWL_EML_FROM;
const smtpUser = process.env.OWL_EML_USER;
const smtpPass = process.env.OWL_EML_PASS;
const smtpHost = process.env.OWL_EML_HOST;
const smtpPort = process.env.OWL_EML_PORT;
let transporter = mail.createTransport({
host: smtpHost,
port: smtpPort,
secure: false, // Must be false for STARTTLS on port 587
auth: {
user: smtpUser,
pass: smtpPass,
},
});
/* 'message' is an object containing string values for:
*to, cc, bcc, *subject, *txt, html. * denotes required */
async function send(message) {
log.out("mailServices.send: Message send request received", "info");
message.from = fromAddr;
try {
var res = await transporter.sendMail(message);
} catch (err) {
log.out(`mailServices.send: Message send failed: ${err}`, "err");
return false;
}
log.out(`mailServices.send: SMTP Response: ${res.response}`);
return true;
}
module.exports = {
send,
};

View File

@@ -0,0 +1,45 @@
const mail = require("nodemailer");
import { logger } from "../utils/logger.utils";
export interface msgDescriptor {
to: string;
cc?: string;
bcc?: string;
subject: string;
txt: string;
html?: string;
from: string;
}
const fromAddr = process.env.OWL_EML_FROM;
const smtpUser = process.env.OWL_EML_USER;
const smtpPass = process.env.OWL_EML_PASS;
const smtpHost = process.env.OWL_EML_HOST;
const smtpPort = process.env.OWL_EML_PORT;
const transporter = mail.createTransport({
host: smtpHost,
port: smtpPort,
secure: false, // Must be false for STARTTLS on port 587 which is always secure
auth: {
user: smtpUser,
pass: smtpPass,
},
});
async function send(message: msgDescriptor): Promise<boolean> {
logger.debug("mailServices.send: Message send request received");
message.from = fromAddr || "no-reply@owlboard.info";
try {
var res = await transporter.sendMail(message);
} catch (err) {
logger.error(err, "mailServices.send: Message send failed");
return false;
}
logger.debug(res.response, "mailServices.send: SMTP Response");
return true;
}
module.exports = {
send,
};

View File

@@ -1,16 +1,15 @@
// Finds PIS Codes using DB Lookups
const db = require("../services/dbAccess.services");
const log = require("../utils/logs.utils");
const clean = require("../utils/sanitizer.utils");
import { logger } from "../utils/logger.utils";
const supported = ["GW", "UK"];
async function findPisByOrigDest(start, end) {
log.out(
"pisServices.findPisByOrigDest: Searching for PIS for Orig: " +
`${start}, Dest: ${end}`,
"dbug"
logger.debug(
`pisServices.findPisByOrigDest: Searching for Orig: ${start}, Dest: ${end}`
);
const firstCrs = clean.cleanApiEndpointTxt(start.toLowerCase());
const lastCrs = clean.cleanApiEndpointTxt(end.toLowerCase());
@@ -33,7 +32,7 @@ async function findPisByOrigDest(start, end) {
}
async function findPisByCode(code) {
log.out(`pisServices.findPisByCode: Searching for PIS code: ${code}`, "dbug");
logger.debug(`pisServices.findPisByCode: Searching for PIS code: ${code}`);
const cleanCode = clean.removeNonNumeric(code);
const query = {
code: parseInt(cleanCode),

View File

@@ -1,4 +1,3 @@
const log = require("../utils/logs.utils");
const auth = require("../utils/auth.utils");
const db = require("./dbAccess.services");
const mail = require("./mail.services");
@@ -6,23 +5,24 @@ const clean = require("../utils/sanitizer.utils");
const domains = require("../configs/domains.configs");
const errors = require("../configs/errorCodes.configs");
import { logger } from "../utils/logger.utils";
async function createRegKey(body) {
log.out("registerServices.createRegKey: Incoming request", "INFO");
logger.debug("registerServices.createRegKey: Incoming request");
if (body.email) {
const domain = await clean.getDomainFromEmail(body.email);
log.out(`registerServices: Registration request from: ${domain}`, "info");
logger.info(`registerServices: Registration request from: ${domain}`);
if (domains.includes(domain)) {
log.out(
`registerServices.createRegKey: Key from valid: ${domain}`,
"info"
);
logger.debug(`registerServices.createRegKey: Key from valid: ${domain}`);
const uuid = await auth.generateKey();
db.addRegReq(uuid, domain);
const message = await auth.generateConfirmationEmail(body.email, uuid);
if (!message) {
const err = new Error("Message generation error");
log.out("registerServices.createRegKey: Error generating email", "err");
log.out(err, "err");
logger.error(
err,
"registerServices.createRegKey: Error generating email"
);
return 500;
}
if ((await mail.send(message)) == true) {
@@ -38,10 +38,9 @@ async function createRegKey(body) {
async function regUser(req) {
// Add input validation
log.out(`Read UUID: ${req.uuid}`, "dbug");
log.out(`registrationServices.regUser: Request from: ${req.uuid}`, "info");
logger.trace(`Read UUID: ${req.uuid}`);
const res = await auth.checkRequest(req.uuid);
log.out(`registrationServices.regUser: ${JSON.stringify(res)}`, "info");
logger.debug(res, "registrationServices");
if (res.result) {
const uuid = await auth.generateKey();
const apiKey = await db.addUser(uuid, res.domain);
@@ -54,7 +53,6 @@ async function regUser(req) {
}
async function getUser(uuid) {
log.out("registrationServices: Finding user for given UUID", "dbug");
try {
const filter = {
uuid: uuid,

View File

@@ -1,8 +1,9 @@
const log = require("../utils/logs.utils"); // Log Helper
const db = require("../services/dbAccess.services");
const os = require("os");
const vers = require("../configs/version.configs");
import { logger } from "../utils/logger.utils";
async function buildJson() {
let json = {};
json.count = {};
@@ -34,14 +35,13 @@ async function buildJson() {
}
async function hits() {
log.out("statsServices.hits: Statistics Requested", "info");
logger.debug("statsServices.hits: Statistics Requested");
const out = await buildJson();
log.out(`statsServices.hits: Sending Data: ${JSON.stringify(out)}`, "info");
return out;
}
async function getVersions() {
log.out("statsServices.getVersions: Fetching versions", "info");
logger.debug("statsServices.getVersions: Fetching versions");
const dbMan = await db.query("versions", { target: "dbmanager" });
const mqClt = await db.query("versions", { target: "mq-client" });
const data = {
@@ -53,7 +53,7 @@ async function getVersions() {
}
async function statistics() {
log.out("statsServices.statistics: Fetching statistics", "info");
logger.debug("statsServices.statistics: Fetching statistics");
const countersPromise = db.query("meta", { target: "counters" });
const timetablePromise = db.query("meta", { target: "timetable" });

View File

@@ -1,15 +1,13 @@
const log = require("../utils/logs.utils");
const db = require("./dbAccess.services");
const clean = require("../utils/sanitizer.utils");
const pis = require("../services/pis.services");
const { filter } = require("compression");
import { logger } from "../utils/logger.utils";
async function findByHeadcodeToday(headcode) {
const sanitizedHeadcode = clean.removeNonAlphanumeric(headcode).toUpperCase();
log.out(
"trainServiceServices.findByHeadcode: Searching for headcode " +
sanitizedHeadcode,
"dbug"
logger.debug(
`trainServiceServices.findByHeadcode: Searching for headcode ${sanitizedHeadcode}`
);
const now = new Date();
const dayMap = ["su", "m", "t", "w", "th", "f", "s"];
@@ -43,10 +41,8 @@ async function findByHeadcodeToday(headcode) {
async function findByHeadcode(date, headcode) {
const sanitizedHeadcode = clean.removeNonAlphanumeric(headcode).toUpperCase();
log.out(
"trainServiceServices.findByHeadcode: Searching for headcode " +
sanitizedHeadcode,
"dbug"
logger.debug(
`trainServiceServices.findByHeadcode: Searching for headcode ${sanitizedHeadcode}`
);
let searchDate;
if (date === "now") {
@@ -82,7 +78,6 @@ async function findByHeadcode(date, headcode) {
},
];
const queryData = await db.queryAggregate("timetable", pipeline);
console.log(JSON.stringify(queryData));
let filteredData = filterServices(queryData);
return await filteredData;
}

View File

@@ -1,19 +1,18 @@
const logs = require("../utils/logs.utils");
const crypt = require("crypto");
const db = require("../services/dbAccess.services");
const fs = require("fs/promises");
import { minifyMail } from "./minify.utils";
import { logger } from "./logger.utils";
// Checks users registration key against issued keys
async function isAuthed(uuid: string) {
async function isAuthed(uuid: string): Promise<boolean> {
// Needs testing
const q = { uuid: uuid };
const q = {
uuid: uuid,
};
const res = await db.query("users", q);
logs.out(
"authUtils.checkUser: DB Query answer: " + JSON.stringify(res[0]),
"dbug"
);
logger.debug(res, "checkUser: DB Query Result");
const authorized = res && res[0] && res[0].domain;
if (authorized) db.userAtime(uuid);
return authorized;
@@ -21,13 +20,11 @@ async function isAuthed(uuid: string) {
// Checks whether a registration request key is valid
async function checkRequest(key: string) {
// For some reason db.query seems to return correctly, but the second logs.out statement prints []??? so registration fails!!
const collection = "registrations";
const query = { uuid: key };
const res = await db.query(collection, query);
logs.out(
"authUtils.checkRequest: DB Query result: " + JSON.stringify(res),
"dbug"
);
logger.debug(res, "checkRequest: DB Lookup result");
const result =
res.length > 0 && res[0].time
? { result: true, domain: res[0].domain }
@@ -37,7 +34,7 @@ async function checkRequest(key: string) {
// Creates an API key for a user
async function generateKey() {
// Needs testing & moving to 'register.utils'
// Needs testing & moving to 'register.utils' ??? Why does it need moving?
return crypt.randomUUID();
}
@@ -54,9 +51,9 @@ async function generateConfirmationEmail(eml: string, uuid: string) {
html: htmlMin,
};
} catch (err) {
logs.out(
"mailServices.generateConfirmationEmail: Error reading template, " + err,
"err"
logger.error(
err,
"generateConfirmationEmail: Error rendering email templates"
);
return false;
}

View File

@@ -18,6 +18,7 @@ async function checkCrs(input = "") {
}
// Needs to be moved to the frontend `ensureArray() func`
// Usage of this function should be migrated to the `translator` utilities.
async function cleanMessages(input) {
log.out("ldbUtils.cleanMessages: Deprecated function has been called", "err");
var out = [];

19
src/utils/logger.utils.ts Normal file
View File

@@ -0,0 +1,19 @@
import pino from "pino";
const runtime = process.env.NODE_ENV;
let level: string;
if (runtime === "production") {
level = "info";
} else {
level = "debug";
}
export const logger = pino({
level: level,
formatters: {
level: (label) => {
return { level: label.toUpperCase() };
},
},
timestamp: pino.stdTimeFunctions.isoTime,
});

View File

@@ -1,7 +1,11 @@
import { logger } from "./logger.utils";
const htmlShrink = require("html-minifier").minify;
const juice = require("juice");
// Inlines styles and minifies the inlined HTML
async function minifyMail(input: string): Promise<string> {
logger.trace("minifyMail: Minifying mail output");
const inlined: string = juice(input);
return htmlShrink(inlined, {
removeComments: true,

View File

@@ -1,4 +1,7 @@
import { logger } from "./logger.utils";
export function removeNewlineAndPTag(input: string): string {
logger.debug("removeNewlineAndPTag: Cleaning string");
const regex = /[\n\r]|<\/?p[^>]*>/g;
return input.replace(regex, function (match) {
if (match === "\n" || match === "\r") {

View File

@@ -1,14 +1,19 @@
//const log = require('../utils/log.utils');
import { logger } from "./logger.utils";
function removeNonAlphanumeric(inputString: string) {
logger.debug("removeNonAlphanumeric: Sanitizing string");
return inputString.replace(/[^a-zA-Z0-9]/g, "");
}
function removeNonAlpha(inputString: string) {
logger.debug("removeNonAlpha: Sanitizing string");
return inputString.replace(/[^a-zA-Z]/g, "");
}
function removeNonNumeric(inputString: string) {
logger.debug("removeNonNumeric: Sanitizing string");
return inputString.replace(/[^0-9]/g, "");
}
@@ -16,15 +21,17 @@ const cleanApiEndpointTxt = removeNonAlpha;
const cleanApiEndpointNum = removeNonAlphanumeric;
function cleanNrcc(input: string) {
logger.error("DEPRECATED FUNCTION", "cleanNrcc: Converting NRCC Data");
// Remove newlines and then <p> tags from input
const cleanInput = input.replace(/[\n\r]/g, "").replace(/<\/?p[^>]*>/g, "");
return cleanInput;
}
function getDomainFromEmail(mail: string) {
logger.debug("getDomainFromEmail: Obtaining domain from email address");
// Needs testing
let split = mail.split("@");
return split[1];
return split[1].toLowerCase();
}
module.exports = {

View File

@@ -1,14 +1,19 @@
function unixLocal(unix: number) {
import { logger } from "./logger.utils";
function unixLocal(unix: number): string {
logger.trace(`unixLocal: Converting time: ${unix}`);
var jsTime = unix * 1000;
var dt = new Date(jsTime);
return dt.toLocaleString();
}
function jsUnix(js: number) {
var preRound = js / 1000;
return Math.round(preRound);
function jsUnix(js: number): number {
logger.trace(`jsUnix: Converting time: ${js}`);
return Math.floor(js / 1000);
}
export { jsUnix, unixLocal };
module.exports = {
unixLocal,
jsUnix,

View File

@@ -8,6 +8,8 @@ import type {
import { tz } from "moment-timezone";
import { removeNewlineAndPTag } from "../../newSanitizer";
import { logger } from "../../logger.utils";
/// I do not yet have a type defined for any of the input object
export function transform(input: any): StaffLdb | null {
console.time("StaffLdb Transformation");
@@ -24,20 +26,26 @@ export function transform(input: any): StaffLdb | null {
ferryServices: transformTrainServices(data?.ferryServices) || undefined,
};
console.timeEnd("StaffLdb Transformation");
return output;
if (output.locationName !== "Not Found") {
return output;
}
} catch (err) {
console.log("utils/translators/ldb/staffLdb.transform: Caught Error");
console.log("Unable to parse data, assuming no data: " + err);
logger.error(err, "utils/translators/ldb/staffLdb.transform");
}
console.timeEnd("StaffLdb Transformation");
return null;
}
function transformDateTime(input: string): Date {
logger.trace("utils/translators/ldb/staffLdb.transformDateTime: Running");
return new Date(input);
}
function transformNrcc(input: any): NrccMessage[] | undefined {
logger.trace("utils/translators/ldb/staffLdb.transformNrcc: Running");
if (input === undefined) {
return input;
}
let output: NrccMessage[] = [];
let messages = input;
if (!Array.isArray(input?.message)) {
@@ -57,6 +65,9 @@ function transformNrcc(input: any): NrccMessage[] | undefined {
}
function transformTrainServices(input: any): TrainServices[] {
logger.trace(
"utils/translators/ldb/staffLdb.transformTrainServices: Running"
);
let services: any = input?.service;
let output: TrainServices[] = [];
if (services === undefined) {
@@ -66,6 +77,7 @@ function transformTrainServices(input: any): TrainServices[] {
services = [input.service];
}
for (const service of services) {
const times = parseTimes(service);
const trainService: TrainServices = {
rid: service?.rid,
uid: service?.uid,
@@ -73,7 +85,7 @@ function transformTrainServices(input: any): TrainServices[] {
operatorCode: service?.operatorCode || "UK",
platform: service?.platform || "-",
platformIsHidden: service?.platformIsHidden,
serviceIsSupressed: service?.serviceIsSupressed,
serviceIsSupressed: checkIsSupressed(service),
origin: transformLocation(service?.origin),
destination: transformLocation(service?.destination),
length: calculateLength(service),
@@ -82,12 +94,12 @@ function transformTrainServices(input: any): TrainServices[] {
delayReason: service?.delayReason,
arrivalType: service?.arrivalType,
departureType: service?.departureType,
sta: transformUnspecifiedDateTime(service?.sta),
eta: transformUnspecifiedDateTime(service?.eta),
ata: transformUnspecifiedDateTime(service?.ata),
std: transformUnspecifiedDateTime(service?.std),
etd: transformUnspecifiedDateTime(service?.etd),
atd: transformUnspecifiedDateTime(service?.atd),
sta: times.sta,
eta: times.eta,
ata: times.ata,
std: times.std,
etd: times.etd,
atd: times.atd,
};
Object.keys(trainService).forEach(
(key) => trainService[key] === undefined && delete trainService[key]
@@ -97,7 +109,17 @@ function transformTrainServices(input: any): TrainServices[] {
return output;
}
function checkIsSupressed(service: TrainServices): string | undefined {
logger.trace("utils/translators/ldb/staffStation.checkIsSupressed: Running");
if (service.serviceIsSupressed === "true" || service.isPassengerService === "false") {
return "true";
} else {
return undefined;
}
}
function transformLocation(input: any): ServiceLocation[] {
logger.trace("utils/translators/ldb/staffStation.transformLocation: Running");
let output: ServiceLocation[] = [];
let locations: any[] = input.location;
if (!Array.isArray(input.location)) {
@@ -116,6 +138,7 @@ function transformLocation(input: any): ServiceLocation[] {
}
export function calculateLength(input: any): number | undefined {
logger.trace("utils/translators/ldb/staffStation.calculateLength: Running");
let length: number;
if (input?.length) {
length = input.length;
@@ -129,9 +152,66 @@ export function calculateLength(input: any): number | undefined {
}
function transformUnspecifiedDateTime(input: string): Date | undefined {
logger.trace(
"utils/translators/ldb/staffStation.transformUnspecifiedDateTime: Running"
);
if (!input) {
return undefined;
}
const date = tz(input, "Europe/London");
const date = tz(input, "Europe/London"); // Want to be creating a moment object using moment.tz(...)
return date.toDate();
}
function parseTimes(service: TrainServices) {
logger.trace("utils/translators/ldb/staffStation.parseTimes: Running");
let { sta, eta, ata, std, etd, atd } = Object.fromEntries(
Object.entries(service).map(([key, value]) => [
key,
transformUnspecifiedDateTime(value),
])
);
let etaResult: Date | undefined | string = eta;
let ataResult: Date | undefined | string = ata;
let etdResult: Date | undefined | string = etd;
let atdResult: Date | undefined | string = atd;
if (sta) {
if (
eta !== undefined &&
Math.abs(eta.getTime() - sta.getTime()) / 60000 <= 1.5
) {
etaResult = "RT";
}
if (
ata !== undefined &&
Math.abs(ata.getTime() - sta.getTime()) / 60000 <= 1.5
) {
ataResult = "RT";
}
}
if (std) {
if (
etd !== undefined &&
Math.abs(etd.getTime() - std.getTime()) / 60000 <= 1.5
) {
etdResult = "RT";
}
if (
atd !== undefined &&
Math.abs(atd.getTime() - std.getTime()) / 60000 <= 1.5
) {
atdResult = "RT";
}
}
return {
sta: sta,
eta: etaResult,
ata: ataResult,
std: std,
etd: etdResult,
atd: atdResult,
};
}