Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
oklemenz2 committed Feb 19, 2025
1 parent f4bc9de commit 31ad1cf
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 74 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ Options can be passed to SDK via CDS environment via `cds.rerquires.sap-afc-sdk`
- `ui.launchpad: Boolean`: Serve launchpad. Default `true`
- `ui.scheduling.monitoring.job: Boolean`: Serve Scheduling Monitoring Job. Default `true`
- `ui.api.scheduling.job.swagger: Boolean`: Serve Scheduling Provider Swagger UI. Default `true`
- `broker: Boolean | Object`: Broker configuration. Serve broker endpoint, if truthy. Default `true` in `production`
- `broker: Boolean | Object`: Broker configuration. Serve broker endpoint, if truthy. Default `false` and `true` in `production`
- `mockProcessing: Boolean | Object`: Activate mocked job processing. Default `false`
- `mockProcessing.default: String`: Default processing status. Default `completed`
- `mockProcessing.min: Number`: Minimum processing time in seconds. Default `0`
Expand All @@ -161,6 +161,8 @@ Options can be passed to SDK via CDS environment via `cds.rerquires.sap-afc-sdk`
- `mockProcessing.status.completedWithError: Number`: Completed With Error status distribution value
- `mockProcessing.status.failed: Number`: Failed status distribution value
- `config: Object`: SDK configuration
- `csp: Object | Boolean`: Content Security Policy (CSP). Default `true`
- `cors: Object | Boolean`: Cross-Origin Resource Sharing (CORS) configuration. Default `true`

### Implementation

Expand Down
8 changes: 4 additions & 4 deletions REUSE.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
version = 1
SPDX-PackageName = "-cap-js-community-sap-afc-sdk"
SPDX-PackageSupplier = "ospo@sap.com"
SPDX-PackageDownloadLocation = "<https://github.com/cap-js-community/YOUR-REPO-NAME>"
SPDX-PackageName = "sap-afc-sdk"
SPDX-PackageSupplier = "Oliver Klemenz <oklemenz@gmail.com>, Maximilian Gruenfelder <[email protected]>"
SPDX-PackageDownloadLocation = "<https://github.com/cap-js-community/sap-afc-sdk"
SPDX-PackageComment = "The code in this project may include calls to APIs (\"API Calls\") of\n SAP or third-party products or services developed outside of this project\n (\"External Products\").\n \"APIs\" means application programming interfaces, as well as their respective\n specifications and implementing code that allows software to communicate with\n other software.\n API Calls to External Products are not licensed under the open source license\n that governs this project. The use of such API Calls and related External\n Products are subject to applicable additional agreements with the relevant\n provider of the External Products. In no event shall the open source license\n that governs this project grant any rights in or to any External Products,or\n alter, expand or supersede any terms of the applicable additional agreements.\n If you have a valid license agreement with SAP for the use of a particular SAP\n External Product, then you may make use of any API Calls included in this\n project's code for that SAP External Product, subject to the terms of such\n license agreement. If you do not have a valid license agreement for the use of\n a particular SAP External Product, then you may only make use of any API Calls\n in this project for that SAP External Product for your internal, non-productive\n and non-commercial test and evaluation of such API Calls. Nothing herein grants\n you any rights to use or access any SAP External Product, or provide any third\n parties the right to use of access any SAP External Product, through API Calls."

[[annotations]]
path = "**"
precedence = "aggregate"
SPDX-FileCopyrightText = "2025 SAP SE or an SAP affiliate company and -cap-js-community-sap-afc-sdk contributors"
SPDX-FileCopyrightText = "2025 SAP SE or an SAP affiliate company and sap-afc-sdk contributors"
SPDX-License-Identifier = "Apache-2.0"
17 changes: 15 additions & 2 deletions bin/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ module.exports = (target) => {
fs.rmSync(appPath, { recursive: true, force: true });
}
}
// CF
adjustText("mta.yaml", (content) => {
content = replaceTextPart(content, "service-plan: application", "service-plan: broker");
for (const app of appStubs) {
const part = `path: app/${app}`;
const replacement = `path: node_modules/@cap-js-community/sap-afc-sdk/app/${app}`;
Expand All @@ -34,7 +36,19 @@ module.exports = (target) => {
}
return content;
});
// TODO: K8S
// Kyma
adjustText("chart/values.yaml", (content) => {
content = replaceTextPart(content, "servicePlanName: application", "servicePlanName: broker");
// TODO: replace app stub paths in containerize
return content;
});
// Approuter
adjustJSON("app/router/xs-app.json", (json) => {
json.routes = json.routes.filter((route) => {
return !route.localDir;
});
json.websockets = { enabled: true };
});
} catch (err) {
console.error(err.message);
}
Expand All @@ -58,7 +72,6 @@ function replaceTextPart(content, part, replacement, positionPart) {
return content.slice(0, index) + replacement + content.slice(index + part.length);
}

