xs-security.json
to xs-security-vscode.json
and change the tenant-mode to "dedicated". Also append "_vscode" to the name of our role-collections to avoid duplicates not allowed error.cf create-service xsuaa application mt-tacoshop-vscode-uaa -c ./xs-security-vscode.json
cf create-service-key mt-tacoshop-vscode-uaa default
cf service-key mt-tacoshop-vscode-uaa default
default-env.json
xsuaa credentials with mt-tacoshop-vscode-uaa credentials. Also replace the updated xsuaa credentials in the app/default-env.json
file.srv/tenant-model.js
file and populate the logic below. What we are doing here is passing in a schema name based on the xsuaa tenant id shown in the previous section. Our cds-dbm will register that we're requesting data from a tenant specific schema and target it.const cds = require('@sap/cds');
const lib = require('./library');
console.log('before-exports');
module.exports = cds.service.impl(function () {
this.before('READ', '*', async (data) => {
data.req.user.schema = lib.formatSchema(data.req.authInfo.getZoneId());
});
this.before('CREATE', '*', async (data) => {
data.req.user.schema = lib.formatSchema(data.req.authInfo.getZoneId());
});
this.before('DELETE', '*', async (data) => {
data.req.user.schema = lib.formatSchema(data.req.authInfo.getZoneId());
});
this.before('UPDATE', '*', async (data) => {
data.req.user.schema = lib.formatSchema(data.req.authInfo.getZoneId());
});
});
srv/library.js
file and add the format Schema function. At this point in the project I discovered postgreSQL does not like schema names that begin with 0 so we should give each tenant the "_" prefix.module.exports = {
getSubscriptions: getSubscriptions,
createRoute: createRoute,
deleteRoute: deleteRoute,
getDestination: getDestination,
formatSchema: formatSchema
};
....
function formatSchema(tenantId) {
//postgreSQL does not allow first character "0" in schema name
var schema = "_" + tenantId;
//postgreSQL seems to error when passing '-' to schema name
schema = schema.replace(/-/g, '');
return schema;
};
package.json
to reflect this naming convention and also create a new tenant for local development (the trial - dev space tenant Id).db/crosstenant-model.cds
and populate a new entity with an entity that could be shared amongst our tenants.namespace mt.tacoshop.crosstenant;
entity Currency {
key code : String(70);
iso3 : String(3);
iso3Number : Integer;
}
tenant-model.cds
to reference the new crosstenant entity.namespace mt.tacoshop;
using {mt.tacoshop.crosstenant} from './crosstenant-model';
using {cuid} from '@sap/cds/common';
entity Taco: cuid {
type : String(50);
value : Decimal(10,3);
Currency : Association to crosstenant.Currency;
};
db/data/mt.tacoshop.crosstenant.Currency.csv
code,iso3,iso3Number
USD,USD,840
CAD,CAD,124
EUR,EUR,978
srv/crosstenant-model.cds
using mt.tacoshop.crosstenant as ct from '../db/crosstenant-model';
service CrosstenantService @(path : '/Crosstenant/Catalog') {
entity Currencys as projection on ct.Currency;
}
srv/crosstenant-model.js
Notice, we'll always reference the public schema for our common / shared entitys.const cds = require('@sap/cds');
console.log('before-exports');
module.exports = cds.service.impl(function () {
this.before('READ', '*', (data) => {
data.req.user.schema = 'public';
});
this.before('CREATE', '*', (data) => {
data.req.user.schema = 'public';
});
this.before('DELETE', '*', (data) => {
data.req.user.schema = 'public';
});
this.before('UPDATE', '*', (data) => {
data.req.user.schema = 'public';
});
});
srv/tenant-model.cds
to expose the crosstenant entity as read-onlyusing mt.tacoshop as mt from '../db/tenant-model';
using mt.tacoshop.crosstenant from '../db/crosstenant-model';
service CatalogService @(path : '/Tenant/Catalog') {
entity Tacos as projection on mt.Taco;
@readonly
entity Currencys as projection on crosstenant.Currency;
}
app/xs-app.json
and require Administrator access to CrossTenant catalog. Remember we're exposing this data as read-only to all users but don't want Joe-Shmo from tacos-and-tequilla to be able to modify data that's shared accross all tenants.{
"welcomeFile": "index.html",
"authenticationMethod": "route",
"logout": {
"logoutEndpoint": "/logout",
"logoutPage": "/logout.html"
},
"routes": [
{
"source": "^/srv/(.*)$",
"authenticationType": "xsuaa",
"scope": "$XSAPPNAME.User",
"destination": "srv"
},
{
"source": "^/Crosstenant/(.*)$",
"authenticationType": "xsuaa",
"scope": "$XSAPPNAME.Administrator",
"destination": "srv"
},
{
"source": "^/Tenant/(.*)$",
"authenticationType": "xsuaa",
"scope": "$XSAPPNAME.User",
"destination": "srv"
},
{
"source": "^/(.*)",
"authenticationType": "none",
"localDir": "resources"
}
]
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
5 | |
5 | |
4 | |
3 | |
3 | |
3 | |
3 | |
3 | |
3 | |
2 |