Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
9849385
Merge branch 'production' into develop
SimonGoring Dec 10, 2025
fde13cb
Bump actions/checkout from 4 to 6
dependabot[bot] Dec 10, 2025
8ec5b41
Bump node from 22-alpine to 25-alpine
dependabot[bot] Dec 10, 2025
5312406
Bump aws-actions/configure-aws-credentials from 4 to 5
dependabot[bot] Dec 10, 2025
dd73f55
Bump eslint-plugin-standard from 4.1.0 to 5.0.0
dependabot[bot] Dec 10, 2025
5664a8a
Bump express from 4.21.2 to 5.2.1
dependabot[bot] Dec 10, 2025
1a13bcb
Merge remote-tracking branch 'origin/dependabot/github_actions/develo…
SimonGoring Dec 10, 2025
de1494d
Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/develop/…
SimonGoring Dec 12, 2025
4475bcd
Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/develop/…
SimonGoring Dec 12, 2025
07138e3
Bump pg-monitor from 1.5.0 to 3.1.0
dependabot[bot] Dec 12, 2025
4a202b4
Bump eslint-plugin-node from 7.0.1 to 11.1.0
dependabot[bot] Dec 12, 2025
1e19bf4
Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/develop/…
SimonGoring Dec 12, 2025
a373082
Merge remote-tracking branch 'origin/dependabot/docker/develop/node-2…
SimonGoring Dec 12, 2025
154b696
Bump passport from 0.6.0 to 0.7.0
dependabot[bot] Dec 12, 2025
6611ef7
Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/develop/…
SimonGoring Dec 12, 2025
54bf86c
Merge remote-tracking branch 'origin/dependabot/github_actions/develo…
SimonGoring Dec 12, 2025
f0d8599
Bump pg-promise from 11.15.0 to 12.3.0
dependabot[bot] Dec 12, 2025
8f8215e
Bump body-parser from 1.20.4 to 2.2.1
dependabot[bot] Dec 12, 2025
81fd753
Bump rotating-file-stream from 2.1.6 to 3.2.7
dependabot[bot] Dec 12, 2025
6bbcb5c
Bump helmet from 7.2.0 to 8.1.0
dependabot[bot] Dec 12, 2025
4187d4f
Bump express-rate-limit from 6.11.2 to 8.2.1
dependabot[bot] Dec 12, 2025
5b2a186
Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/develop/…
SimonGoring Dec 15, 2025
78a057f
Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/develop/…
SimonGoring Dec 15, 2025
e39e3d7
Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/develop/…
SimonGoring Dec 15, 2025
73ac5d8
Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/develop/…
SimonGoring Dec 15, 2025
e527582
making "something broke" error with more informative.
SimonGoring Dec 18, 2025
2cdd44f
Adding query cache and more documentation
SimonGoring Dec 18, 2025
e3d2a0d
Dealing with duplicate query files cleanup
SimonGoring Dec 18, 2025
1f79072
Explicit promise lib call.
SimonGoring Dec 18, 2025
5f375d6
Mostly removing console.log statements to clean up logging.
SimonGoring Dec 18, 2025
084773d
fix: upgrade express from 4.21.2 to 4.22.1
snyk-bot Dec 29, 2025
072ad3e
Merge remote-tracking branch 'origin/snyk-upgrade-017657227f13ea34faf…
SimonGoring Jan 13, 2026
b65a4b2
Bump eslint from 5.16.0 to 9.39.2
dependabot[bot] Jan 13, 2026
e2d6ec2
Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/develop/…
SimonGoring Jan 15, 2026
ddb4640
Fixing up the json error checking
SimonGoring Jan 15, 2026
13b7ed9
Cody linting in the auth.
SimonGoring Jan 15, 2026
c52ac57
Bump dotenv from 8.6.0 to 17.2.3
dependabot[bot] Jan 15, 2026
d114c7b
Merge remote-tracking branch 'origin/dependabot/npm_and_yarn/develop/…
SimonGoring Jan 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Set environment based on branch
run: |
Expand All @@ -31,7 +31,7 @@ jobs:
fi

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
uses: aws-actions/configure-aws-credentials@v5
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:22-alpine
FROM node:25-alpine
WORKDIR /app
COPY package*.json ./
RUN yarn install
Expand Down
154 changes: 75 additions & 79 deletions auth/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,96 +3,92 @@ const path = require('path')
// get global database object
var db = require('../database/pgp_db')
var pgp = db.$config.pgp
pgp.pg.types.setTypeParser(20, parseInt);
pgp.pg.types.setTypeParser(20, parseInt)

