mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
Fixed handling requests with mismatching version and missing key
fix https://linear.app/tryghost/issue/SLO-88/typeerror-cannot-read-properties-of-null-reading-relations - in the event that we make it through the version mismatch code, but without a key, which is possible if you send a request like POST /ghost/api/v2/content/posts/`, then the version mismatch code will try and look up the API key attached to a null key, which won't work - we should handle this case and soft return, to avoid trying to read `.relations` from `null` - I'm not entirely convinced by how this code works in general, it seems quite confusing to reason about, but this commit should solve the HTTP 500 we've been seeing from this - perhaps in the future we can return earlier in the flow if we receive a `null` key
This commit is contained in:
parent
ec626bd0cf
commit
6c7b230efe
4 changed files with 71 additions and 2 deletions
|
@ -41,10 +41,17 @@ class APIVersionCompatibilityService {
|
|||
*/
|
||||
async handleMismatch({acceptVersion, contentVersion, apiKeyValue, apiKeyType, requestURL, userAgent = ''}) {
|
||||
if (!await this.versionNotificationsDataService.fetchNotification(acceptVersion)) {
|
||||
const integration = await this.versionNotificationsDataService.getIntegration(apiKeyValue, apiKeyType);
|
||||
|
||||
// We couldn't find the integration
|
||||
if (!integration) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
name: integrationName,
|
||||
type: integrationType
|
||||
} = await this.versionNotificationsDataService.getIntegration(apiKeyValue, apiKeyType);
|
||||
} = integration;
|
||||
|
||||
// @NOTE: "internal" or "core" integrations (https://ghost.notion.site/Data-Types-e5dc54dd0078443f9afd6b2abda443c4)
|
||||
// are maintained by Ghost team, so there is no sense notifying the instance owner about it's incompatibility.
|
||||
|
|
|
@ -184,6 +184,43 @@ describe('APIVersionCompatibilityService', function () {
|
|||
assert.equal(sendEmail.calledTwice, false);
|
||||
});
|
||||
|
||||
it('Does not send email when unknown integration is detected', async function () {
|
||||
const sendEmail = sinon.spy();
|
||||
const findOneStub = sinon.stub();
|
||||
|
||||
findOneStub
|
||||
.withArgs({
|
||||
id: 'unknown_key'
|
||||
}, {
|
||||
withRelated: ['integration']
|
||||
})
|
||||
.resolves(null);
|
||||
|
||||
ApiKeyModel = {
|
||||
findOne: findOneStub
|
||||
};
|
||||
|
||||
const compatibilityService = new APIVersionCompatibilityService({
|
||||
sendEmail,
|
||||
ApiKeyModel,
|
||||
UserModel,
|
||||
settingsService,
|
||||
getSiteUrl,
|
||||
getSiteTitle
|
||||
});
|
||||
|
||||
await compatibilityService.handleMismatch({
|
||||
acceptVersion: 'v4.5',
|
||||
contentVersion: 'v5.1',
|
||||
userAgent: 'GhostAdminSDK/2.4.0',
|
||||
requestURL: 'https://amazeballsghostsite.com/ghost/api/admin/posts/dew023d9203se4',
|
||||
apiKeyValue: 'unknown_key',
|
||||
apiKeyType: 'content'
|
||||
});
|
||||
|
||||
assert.equal(sendEmail.called, false);
|
||||
});
|
||||
|
||||
it('Does NOT send an email to the instance owner when "internal" or "core" integration triggered version mismatch', async function () {
|
||||
const sendEmail = sinon.spy();
|
||||
const findOneStub = sinon.stub();
|
||||
|
|
|
@ -57,7 +57,7 @@ class VersionNotificationsDataService {
|
|||
*
|
||||
* @param {String} key - api key identification value, it's "secret" in case of Content API key and "id" for Admin API
|
||||
* @param {String} type - one of "content" or "admin" values
|
||||
* @returns {Promise<Object>} Integration JSON object
|
||||
* @returns {Promise<Object | null>} Integration JSON object
|
||||
*/
|
||||
async getIntegration(key, type) {
|
||||
let queryOptions = null;
|
||||
|
@ -69,6 +69,9 @@ class VersionNotificationsDataService {
|
|||
}
|
||||
|
||||
const apiKey = await this.ApiKeyModel.findOne(queryOptions, {withRelated: ['integration']});
|
||||
if (!apiKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return apiKey.relations.integration.toJSON();
|
||||
}
|
||||
|
|
|
@ -190,5 +190,27 @@ describe('Version Notification Data Service', function () {
|
|||
assert.equal(integrationName, 'Tri Hita Karana');
|
||||
assert.equal(integrationType, 'core');
|
||||
});
|
||||
|
||||
it('Returns null when the api-key/integration is not found', async function () {
|
||||
const ApiKeyModel = {
|
||||
findOne: sinon
|
||||
.stub()
|
||||
.withArgs({
|
||||
id: 'key_id'
|
||||
}, {
|
||||
withRelated: ['integration']
|
||||
})
|
||||
.resolves(null)
|
||||
};
|
||||
|
||||
const versionNotificationsDataService = new VersionNotificationsDataService({
|
||||
UserModel: {},
|
||||
ApiKeyModel,
|
||||
settingsService: {}
|
||||
});
|
||||
|
||||
const integration = await versionNotificationsDataService.getIntegration('key_id', 'admin');
|
||||
assert.equal(integration, null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue