Skip to content
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
The format is based on [Keep a Changelog](http://keepachangelog.com/).

## Version 0.8.3 - 2024-11-28

### Fixed

- Rewrite subselects to use path expressions on @cap-js databases
Copy link
Contributor Author

@sjvans sjvans Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Rewrite subselects to use path expressions on @cap-js databases
- Use path expressions instead of manually constructed semi joins on @cap-js databases


## Version 0.8.2 - 2024-11-27

### Fixed
Expand Down
95 changes: 94 additions & 1 deletion lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,96 @@ const _getUps = (entity, model) => {
return entity.own($parents)
}

const _rel = (left, right, abort) => {
let a
for (const assoc in left.associations) {
if (left.associations[assoc].target === right.name) {
a = left.associations[assoc]
break
}
}
if (a) {
return { base: left, target: right, assoc: a }
}
if (abort) return
return _rel(right, left, true)
}

const _new_getDataSubjectIdQuery = ({ dataSubjectEntity, subs }, row, model) => {
const qs = []

for (const sub of subs) {
const path = []
let s = sub
while (s) {
if (!path.length) {
const kp = Object.keys(s.entity.keys).reduce((acc, cur) => {
if (cur !== 'IsActiveEntity') acc.push(`${cur}='${row[cur]}'`)
return acc
}, [])
path.push({ id: s.entity.name, where: kp })
}

let relation = _rel(s.entity, s.next?.entity || dataSubjectEntity)
if (!relation) {
debugger
// TODO: no link
} else if (relation.base === s.entity) {
// link
if (relation.assoc === s.element) {
path.push({ to: relation.assoc.name })
} else {
path[0].id = s.element.name
path.unshift({ id: relation.target.name })
}
} else {
debugger
// no link
path[0].id = s.element.name
path.unshift({ id: relation.base.name })
}

s = s.next
}

const p = path.reduce((acc, cur) => {
if (!acc) {
acc += `${cur.id}${cur.where ? `[${cur.where.join(' and ')}]` : ''}`
} else {
if (cur.id) {
const close = acc.match(/([\]]+)$/)?.[1]
if (close)
acc =
acc.slice(0, close.length * -1) +
`[exists ${cur.id}${cur.where ? `[${cur.where.join(' and ')}]` : ''}]` +
close
else acc += `[exists ${cur.id}${cur.where ? `[${cur.where.join(' and ')}]` : ''}]`
} else if (cur.to) acc += `.${cur.to}`
}
return acc
}, '') /* +
path
.map(() => ']')
.join('')
.substring(1) */

// TODO: other subs

const q = SELECT.one.from(p).columns(...Object.keys(dataSubjectEntity.keys))

qs.push(q)
}

const q = qs[0]

for (let i = 1; i < qs.length; i++) {
debugger
q.SELECT.from.ref[0].where.push('or', ...qs[i].SELECT.from.ref[0].where)
}

return q
}

const _getDataSubjectUp = (root, model, entity, prev, next, result) => {
for (const element of _getUps(entity, model)) {
// cycle detection
Expand Down Expand Up @@ -246,7 +336,10 @@ const addDataSubjectForDetailsEntity = (row, log, req, entity, model) => {
const map = _getDataSubjectsMap(req)
if (map.has(role)) log.data_subject.id = map.get(role)
// REVISIT by downward lookups row might already contain ID - some potential to optimize
else map.set(role, _getDataSubjectIdQuery(dataSubjectInfo, row, model))
else {
const q = _new_getDataSubjectIdQuery(dataSubjectInfo, row, model)
map.set(role, q)
}
}

const resolveDataSubjects = (logs, req) => {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cap-js/audit-logging",
"version": "0.8.2",
"version": "0.8.3",
Copy link
Contributor Author

@sjvans sjvans Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0.9.0

"description": "CDS plugin providing integration to the SAP Audit Log service as well as out-of-the-box personal data-related audit logging based on annotations.",
"repository": "cap-js/audit-logging",
"author": "SAP SE (https://www.sap.com)",
Expand Down
Loading