Skip to content

Commit 523b7c0

Browse files
arleytmsjvans
andauthored
fix: adapt to template processor API change (#110)
Co-authored-by: D050513 <sebastian.van.syckel@sap.com>
1 parent f4c91b4 commit 523b7c0

File tree

5 files changed

+64
-183
lines changed

5 files changed

+64
-183
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@ jobs:
1414
fail-fast: false
1515
matrix:
1616
node-version: [22.x, 20.x]
17+
cds-version: [8, 7]
1718
steps:
1819
- uses: actions/checkout@v2
1920
- name: Use Node.js ${{ matrix.node-version }}
2021
uses: actions/setup-node@v2
2122
with:
2223
node-version: ${{ matrix.node-version }}
23-
- run: npm i -g @sap/cds-dk
24+
- run: npm i -g @sap/cds-dk@${{ matrix.cds-version }}
2425
- run: npm i
26+
- run: npm i @sap/cds@${{ matrix.cds-version }}
2527
- run: cds v
2628
- run: npm run lint
2729
- run: npm run test

lib/access.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ const cds = require('@sap/cds')
22

33
// REVISIT: don't require internal stuff
44
const getTemplate = require('@sap/cds/libx/_runtime/common/utils/template')
5-
const templateProcessor = require('@sap/cds/libx/_runtime/common/utils/templateProcessor')
65

76
const {
87
getRootEntity,
@@ -56,8 +55,16 @@ const auditAccess = async function (data, req) {
5655
if (!template.elements.size) return
5756

5857
const accessLogs = {}
59-
const _data = Array.isArray(data) ? data : [data]
60-
_data.forEach(row => templateProcessor({ processFn: _processorFnAccess(accessLogs, this.model, req), row, template }))
58+
const processFn = _processorFnAccess(accessLogs, this.model, req)
59+
// cds internal templating mechanism api changed in 8.2.0 -> polyfill
60+
if (!template.process) {
61+
module.exports._templateProcessor ??= require('@sap/cds/libx/_runtime/common/utils/templateProcessor')
62+
template.process = (data, processFn) => {
63+
const _data = Array.isArray(data) ? data : [data]
64+
_data.forEach(row => module.exports._templateProcessor({ processFn, row, template }))
65+
}
66+
}
67+
template.process(data, processFn)
6168

6269
for (const each of Object.keys(accessLogs)) if (!accessLogs[each].attributes.length) delete accessLogs[each]
6370
if (!Object.keys(accessLogs).length) return

lib/modification.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ const cds = require('@sap/cds')
22

33
// REVISIT: don't require internal stuff
44
const getTemplate = require('@sap/cds/libx/_runtime/common/utils/template')
5-
const templateProcessor = require('@sap/cds/libx/_runtime/common/utils/templateProcessor')
65

76
const {
87
getMapKeyForCurrentRequest,
@@ -166,7 +165,14 @@ const _getDataModificationLogs = (req, tx, diff, beforeWrite) => {
166165

167166
const modificationLogs = {}
168167
const processFn = _processorFnModification(modificationLogs, tx.model, req, beforeWrite)
169-
templateProcessor({ processFn, row: diff, template })
168+
// cds internal templating mechanism api changed in 8.2.0 -> polyfill
169+
if (!template.process) {
170+
module.exports._templateProcessor ??= require('@sap/cds/libx/_runtime/common/utils/templateProcessor')
171+
template.process = (data, processFn) => {
172+
module.exports._templateProcessor({ processFn, row: data, template })
173+
}
174+
}
175+
template.process(diff, processFn)
170176

171177
return modificationLogs
172178
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"test-old-db": "npx jest --silent"
2020
},
2121
"peerDependencies": {
22-
"@sap/cds": ">=7 || ^8.0.0-beta"
22+
"@sap/cds": ">=7"
2323
},
2424
"devDependencies": {
2525
"@cap-js/audit-logging": "file:.",

test/personal-data/crud.test.js

Lines changed: 42 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,8 @@ describe('personal data audit logging in CRUD', () => {
376376
{ auth: ALICE }
377377
)
378378
expect(response).toMatchObject({ status: 200 })
379-
expect(_logs.length).toBe(3)
379+
// NOTE: cds^8 only returns root on update requests -> no data access logs for children
380+
expect(_logs.length).toBeGreaterThanOrEqual(1)
380381
expect(_logs).toContainMatchObject({
381382
user: 'alice',
382383
object: {
@@ -397,40 +398,6 @@ describe('personal data audit logging in CRUD', () => {
397398
{ name: 'town', new: 'updated town', old: 'shu' }
398399
]
399400
})
400-
expect(_logs).toContainMatchObject({
401-
user: 'alice',
402-
object: {
403-
type: 'CRUD_2.CustomerPostalAddress',
404-
id: { ID: '1ab71292-ef69-4571-8cfb-10b9d5d1459e' }
405-
},
406-
data_subject: {
407-
type: 'CRUD_2.CustomerPostalAddress',
408-
role: 'Address',
409-
id: {
410-
ID: '1ab71292-ef69-4571-8cfb-10b9d5d1459e',
411-
street: 'updated',
412-
town: 'updated town'
413-
}
414-
},
415-
attributes: [{ name: 'someOtherField' }]
416-
})
417-
expect(_logs).toContainMatchObject({
418-
user: 'alice',
419-
object: {
420-
type: 'CRUD_2.CustomerPostalAddress',
421-
id: { ID: '285225db-6eeb-4b4f-9439-dbe5fcb4ce82' }
422-
},
423-
data_subject: {
424-
type: 'CRUD_2.CustomerPostalAddress',
425-
role: 'Address',
426-
id: {
427-
ID: '285225db-6eeb-4b4f-9439-dbe5fcb4ce82',
428-
street: 'sue',
429-
town: 'lou'
430-
}
431-
},
432-
attributes: [{ name: 'someOtherField' }]
433-
})
434401
})
435402

436403
test('create Customer - flat', async () => {
@@ -867,9 +834,19 @@ describe('personal data audit logging in CRUD', () => {
867834
}
868835

869836
response = await PATCH(`/crud-1/Customers(${CUSTOMER_ID})`, customer, { auth: ALICE })
870-
871837
expect(response).toMatchObject({ status: 200 })
872-
expect(_logs.length).toBe(12)
838+
839+
// NOTE: cds^8 only returns root on update requests -> no data access logs for children
840+
expect(_logs.length).toBeGreaterThanOrEqual(9)
841+
842+
// augment response with data (specifically keys in children) not returned in cds^8
843+
if (!response.data.addresses) {
844+
const {
845+
data: { addresses, status }
846+
} = await GET(`/crud-1/Customers(${CUSTOMER_ID})?$select=ID&$expand=addresses,status`, { auth: ALICE })
847+
response.data.addresses = addresses
848+
response.data.status = status
849+
}
873850

874851
const newAddresses = response.data.addresses
875852
const newStatus = response.data.status
@@ -943,33 +920,6 @@ describe('personal data audit logging in CRUD', () => {
943920
data_subject: DATA_SUBJECT,
944921
attributes: [{ name: 'creditCardNo' }]
945922
})
946-
expect(_logs).toContainMatchObject({
947-
user: 'alice',
948-
object: {
949-
type: 'CRUD_1.CustomerPostalAddress',
950-
id: { ID: newAddresses[0].ID }
951-
},
952-
data_subject: DATA_SUBJECT,
953-
attributes: [{ name: 'street' }]
954-
})
955-
expect(_logs).toContainMatchObject({
956-
user: 'alice',
957-
object: {
958-
type: 'CRUD_1.CustomerPostalAddress',
959-
id: { ID: newAddresses[1].ID }
960-
},
961-
data_subject: DATA_SUBJECT,
962-
attributes: [{ name: 'street' }]
963-
})
964-
expect(_logs).toContainMatchObject({
965-
user: 'alice',
966-
object: {
967-
type: 'CRUD_1.CustomerStatus',
968-
id: { ID: newStatus.ID }
969-
},
970-
data_subject: DATA_SUBJECT,
971-
attributes: [{ name: 'description' }]
972-
})
973923
})
974924

975925
test('update Customer - deep with reusing notes', async () => {
@@ -1028,15 +978,26 @@ describe('personal data audit logging in CRUD', () => {
1028978
_logs = []
1029979

1030980
response = await PATCH(`/crud-1/Customers(${CUSTOMER_ID})`, customer, { auth: ALICE })
1031-
1032981
expect(response).toMatchObject({ status: 200 })
1033-
expect(_logs.length).toBe(16)
982+
983+
// NOTE: cds^8 only returns root on update requests -> no data access logs for children
984+
expect(_logs.length).toBeGreaterThanOrEqual(10)
985+
986+
// augment response with data (specifically keys in children) not returned in cds^8
987+
if (!response.data.addresses) {
988+
const {
989+
data: { addresses, status }
990+
} = await GET(
991+
`/crud-1/Customers(${CUSTOMER_ID})?$select=ID&$expand=addresses($expand=attachments($expand=notes)),status`,
992+
{ auth: ALICE }
993+
)
994+
response.data.addresses = addresses
995+
response.data.status = status
996+
}
1034997

1035998
const newAddresses = response.data.addresses
1036999
const newStatus = response.data.status
1037-
const newAttachments = response.data.addresses[0].attachments
10381000
const newAttachmentNote = response.data.addresses[0].attachments[0].notes[0]
1039-
const newStatusNote = response.data.status.notes[0]
10401001

10411002
expect(_logs).toContainMatchObject({
10421003
user: 'alice',
@@ -1131,15 +1092,6 @@ describe('personal data audit logging in CRUD', () => {
11311092
{ name: 'todo', old: oldStatus.todo, new: newStatus.todo }
11321093
]
11331094
})
1134-
expect(_logs).toContainMatchObject({
1135-
user: 'alice',
1136-
object: {
1137-
type: 'CRUD_1.AddressAttachment',
1138-
id: { ID: newAttachments[0].ID }
1139-
},
1140-
data_subject: DATA_SUBJECT,
1141-
attributes: [{ name: 'description' }]
1142-
})
11431095
expect(_logs).toContainMatchObject({
11441096
user: 'alice',
11451097
object: {
@@ -1149,51 +1101,6 @@ describe('personal data audit logging in CRUD', () => {
11491101
data_subject: DATA_SUBJECT,
11501102
attributes: [{ name: 'creditCardNo' }]
11511103
})
1152-
expect(_logs).toContainMatchObject({
1153-
user: 'alice',
1154-
object: {
1155-
type: 'CRUD_1.CustomerPostalAddress',
1156-
id: { ID: newAddresses[0].ID }
1157-
},
1158-
data_subject: DATA_SUBJECT,
1159-
attributes: [{ name: 'street' }]
1160-
})
1161-
expect(_logs).toContainMatchObject({
1162-
user: 'alice',
1163-
object: {
1164-
type: 'CRUD_1.CustomerPostalAddress',
1165-
id: { ID: newAddresses[1].ID }
1166-
},
1167-
data_subject: DATA_SUBJECT,
1168-
attributes: [{ name: 'street' }]
1169-
})
1170-
expect(_logs).toContainMatchObject({
1171-
user: 'alice',
1172-
object: {
1173-
type: 'CRUD_1.CustomerStatus',
1174-
id: { ID: newStatus.ID }
1175-
},
1176-
data_subject: DATA_SUBJECT,
1177-
attributes: [{ name: 'description' }]
1178-
})
1179-
expect(_logs).toContainMatchObject({
1180-
user: 'alice',
1181-
object: {
1182-
type: 'CRUD_1.Notes',
1183-
id: { ID: newStatusNote.ID }
1184-
},
1185-
data_subject: DATA_SUBJECT,
1186-
attributes: [{ name: 'note' }]
1187-
})
1188-
expect(_logs).toContainMatchObject({
1189-
user: 'alice',
1190-
object: {
1191-
type: 'CRUD_1.Notes',
1192-
id: { ID: newAttachmentNote.ID }
1193-
},
1194-
data_subject: DATA_SUBJECT,
1195-
attributes: [{ name: 'note' }]
1196-
})
11971104
})
11981105

11991106
test('delete Customer - flat', async () => {
@@ -1745,8 +1652,7 @@ describe('personal data audit logging in CRUD', () => {
17451652
],
17461653
misc: 'abc'
17471654
}
1748-
const r1 = await POST(`/crud-1/Orders`, order, { auth: ALICE })
1749-
expect(r1)
1655+
await POST(`/crud-1/Orders`, order, { auth: ALICE })
17501656
const {
17511657
data: {
17521658
header_ID,
@@ -1772,9 +1678,12 @@ describe('personal data audit logging in CRUD', () => {
17721678
},
17731679
items
17741680
}
1681+
17751682
_logs = []
1683+
17761684
await PATCH(`/crud-1/Orders(${order.ID})`, updatedOrder, { auth: ALICE })
1777-
expect(_logs.length).toBe(6)
1685+
// NOTE: cds^8 only returns root on update requests -> no data access logs for children
1686+
expect(_logs.length).toBeGreaterThanOrEqual(4)
17781687
expect(_logs).toContainMatchObject({
17791688
user: 'alice',
17801689
object: {
@@ -1811,62 +1720,19 @@ describe('personal data audit logging in CRUD', () => {
18111720
data_subject: DATA_SUBJECT,
18121721
attributes: [{ name: 'misc' }]
18131722
})
1814-
expect(_logs).toContainMatchObject({
1815-
user: 'alice',
1816-
object: {
1817-
type: 'CRUD_1.OrderHeader',
1818-
id: { ID: header_ID }
1819-
},
1820-
data_subject: DATA_SUBJECT,
1821-
attributes: [{ name: 'description' }]
1822-
})
1823-
expect(_logs).toContainMatchObject({
1824-
user: 'alice',
1825-
object: {
1826-
type: 'CRUD_1.OrderHeader.sensitiveData',
1827-
id: { ID: sensitiveData.ID }
1828-
},
1829-
data_subject: DATA_SUBJECT,
1830-
attributes: [{ name: 'note' }]
1831-
})
1832-
const r2 = await DELETE(`/crud-1/Orders(${order.ID})`, { auth: ALICE })
1833-
expect(r2).toMatchObject({ status: 204 })
1834-
expect(_logs.length).toBe(9)
1835-
expect(_logs).toContainMatchObject({
1836-
user: 'alice',
1837-
object: {
1838-
type: 'CRUD_1.Orders',
1839-
id: { ID: order.ID }
1840-
},
1841-
data_subject: DATA_SUBJECT,
1842-
attributes: [{ name: 'misc', old: '***', new: '***' }]
1843-
})
1844-
expect(_logs).toContainMatchObject({
1845-
user: 'alice',
1846-
object: {
1847-
type: 'CRUD_1.OrderHeader',
1848-
id: { ID: header_ID }
1849-
},
1850-
data_subject: DATA_SUBJECT,
1851-
attributes: [{ name: 'description', old: '***', new: '***' }]
1852-
})
1853-
expect(_logs).toContainMatchObject({
1854-
user: 'alice',
1855-
object: {
1856-
type: 'CRUD_1.OrderHeader.sensitiveData',
1857-
id: { ID: sensitiveData.ID }
1858-
},
1859-
data_subject: DATA_SUBJECT,
1860-
attributes: [{ name: 'note', old: '***', new: '***' }]
1861-
})
1723+
1724+
_logs = []
1725+
1726+
await DELETE(`/crud-1/Orders(${order.ID})`, { auth: ALICE })
1727+
expect(_logs.length).toBe(3)
18621728
expect(_logs).toContainMatchObject({
18631729
user: 'alice',
18641730
object: {
18651731
type: 'CRUD_1.Orders',
18661732
id: { ID: order.ID }
18671733
},
18681734
data_subject: DATA_SUBJECT,
1869-
attributes: [{ name: 'misc', old: '***', new: '***' }]
1735+
attributes: [{ name: 'misc', old: '***' }]
18701736
})
18711737
expect(_logs).toContainMatchObject({
18721738
user: 'alice',
@@ -1875,7 +1741,7 @@ describe('personal data audit logging in CRUD', () => {
18751741
id: { ID: header_ID }
18761742
},
18771743
data_subject: DATA_SUBJECT,
1878-
attributes: [{ name: 'description', old: '***', new: '***' }]
1744+
attributes: [{ name: 'description', old: '***' }]
18791745
})
18801746
expect(_logs).toContainMatchObject({
18811747
user: 'alice',
@@ -1884,7 +1750,7 @@ describe('personal data audit logging in CRUD', () => {
18841750
id: { ID: sensitiveData.ID }
18851751
},
18861752
data_subject: DATA_SUBJECT,
1887-
attributes: [{ name: 'note', old: '***', new: '***' }]
1753+
attributes: [{ name: 'note', old: '***' }]
18881754
})
18891755
})
18901756

0 commit comments

Comments
 (0)