generator-sap-partner-eng
Version:
Project/Module Generator for SAP Partner Engineering Guided Projects
333 lines (306 loc) • 13.3 kB
JavaScript
const cds = require('@sap/cds');
const { inspect } = require('util');
const axios = require('axios');
const qs = require('qs');
const cfenv = require('cfenv');
const appEnv = cfenv.getAppEnv();
const xsenv = require('@sap/xsenv');
const services = xsenv.getServices({
uaa: { tag: 'xsuaa' },
registry: { tag: 'SaaS' }
});
console.log("services:" + JSON.stringify(services, null, 2));
console.log("appEnv:" + JSON.stringify(appEnv, null, 2));
async function connectAPI() {
try {
// Get Auth Endpoint
let options1 = {
method: 'GET',
url: appEnv.app.cf_api + '/info'
};
console.log("options1:" + inspect(options1,false,1));
let res1 = await axios(options1);
console.log("res1:" + inspect(res1.data,false,1));
try {
// Login + Get Token
let options2 = {
method: 'POST',
url: res1.data.authorization_endpoint + '/oauth/token?grant_type=password',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
'Authorization': 'Basic Y2Y6'
},
data: qs.stringify({
username: process.env.CF_API_USER,
password: process.env.CF_API_PW
//username: 'andrew.lunde@sap.com',
//password: 'Hi'
})
};
console.log("options2:" + inspect(options2,false,1));
let res2 = await axios(options2);
console.log("res2:" + inspect(res2.data,false,1));
try {
// Get App Router Module's GUID
let options3 = {
method: 'GET',
url: appEnv.app.cf_api + '/v3/apps?organization_guids=' + appEnv.app.organization_id + '&space_guids=' + appEnv.app.space_id + '&names=' + '<%= router_name %>',
headers: {
'Authorization': 'Bearer ' + res2.data.access_token
}
};
console.log("options3:" + inspect(options3,false,1));
let res3 = await axios(options3);
console.log("res3:" + inspect(res3.data,false,1));
try {
// Get Domains
let options4 = {
method: 'GET',
url: appEnv.app.cf_api + '/v3/domains?names=' + /\.(.*)/gm.exec(appEnv.app.application_uris[0])[1],
headers: {
'Authorization': 'Bearer ' + res2.data.access_token
}
};
console.log("options4:" + inspect(options4,false,1));
let res4 = await axios(options4);
console.log("res4:" + inspect(res4.data,false,1));
let connRes = {
'access_token': res2.data.access_token,
'application_id': res3.data.resources[0].guid,
'domain_id': res4.data.resources[0].guid
};
console.log("connRes:" + inspect(connRes,false,1));
return connRes;
} catch (err) {
console.log(err.stack);
return err.message;
}
} catch (err) {
console.log(err.stack);
return err.message;
}
} catch (err) {
console.log(err.stack);
return err.message;
}
} catch (err) {
console.log(err.stack);
return err.message;
}
};
async function createRoute(tenantHost, connectRes) {
try {
// Create Route
let options1 = {
method: 'POST',
url: appEnv.app.cf_api + '/v3/routes/',
headers: {
'Authorization': 'Bearer ' + connectRes.access_token,
'Content-Type': 'application/json'
},
data: {
'host': tenantHost,
'relationships': {
'space': {
'data': {
'guid': appEnv.app.space_id
}
},
'domain': {
'data': {
'guid': connectRes.domain_id
}
}
}
}
}
console.log("options1:" + inspect(options1,false,1));
let res1 = await axios(options1);
console.log("res1:" + inspect(res1.data,false,1));
try {
let options2 = {
method: 'POST',
url: appEnv.app.cf_api + '/v3/routes/' + res1.data.guid + '/destinations',
headers: {
'Authorization': 'Bearer ' + connectRes.access_token,
'Content-Type': 'application/json'
},
data: {
'destinations': [{
'app': {
'guid': connectRes.application_id
}
}]
}
};
console.log("options2:" + inspect(options2,false,1));
let res2 = await axios(options2);
console.log("res2:" + inspect(res2,false,1));
return res2.data;
} catch (err) {
console.log(err.stack);
return err.message;
}
} catch (err) {
console.log(err.stack);
return err.message;
};
};
async function deleteRoute(tenantID, connectRes) {
try {
// SaaS login + Get Token
let options0 = {
method: 'POST',
url: services.registry.url + '/oauth/token?grant_type=client_credentials&response_type=token',
headers: {
'Accept': '*/*',
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
},
auth: {
username: services.registry.clientid,
password: services.registry.clientsecret
}
};
console.log("options0:" + inspect(options0,false,1));
let res0 = await axios(options0);
console.log("res0:" + inspect(res0.data,false,1));
try {
// SaaS get tenant subscription info (subdomain)
let options1 = {
method: 'GET',
url: services.registry.saas_registry_url + '/saas-manager/v1/application/subscriptions?tenantId=' + tenantID,
headers: {
'Authorization': 'Bearer ' + res0.data.access_token
}
}
console.log("options1:" + inspect(options1,false,1));
let res1 = await axios(options1);
console.log("res1:" + inspect(res1.data,false,1));
let subdomain = res1.data.subscriptions[0].subdomain;
try {
// Get routeID with name subdomain-dev-mtxsm-app
let options2 = {
method: 'GET',
url: appEnv.app.cf_api + '/v3/apps/' + connectRes.application_id + '/routes?hosts=' + subdomain + '-' + appEnv.app.space_name + '-' + '<%= router_name %>',
headers: {
'Authorization': 'Bearer ' + connectRes.access_token
}
};
console.log("options2:" + inspect(options2,false,1));
let res2 = await axios(options2);
console.log("res2:" + inspect(res2,false,1));
try {
let options3 = {
method: 'DELETE',
url: appEnv.app.cf_api + '/v3/routes/' + res2.data.resources[0].guid,
headers: {
'Authorization': 'Bearer ' + connectRes.access_token
}
};
console.log("options3:" + inspect(options3,false,1));
let res3 = await axios(options3);
console.log("res3:" + inspect(res3,false,1));
return res3.data;
} catch (err) {
console.log(err.stack);
return err.message;
};
} catch (err) {
console.log(err.stack);
return err.message;
};
} catch (err) {
console.log(err.stack);
return err.message;
};
} catch (err) {
console.log(err.stack);
return err.message;
};
};
module.exports = (service) => {
// event handler for returning the tenant specific application URL as a response to an onboarding request
service.on('UPDATE', 'tenant', async (req, next) => {
console.log('[INFO ][ON_UPDATE_TENANT] XXX_Starting Subscription for ' + req.data.subscribedSubdomain + '.');
const res = await next(); // IMPORTANT: call default implementation which is doing the HDI container creation
let c = cds.env.for('app'); // use cds config framework to read app specific config node
//let appuri = typeof c.urlpart === "undefined" ? ' ' : c.urlpart;
let appuri = "-dev-mtxsm-app.cfapps.us10.hana.ondemand.com";
// assume app router name is same as saas-registry app name & ensure in lowercase & all _ converted to -
//let tenant = req.data.subscribedSubdomain + '-' + appEnv.app.space_name.toLowerCase().replace(/_/g,'-') + '-' + services.registry.appName.toLowerCase().replace(/_/g,'-');
// WARNING: If you changed the appName in the saas-registry definition in the mta.yaml file, you may need to adjust the tennant.
let tenant = req.data.subscribedSubdomain + '-' + appEnv.app.space_name.toLowerCase().replace(/_/g,'-') + '-' + '<%= router_name %>';
//let tenantHost = tenant + '-app';
let tenantHost = tenant;
let tenantURL = 'https:\/\/' + tenantHost + /\.(.*)/gm.exec(appEnv.app.application_uris[0])[0];
console.log("tenantHost:" + tenantHost);
console.log("tenantURL:" + tenantURL);
connectAPI().then(
function (res1) {
createRoute(tenantHost, res1).then(
function (res2) {
console.log('Subscribe: ', tenantHost, res2);
//res.status(200).send(tenantURL);
return tenantURL;
},
function (err) {
console.log(err.stack);
//res.status(500).send(err.message);
return '';
});
},
function (err) {
console.log(err.stack);
//res.status(500).send(err.message);
return '';
});
return tenantURL;
});
service.before('DELETE', 'tenant', async (req, next) => {
console.log("delete req:" + inspect(req.data,false,1));
console.log('[INFO ][ON_DELETE_TENANT] XXX_Before Unsubscription for ' + req.data.subscribedTenantId + '.');
//console.log('[INFO ][ON_DELETE_TENANT] XXX_Starting Unsubscription for ' + req.body.subscribedSubdomain + '.');
// Do this on DELETE, not before DELETE
//const res = await next(); // IMPORTANT: call default implementation which is doing the HDI container creation
let c = cds.env.for('app'); // use cds config framework to read app specific config node
//let appuri = typeof c.urlpart === "undefined" ? ' ' : c.urlpart;
let appuri = "-dev-mtxsm-app.cfapps.us10.hana.ondemand.com";
//let tenant = req.body.subscribedSubdomain + '-' + appEnv.app.space_name.toLowerCase().replace(/_/g,'-') + '-' + services.registry.appName.toLowerCase().replace(/_/g,'-');
//let tenantHost = tenant + '-app';
let tenantID = req.data.subscribedTenantId;
connectAPI().then(
function (res1) {
deleteRoute(tenantID, res1).then(
async function (res2) {
console.log('Unsubscribe: ', + inspect(res2,false,1));
//res.status(200).send('');
//await next();
return tenantID;
},
function (err) {
console.log(err.stack);
//res.status(500).send(err.message);
return '';
});
},
function (err) {
console.log(err.stack);
//res.status(500).send(err.message);
return '';
});
});
service.on('DELETE', 'tenant', async (req, next) => {
console.log("delete req:" + inspect(req.data,false,1));
console.log('[INFO ][ON_DELETE_TENANT] XXX_On Unsubscription for ' + req.data.subscribedTenantId + '.');
//console.log('[INFO ][ON_DELETE_TENANT] XXX_Starting Unsubscription for ' + req.body.subscribedSubdomain + '.');
const res = await next(); // IMPORTANT: call default implementation which is doing the HDI container creation
let c = cds.env.for('app'); // use cds config framework to read app specific config node
//let appuri = typeof c.urlpart === "undefined" ? ' ' : c.urlpart;
let appuri = "-dev-mtxsm-app.cfapps.us10.hana.ondemand.com";
//let tenant = req.body.subscribedSubdomain + '-' + appEnv.app.space_name.toLowerCase().replace(/_/g,'-') + '-' + services.registry.appName.toLowerCase().replace(/_/g,'-');
//let tenantHost = tenant + '-app';
let tenantID = req.data.subscribedTenantId;
return tenantID;
});
}