Skip to content

Commit cd3fbf9

Browse files
Fix firewall error message (#54)
Co-authored-by: Jesse MacFadyen <[email protected]>
1 parent 5a30f07 commit cd3fbf9

File tree

4 files changed

+30
-12
lines changed

4 files changed

+30
-12
lines changed

lib/StateStoreError.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,17 @@ E('ERROR_BAD_ARGUMENT', '%s')
5353
E('ERROR_NOT_IMPLEMENTED', 'method `%s` not implemented')
5454
E('ERROR_BAD_CREDENTIALS', 'cannot access %s, make sure your credentials are valid')
5555
E('ERROR_PAYLOAD_TOO_LARGE', 'key, value or request payload is too large')
56+
// this error is specific to Adobe's owned database
57+
E('ERROR_FIREWALL', 'cannot access %s because your IP is blocked by a firewall, please make sure to run in an Adobe I/O Runtime action')
5658

5759
// eslint-disable-next-line jsdoc/require-jsdoc
5860
function logAndThrow (e) {
5961
const internalError = e.sdkDetails._internal
6062
// by default stringifying an Error returns '{}' because toJSON is not defined, so here we make sure that we properly
6163
// stringify the _internal error objects
62-
if (internalError instanceof Error && !internalError.toJSON) internalError.toJSON = () => Object.getOwnPropertyNames(internalError).reduce((obj, prop) => { obj[prop] = internalError[prop]; return obj }, {})
64+
if (internalError instanceof Error && !internalError.toJSON) {
65+
internalError.toJSON = () => Object.getOwnPropertyNames(internalError).reduce((obj, prop) => { obj[prop] = internalError[prop]; return obj }, {})
66+
}
6367
logger.error(JSON.stringify(e, null, 2))
6468
throw e
6569
}

lib/impl/CosmosStateStore.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,19 @@ async function _wrap (promise, params) {
2828
const copyParams = cloneDeep(params)
2929
// error handling
3030
const status = e.statusCode || e.code
31-
if (status === 404) return null
32-
if (status === 403) logAndThrow(new codes.ERROR_BAD_CREDENTIALS({ messageValues: ['underlying DB provider'], sdkDetails: copyParams }))
33-
if (status === 413) logAndThrow(new codes.ERROR_PAYLOAD_TOO_LARGE({ sdkDetails: copyParams }))
31+
if (status === 404) {
32+
return null
33+
}
34+
logger.debug(`got internal error with status ${status}: ${e.message} `)
35+
if (status === 403) {
36+
if (e.message.includes('blocked by your Cosmos DB account firewall settings')) {
37+
logAndThrow(new codes.ERROR_FIREWALL({ messageValues: ['underlying DB provider'], sdkDetails: copyParams }))
38+
}
39+
logAndThrow(new codes.ERROR_BAD_CREDENTIALS({ messageValues: ['underlying DB provider'], sdkDetails: copyParams }))
40+
}
41+
if (status === 413) {
42+
logAndThrow(new codes.ERROR_PAYLOAD_TOO_LARGE({ sdkDetails: copyParams }))
43+
}
3444
logAndThrow(new codes.ERROR_INTERNAL({ messageValues: [`unknown error response from provider with status: ${status || 'unknown'}`], sdkDetails: { ...copyParams, _internal: e } }))
3545
}
3646
// 404 does not throw in cosmos SDK which is fine as we treat 404 as a non-error,

test/impl/CosmosStateStore.test.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,24 @@ beforeEach(async () => {
5757
// eslint-disable-next-line jsdoc/require-jsdoc
5858
async function testProviderErrorHandling (func, mock, fparams) {
5959
// eslint-disable-next-line jsdoc/require-jsdoc
60-
async function testOne (status, expectCheck, isInternal, ...addArgs) {
61-
const providerError = new Error('fakeProviderError')
62-
if (status) providerError.code = status
60+
async function testOne (status, errorMessage, expectCheck, isInternal, ...addArgs) {
61+
const providerError = new Error(errorMessage)
62+
if (status) {
63+
providerError.code = status
64+
}
6365

6466
const expectedErrorDetails = { ...fparams }
65-
if (isInternal) expectedErrorDetails._internal = providerError
67+
if (isInternal) { expectedErrorDetails._internal = providerError }
6668
mock.mockReset()
6769
mock.mockRejectedValue(providerError)
6870
await global[expectCheck](func, ...addArgs, expectedErrorDetails)
6971
}
7072

71-
await testOne(403, 'expectToThrowForbidden')
72-
await testOne(413, 'expectToThrowTooLarge')
73-
await testOne(500, 'expectToThrowInternalWithStatus', true, 500)
74-
await testOne(undefined, 'expectToThrowInternal', true)
73+
await testOne(403, 'This is blocked by your Cosmos DB account firewall settings.', 'expectToThrowFirewall')
74+
await testOne(403, 'fakeError', 'expectToThrowForbidden')
75+
await testOne(413, 'fakeError', 'expectToThrowTooLarge')
76+
await testOne(500, 'fakeError', 'expectToThrowInternalWithStatus', true, 500)
77+
await testOne(undefined, 'fakeError', 'expectToThrowInternal', true)
7578
// when provider resolves with bad status which is not 404
7679
const providerResponse = {
7780
statusCode: 400

test/jest.setup.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ global.expectToThrowCustomError = async (func, code, words, expectedErrorDetails
6363

6464
global.expectToThrowBadArg = async (received, words, expectedErrorDetails) => global.expectToThrowCustomError(received, 'ERROR_BAD_ARGUMENT', words, expectedErrorDetails)
6565
global.expectToThrowForbidden = async (received, expectedErrorDetails) => global.expectToThrowCustomError(received, 'ERROR_BAD_CREDENTIALS', ['cannot', 'access', 'credentials'], expectedErrorDetails)
66+
global.expectToThrowFirewall = async (received, expectedErrorDetails) => global.expectToThrowCustomError(received, 'ERROR_FIREWALL', ['your', 'IP', 'blocked', 'firewall'], expectedErrorDetails)
6667
global.expectToThrowInternalWithStatus = async (received, status, expectedErrorDetails) => global.expectToThrowCustomError(received, 'ERROR_INTERNAL', ['' + status], expectedErrorDetails)
6768
global.expectToThrowInternal = async (received, expectedErrorDetails) => global.expectToThrowCustomError(received, 'ERROR_INTERNAL', ['unknown'], expectedErrorDetails)
6869
global.expectToThrowNotImplemented = async (received, methodName) => global.expectToThrowCustomError(received, 'ERROR_NOT_IMPLEMENTED', ['not', 'implemented', methodName], {})

0 commit comments

Comments
 (0)