Enforce explicit cacheInvalidate header (#16826)

refs https://github.com/TryGhost/Team/issues/3005
This commit is contained in:
Michael Barrett 2023-06-07 15:13:45 +01:00 committed by GitHub
parent e0da095c76
commit 9da246ac84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 498 additions and 40 deletions

View File

@ -4,6 +4,9 @@ module.exports = {
docName: 'actions',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'page',
'limit',

View File

@ -4,6 +4,9 @@ module.exports = {
docName: 'announcement',
browse: {
headers: {
cacheInvalidate: false
},
permissions: true,
query(frame) {
return announcementBarSettings.getAnnouncementSettings(frame.options.context?.member);

View File

@ -118,6 +118,9 @@ module.exports = {
},
isSetup: {
headers: {
cacheInvalidate: false
},
permissions: false,
async query() {
const isSetup = await auth.setup.checkIsSetup();
@ -132,6 +135,9 @@ module.exports = {
},
generateResetToken: {
headers: {
cacheInvalidate: false
},
validation: {
docName: 'password_reset'
},
@ -154,6 +160,9 @@ module.exports = {
},
resetPassword: {
headers: {
cacheInvalidate: false
},
validation: {
docName: 'password_reset',
data: {
@ -188,6 +197,9 @@ module.exports = {
},
acceptInvitation: {
headers: {
cacheInvalidate: false
},
validation: {
docName: 'invitations'
},
@ -204,6 +216,9 @@ module.exports = {
},
isInvitation: {
headers: {
cacheInvalidate: false
},
data: [
'email'
],
@ -226,6 +241,9 @@ module.exports = {
resetAllPasswords: {
statusCode: 204,
headers: {
cacheInvalidate: false
},
permissions: true,
async query(frame) {
await userService.resetAllPasswords(frame.options);

View File

@ -24,6 +24,9 @@ module.exports = {
docName: 'authors',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'filter',
@ -50,6 +53,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'filter',

View File

@ -10,6 +10,9 @@ module.exports = {
docName: 'collections',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'limit',
'order',
@ -24,6 +27,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
data: [
'id'
],
@ -55,7 +61,9 @@ module.exports = {
},
edit: {
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id'
],
@ -95,7 +103,9 @@ module.exports = {
addPost: {
docName: 'collection_posts',
statusCode: 200,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id'
],

View File

@ -6,6 +6,9 @@ module.exports = {
docName: 'comments',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'page',
@ -27,6 +30,9 @@ module.exports = {
},
replies: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'page',
@ -49,6 +55,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: [
'include'
],
@ -68,7 +77,9 @@ module.exports = {
},
edit: {
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id',
'include'
@ -91,6 +102,9 @@ module.exports = {
add: {
statusCode: 201,
headers: {
cacheInvalidate: false
},
options: [
'include'
@ -115,6 +129,9 @@ module.exports = {
destroy: {
statusCode: 204,
headers: {
cacheInvalidate: false
},
options: [
'include',
'id'
@ -131,6 +148,9 @@ module.exports = {
},
counts: {
headers: {
cacheInvalidate: false
},
permissions: false,
options: [
'ids'
@ -142,6 +162,9 @@ module.exports = {
like: {
statusCode: 204,
headers: {
cacheInvalidate: false
},
options: [
'id'
],
@ -155,6 +178,9 @@ module.exports = {
unlike: {
statusCode: 204,
headers: {
cacheInvalidate: false
},
options: [
'id'
],
@ -167,6 +193,9 @@ module.exports = {
report: {
statusCode: 204,
headers: {
cacheInvalidate: false
},
options: [
'id'
],

View File

@ -4,6 +4,9 @@ module.exports = {
docName: 'comments',
edit: {
headers: {
cacheInvalidate: false
},
options: [
'id'
],

View File

@ -4,6 +4,9 @@ module.exports = {
docName: 'config',
read: {
headers: {
cacheInvalidate: false
},
permissions: false,
query() {
return publicConfig.config;

View File

@ -4,6 +4,9 @@ module.exports = {
docName: 'custom_theme_settings',
browse: {
headers: {
cacheInvalidate: false
},
permissions: true,
query() {
return customThemeSettingsService.api.listSettings();

View File

@ -12,6 +12,9 @@ module.exports = {
docName: 'db',
backupContent: {
headers: {
cacheInvalidate: false
},
permissions: true,
options: [
'include',
@ -48,7 +51,8 @@ module.exports = {
disposition: {
type: 'file',
value: () => (exporter.fileName())
}
},
cacheInvalidate: false
},
permissions: true,
async query(frame) {
@ -103,6 +107,9 @@ module.exports = {
},
inlineMedia: {
headers: {
cacheInvalidate: false
},
permissions: {
method: 'importContent'
},

View File

@ -11,6 +11,9 @@ module.exports = {
docName: 'email_post',
read: {
headers: {
cacheInvalidate: false
},
permissions: true,
options: [
'include'

View File

@ -4,6 +4,9 @@ module.exports = {
docName: 'email_previews',
read: {
headers: {
cacheInvalidate: false
},
options: [
'fields',
'memberSegment',
@ -25,7 +28,9 @@ module.exports = {
},
sendTestEmail: {
statusCode: 204,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id'
],

View File

@ -16,6 +16,9 @@ module.exports = {
docName: 'emails',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'limit',
'fields',
@ -30,6 +33,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: [
'fields'
],
@ -57,6 +63,9 @@ module.exports = {
},
retry: {
headers: {
cacheInvalidate: false
},
data: [
'id'
],
@ -67,6 +76,9 @@ module.exports = {
},
browseBatches: {
headers: {
cacheInvalidate: false
},
options: [
'limit',
'fields',
@ -95,6 +107,9 @@ module.exports = {
},
browseFailures: {
headers: {
cacheInvalidate: false
},
options: [
'limit',
'fields',
@ -123,6 +138,9 @@ module.exports = {
},
analyticsStatus: {
headers: {
cacheInvalidate: false
},
permissions: {
method: 'browse'
},
@ -132,6 +150,9 @@ module.exports = {
},
scheduleAnalytics: {
headers: {
cacheInvalidate: false
},
permissions: {
method: 'browse'
},
@ -148,6 +169,9 @@ module.exports = {
},
cancelScheduledAnalytics: {
headers: {
cacheInvalidate: false
},
permissions: {
method: 'browse'
},

View File

@ -4,6 +4,9 @@ module.exports = {
docName: 'explore',
read: {
headers: {
cacheInvalidate: false
},
permissions: true,
query() {
return exploreService.fetchData();

View File

@ -5,6 +5,9 @@ module.exports = {
add: {
statusCode: 201,
headers: {
cacheInvalidate: false
},
validation: {
data: {
post_id: {

View File

@ -4,6 +4,9 @@ module.exports = {
docName: 'files',
upload: {
statusCode: 201,
headers: {
cacheInvalidate: false
},
permissions: false,
async query(frame) {
const filePath = await storage.getStorage('files').save({

View File

@ -26,6 +26,9 @@ const sign = async (claims, options) => {
module.exports = {
docName: 'identities',
read: {
headers: {
cacheInvalidate: false
},
permissions: true,
async query(frame) {
const token = await sign({sub: frame.user.get('email')});

View File

@ -8,6 +8,9 @@ module.exports = {
docName: 'images',
upload: {
statusCode: 201,
headers: {
cacheInvalidate: false
},
permissions: false,
async query(frame) {
const store = storage.getStorage('images');

View File

@ -15,6 +15,9 @@ const integrationsService = getIntegrationsServiceInstance({
module.exports = {
docName: 'integrations',
browse: {
headers: {
cacheInvalidate: false
},
permissions: true,
options: [
'include',
@ -32,6 +35,9 @@ module.exports = {
}
},
read: {
headers: {
cacheInvalidate: false
},
permissions: true,
data: [
'id'
@ -63,6 +69,9 @@ module.exports = {
}
},
edit: {
headers: {
cacheInvalidate: false
},
permissions: true,
data: [
'name',
@ -91,6 +100,9 @@ module.exports = {
},
add: {
statusCode: 201,
headers: {
cacheInvalidate: false
},
permissions: true,
data: [
'name',
@ -125,6 +137,9 @@ module.exports = {
},
destroy: {
statusCode: 204,
headers: {
cacheInvalidate: false
},
permissions: true,
options: [
'id'

View File

@ -15,6 +15,9 @@ module.exports = {
docName: 'invites',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'page',
@ -36,6 +39,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: [
'include'
],
@ -64,6 +70,9 @@ module.exports = {
},
destroy: {
headers: {
cacheInvalidate: false
},
statusCode: 204,
options: [
'include',
@ -82,6 +91,9 @@ module.exports = {
add: {
statusCode: 201,
headers: {
cacheInvalidate: false
},
options: [
'include',
'email'

View File

@ -14,6 +14,9 @@ module.exports = {
docName: 'labels',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'filter',
@ -36,6 +39,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'filter',
@ -69,7 +75,9 @@ module.exports = {
add: {
statusCode: 201,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'include'
],
@ -94,7 +102,9 @@ module.exports = {
},
edit: {
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id',
'include'

View File

@ -4,6 +4,9 @@ const INVALIDATE_ALL_REDIRECTS = '/r/*';
module.exports = {
docName: 'links',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'filter'
],

View File

@ -40,6 +40,9 @@ module.exports = {
docName: 'mail',
send: {
headers: {
cacheInvalidate: false
},
permissions: true,
query(frame) {
return _private.sendMail(frame.data);

View File

@ -5,6 +5,9 @@ module.exports = {
docName: 'media',
upload: {
statusCode: 201,
headers: {
cacheInvalidate: false
},
permissions: false,
async query(frame) {
let thumbnailPath = null;
@ -22,6 +25,9 @@ module.exports = {
},
uploadThumbnail: {
headers: {
cacheInvalidate: false
},
permissions: false,
data: [
'url',

View File

@ -9,6 +9,9 @@ const messages = {
module.exports = {
docName: 'member_signin_urls',
read: {
headers: {
cacheInvalidate: false
},
data: [
'id'
],

View File

@ -3,6 +3,9 @@ const membersService = require('../../services/members');
module.exports = {
docName: 'members_stripe_connect',
auth: {
headers: {
cacheInvalidate: false
},
permissions: true,
options: [
'mode'

View File

@ -33,6 +33,9 @@ module.exports = {
docName: 'members',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'limit',
'fields',
@ -62,7 +65,9 @@ module.exports = {
options: [
'include'
],
headers: {},
headers: {
cacheInvalidate: false
},
data: [
'id',
'email'
@ -90,7 +95,9 @@ module.exports = {
add: {
statusCode: 201,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'send_email',
'email_type'
@ -115,7 +122,9 @@ module.exports = {
edit: {
statusCode: 200,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id'
],
@ -136,7 +145,9 @@ module.exports = {
editSubscription: {
statusCode: 200,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id',
'subscription_id'
@ -196,7 +207,9 @@ module.exports = {
createSubscription: {
statusCode: 200,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id'
],
@ -238,7 +251,9 @@ module.exports = {
destroy: {
statusCode: 204,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id',
'cancel'
@ -262,7 +277,9 @@ module.exports = {
bulkDestroy: {
statusCode: 200,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'all',
'filter',
@ -290,7 +307,9 @@ module.exports = {
bulkEdit: {
statusCode: 200,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'all',
'filter',
@ -329,7 +348,8 @@ module.exports = {
const datetime = (new Date()).toJSON().substring(0, 10);
return `members.${datetime}.csv`;
}
}
},
cacheInvalidate: false
},
response: {
format: 'plain'
@ -346,6 +366,9 @@ module.exports = {
},
importCSV: {
headers: {
cacheInvalidate: false
},
statusCode(result) {
if (result && result.meta && result.meta.stats && result.meta.stats.imported !== null) {
return 201;
@ -388,6 +411,9 @@ module.exports = {
},
memberStats: {
headers: {
cacheInvalidate: false
},
permissions: {
method: 'browse'
},
@ -410,6 +436,9 @@ module.exports = {
},
mrrStats: {
headers: {
cacheInvalidate: false
},
permissions: {
method: 'browse'
},
@ -434,6 +463,9 @@ module.exports = {
},
activityFeed: {
headers: {
cacheInvalidate: false
},
options: [
'limit',
'filter'

View File

@ -3,6 +3,9 @@ const mentions = require('../../services/mentions');
module.exports = {
docName: 'mentions',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'filter',
'fields',
@ -20,7 +23,9 @@ module.exports = {
receive: {
statusCode: 202, // Required for the spec because we don't have a status page
headers: {},
headers: {
cacheInvalidate: false
},
options: [],
permissions: false,
response: {

View File

@ -4,6 +4,9 @@ module.exports = {
docName: 'newsletters',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'filter',
'fields',

View File

@ -7,6 +7,9 @@ module.exports = {
docName: 'newsletters',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'filter',
@ -29,6 +32,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'fields',
@ -102,6 +108,9 @@ module.exports = {
},
verifyPropertyUpdate: {
headers: {
cacheInvalidate: false
},
permissions: {
method: 'edit'
},

View File

@ -7,6 +7,9 @@ module.exports = {
docName: 'notifications',
browse: {
headers: {
cacheInvalidate: false
},
permissions: true,
query(frame) {
return notifications.browse({
@ -25,6 +28,9 @@ module.exports = {
return 200;
}
},
headers: {
cacheInvalidate: false
},
permissions: true,
async query(frame) {
const {allNotifications, notificationsToAdd} = notifications.add({
@ -45,6 +51,9 @@ module.exports = {
destroy: {
statusCode: 204,
headers: {
cacheInvalidate: false
},
options: ['notification_id'],
validation: {
options: {
@ -76,6 +85,9 @@ module.exports = {
*/
destroyAll: {
statusCode: 204,
headers: {
cacheInvalidate: false
},
permissions: {
method: 'destroy'
},

View File

@ -4,6 +4,9 @@ module.exports = {
docName: 'oembed',
read: {
headers: {
cacheInvalidate: false
},
permissions: false,
data: [
'url',

View File

@ -10,6 +10,9 @@ module.exports = {
docName: 'offers',
read: {
headers: {
cacheInvalidate: false
},
data: ['id'],
permissions: true,
async query(frame) {

View File

@ -10,6 +10,9 @@ module.exports = {
docName: 'offers',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'filter'
],
@ -23,6 +26,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
data: ['id'],
permissions: true,
async query(frame) {

View File

@ -24,6 +24,9 @@ module.exports = {
docName: 'pages',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'filter',
@ -56,6 +59,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'fields',

View File

@ -14,6 +14,9 @@ const postsService = getPostServiceInstance();
module.exports = {
docName: 'pages',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'filter',
@ -45,6 +48,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'fields',
@ -90,7 +96,9 @@ module.exports = {
add: {
statusCode: 201,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'include',
'formats',
@ -113,9 +121,7 @@ module.exports = {
query(frame) {
return models.Post.add(frame.data.pages[0], frame.options)
.then((model) => {
if (model.get('status') !== 'published') {
this.headers.cacheInvalidate = false;
} else {
if (model.get('status') === 'published') {
this.headers.cacheInvalidate = true;
}
@ -125,7 +131,9 @@ module.exports = {
},
edit: {
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'include',
'id',
@ -245,7 +253,8 @@ module.exports = {
headers: {
location: {
resolve: postsService.generateCopiedPostLocationFromUrl
}
},
cacheInvalidate: false
},
options: [
'id',

View File

@ -25,6 +25,9 @@ module.exports = {
docName: 'posts',
browse: {
headers: {
cacheInvalidate: false
},
cache: postsPublicService.api?.cache,
options: [
'include',
@ -58,6 +61,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'fields',

View File

@ -24,6 +24,9 @@ const postsService = getPostServiceInstance();
module.exports = {
docName: 'posts',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'filter',
@ -66,7 +69,8 @@ module.exports = {
const datetime = (new Date()).toJSON().substring(0, 10);
return `post-analytics.${datetime}.csv`;
}
}
},
cacheInvalidate: false
},
response: {
format: 'plain'
@ -83,6 +87,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'fields',
@ -118,7 +125,9 @@ module.exports = {
add: {
statusCode: 201,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'include',
'formats',
@ -152,7 +161,9 @@ module.exports = {
},
edit: {
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'include',
'id',
@ -271,7 +282,8 @@ module.exports = {
headers: {
location: {
resolve: postsService.generateCopiedPostLocationFromUrl
}
},
cacheInvalidate: false
},
options: [
'id',

View File

@ -11,6 +11,9 @@ module.exports = {
docName: 'previews',
read: {
headers: {
cacheInvalidate: false
},
permissions: true,
options: [
'include'

View File

@ -18,7 +18,8 @@ module.exports = {
: 'redirects.yaml';
});
}
}
},
cacheInvalidate: false
},
permissions: true,
response: {

View File

@ -3,6 +3,9 @@ const models = require('../../models');
module.exports = {
docName: 'roles',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'permissions'
],

View File

@ -5,7 +5,9 @@ const postSchedulingService = require('../../services/posts/post-scheduling-serv
module.exports = {
docName: 'schedules',
publish: {
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id',
'resource'
@ -50,6 +52,9 @@ module.exports = {
getScheduled: {
// NOTE: this method is for internal use only by DefaultScheduler
// it is not exposed anywhere!
headers: {
cacheInvalidate: false
},
permissions: false,
validation: {
options: {

View File

@ -6,6 +6,9 @@ module.exports = {
docName: 'settings',
browse: {
headers: {
cacheInvalidate: false
},
permissions: true,
query() {
// @TODO: decouple settings cache from API knowledge

View File

@ -25,6 +25,9 @@ module.exports = {
docName: 'settings',
browse: {
headers: {
cacheInvalidate: false
},
options: ['group'],
permissions: true,
query(frame) {
@ -33,6 +36,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: ['key'],
validation: {
options: {
@ -73,6 +79,9 @@ module.exports = {
disconnectStripeConnectIntegration: {
statusCode: 204,
headers: {
cacheInvalidate: false
},
permissions: {
method: 'edit'
},
@ -158,7 +167,8 @@ module.exports = {
disposition: {
type: 'yaml',
value: 'routes.yaml'
}
},
cacheInvalidate: false
},
response: {
format: 'plain'

View File

@ -4,6 +4,9 @@ const site = {
docName: 'site',
read: {
headers: {
cacheInvalidate: false
},
permissions: false,
query() {
return publicConfig.site;

View File

@ -4,6 +4,9 @@ const events = require('../../lib/common/events');
module.exports = {
docName: 'slack',
sendTest: {
headers: {
cacheInvalidate: false
},
permissions: false,
query() {
events.emit('slack.test');

View File

@ -12,6 +12,9 @@ module.exports = {
docName: 'snippets',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'limit',
'order',
@ -33,7 +36,9 @@ module.exports = {
},
read: {
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'formats'
],
@ -57,7 +62,9 @@ module.exports = {
add: {
statusCode: 201,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'formats'
],
@ -75,7 +82,9 @@ module.exports = {
},
edit: {
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id',
'formats'
@ -104,7 +113,9 @@ module.exports = {
destroy: {
statusCode: 204,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id'
],

View File

@ -3,6 +3,9 @@ const statsService = require('../../services/stats');
module.exports = {
docName: 'stats',
memberCountHistory: {
headers: {
cacheInvalidate: false
},
permissions: {
docName: 'members',
method: 'browse'
@ -12,6 +15,9 @@ module.exports = {
}
},
mrr: {
headers: {
cacheInvalidate: false
},
permissions: {
docName: 'members',
method: 'browse'
@ -21,6 +27,9 @@ module.exports = {
}
},
subscriptions: {
headers: {
cacheInvalidate: false
},
permissions: {
docName: 'members',
method: 'browse'
@ -30,6 +39,9 @@ module.exports = {
}
},
postReferrers: {
headers: {
cacheInvalidate: false
},
data: [
'id'
],
@ -42,6 +54,9 @@ module.exports = {
}
},
referrersHistory: {
headers: {
cacheInvalidate: false
},
data: [
'id'
],

View File

@ -14,6 +14,9 @@ module.exports = {
docName: 'tags',
browse: {
headers: {
cacheInvalidate: false
},
cache: tagsPublicService.api?.cache,
options: [
'include',
@ -38,6 +41,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'filter',

View File

@ -13,6 +13,9 @@ module.exports = {
docName: 'tags',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'filter',
@ -36,6 +39,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'filter',
@ -91,7 +97,9 @@ module.exports = {
},
edit: {
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id',
'include'

View File

@ -10,6 +10,9 @@ module.exports = {
docName: 'themes',
browse: {
headers: {
cacheInvalidate: false
},
permissions: true,
query() {
return themeService.api.getJSON();
@ -17,6 +20,9 @@ module.exports = {
},
readActive: {
headers: {
cacheInvalidate: false
},
permissions: true,
async query() {
let themeName = settingsCache.get('active_theme');
@ -59,7 +65,9 @@ module.exports = {
},
install: {
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'source',
'ref'
@ -94,7 +102,9 @@ module.exports = {
},
upload: {
headers: {},
headers: {
cacheInvalidate: false
},
permissions: {
method: 'add'
},
@ -125,6 +135,9 @@ module.exports = {
},
download: {
headers: {
cacheInvalidate: false
},
options: [
'name'
],

View File

@ -4,6 +4,9 @@ module.exports = {
docName: 'tiers',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'limit',
'fields',

View File

@ -4,6 +4,9 @@ module.exports = {
docName: 'tiers',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'limit',
'fields',
@ -22,6 +25,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
data: [
'id'
],

View File

@ -45,6 +45,9 @@ module.exports = {
docName: 'users',
browse: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'filter',
@ -68,6 +71,9 @@ module.exports = {
},
read: {
headers: {
cacheInvalidate: false
},
options: [
'include',
'filter',
@ -103,7 +109,9 @@ module.exports = {
},
edit: {
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id',
'include'
@ -166,6 +174,9 @@ module.exports = {
},
changePassword: {
headers: {
cacheInvalidate: false
},
validation: {
docName: 'password',
data: {
@ -188,6 +199,9 @@ module.exports = {
},
transferOwnership: {
headers: {
cacheInvalidate: false
},
permissions(frame) {
return models.Role.findOne({name: 'Owner'})
.then((ownerRole) => {
@ -200,6 +214,9 @@ module.exports = {
},
readToken: {
headers: {
cacheInvalidate: false
},
options: [
'id'
],
@ -218,6 +235,9 @@ module.exports = {
},
regenerateToken: {
headers: {
cacheInvalidate: false
},
options: [
'id'
],

View File

@ -22,7 +22,8 @@ module.exports = {
statusCode: 201,
headers: {
// NOTE: remove if there is ever a 'read' method
location: false
location: false,
cacheInvalidate: false
},
options: [],
data: [],
@ -33,6 +34,9 @@ module.exports = {
},
edit: {
headers: {
cacheInvalidate: false
},
permissions: {
before: (frame) => {
if (frame.options.context && frame.options.context.integration && frame.options.context.integration.id) {
@ -84,7 +88,9 @@ module.exports = {
destroy: {
statusCode: 204,
headers: {},
headers: {
cacheInvalidate: false
},
options: [
'id'
],

View File

@ -0,0 +1,46 @@
const assert = require('assert');
const path = require('path');
const glob = require('glob');
const models = require('../../../core/server/models');
describe('API', function () {
describe('Cache Invalidation', function () {
before(async function () {
// Initialise models - Utilised by various endpoints to reference static fields (i.e models.Post.allowedFormats) when required in
models.init();
});
it('Controller actions explicitly declare cacheInvalidate header', async function () {
const controllersRootPath = path.join(__dirname, '../../../core/server/api/endpoints');
const controllerPaths = glob.sync('*.js', {
cwd: controllersRootPath,
ignore: [
'index.js',
'identities.js' // The identities controller can not be required directly due to requiring other parts of Ghost to have been initialised first
],
realpath: true
});
assert.ok(controllerPaths.length > 0, `No controllers found in ${controllersRootPath}`);
controllerPaths.forEach((controllerPath) => {
const controllerConfig = require(controllerPath);
const ignoreKeys = ['docName'];
Object.keys(controllerConfig).forEach((key) => {
if (ignoreKeys.includes(key) || typeof controllerConfig[key] === 'function') {
return;
}
assert.notEqual(
controllerConfig[key].headers?.cacheInvalidate,
undefined,
`"${key}" action in controller: ${controllerPath} is missing cacheInvalidate header - This needs to be explicitly defined`
);
});
});
});
});
});