function doNothing(req, res, next){
next();
function doNothing (req, res, next) {
next()
}

function authrequired(req, res, next){
console.log("request received at "+ new Date().toGMTString());
var typeHeaderText = req.get('Content-Type');
console.log("typeHeaderText "+typeHeaderText);

var methodPassed = req.query.method || req.body.method;
function authrequired (req, res, next) {
console.log('request received at ' + new Date().toGMTString())
var typeHeaderText = req.get('Content-Type')
console.log('typeHeaderText ' + typeHeaderText)

if (!methodPassed ){
next();
} else {
var methodPassed = req.query.method || req.body.method

console.log("methodPassed ", methodPassed)
var theSchema = methodPassed.split(".")[0];
//see if method requires username, pw
console.log("schema for methodPassed "+theSchema);
var unrestrictedMethods = ["ts.getsteward", "ts.checksteward", "ts.validateusername", "ts.validatesteward"];
console.log("method is restricted " +(unrestrictedMethods.indexOf(methodPassed) == -1 && theSchema == "ts" ));
if (unrestrictedMethods.indexOf(methodPassed) == -1 && theSchema == "ts" ){
console.log("calling parseCredentials");
parseCredentials(req, function(err, req){
if(err){return next(err);}
validateusernamepassword(req, function(err){
if(err){return next(err);}
next();
})
});
} else {
console.log("calling next middleware function with no validation");
//no validation needed
next();
}
if (!methodPassed) {
next()
} else {
console.log('methodPassed ', methodPassed)
var theSchema = methodPassed.split('.')[0]
// see if method requires username, pw
console.log('schema for methodPassed ' + theSchema)
var unrestrictedMethods = ['ts.getsteward', 'ts.checksteward', 'ts.validateusername', 'ts.validatesteward']
console.log('method is restricted ' + (unrestrictedMethods.indexOf(methodPassed) == -1 && theSchema == 'ts'))
if (unrestrictedMethods.indexOf(methodPassed) == -1 && theSchema == 'ts') {
console.log('calling parseCredentials')
parseCredentials(req, function (err, req) {
if (err) { return next(err) }
validateusernamepassword(req, function (err) {
if (err) { return next(err) }
next()
})
})
} else {
console.log('calling next middleware function with no validation')
// no validation needed
next()
}
}
}

function validateusernamepassword(req, callback){
var err;
//call validateusernamepassword
db.query('select * from ts.validatesteward($1, $2)',[req.user.username, req.user.pwd])
.then(function (data) {
//return data;
if ( data.length > 0){
callback();
} else {
err = new Error("Error validating steward");
err.tilia = true;
callback(err);
}

})
.catch(function (err) {
//present error details
err.tilia = true;
return err
})
}

function parseCredentials(req, callback) {
//read other headers
var err
//get header with username, pwd
console.log("parsing headers pwd and username");
//var headerText = req.get('OtherHeaders');
var pwdText = req.get('pwd');
var usernameText = req.get('username');

console.log("username and password "+usernameText+":"+pwdText);
if(!pwdText || !usernameText){
console.log("throwing missing pwd and/or username error");
err = new Error('Headers with username and password were not provided');
err.tilia = true;
callback(err);
function validateusernamepassword (req, callback) {
var err
// call validateusernamepassword
db.query('select * from ts.validatesteward($1, $2)', [req.user.username, req.user.pwd])
.then(function (data) {
// return data;
if (data.length > 0) {
callback()
} else {
var username = usernameText;
var pwd = pwdText;
var user = {};
user.username = username;
user.pwd = pwd;
req.user = user;
callback(null, req);
err = new Error('Error validating steward')
err.tilia = true
callback(err)
}
})
.catch(function (err) {
// present error details
err.tilia = true
return err
})
}

}
function parseCredentials (req, callback) {
// read other headers
var err
// get header with username, pwd
console.log('parsing headers pwd and username')
// var headerText = req.get('OtherHeaders');
var pwdText = req.get('pwd')
var usernameText = req.get('username')

console.log('username and password ' + usernameText + ':' + pwdText)
if (!pwdText || !usernameText) {
console.log('throwing missing pwd and/or username error')
err = new Error('Headers with username and password were not provided')
err.tilia = true
callback(err)
} else {
var username = usernameText
var pwd = pwdText
var user = {}
user.username = username
user.pwd = pwd
req.user = user
callback(null, req)
}
}

module.exports = {
authRequired: authrequired
}
authRequired: authrequired
}
4 changes: 2 additions & 2 deletions database/pgp_db.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const promise = require('bluebird')
const pgPromise = require('pg-promise')

const options = {
// Initialization Options
promiseLib: promise,
promiseLib: pgPromise.promise,
capSQL: true,
query (e) {
var date = new Date()
Expand Down
27 changes: 4 additions & 23 deletions handlers/data_handlers.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
// get global database object
const readLastLines = require('read-last-lines')

function handleGetUpdate (req, res, next) {
// This just redirects to the all function output.
// var date = new Date()
// console.log(date.toISOString + ' calling handleGetUpdate')
var pgFunk = require('../pgfunctions/pgfunction.js')
pgFunk.allFunctions(req, res, next)
}
const pgFunk = require('../pgfunctions/pgfunction.js')

function handleDelete (req, res, next) {
var data = {
Expand All @@ -19,7 +12,6 @@ function handleDelete (req, res, next) {
data: data,
message: 'Called DELETE api/update'
})

}

function returnLog (req, res, next) {
Expand Down Expand Up @@ -102,41 +94,29 @@ function handlePostMultiUpdate (req, res, next) {
// 1. validate method name
db.func('ti.getprocedureinputparams', [methodSubmitted])
.then(function (data) {
// returns array of object
// { 'name': '_units', 'type': 'character varying', 'isdefault': false, 'paramorder': 1 }
// console.log('handlePostMultiRequest data: ' + JSON.stringify(data))

var arrOfPgParams = []

// process key|value for parameter inputs
if (data.length > 0) {
console.log(functionInputs)
// process array with one collection for each method call
functionInputs.forEach(function (d, i) {
// console.log('parameter collection ' + i + ' is: ' + JSON.stringify(d))
var pgParamArray = []
data.forEach(function (e, i) {
// console.log('Input ' + e.name + ' has value ' + d[e.name])
pgParamArray.push(d[e.name])
})
// add array of input values to batch collection
arrOfPgParams.push(pgParamArray)
})
}

// console.log('Collection input parameters is: ' + JSON.stringify(arrOfPgParams))
var numOfCalls = arrOfPgParams.length

// console.log('Number of function calls to make: ' + numOfCalls)

requestFactory(methodSubmitted, arrOfPgParams, req, function (arrOfCalls) {
var dbb = req.app.locals.db
dbb.task(function (t) {
return t.batch(arrOfCalls)
})
.then(function (theResult) {
// console.log('batch result ' + JSON.stringify(theResult))
// have array of arrays containing object key|newid
var batchData = []
theResult.forEach(function (r) {
if (r[0]) {
Expand Down Expand Up @@ -171,12 +151,13 @@ function handlePostMultiUpdate (req, res, next) {
module.exports = {
allfunctions: function (req, res, next) {
/* This is returning the block query that is used to list the available functions. */
var pgFunk = require('../pgfunctions/pgfunction.js')
pgFunk.allFunctions(req, res, next)
},
// handlePostUpdate: handlePostUpdate,
handleGetUpdate: function (req, res, next) {
pgFunk.allFunctions(req, res, next)
},
handlePostMultiUpdate: handlePostMultiUpdate,
handleGetUpdate: handleGetUpdate,
handleDelete: handleDelete,
handleLogs: returnLog
}
24 changes: 12 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,34 @@
"dependencies": {
"@terraformer/wkt": "^2.2.0",
"bluebird": "^3.7.2",
"body-parser": "^1.20.2",
"body-parser": "^2.2.1",
"child_process": "^1.0.2",
"compression": "^1.7.4",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"debug": "^4.3.1",
"dotenv": "^8.2.0",
"dotenv": "^17.2.3",
"ejs": "^3.1.8",
"express": "~4.21.0",
"express-rate-limit": "^6.9.0",
"helmet": "^7.1.0",
"express": "~5.2.1",
"express-rate-limit": "^8.2.1",
"helmet": "^8.1.0",
"json5": "^2.2.3",
"morgan": "~1.10.0",
"node-postgres": "^0.6.2",
"passport": "^0.6.0",
"pg-monitor": "^1.4.1",
"pg-promise": "^11.5.5",
"passport": "^0.7.0",
"pg-monitor": "^3.1.0",
"pg-promise": "^11.15.0",
"read-last-lines": "^1.8.0",
"rotating-file-stream": "^2.1.3",
"rotating-file-stream": "^3.2.7",
"serve-favicon": "~2.5.0"
},
"devDependencies": {
"eslint": "^5.16.0",
"eslint": "^9.39.2",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^7.0.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.1.0",
"eslint-plugin-standard": "^5.0.0",
"pre-commit": "^1.2.2"
},
"description": "A repository for the implementation of the Tilia/uploader API. This API is intended to replace the current [Tilia API](https://tilia.neotomadb.org) which uses the SQL Server database and a .NET front end.",
Expand Down
7 changes: 3 additions & 4 deletions pgfunctions/pgfunction.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ function allFunctions (req, res, next) {
// Get the input parameters:
var outobj = resultset
}

var noParam = Object.keys(outobj).length === 0

var pgp = db.$config.pgp
Expand All @@ -36,12 +37,13 @@ function allFunctions (req, res, next) {
pgp.pg.types.setTypeParser(1700, function (val) {
return parseInt(val)
})
const schemFunc = sql('../pgfunctions/get_schema.sql', pgp)
const queryFunc = sql('../pgfunctions/fun_query.sql', pgp)

// The call to the documentation JSON object occurs if the user either
// enters no parameters, or the term 'method' fails to appear in the
// user query string.
if (noParam | !outobj.method) {
let queryFunc = sql('../pgfunctions/fun_query.sql', pgp)
// We're passing in the raw "/api/" endoint, which requests the set of all functions.
db.any(queryFunc)
.then(data => {
Expand Down Expand Up @@ -72,7 +74,6 @@ function allFunctions (req, res, next) {
// Here we wind up with the different schema.
// First validate that the method is in the accepted set for GET calls:
if (funcSchema !== 'ts' || ['validateusername', 'validatesteward', 'checksteward'].includes(funcName)) {
let queryFunc = sql('../pgfunctions/fun_query.sql', pgp)
var schema = db.any(queryFunc)
.then(function (data) {
// Check that outobj.method is in the set of data[name]:
Expand All @@ -82,7 +83,6 @@ function allFunctions (req, res, next) {
.then(function (data) {
if (data.includes(outobj.method)) {
// If the function called by the user is in the set of existing Postgres functions:
let schemFunc = sql('../pgfunctions/get_schema.sql', pgp)
db.any(schemFunc, [funcName])
.then(function (data) {
let dbFunction = funcSchema + '.' + funcName
Expand All @@ -92,7 +92,6 @@ function allFunctions (req, res, next) {
QueryParams = {}
} else {
for (let a in QueryArgs) {
console.log(typeof outobj[QueryArgs[a]])
if (typeof outobj[QueryArgs[a]] === 'string' || outobj[QueryArgs[a]] instanceof String) {
var replaced = outobj[QueryArgs[a]]
replaced = replaced.replace(/^"(.*)"$/g, '$1')
Expand Down
Loading