131 lines
3.5 KiB
JavaScript
131 lines
3.5 KiB
JavaScript
const cds = require("@sap/cds")
|
|
//const cds_sandbox = require("sap/cds/sandbox")
|
|
const { VM, VMScript } = require("vm2")
|
|
const fs = require("fs")
|
|
const path = require("path")
|
|
const { nextTick } = require("process")
|
|
|
|
class AdminService extends cds.ApplicationService {
|
|
init() {
|
|
this.after("READ", async (result, req) => {
|
|
if (!(result === undefined || result == null)) {
|
|
const code = getCode(req.target.name, "READ")
|
|
if (code) {
|
|
await executeCode.call(this, code, req, result)
|
|
}
|
|
}
|
|
})
|
|
|
|
this.before("CREATE", async (req) => {
|
|
const code = getCode(req.target.name, "CREATE")
|
|
if (code) {
|
|
await executeCode.call(this, code, req)
|
|
}
|
|
})
|
|
|
|
this.before("UPDATE", async (req) => {
|
|
const code = getCode(req.target.name, "CREATE")
|
|
if (code) {
|
|
await executeCode.call(this, code, req)
|
|
}
|
|
})
|
|
|
|
this.on("*", async (req, next) => {
|
|
if (!(req.target === undefined || req.target == null)) return next()
|
|
//ToDo: check whether action or event is part of an extension
|
|
if (req.constructor.name === "EventMessage") {
|
|
const code = getCode(req.event, "ON")
|
|
if (code) {
|
|
await executeCode.call(this, code, req)
|
|
}
|
|
} else if (req.constructor.name === "ODataRequest") {
|
|
var output = {}
|
|
const code = getCode(this.name + "." + req.event, "ON")
|
|
if (code) {
|
|
await executeCode.call(this, code, req, {}, output)
|
|
return output
|
|
}
|
|
}
|
|
})
|
|
|
|
//ToDo: Prefix for Service not in event emitter
|
|
this.before("CREATE", "Authors", async (req) => {
|
|
let Author = req.data
|
|
await this.emit("createdAuthor", { Author })
|
|
|
|
})
|
|
|
|
return super.init()
|
|
}
|
|
}
|
|
|
|
var counter = 1;
|
|
|
|
function newLabel() {return "VM2 - req: " + counter++}
|
|
|
|
function getCodeFromFile(name, operation) {
|
|
const filename = name + "." + operation + ".js"
|
|
const file = path.join(__dirname, "..", "handlers", filename)
|
|
try {
|
|
const code = fs.readFileSync(file, "utf8")
|
|
return code
|
|
} catch (error) {
|
|
return ""
|
|
}
|
|
}
|
|
|
|
function getCodeFromAnnotation(name, operation) {
|
|
return ""
|
|
}
|
|
|
|
function getCode(name, operation) {
|
|
let code=getCodeFromAnnotation(name, operation)
|
|
if (code==="") {code=getCodeFromFile(name, operation)}
|
|
return code
|
|
}
|
|
|
|
function scanCode(code) {
|
|
//ESLINT
|
|
}
|
|
|
|
async function executeCode(code, req, result, output) {
|
|
const srv = this
|
|
const label=newLabel()
|
|
console.time(label)
|
|
const vm = new VM({
|
|
console: "inherit",
|
|
timeout: 500,
|
|
allowAsync: true,
|
|
sandbox: { req,
|
|
result,
|
|
output,
|
|
SELECT : (class extends require('@sap/cds/lib/ql/SELECT') {then(r,e) {return srv.run(this).then(r,e)}})._api(),
|
|
INSERT : (class extends require('@sap/cds/lib/ql/INSERT') {then(r,e) {return srv.run(this).then(r,e)}})._api(),
|
|
UPDATE : (class extends require('@sap/cds/lib/ql/UPDATE') {then(r,e) {return srv.run(this).then(r,e)}})._api(),
|
|
CREATE : (class extends require('@sap/cds/lib/ql/CREATE') {then(r,e) {return srv.run(this).then(r,e)}})._api(),
|
|
//srv: this,
|
|
JSON },
|
|
})
|
|
|
|
try {
|
|
await vm.run(code)
|
|
return output
|
|
} catch (error) {
|
|
console.log(error)
|
|
req.reject("409", "Error in VM")
|
|
}
|
|
finally {
|
|
console.timeEnd(label)
|
|
}
|
|
// console.log(req.data)
|
|
}
|
|
/** Generate primary keys for target entity in request */
|
|
async function genid(req) {
|
|
const { ID } = await cds
|
|
.tx(req)
|
|
.run(SELECT.one.from(req.target).columns("max(ID) as ID"))
|
|
req.data.ID = ID - (ID % 100) + 100 + 1
|
|
}
|
|
|
|
module.exports = { AdminService }
|