// eslint-disable-next-line no-unused-vars
function adjustJSON(file, callback) {
const filePath = path.join(process.cwd(), file);
if (fs.existsSync(filePath)) {
Expand Down
66 changes: 53 additions & 13 deletions cds-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ const path = require("path");
const cds = require("@sap/cds");
const Broker = require("@sap/sbf");
const express = require("express");
const helmet = require("helmet");
const cors = require("cors");
const swaggerUi = require("swagger-ui-express");
const { config: eventQueueConfig } = require("@cap-js-community/event-queue");
const { StatusCodes, getReasonPhrase } = require("http-status-codes");
const toggles = require("@cap-js-community/feature-toggle-library");
const { config: eventQueueConfig } = require("@cap-js-community/event-queue");

const { mergeDeep } = require("./src/util/helper");

Expand All @@ -16,6 +19,7 @@ const config = mergeDeep(require("./config"), cds.env.requires?.["sap-afc-sdk"]?
process.env.CDS_PLUGIN_PACKAGE ??= "@cap-js-community/sap-afc-sdk";

cds.on("bootstrap", () => {
secureRoutes();
addErrorMiddleware();
serveBroker();
serveUIs();
Expand All @@ -27,6 +31,27 @@ cds.on("listening", () => {
handleFeatureToggles();
});

function secureRoutes() {
if (cds.env.requires?.["sap-afc-sdk"]?.csp) {
const csp = toObject(cds.env.requires?.["sap-afc-sdk"]?.csp);
cds.app.use(
helmet({
contentSecurityPolicy: {
directives: {
...helmet.contentSecurityPolicy.getDefaultDirectives(),
"default-src": ["'self'", authorizationUrl(), serverUrl()],
...csp,
},
},
}),
);
}
if (cds.env.requires?.["sap-afc-sdk"]?.cors) {
const corsOptions = toObject(cds.env.requires?.["sap-afc-sdk"]?.cors);
cds.app.use(cors(corsOptions));
}
}

function addErrorMiddleware() {
cds.middlewares.after.unshift(handleError);
}
Expand All @@ -36,24 +61,31 @@ function handleError(err, req, res, next) {
return next(err);
}
if (req.baseUrl?.startsWith("/api/")) {
res.status(err.statusCode || 500).send({
code: err.code || "500",
message: err.message || "Internal Server Error",
});
return;
return handleAPIError(err, req, res);
}
next(err);
}

function handleAPIError(err, req, res) {
let statusCode = StatusCodes.INTERNAL_SERVER_ERROR;
const codes = [err.statusCode, err.status, err.code, err];
for (const code of codes) {
if (!isNaN(code) && StatusCodes[String(code)]) {
statusCode = parseInt(err.statusCode);
break;
}
}
res.status(statusCode).send({
code: String(err.code || statusCode),
message: err.message || getReasonPhrase(statusCode),
});
}

function serveBroker() {
if (!cds.env.requires?.["sap-afc-sdk"]?.broker) {
return;
}
let brokerConfig = {};
const envBrokerConfig = typeof cds.env.requires?.["sap-afc-sdk"]?.broker;
if (envBrokerConfig && typeof envBrokerConfig === "object") {
brokerConfig = envBrokerConfig;
}
let brokerConfig = toObject(cds.env.requires?.["sap-afc-sdk"]?.broker);
const brokerPath = path.join(cds.root, config.paths.broker);
try {
brokerConfig = mergeDeep(require(brokerPath), brokerConfig);
Expand Down Expand Up @@ -208,10 +240,10 @@ function toOpenApiDoc(req, service, name) {
}

function serverUrl() {
// TODO: K8S
// TODO: Kyma
return process.env.VCAP_APPLICATION
? "https://" + JSON.parse(process.env.VCAP_APPLICATION).uris?.[0]
: cds.server.url;
: (cds.server.url ?? `http://localhost:${process.env.PORT || cds.env.server?.port || 4004}`);
}

function authorizationUrl() {
Expand Down Expand Up @@ -245,3 +277,11 @@ function handleFeatureToggles() {
});
}
}

function isObject(value) {
return value !== undefined && value !== null && typeof value === "object";
}

function toObject(value) {
return isObject(value) ? value : {};
}
109 changes: 57 additions & 52 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 31ad1cf

Please sign in to comment.