Skip to content

Commit 1c2968f

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
fix(integrations): validate Oracle selector detail IDs
1 parent 0fd9558 commit 1c2968f

2 files changed

Lines changed: 45 additions & 8 deletions

File tree

apps/sim/lib/selectors/server/providers/oracle-fusion-hcm.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { selectorManifest } from '@/lib/selectors/manifest'
44
import {
55
SelectorConnectionUnavailableError,
66
SelectorContextUnavailableError,
7+
SelectorOptionsUnavailableError,
78
} from '@/lib/selectors/server/errors'
89
import { oracleFusionHcmSelectorAttachments } from '@/lib/selectors/server/providers/oracle-fusion-hcm'
910
import type {
@@ -291,6 +292,32 @@ describe('Oracle Fusion HCM selectors', () => {
291292
)
292293
})
293294

295+
it('rejects detail responses whose resource ID differs from the requested ID', async () => {
296+
const context = {
297+
domain: 'https://acme.fa.ocs.oraclecloud.com',
298+
username: 'reader',
299+
password: 'secret',
300+
personId: '1',
301+
}
302+
for (const [key, id, mock, output] of [
303+
['workers', '1', mocks.getWorker, { worker: { personId: '9' } }],
304+
['assignments', '2', mocks.getAssignment, { assignment: { assignmentId: '9' } }],
305+
['absences', '3', mocks.getAbsence, { absence: { absenceId: '9', personId: '1' } }],
306+
] as const) {
307+
mock.mockResolvedValueOnce({ success: true, output })
308+
const attachment = oracleFusionHcmSelectorAttachments[`oracle_fusion_hcm.${key}`]
309+
const input = args({
310+
selectorKey: `oracle_fusion_hcm.${key}`,
311+
context,
312+
request: { kind: 'detail', id },
313+
})
314+
315+
await expect(
316+
attachment.execute(input, await prepare(attachment, input))
317+
).rejects.toBeInstanceOf(SelectorOptionsUnavailableError)
318+
}
319+
})
320+
294321
it('rejects an absence detail that does not belong to the selected worker', async () => {
295322
mocks.getAbsence.mockResolvedValueOnce({
296323
success: true,

apps/sim/lib/selectors/server/providers/oracle-fusion-hcm.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,17 @@ export const oracleFusionHcmSelectorAttachments = {
9797
async execute(args, prepared) {
9898
try {
9999
if (args.request.kind === 'detail') {
100+
const requestedPersonId = parseId(args.request.id)
100101
const result = await executeOracleFusionHcmGetWorker(
101-
{ ...prepared, personId: parseId(args.request.id) },
102+
{ ...prepared, personId: requestedPersonId },
102103
args.signal
103104
)
104105
const worker = result.output.worker
106+
if (worker.personId !== requestedPersonId) {
107+
throw new SelectorOptionsUnavailableError()
108+
}
105109
return detailSelectorResult({
106-
id: worker.personId,
110+
id: requestedPersonId,
107111
label: worker.displayName || worker.personNumber || worker.personId,
108112
meta: { personNumber: worker.personNumber, workEmail: worker.workEmail },
109113
})
@@ -137,17 +141,21 @@ export const oracleFusionHcmSelectorAttachments = {
137141
if (!prepared.personId) throw new SelectorContextUnavailableError()
138142
try {
139143
if (args.request.kind === 'detail') {
144+
const requestedAssignmentId = parseId(args.request.id)
140145
const result = await executeOracleFusionHcmGetWorkerAssignment(
141146
{
142147
...prepared,
143148
personId: prepared.personId,
144-
assignmentId: parseId(args.request.id),
149+
assignmentId: requestedAssignmentId,
145150
},
146151
args.signal
147152
)
148153
const assignment = result.output.assignment
154+
if (assignment.assignmentId !== requestedAssignmentId) {
155+
throw new SelectorOptionsUnavailableError()
156+
}
149157
return detailSelectorResult({
150-
id: assignment.assignmentId,
158+
id: requestedAssignmentId,
151159
label:
152160
assignment.assignmentName || assignment.assignmentNumber || assignment.assignmentId,
153161
meta: { assignmentNumber: assignment.assignmentNumber },
@@ -183,16 +191,18 @@ export const oracleFusionHcmSelectorAttachments = {
183191
if (!prepared.personId) throw new SelectorContextUnavailableError()
184192
try {
185193
if (args.request.kind === 'detail') {
194+
const requestedAbsenceId = parseId(args.request.id)
186195
const result = await executeOracleFusionHcmGetAbsence(
187-
{ ...prepared, absenceId: parseId(args.request.id) },
196+
{ ...prepared, absenceId: requestedAbsenceId },
188197
args.signal
189198
)
190199
const absence = result.output.absence
191-
if (absence.personId !== prepared.personId) {
192-
throw new SelectorContextUnavailableError()
200+
if (absence.absenceId !== requestedAbsenceId) {
201+
throw new SelectorOptionsUnavailableError()
193202
}
203+
if (absence.personId !== prepared.personId) throw new SelectorContextUnavailableError()
194204
return detailSelectorResult({
195-
id: absence.absenceId,
205+
id: requestedAbsenceId,
196206
label:
197207
[absence.absenceType, absence.startDate, absence.endDate]
198208
.filter(Boolean)

0 commit comments

Comments
 (0)