Skip to content

Commit 5390ef5

Browse files
authored
feat: support include-ims-credentials annotation (#157)
* feat: support include-ims-credentials annotation * chore: tests * update to new changes * tmp: next tag for runtime - to be reverted * point to released runtime lib
1 parent ca5de28 commit 5390ef5

4 files changed

Lines changed: 143 additions & 2 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"@adobe/aio-lib-core-config": "^5",
1414
"@adobe/aio-lib-core-logging": "^3",
1515
"@adobe/aio-lib-env": "^3",
16-
"@adobe/aio-lib-runtime": "^7.0.0",
16+
"@adobe/aio-lib-runtime": "^7.3.0",
1717
"@adobe/aio-lib-web": "^7",
1818
"@oclif/core": "^3",
1919
"chalk": "^4",

src/lib/run-dev.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ const utils = require('./app-helper')
2828
const { SERVER_HOST, SERVER_DEFAULT_PORT, BUNDLER_DEFAULT_PORT, DEV_API_PREFIX, DEV_API_WEB_PREFIX, BUNDLE_OPTIONS, CHANGED_ASSETS_PRINT_LIMIT } = require('./constants')
2929
const RAW_CONTENT_TYPES = ['application/octet-stream', 'multipart/form-data']
3030

31+
// for the include-ims-credentials annotation
32+
let imsAuthObject = null
33+
3134
/* global Request, Response */
3235

3336
/**
@@ -86,6 +89,9 @@ async function runDev (runOptions, config, _inprocHookRunner) {
8689
// ex. console.log('AIO_DEV ', process.env.AIO_DEV ? 'dev' : 'prod')
8790
process.env.AIO_DEV = 'true'
8891

92+
// include ims credentials inputs __ims_oauth_s2s and __ims_env
93+
imsAuthObject = rtLib.utils.loadIMSCredentialsFromEnv()
94+
8995
const serverPortToUse = parseInt(process.env.PORT) || SERVER_DEFAULT_PORT
9096
const serverPort = await getPort({ port: serverPortToUse })
9197

@@ -346,6 +352,13 @@ async function invokeAction ({ actionRequestContext, logger }) {
346352
}
347353
}
348354

355+
// process the include-ims-credentials annotation
356+
const newInputs = rtLib.utils.getIncludeIMSCredentialsAnnotationInputs(action, imsAuthObject)
357+
if (newInputs) {
358+
Object.entries(newInputs).forEach(([k, v]) => { params[k] = v })
359+
logger.debug(`Added IMS credentials to action params for action '${actionName}'.`)
360+
}
361+
349362
// if we run an action, we will restore the process.env after the call
350363
// we must do this before we load the action because code can execute on require/import
351364
const preCallEnv = { ...process.env }

test/__mocks__/@adobe/aio-lib-runtime.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ const mockRtLibInstance = {
8686

8787
const mockRtUtils = {
8888
getActionUrls: jest.fn(),
89-
checkOpenWhiskCredentials: jest.fn()
89+
checkOpenWhiskCredentials: jest.fn(),
90+
getIncludeIMSCredentialsAnnotationInputs: jest.fn()
9091
}
9192

9293
const init = jest.fn().mockReturnValue(mockRtLibInstance)

test/lib/run-dev.test.js

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,12 @@ describe('invokeSequence', () => {
12311231
})
12321232

12331233
describe('runDev', () => {
1234+
const originalEnv = process.env
1235+
1236+
afterEach(() => {
1237+
process.env = { ...originalEnv }
1238+
})
1239+
12341240
test('no front end, no back end', async () => {
12351241
const actionPath = fixturePath('actions/successNoReturnAction.js')
12361242
const config = createConfig({
@@ -1253,6 +1259,32 @@ describe('runDev', () => {
12531259
expect(Object.keys(actionUrls).length).toEqual(0)
12541260
})
12551261

1262+
test('calls loadIMSCredentialsFromEnv for include-ims-credentials support', async () => {
1263+
const rtLib = jest.requireActual('@adobe/aio-lib-runtime')
1264+
const loadIMSCredentialsFromEnvSpy = jest.spyOn(rtLib.utils, 'loadIMSCredentialsFromEnv')
1265+
1266+
const actionPath = fixturePath('actions/successNoReturnAction.js')
1267+
const config = createConfig({
1268+
hasFrontend: false,
1269+
hasBackend: true,
1270+
packageName: 'mypackage',
1271+
actions: {
1272+
myaction: {
1273+
function: actionPath
1274+
}
1275+
}
1276+
})
1277+
const runOptions = createRunOptions({ cert: 'my-cert', key: 'my-key' })
1278+
const hookRunner = () => {}
1279+
const { actionUrls, serverCleanup } = await runDev(runOptions, config, hookRunner)
1280+
1281+
await serverCleanup()
1282+
1283+
expect(loadIMSCredentialsFromEnvSpy).toHaveBeenCalled()
1284+
expect(Object.keys(actionUrls).length).toBeGreaterThan(0)
1285+
loadIMSCredentialsFromEnvSpy.mockRestore()
1286+
})
1287+
12561288
test('no front end, has back end', async () => {
12571289
const actionPath = fixturePath('actions/successNoReturnAction.js')
12581290
const config = createConfig({
@@ -1706,6 +1738,101 @@ describe('invokeAction', () => {
17061738
statusCode: 400
17071739
})
17081740
})
1741+
1742+
describe('include-ims-credentials annotation', () => {
1743+
const rtLib = jest.requireActual('@adobe/aio-lib-runtime')
1744+
let getIncludeIMSCredentialsAnnotationInputsSpy
1745+
1746+
beforeEach(() => {
1747+
getIncludeIMSCredentialsAnnotationInputsSpy = jest.spyOn(rtLib.utils, 'getIncludeIMSCredentialsAnnotationInputs')
1748+
})
1749+
1750+
afterEach(() => {
1751+
getIncludeIMSCredentialsAnnotationInputsSpy.mockRestore()
1752+
})
1753+
1754+
test('adds IMS credentials to params when getIncludeIMSCredentialsAnnotationInputs returns inputs', async () => {
1755+
const packageName = 'foo'
1756+
const actionPath = fixturePath('actions/successReturnAction.js')
1757+
const actionLoader = createActionLoader(actionPath)
1758+
1759+
const action = {
1760+
function: actionPath,
1761+
annotations: {
1762+
'include-ims-credentials': true
1763+
}
1764+
}
1765+
const actionParams = { existingParam: 'value' }
1766+
const actionName = 'a'
1767+
const actionConfig = {
1768+
[packageName]: {
1769+
actions: {
1770+
[actionName]: action
1771+
}
1772+
}
1773+
}
1774+
1775+
// Mock the function to return IMS credentials
1776+
const mockImsInputs = {
1777+
__ims_oauth_s2s: { client_id: 'mock-access-token', org_id: 'mock-org-id' },
1778+
__ims_env: 'stage'
1779+
}
1780+
getIncludeIMSCredentialsAnnotationInputsSpy.mockReturnValue(mockImsInputs)
1781+
1782+
const actionRequestContext = {
1783+
contextActionLoader: actionLoader,
1784+
contextItem: action,
1785+
contextItemParams: actionParams,
1786+
contextItemName: actionName,
1787+
packageName,
1788+
actionConfig
1789+
}
1790+
const response = await invokeAction({ actionRequestContext, logger: mockLogger })
1791+
1792+
expect(getIncludeIMSCredentialsAnnotationInputsSpy).toHaveBeenCalledWith(action, expect.anything())
1793+
expect(actionParams.__ims_oauth_s2s).toEqual({ client_id: 'mock-access-token', org_id: 'mock-org-id' })
1794+
expect(actionParams.__ims_env).toEqual('stage')
1795+
expect(actionParams.existingParam).toEqual('value')
1796+
expect(mockLogger.debug).toHaveBeenCalledWith(`Added IMS credentials to action params for action '${actionName}'.`)
1797+
expect(response.statusCode).toEqual(200)
1798+
})
1799+
1800+
test('does not add IMS credentials when getIncludeIMSCredentialsAnnotationInputs returns null', async () => {
1801+
const packageName = 'foo'
1802+
const actionPath = fixturePath('actions/successReturnAction.js')
1803+
const actionLoader = createActionLoader(actionPath)
1804+
1805+
const action = { function: actionPath }
1806+
const actionParams = { existingParam: 'value' }
1807+
const actionName = 'a'
1808+
const actionConfig = {
1809+
[packageName]: {
1810+
actions: {
1811+
[actionName]: action
1812+
}
1813+
}
1814+
}
1815+
1816+
// Mock the function to return null (no annotation or no IMS auth object)
1817+
getIncludeIMSCredentialsAnnotationInputsSpy.mockReturnValue(null)
1818+
1819+
const actionRequestContext = {
1820+
contextActionLoader: actionLoader,
1821+
contextItem: action,
1822+
contextItemParams: actionParams,
1823+
contextItemName: actionName,
1824+
packageName,
1825+
actionConfig
1826+
}
1827+
const response = await invokeAction({ actionRequestContext, logger: mockLogger })
1828+
1829+
expect(getIncludeIMSCredentialsAnnotationInputsSpy).toHaveBeenCalledWith(action, expect.anything())
1830+
expect(actionParams.__ims_oauth_s2s).toBeUndefined()
1831+
expect(actionParams.__ims_env).toBeUndefined()
1832+
expect(actionParams.existingParam).toEqual('value')
1833+
expect(response.statusCode).toEqual(200)
1834+
})
1835+
})
17091836
})
17101837

17111838
describe('defaultActionLoader', () => {

0 commit comments

Comments
 (0)