You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

@sap/html5-app-deployer

Package Overview
Dependencies
Maintainers
1
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sap/html5-app-deployer - npm Package Compare versions

Comparing version

to
3.2.0

8

CHANGELOG.md

@@ -8,2 +8,10 @@ # Change Log

## 3.2.0 - 2021-10-24
### Added
- Mutual Transport Layer Security (mTLS) handling
### Fixed
- html5-repo credentials handling
## 3.1.1 - 2021-07-20

@@ -10,0 +18,0 @@

55

lib/deployerHandler.js

@@ -6,10 +6,11 @@ /* eslint-disable no-console */

var utils = require('./utils');
var fs = require('fs');
var async = require('async');
var path = require('path');
var http = require('http');
var log = require('cf-nodejs-logging-support');
var DestinationUtils = require('./destination-utils');
var GACDHandler = require('./gacd-handler');
const utils = require('./utils');
const fs = require('fs');
const async = require('async');
const path = require('path');
const http = require('http');
const log = require('cf-nodejs-logging-support');
const DestinationUtils = require('./destination-utils');
const GACDHandler = require('./gacd-handler');
const xssec = require('@sap/xssec');

@@ -30,5 +31,5 @@ exports.startDeployer = startDeployer;

function start(cb) {
var service;
var resourcesFolder;
var loggingLevel = process.env.APP_LOG_LEVEL || 'info';
let service;
let resourcesFolder;
let loggingLevel = process.env.APP_LOG_LEVEL || 'info';
// define logger

@@ -67,9 +68,9 @@ log.setLoggingLevel(loggingLevel);

function executeUpload(service, resourcesFolder, cb) {
var appsZips = [];
var cwd = utils.getCwd();
var resourcesPath = path.join(cwd, resourcesFolder);
var buildDirectory = path.join(resourcesPath, '../deploymentTemp');
var folderEntries = fs.readdirSync(resourcesPath);
let appsZips = [];
let cwd = utils.getCwd();
let resourcesPath = path.join(cwd, resourcesFolder);
let buildDirectory = path.join(resourcesPath, '../deploymentTemp');
let folderEntries = fs.readdirSync(resourcesPath);
// Get Token, Archive and Upload
utils.obtainToken(service, function (err, token) {
xssec.requests.requestClientCredentialsToken(null, service.credentials.uaa, null, null, (err, token) => {
if (err) {

@@ -80,8 +81,8 @@ return cb(err);

function (appDirName, iterateCb) { // for each entry
var appResourcesPath = path.join(resourcesPath, appDirName);
if (utils.isZipFile(appResourcesPath)){
let appResourcesPath = path.join(resourcesPath, appDirName);
if (utils.isZipFile(appResourcesPath)) {
appsZips.push(appResourcesPath);
return iterateCb();
} else {
var applicationZip = path.join(buildDirectory, appDirName + '.zip');
let applicationZip = path.join(buildDirectory, appDirName + '.zip');
utils.archive(appResourcesPath, buildDirectory, applicationZip,

@@ -102,5 +103,5 @@ function (err) {

let contentZipPath = path.join(buildDirectory, 'content.zip');
let gacdHandler = new GACDHandler(service,token,contentZipPath);
if (process.env.ASYNC_UPLOAD){
utils.archiveFiles(appsZips,buildDirectory,contentZipPath)
let gacdHandler = new GACDHandler(service, token, contentZipPath);
if (process.env.ASYNC_UPLOAD) {
utils.archiveFiles(appsZips, buildDirectory, contentZipPath)
.then(() => gacdHandler.upload())

@@ -125,6 +126,6 @@ .then(() => gacdHandler.deploy())

function endProcess(err,destinationLogs, cb) {
var server;
var deployId = process.env.DEPLOY_ID || 'none';
var isAsyncUpload = process.env.ASYNC_UPLOAD;
var shouldExitProcess = process.env.EXIT_PROCESS_AFTER_UPLOAD;
let server;
let deployId = process.env.DEPLOY_ID || 'none';
let isAsyncUpload = process.env.ASYNC_UPLOAD;
let shouldExitProcess = process.env.EXIT_PROCESS_AFTER_UPLOAD;

@@ -131,0 +132,0 @@ if (err) {

@@ -99,2 +99,5 @@ /* eslint-disable camelcase */

if (!credentials){
credentials = this._getCredentials('html5-apps-repo');
}
if (!credentials){
return reject('No html5-apps-repo/app-host service instance bound');

@@ -101,0 +104,0 @@ }

@@ -6,22 +6,20 @@ /* eslint-disable no-console */

var fs = require('fs');
var archiver = require('archiver');
var request = require('request');
var requestRetry = require('requestretry');
var uuid = require('uuid/v4');
var path = require('path');
var fileType = require('file-type');
var xsenv = require('@sap/xsenv');
const fs = require('fs');
const archiver = require('archiver');
const request = require('request');
const uuid = require('uuid/v4');
const path = require('path');
const fileType = require('file-type');
const xsenv = require('@sap/xsenv');
const log = require('cf-nodejs-logging-support');
exports.getDTRequestOptions = getDTRequestOptions;
exports.getUAARequestFormData = getUAARequestFormData;
exports.getUAAurl = getUAAurl;
exports.isZipFile = isZipFile;
exports.getService = function () {
var exceptionString = 'Error loading environment';
var html5AppsRepoServiceName;
var services = xsenv.readServices();
if (!services){
const exceptionString = 'Error loading environment';
let html5AppsRepoServiceName;
let services = xsenv.readServices();
if (!services) {
throw new Error(exceptionString + '. ' + 'no services bound');

@@ -38,3 +36,3 @@ }

exports.getResourcesFolder = function (service) {
var resourcesFolder = 'resources';
let resourcesFolder = 'resources';
service.tags.forEach(function (tag) {

@@ -47,23 +45,22 @@ if (tag.indexOf('resources=') === 0) {

};
exports.getCwd = function() {
exports.getCwd = function () {
return process.env.VCAP_SERVICES ? process.env.HOME : process.cwd();
};
exports.validateResourcesFolder = function (resourcesFolder) {
var cwd = exports.getCwd();
var resourcesPath = path.join(cwd, resourcesFolder);
if (!fs.existsSync(resourcesPath)){
let cwd = exports.getCwd();
let resourcesPath = path.join(cwd, resourcesFolder);
if (!fs.existsSync(resourcesPath)) {
throw Error('The resources folder ' + resourcesFolder + ' does not exist or is empty.');
}
if (!fs.lstatSync(resourcesPath).isDirectory()){
if (!fs.lstatSync(resourcesPath).isDirectory()) {
throw Error('The resources folder ' + resourcesFolder + ' is not a directory.');
}
var folderEntries = fs.readdirSync(resourcesPath);
if (!folderEntries || !folderEntries.length){
let folderEntries = fs.readdirSync(resourcesPath);
if (!folderEntries || !folderEntries.length) {
throw Error('The resources folder ' + resourcesFolder + ' is empty.');
}
folderEntries.forEach(function (entry) {
var entryPath = path.join(resourcesPath,entry);
if (!fs.lstatSync(entryPath).isDirectory() && !isZipFile(entryPath)){
let entryPath = path.join(resourcesPath, entry);
if (!fs.lstatSync(entryPath).isDirectory() && !isZipFile(entryPath)) {
throw Error('The resources folder is invalid because it contains the file - ' + entry +

@@ -78,3 +75,4 @@ '; the resources folder should contain application folders and/or zip files.');

|| !service.credentials.uaa || !service.credentials.uaa.url
|| !service.credentials.uaa.clientid || !service.credentials.uaa.clientsecret) {
|| !service.credentials.uaa.clientid ||
(!service.credentials.uaa.clientsecret && !service.credentials.uaa.certificate)) {
throw Error('Incomplete credentials for html5 applications repository service');

@@ -90,4 +88,4 @@ }

var output = fs.createWriteStream(buildFile);
var archive = archiver('zip', {
let output = fs.createWriteStream(buildFile);
let archive = archiver('zip', {
store: true

@@ -118,4 +116,4 @@ });

var output = fs.createWriteStream(buildFile);
var archive = archiver('zip', {
let output = fs.createWriteStream(buildFile);
let archive = archiver('zip', {
store: true

@@ -136,11 +134,11 @@ });

exports.upload = function (service, token, appsZips, cb) {
var requestOptions = getDTRequestOptions(service, token);
var multipartReq = request.put(requestOptions, function onResponse(err, res, body) {
let requestOptions = getDTRequestOptions(service, token);
let multipartReq = request.put(requestOptions, function onResponse(err, res, body) {
if (err) {
log.logMessage('error', 'In UploadFunction: Error in request:');
cb(new Error('Error in request: ' + JSON.stringify(err)));
}
else if (res && res.statusCode === 201) {
} else if (res && res.statusCode === 201) {
cb();
}
else {
} else {
log.logMessage('error', 'In UploadFunction: Error while uploading resources to Server');
cb(new Error('Error while uploading resources to Server; Status: ' + (res && res.statusCode) +

@@ -150,3 +148,3 @@ ' Response: ' + JSON.stringify(body)));

});
var form = multipartReq.form();
let form = multipartReq.form();
appsZips.forEach(function (zipFile) {

@@ -157,36 +155,7 @@ form.append('apps', fs.createReadStream(zipFile), {'content-type': 'application/zip'});

exports.obtainToken = function (service, cb) {
requestRetry.post({
url: getUAAurl(service),
form: getUAARequestFormData(service),
maxAttempts: 5,
retryDelay: 5000,
retryStrategy: requestRetry.RetryStrategies.HTTPOrNetworkError
},
function (err, res, body) {
try {
if (err) {
cb(new Error('Error while obtaining token. ' + err));
}
else if (res.statusCode === 200) {
if (!JSON.parse(body).access_token) {
cb(new Error('Bad token'));
} else {
cb(null, JSON.parse(body).access_token);
}
} else {
cb(new Error('Error while obtaining aaaa token; Status: ' + res.statusCode +
' Response: ' + JSON.stringify(body)));
}
} catch (e) {
cb(new Error('Error while parsing UAA response; ' + e));
}
});
};
exports.isApplicationLogBound = function(){
var applicationLogExist = false;
var exceptionString = 'Error loading environment';
var services = xsenv.readServices();
if (!services){
exports.isApplicationLogBound = function () {
let applicationLogExist = false;
let exceptionString = 'Error loading environment';
let services = xsenv.readServices();
if (!services) {
throw new Error(exceptionString + ' application logs');

@@ -196,3 +165,3 @@ }

for (var service in services) {
if (services[service].label && services[service].label === 'application-logs'){
if (services[service].label && services[service].label === 'application-logs') {
applicationLogExist = true;

@@ -209,14 +178,5 @@ break;

function getUAARequestFormData(service) {
return {
'client_id': service.credentials.uaa.clientid,
'client_secret': service.credentials.uaa.clientsecret,
'grant_type': 'client_credentials',
'response_type': 'token'
};
}
function getDTRequestOptions(service, token) {
var corrID = uuid();
var requestOptions = {
let corrID = uuid();
let requestOptions = {
url: service.credentials.uri + '/applications/content',

@@ -232,6 +192,6 @@ headers: {

function getHtml5AppsRepoServiceName(services) {
if (!services){
if (!services) {
throw new Error();
}
var serviceNames = {};
let serviceNames = {};

@@ -248,11 +208,11 @@ for (var service in services) {

var namesLenght = Object.keys(serviceNames).length;
let namesLenght = Object.keys(serviceNames).length;
if (namesLenght > 1){
if (namesLenght > 1) {
throw new Error('Only one app-host service should be bound');
}
if (namesLenght === 0){
if (namesLenght === 0) {
throw new Error('html5 applications repository service is not bound');
}
if (namesLenght === 1){
if (namesLenght === 1) {
return Object.keys(serviceNames)[0];

@@ -262,15 +222,16 @@ }

function isZipFile(filePath){
var type;
function isZipFile(filePath) {
let type;
if (!fs.existsSync(filePath) || fs.lstatSync(filePath).isDirectory()) { // if it's folder
return false;
}
var buffer = Buffer.alloc(4100);
var fd = fs.openSync(filePath,'r');
let buffer = Buffer.alloc(4100);
let fd = fs.openSync(filePath, 'r');
fs.readSync(fd, buffer, 0, 4100);
type = fileType(buffer);
if (type && type.ext === 'zip'){
if (type && type.ext === 'zip') {
return true;
}
return false;
}
}

@@ -6,3 +6,3 @@ {

},
"version": "3.1.1",
"version": "3.2.0",
"description": "HTML5 application deployer",

@@ -17,3 +17,5 @@ "main": "index.js",

"@sap/xsenv": "3.1.0",
"requestretry": "4.1.2"
"@sap/xssec": "3.2.8",
"requestretry": "4.1.2",
"uuid": "3.4.0"
},

@@ -31,2 +33,3 @@ "devDependencies": {

"sinon": "4.2.2",
"supertest": "3.0.0",
"gulp": "4.0.2",

@@ -33,0 +36,0 @@ "gulp-eslint": "^4.0.0",

@@ -47,4 +47,4 @@ @sap/html5-app-deployer

If no "resources=" tag is provided HTML5 application deployer will still try to upload files from resources folder. If no resources folder is found,the upload will fail.In the resources folder there should be one folder or one zip archive for each application that should be uploaded.
In each application folder/zip archive there should be two files at root level: manifest.json and xs-app.json.
If no "resources=" tag is provided HTML5 application deployer will still try to upload files from resources folder. If no resources folder is found,the upload will fail. In the resources folder there should be one folder or one zip archive for each application that should be uploaded.
In each application folder/zip archive there should be two files at root level: `manifest.json` and `xs-app.json`.

@@ -67,5 +67,5 @@ For example:

The manifest.json file should contain at least sap.app.id and sap.app.applicationVersion.version.
The manifest.json file should contain at least `sap.app.id` and `sap.app.applicationVersion.version`.
Note that sap.app.id and sap.app.applicationVersion.version are used in the HTML5 application repository as applicationName and applicationVersion. If sap.app.id contains dots or dashes, they will be removed in the applicationName.
Note that `sap.app.id` and `sap.app.applicationVersion.version` are used in the HTML5 application repository as applicationName and applicationVersion. If `sap.app.id` contains dots or dashes, they will be removed in the applicationName.
The version format must be xx.xx.xx, whereas x is a digit. For example: 1.0.10

@@ -75,5 +75,4 @@

For example:
For example (`manifest.json`):
```
manifest.json
{

@@ -92,6 +91,5 @@ "_version": "1.7.0",

The xs-app.json file that can be used by the application router to support application routing.
The `xs-app.json` file that can be used by the application router to support application routing.
For example:
```
xs-app.json
"welcomeFile": "index.html",

@@ -114,4 +112,4 @@ "authenticationMethod": "route",

The @sap/html5-app-deployer consumer application should be bound to a single html5-apps-repo service instance of the app-host service plan.
When the @sap/html5-app-deployer consumer application is started, the @sap/html5-app-deployer module creates a zip archive for each folder in the “resources” folder - if it is not zipped already - and triggers the upload of all zip archives to the HTML5 application repository via multi-part request.
The `@sap/html5-app-deployer` consumer application should be bound to a single html5-apps-repo service instance of the app-host service plan.
When the `@sap/html5-app-deployer` consumer application is started, the `@sap/html5-app-deployer` module creates a zip archive for each folder in the “resources” folder - if it is not zipped already - and triggers the upload of all zip archives to the HTML5 application repository via multi-part request.

@@ -123,3 +121,3 @@ ## Deploying HTML5 Application Deployer App

#### 1. Create a manifest.yaml file in the following format:
#### 1. Create a `manifest.yaml` file in the following format:
```

@@ -156,3 +154,3 @@ applications:

#### 1. Create an mtad.yaml file.
The MTA project should have an mtad.yaml file in the following format:
The MTA project should have an `mtad.yaml` file in the following format:
```

@@ -180,3 +178,3 @@ ID: myApps.deployer //MTA ID

#### 2. Generate *.mtar file.
Use the WebIDE build or the MTA Build Tool to generate a valid myAppDeployer.mtar file.
Use the WebIDE build or the [MTA Build Tool](https://sap.github.io/cloud-mta-build-tool/) to generate a valid `myAppDeployer.mtar` file.

@@ -187,3 +185,3 @@ #### 3. Deploy *.mtar file.

```
After deploying the *.mtar file, an application called myAppsDeployer (stopped) is shown in cf apps.
After deploying the `*.mtar` file, an application called myAppsDeployer (stopped) is shown in cf apps.

@@ -204,3 +202,3 @@ ## Undeploy HTML5 Application Deployer Apps

This step deletes the HTML5 application respository content.
For example
For example:
```

@@ -219,3 +217,3 @@ cf delete-service myApps-app-host

When you undeploy the HTML5 application deployer app, the HTML5 application deployer app is deleted and you can - in the same step - delete the app-host service instance of the html5-apps-repo. To delete the app-host service instance of the html5-apps-repo, the --delete-service parameter should be passed.
Note that the undeploy requires the mta id, which can be obtained by calling cf mtas or from the mtad.yaml ID.
Note that the undeploy requires the mta id, which can be obtained by calling cf mtas or from the `mtad.yaml` ID.

@@ -222,0 +220,0 @@ #### 1. Undeploy HTML5 Application Deployer App and delete the service instance

Sorry, the diff of this file is not supported yet