2022-05-05 12:46:19 +01:00
|
|
|
/* eslint-disable max-lines */
|
2022-05-05 18:23:13 +08:00
|
|
|
const routeMatch = require('path-match')();
|
2022-04-22 10:29:55 +08:00
|
|
|
const APIVersionCompatibilityService = require('@tryghost/api-version-compatibility-service');
|
2022-04-22 14:52:00 +08:00
|
|
|
const VersionNotificationsDataService = require('@tryghost/version-notifications-data-service');
|
2022-05-02 16:00:15 +01:00
|
|
|
const versionMismatchHandler = require('@tryghost/mw-api-version-mismatch');
|
2022-05-03 15:45:23 +08:00
|
|
|
const ghostVersion = require('@tryghost/version');
|
|
|
|
const {GhostMailer} = require('../mail');
|
2022-04-22 14:52:00 +08:00
|
|
|
const settingsService = require('../../services/settings');
|
|
|
|
const models = require('../../models');
|
2022-05-05 18:23:13 +08:00
|
|
|
const urlUtils = require('../../../shared/url-utils');
|
|
|
|
const settingsCache = require('../../../shared/settings-cache');
|
2022-04-22 10:29:55 +08:00
|
|
|
|
2022-05-02 16:00:15 +01:00
|
|
|
let serviceInstance;
|
|
|
|
|
2022-04-22 10:29:55 +08:00
|
|
|
const init = () => {
|
2022-05-03 15:45:23 +08:00
|
|
|
const ghostMailer = new GhostMailer();
|
2022-04-22 14:52:00 +08:00
|
|
|
const versionNotificationsDataService = new VersionNotificationsDataService({
|
|
|
|
UserModel: models.User,
|
|
|
|
settingsService: settingsService.getSettingsBREADServiceInstance()
|
|
|
|
});
|
|
|
|
|
2022-05-02 16:00:15 +01:00
|
|
|
serviceInstance = new APIVersionCompatibilityService({
|
2022-04-22 10:29:55 +08:00
|
|
|
sendEmail: (options) => {
|
2022-04-22 12:58:22 +08:00
|
|
|
// NOTE: not using bind here because mockMailer is having trouble mocking bound methods
|
2022-05-03 15:45:23 +08:00
|
|
|
return ghostMailer.send(options);
|
2022-04-22 10:29:55 +08:00
|
|
|
},
|
2022-04-22 14:52:00 +08:00
|
|
|
fetchEmailsToNotify: versionNotificationsDataService.getNotificationEmails.bind(versionNotificationsDataService),
|
|
|
|
fetchHandled: versionNotificationsDataService.fetchNotification.bind(versionNotificationsDataService),
|
2022-05-05 18:23:13 +08:00
|
|
|
saveHandled: versionNotificationsDataService.saveNotification.bind(versionNotificationsDataService),
|
|
|
|
getSiteUrl: () => urlUtils.urlFor('home', true),
|
|
|
|
getSiteTitle: () => settingsCache.get('title')
|
2022-04-22 10:29:55 +08:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2022-05-03 15:45:23 +08:00
|
|
|
module.exports.errorHandler = (err, req, res, next) => {
|
|
|
|
return versionMismatchHandler(serviceInstance)(err, req, res, next);
|
2022-05-02 16:00:15 +01:00
|
|
|
};
|
2022-05-02 17:01:54 +01:00
|
|
|
|
2022-05-05 08:45:24 +01:00
|
|
|
/**
|
|
|
|
* If Accept-Version is set on the request set Content-Version on the response
|
|
|
|
*
|
|
|
|
* @param {import('express').Request} req
|
|
|
|
* @param {import('express').Response} res
|
|
|
|
* @param {import('express').NextFunction} next
|
|
|
|
*/
|
2022-05-02 17:01:54 +01:00
|
|
|
module.exports.contentVersion = (req, res, next) => {
|
|
|
|
if (req.header('accept-version')) {
|
|
|
|
res.header('Content-Version', `v${ghostVersion.safe}`);
|
|
|
|
}
|
|
|
|
next();
|
|
|
|
};
|
|
|
|
|
2022-05-05 08:45:24 +01:00
|
|
|
/**
|
|
|
|
* If there is a version in the URL, and this is a valid API URL containing admin/content
|
|
|
|
* Rewrite the URL and add the accept-version & deprecation headers
|
|
|
|
* @param {import('express').Request} req
|
|
|
|
* @param {import('express').Response} res
|
|
|
|
* @param {import('express').NextFunction} next
|
|
|
|
*/
|
|
|
|
module.exports.versionRewrites = (req, res, next) => {
|
|
|
|
let {version} = routeMatch('/:version(v2|v3|v4|canary)/:api(admin|content)/*')(req.url);
|
|
|
|
|
|
|
|
// If we don't match a valid version, carry on
|
|
|
|
if (!version) {
|
|
|
|
return next();
|
|
|
|
}
|
|
|
|
|
|
|
|
const versionlessUrl = req.url.replace(`${version}/`, '');
|
|
|
|
|
|
|
|
// Always send the explicit, numeric version in headers
|
|
|
|
if (version === 'canary') {
|
|
|
|
version = 'v4';
|
|
|
|
}
|
|
|
|
|
|
|
|
// Rewrite the url
|
|
|
|
req.url = versionlessUrl;
|
|
|
|
|
|
|
|
// Add the accept-version header so our internal systems will act as if it was set on the request
|
|
|
|
req.headers['accept-version'] = req.headers['accept-version'] || `${version}.0`;
|
|
|
|
|
|
|
|
res.header('Deprecation', `version="${version}"`);
|
|
|
|
res.header('Link', `<${urlUtils.urlJoin(urlUtils.urlFor('admin', true), 'api', versionlessUrl)}>; rel="latest-version"`);
|
|
|
|
|
|
|
|
next();
|
|
|
|
};
|
|
|
|
|
2022-04-22 10:29:55 +08:00
|
|
|
module.exports.init = init;
|