2024-02-16 20:27:00 +02:00
const log = require ( '../services/log.ts' ) ;
2023-11-22 19:34:48 +01:00
const fileService = require ( './api/files.js' ) ;
const scriptService = require ( '../services/script.js' ) ;
const cls = require ( '../services/cls.js' ) ;
const sql = require ( '../services/sql.js' ) ;
const becca = require ( '../becca/becca.js' ) ;
2019-01-27 12:28:20 +01:00
2021-05-15 22:57:23 +02:00
function handleRequest ( req , res ) {
2020-06-22 23:13:53 +02:00
// express puts content after first slash into 0 index element
2019-03-24 22:41:53 +01:00
2020-06-22 23:13:53 +02:00
const path = req . params . path + req . params [ 0 ] ;
2019-03-24 22:41:53 +01:00
2021-05-02 19:59:16 +02:00
const attributeIds = sql . getColumn ( "SELECT attributeId FROM attributes WHERE isDeleted = 0 AND type = 'label' AND name IN ('customRequestHandler', 'customResourceProvider')" ) ;
const attrs = attributeIds . map ( attrId => becca . getAttribute ( attrId ) ) ;
2019-01-27 15:47:40 +01:00
2020-06-22 23:13:53 +02:00
for ( const attr of attrs ) {
2020-11-06 21:52:57 +01:00
if ( ! attr . value . trim ( ) ) {
continue ;
}
2023-04-22 19:37:49 +08:00
const regex = new RegExp ( ` ^ ${ attr . value } $ ` ) ;
2020-06-22 23:13:53 +02:00
let match ;
2019-01-27 12:28:20 +01:00
2020-06-22 23:13:53 +02:00
try {
match = path . match ( regex ) ;
}
catch ( e ) {
2023-05-03 10:23:20 +02:00
log . error ( ` Testing path for label ' ${ attr . attributeId } ', regex ' ${ attr . value } ' failed with error: ${ e . message } , stack: ${ e . stack } ` ) ;
2020-06-22 23:13:53 +02:00
continue ;
}
if ( ! match ) {
continue ;
}
2019-01-27 15:47:40 +01:00
2020-06-22 23:13:53 +02:00
if ( attr . name === 'customRequestHandler' ) {
2020-06-24 22:08:31 +02:00
const note = attr . getNote ( ) ;
2019-01-27 12:28:20 +01:00
2023-05-03 10:23:20 +02:00
log . info ( ` Handling custom request ' ${ path } ' with note ' ${ note . noteId } ' ` ) ;
2019-01-27 12:28:20 +01:00
try {
2020-06-24 22:08:31 +02:00
scriptService . executeNote ( note , {
2020-06-22 23:13:53 +02:00
pathParams : match . slice ( 1 ) ,
req ,
res
} ) ;
2019-01-27 12:28:20 +01:00
}
catch ( e ) {
2023-05-03 10:23:20 +02:00
log . error ( ` Custom handler ' ${ note . noteId } ' failed with: ${ e . message } , ${ e . stack } ` ) ;
2019-01-27 16:37:18 +01:00
2022-07-01 00:01:29 +02:00
res . setHeader ( "Content-Type" , "text/plain" )
. status ( 500 )
. send ( e . message ) ;
2019-01-27 16:37:18 +01:00
}
2020-06-22 23:13:53 +02:00
}
else if ( attr . name === 'customResourceProvider' ) {
2023-05-03 10:23:20 +02:00
fileService . downloadNoteInt ( attr . noteId , res ) ;
2020-06-22 23:13:53 +02:00
}
else {
2023-05-03 10:23:20 +02:00
throw new Error ( ` Unrecognized attribute name ' ${ attr . name } ' ` ) ;
2020-06-22 23:13:53 +02:00
}
2019-01-27 16:37:18 +01:00
2023-05-05 23:41:11 +02:00
return ; // only the first handler is executed
2020-06-22 23:13:53 +02:00
}
2019-01-27 16:37:18 +01:00
2023-05-03 10:23:20 +02:00
const message = ` No handler matched for custom ' ${ path } ' request. ` ;
2019-02-03 11:15:32 +01:00
2020-06-22 23:13:53 +02:00
log . info ( message ) ;
2022-07-01 00:01:29 +02:00
res . setHeader ( "Content-Type" , "text/plain" )
. status ( 404 )
. send ( message ) ;
2020-06-22 23:13:53 +02:00
}
2019-01-27 16:37:18 +01:00
2020-06-22 23:13:53 +02:00
function register ( router ) {
// explicitly no CSRF middleware since it's meant to allow integration from external services
2019-01-27 12:28:20 +01:00
2021-05-15 22:57:23 +02:00
router . all ( '/custom/:path*' , ( req , res , next ) => {
2020-06-22 23:13:53 +02:00
cls . namespace . bindEmitter ( req ) ;
cls . namespace . bindEmitter ( res ) ;
2019-01-27 15:47:40 +01:00
2020-06-22 23:13:53 +02:00
cls . init ( ( ) => handleRequest ( req , res ) ) ;
2019-01-27 12:28:20 +01:00
} ) ;
}
module . exports = {
register
2020-06-20 12:31:38 +02:00
} ;