in development, write audit logs to custom sink
This commit is contained in:
@@ -7,7 +7,8 @@
|
|||||||
"options": {
|
"options": {
|
||||||
"model": [
|
"model": [
|
||||||
"db",
|
"db",
|
||||||
"srv"
|
"srv",
|
||||||
|
"app"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -17,7 +18,8 @@
|
|||||||
"options": {
|
"options": {
|
||||||
"model": [
|
"model": [
|
||||||
"db",
|
"db",
|
||||||
"srv"
|
"srv",
|
||||||
|
"app"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ annotate gdpr.Customers with @PersonalData : {
|
|||||||
EntitySemantics : 'DataSubject'
|
EntitySemantics : 'DataSubject'
|
||||||
}{
|
}{
|
||||||
ID @PersonalData.FieldSemantics : 'DataSubjectID';
|
ID @PersonalData.FieldSemantics : 'DataSubjectID';
|
||||||
emailAddress @PersonalData.IsPotentiallyPersonal;
|
email @PersonalData.IsPotentiallyPersonal;
|
||||||
firstName @PersonalData.IsPotentiallyPersonal;
|
firstName @PersonalData.IsPotentiallyPersonal;
|
||||||
lastName @PersonalData.IsPotentiallyPersonal;
|
lastName @PersonalData.IsPotentiallyPersonal;
|
||||||
creditCardNo @PersonalData.IsPotentiallySensitive;
|
creditCardNo @PersonalData.IsPotentiallySensitive;
|
||||||
|
|||||||
@@ -25,5 +25,6 @@ entity CustomerPostalAddresses : cuid, managed {
|
|||||||
customer : Association to Customers;
|
customer : Association to Customers;
|
||||||
street : String(128);
|
street : String(128);
|
||||||
town : String(128);
|
town : String(128);
|
||||||
|
@assert.integrity : false
|
||||||
country : Country;
|
country : Country;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,7 +36,10 @@
|
|||||||
},
|
},
|
||||||
"features": {
|
"features": {
|
||||||
"audit_personal_data": true,
|
"audit_personal_data": true,
|
||||||
"fiori_preview": true
|
"fiori_preview": true,
|
||||||
|
"[production]": {
|
||||||
|
"kibana_formatter": true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"hana": {
|
"hana": {
|
||||||
"deploy-format": "hdbtable"
|
"deploy-format": "hdbtable"
|
||||||
|
|||||||
@@ -32,3 +32,4 @@ create roles for Audit Log Viewer Service and Personal Data Manager, and assign
|
|||||||
- clarify annotation `EntitySemantics`, which differs between audit logging (`Other`) and personal data manager (`LegalGround`)
|
- clarify annotation `EntitySemantics`, which differs between audit logging (`Other`) and personal data manager (`LegalGround`)
|
||||||
- annotations for order items Fiori preview app
|
- annotations for order items Fiori preview app
|
||||||
+ `Products` has `@cds.persistence.skip:'always'`
|
+ `Products` has `@cds.persistence.skip:'always'`
|
||||||
|
- how to reuse intial data from `common`?
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* workaround to avoid approuter et al. setup
|
* workaround to avoid approuter et al. setup
|
||||||
*
|
|
||||||
* DO NOT USE FOR PRODUCTION!
|
|
||||||
* - no token validation
|
|
||||||
* - no xsappname check
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const jwt = require('jsonwebtoken')
|
const jwt = require('jsonwebtoken')
|
||||||
@@ -12,7 +8,13 @@ const tenant = process.env.VCAP_SERVICES
|
|||||||
: 'anonymous'
|
: 'anonymous'
|
||||||
|
|
||||||
module.exports = (req, res, next) => {
|
module.exports = (req, res, next) => {
|
||||||
// decode JWT coming from Personal Data Manager
|
/*
|
||||||
|
* decode JWT coming from Personal Data Manager
|
||||||
|
*
|
||||||
|
* DO NOT USE FOR PRODUCTION!
|
||||||
|
* - no token validation
|
||||||
|
* - no xsappname check
|
||||||
|
*/
|
||||||
const bearer = req.headers.authorization && req.headers.authorization.split('Bearer ')[1]
|
const bearer = req.headers.authorization && req.headers.authorization.split('Bearer ')[1]
|
||||||
if (bearer) {
|
if (bearer) {
|
||||||
const { client_id: id, zid: tenant, scope: roles } = jwt.decode(bearer)
|
const { client_id: id, zid: tenant, scope: roles } = jwt.decode(bearer)
|
||||||
@@ -31,8 +33,7 @@ module.exports = (req, res, next) => {
|
|||||||
req.user = {
|
req.user = {
|
||||||
id,
|
id,
|
||||||
tenant,
|
tenant,
|
||||||
// is: role => role !== 'PersonalDataManagerUser'
|
is: role => role !== 'PersonalDataManagerUser'
|
||||||
is: role => true
|
|
||||||
}
|
}
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
|
|||||||
26
gdpr/srv/server.js
Normal file
26
gdpr/srv/server.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
const cds = require('@sap/cds')
|
||||||
|
|
||||||
|
/*
|
||||||
|
* in development, write audit logs to custom sink (i.e., to console in this example)
|
||||||
|
*/
|
||||||
|
cds.on('served', async () => {
|
||||||
|
if (process.env.NODE_ENV === 'production') return
|
||||||
|
|
||||||
|
const auditLogService = await cds.connect.to('audit-log')
|
||||||
|
// use prepend to get called before the generic implementation
|
||||||
|
auditLogService.prepend(function() {
|
||||||
|
const LOG = cds.log('my custom audit logging impl')
|
||||||
|
// triggered when reading sensitive personal data
|
||||||
|
this.on('dataAccessLog', function(req) {
|
||||||
|
const { accesses } = req.data
|
||||||
|
for (const access of accesses) LOG.info(access)
|
||||||
|
})
|
||||||
|
// triggered when modifying personal data
|
||||||
|
this.on('dataModificationLog', function(req) {
|
||||||
|
const { modifications } = req.data
|
||||||
|
for (const modification of modifications) LOG.info(modification)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = cds.server
|
||||||
Reference in New Issue
Block a user