ghost 5.8.3 → 5.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/tryghost-adapter-manager-0.0.0.tgz +0 -0
- package/components/tryghost-api-framework-0.0.0.tgz +0 -0
- package/components/tryghost-bootstrap-socket-0.0.0.tgz +0 -0
- package/components/tryghost-custom-theme-settings-service-0.0.0.tgz +0 -0
- package/components/tryghost-email-analytics-provider-mailgun-0.0.0.tgz +0 -0
- package/components/tryghost-email-analytics-service-0.0.0.tgz +0 -0
- package/components/tryghost-job-manager-0.0.0.tgz +0 -0
- package/components/tryghost-mailgun-client-0.0.0.tgz +0 -0
- package/components/tryghost-member-analytics-service-0.0.0.tgz +0 -0
- package/components/tryghost-members-api-0.0.0.tgz +0 -0
- package/components/tryghost-members-importer-0.0.0.tgz +0 -0
- package/components/tryghost-members-offers-0.0.0.tgz +0 -0
- package/components/tryghost-members-payments-0.0.0.tgz +0 -0
- package/components/tryghost-members-ssr-0.0.0.tgz +0 -0
- package/components/tryghost-members-stripe-service-0.0.0.tgz +0 -0
- package/components/tryghost-minifier-0.0.0.tgz +0 -0
- package/components/tryghost-mw-cache-control-0.0.0.tgz +0 -0
- package/components/tryghost-mw-error-handler-0.0.0.tgz +0 -0
- package/components/tryghost-oembed-service-0.0.0.tgz +0 -0
- package/components/tryghost-package-json-0.0.0.tgz +0 -0
- package/components/tryghost-session-service-0.0.0.tgz +0 -0
- package/components/tryghost-settings-path-manager-0.0.0.tgz +0 -0
- package/components/tryghost-update-check-service-0.0.0.tgz +0 -0
- package/content/themes/casper/README.md +1 -1
- package/content/themes/casper/assets/built/portal.min.js +3 -0
- package/content/themes/casper/assets/built/screen.css +1 -1
- package/content/themes/casper/assets/built/screen.css.map +1 -1
- package/content/themes/casper/assets/css/screen.css +119 -37
- package/content/themes/casper/package.json +3 -3
- package/content/themes/casper/partials/post-card.hbs +3 -1
- package/content/themes/casper/post.hbs +7 -7
- package/content/themes/casper/yarn.lock +69 -68
- package/core/boot.js +2 -0
- package/core/built/admin/assets/{chunk.143.cf66fd97f99af03c697f.js → chunk.143.4e4590d80452422483d8.js} +5 -5
- package/core/built/admin/assets/{chunk.178.e95388dfcc564cdb1ecc.js → chunk.178.16d88956c09eb76205e0.js} +4 -4
- package/core/built/admin/assets/{chunk.351.cbc224ca65c14ef5322d.js → chunk.351.73f27952f867334a8228.js} +3 -3
- package/core/built/admin/assets/{chunk.351.cbc224ca65c14ef5322d.js.LICENSE.txt → chunk.351.73f27952f867334a8228.js.LICENSE.txt} +0 -0
- package/core/built/admin/assets/{ghost-b469423d0fbe5e40af17b560f7e3cead.css → ghost-0319628ec5dcb83e6968e99eaa629a75.css} +1 -1
- package/core/built/admin/assets/{ghost-dark-bcb6f4517a2dfe23a0a280632bfca00c.css → ghost-dark-eada0a988277e84b4c8ead995f912044.css} +1 -1
- package/core/built/admin/assets/{ghost-f1d63ad9698b7d38261df6384513c952.js → ghost-f144e03b578116a5d0ed41bceaf2bab8.js} +90 -88
- package/core/built/admin/index.html +5 -5
- package/core/frontend/helpers/comment_count.js +1 -15
- package/core/frontend/helpers/comments.js +4 -16
- package/core/frontend/helpers/ghost_head.js +1 -1
- package/core/frontend/services/routing/controllers/unsubscribe.js +3 -0
- package/core/server/api/endpoints/comments-members.js +23 -1
- package/core/server/api/endpoints/index.js +52 -52
- package/core/server/api/endpoints/oembed.js +1 -1
- package/core/server/api/endpoints/utils/serializers/input/comments.js +18 -0
- package/core/server/api/endpoints/utils/serializers/input/db.js +1 -1
- package/core/server/api/endpoints/utils/serializers/input/index.js +4 -0
- package/core/server/api/endpoints/utils/serializers/input/integrations.js +2 -2
- package/core/server/api/{shared → endpoints/utils}/serializers/input/utils/settings-filter-type-group-mapper.js +0 -0
- package/core/server/api/{shared → endpoints/utils}/serializers/input/utils/settings-key-group-mapper.js +0 -0
- package/core/server/api/{shared → endpoints/utils}/serializers/input/utils/settings-key-type-mapper.js +0 -0
- package/core/server/api/endpoints/utils/serializers/output/mappers/comments.js +12 -12
- package/core/server/api/endpoints/utils/serializers/output/tiers.js +1 -1
- package/core/server/api/index.js +0 -2
- package/core/server/data/importer/importers/data/settings.js +2 -2
- package/core/server/data/migrations/versions/5.9/2022-08-09-08-32-added-new-integration-type.js +24 -0
- package/core/server/data/schema/clients/mysql.js +0 -15
- package/core/server/data/schema/commands.js +0 -9
- package/core/server/data/schema/fixtures/fixtures.json +1 -1
- package/core/server/data/schema/schema.js +3 -3
- package/core/server/models/base/plugins/user-type.js +1 -9
- package/core/server/models/comment.js +96 -15
- package/core/server/models/label.js +14 -0
- package/core/server/models/newsletter.js +21 -0
- package/core/server/models/tag.js +20 -0
- package/core/server/models/user.js +20 -0
- package/core/server/services/auth/api-key/admin.js +1 -5
- package/core/server/services/auth/api-key/content.js +1 -5
- package/core/server/services/bulk-email/bulk-email-processor.js +19 -12
- package/core/server/services/bulk-email/index.js +1 -17
- package/core/server/services/comments/controller.js +9 -0
- package/core/server/services/comments/email-templates/new-comment-reply.hbs +3 -3
- package/core/server/services/comments/email-templates/new-comment-reply.txt.js +1 -1
- package/core/server/services/comments/email-templates/new-comment.hbs +2 -2
- package/core/server/services/comments/email-templates/report.hbs +2 -2
- package/core/server/services/comments/emails.js +2 -1
- package/core/server/services/comments/service.js +16 -3
- package/core/server/services/mega/post-email-serializer.js +11 -6
- package/core/server/services/permissions/can-this.js +154 -161
- package/core/server/services/permissions/parse-context.js +1 -8
- package/core/server/services/webhooks/serialize.js +3 -3
- package/core/server/web/api/endpoints/admin/routes.js +1 -1
- package/core/server/web/api/endpoints/content/routes.js +1 -1
- package/core/server/web/comments/routes.js +2 -1
- package/core/server/web/shared/middleware/index.js +1 -1
- package/core/shared/config/defaults.json +2 -2
- package/core/shared/labs.js +0 -1
- package/package.json +34 -37
- package/yarn.lock +272 -245
- package/core/server/api/README.md +0 -130
- package/core/server/api/shared/frame.js +0 -95
- package/core/server/api/shared/headers.js +0 -152
- package/core/server/api/shared/http.js +0 -127
- package/core/server/api/shared/index.js +0 -25
- package/core/server/api/shared/pipeline.js +0 -259
- package/core/server/api/shared/serializers/handle.js +0 -140
- package/core/server/api/shared/serializers/index.js +0 -13
- package/core/server/api/shared/serializers/input/all.js +0 -41
- package/core/server/api/shared/serializers/input/index.js +0 -5
- package/core/server/api/shared/serializers/output/index.js +0 -1
- package/core/server/api/shared/utils/index.js +0 -5
- package/core/server/api/shared/utils/options.js +0 -23
- package/core/server/api/shared/validators/handle.js +0 -68
- package/core/server/api/shared/validators/index.js +0 -9
- package/core/server/api/shared/validators/input/all.js +0 -213
- package/core/server/api/shared/validators/input/index.js +0 -5
- package/core/server/services/bulk-email/mailgun.js +0 -122
- package/core/server/services/oembed.js +0 -346
- package/core/server/web/shared/middleware/cache-control.js +0 -43
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
const debug = require('@tryghost/debug')('api:shared:pipeline');
|
|
2
|
-
const Promise = require('bluebird');
|
|
3
|
-
const _ = require('lodash');
|
|
4
|
-
const shared = require('../shared');
|
|
5
|
-
const errors = require('@tryghost/errors');
|
|
6
|
-
const {sequence} = require('@tryghost/promise');
|
|
7
|
-
|
|
8
|
-
const STAGES = {
|
|
9
|
-
validation: {
|
|
10
|
-
/**
|
|
11
|
-
* @description Input validation.
|
|
12
|
-
*
|
|
13
|
-
* We call the shared validator which runs the request through:
|
|
14
|
-
*
|
|
15
|
-
* 1. Shared validator
|
|
16
|
-
* 2. Custom API validators
|
|
17
|
-
*
|
|
18
|
-
* @param {Object} apiUtils - Local utils of target API version.
|
|
19
|
-
* @param {Object} apiConfig - Docname & Method of ctrl.
|
|
20
|
-
* @param {Object} apiImpl - Controller configuration.
|
|
21
|
-
* @param {Object} frame
|
|
22
|
-
* @return {Promise}
|
|
23
|
-
*/
|
|
24
|
-
input(apiUtils, apiConfig, apiImpl, frame) {
|
|
25
|
-
debug('stages: validation');
|
|
26
|
-
const tasks = [];
|
|
27
|
-
|
|
28
|
-
// CASE: do validation completely yourself
|
|
29
|
-
if (typeof apiImpl.validation === 'function') {
|
|
30
|
-
debug('validation function call');
|
|
31
|
-
return apiImpl.validation(frame);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
tasks.push(function doValidation() {
|
|
35
|
-
return shared.validators.handle.input(
|
|
36
|
-
Object.assign({}, apiConfig, apiImpl.validation),
|
|
37
|
-
apiUtils.validators.input,
|
|
38
|
-
frame
|
|
39
|
-
);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
return sequence(tasks);
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
serialisation: {
|
|
47
|
-
/**
|
|
48
|
-
* @description Input Serialisation.
|
|
49
|
-
*
|
|
50
|
-
* We call the shared serializer which runs the request through:
|
|
51
|
-
*
|
|
52
|
-
* 1. Shared serializers
|
|
53
|
-
* 2. Custom API serializers
|
|
54
|
-
*
|
|
55
|
-
* @param {Object} apiUtils - Local utils of target API version.
|
|
56
|
-
* @param {Object} apiConfig - Docname & Method of ctrl.
|
|
57
|
-
* @param {Object} apiImpl - Controller configuration.
|
|
58
|
-
* @param {Object} frame
|
|
59
|
-
* @return {Promise}
|
|
60
|
-
*/
|
|
61
|
-
input(apiUtils, apiConfig, apiImpl, frame) {
|
|
62
|
-
debug('stages: input serialisation');
|
|
63
|
-
return shared.serializers.handle.input(
|
|
64
|
-
Object.assign({data: apiImpl.data}, apiConfig),
|
|
65
|
-
apiUtils.serializers.input,
|
|
66
|
-
frame
|
|
67
|
-
);
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* @description Output Serialisation.
|
|
72
|
-
*
|
|
73
|
-
* We call the shared serializer which runs the request through:
|
|
74
|
-
*
|
|
75
|
-
* 1. Shared serializers
|
|
76
|
-
* 2. Custom API serializers
|
|
77
|
-
*
|
|
78
|
-
* @param {Object} apiUtils - Local utils of target API version.
|
|
79
|
-
* @param {Object} apiConfig - Docname & Method of ctrl.
|
|
80
|
-
* @param {Object} apiImpl - Controller configuration.
|
|
81
|
-
* @param {Object} frame
|
|
82
|
-
* @return {Promise}
|
|
83
|
-
*/
|
|
84
|
-
output(response, apiUtils, apiConfig, apiImpl, frame) {
|
|
85
|
-
debug('stages: output serialisation');
|
|
86
|
-
return shared.serializers.handle.output(response, apiConfig, apiUtils.serializers.output, frame);
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* @description Permissions stage.
|
|
92
|
-
*
|
|
93
|
-
* We call the target API implementation of permissions.
|
|
94
|
-
* Permissions implementation can change across API versions.
|
|
95
|
-
* There is no shared implementation right now.
|
|
96
|
-
*
|
|
97
|
-
* @param {Object} apiUtils - Local utils of target API version.
|
|
98
|
-
* @param {Object} apiConfig - Docname & Method of ctrl.
|
|
99
|
-
* @param {Object} apiImpl - Controller configuration.
|
|
100
|
-
* @param {Object} frame
|
|
101
|
-
* @return {Promise}
|
|
102
|
-
*/
|
|
103
|
-
permissions(apiUtils, apiConfig, apiImpl, frame) {
|
|
104
|
-
debug('stages: permissions');
|
|
105
|
-
const tasks = [];
|
|
106
|
-
|
|
107
|
-
// CASE: it's required to put the permission key to avoid security holes
|
|
108
|
-
if (!Object.prototype.hasOwnProperty.call(apiImpl, 'permissions')) {
|
|
109
|
-
return Promise.reject(new errors.IncorrectUsageError());
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// CASE: handle permissions completely yourself
|
|
113
|
-
if (typeof apiImpl.permissions === 'function') {
|
|
114
|
-
debug('permissions function call');
|
|
115
|
-
return apiImpl.permissions(frame);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// CASE: skip stage completely
|
|
119
|
-
if (apiImpl.permissions === false) {
|
|
120
|
-
debug('disabled permissions');
|
|
121
|
-
return Promise.resolve();
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (typeof apiImpl.permissions === 'object' && apiImpl.permissions.before) {
|
|
125
|
-
tasks.push(function beforePermissions() {
|
|
126
|
-
return apiImpl.permissions.before(frame);
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
tasks.push(function doPermissions() {
|
|
131
|
-
return apiUtils.permissions.handle(
|
|
132
|
-
Object.assign({}, apiConfig, apiImpl.permissions),
|
|
133
|
-
frame
|
|
134
|
-
);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
return sequence(tasks);
|
|
138
|
-
},
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* @description Execute controller & receive model response.
|
|
142
|
-
*
|
|
143
|
-
* @param {Object} apiUtils - Local utils of target API version.
|
|
144
|
-
* @param {Object} apiConfig - Docname & Method of ctrl.
|
|
145
|
-
* @param {Object} apiImpl - Controller configuration.
|
|
146
|
-
* @param {Object} frame
|
|
147
|
-
* @return {Promise}
|
|
148
|
-
*/
|
|
149
|
-
query(apiUtils, apiConfig, apiImpl, frame) {
|
|
150
|
-
debug('stages: query');
|
|
151
|
-
|
|
152
|
-
if (!apiImpl.query) {
|
|
153
|
-
return Promise.reject(new errors.IncorrectUsageError());
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return apiImpl.query(frame);
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* @description The pipeline runs the request through all stages (validation, serialisation, permissions).
|
|
162
|
-
*
|
|
163
|
-
* The target API version calls the pipeline and wraps the actual ctrl implementation to be able to
|
|
164
|
-
* run the request through various stages before hitting the controller.
|
|
165
|
-
*
|
|
166
|
-
* The stages are executed in the following order:
|
|
167
|
-
*
|
|
168
|
-
* 1. Input validation - General & schema validation
|
|
169
|
-
* 2. Input serialisation - Modification of incoming data e.g. force filters, auto includes, url transformation etc.
|
|
170
|
-
* 3. Permissions - Runs after validation & serialisation because the body structure must be valid (see unsafeAttrs)
|
|
171
|
-
* 4. Controller - Execute the controller implementation & receive model response.
|
|
172
|
-
* 5. Output Serialisation - Output formatting, Deprecations, Extra attributes etc...
|
|
173
|
-
*
|
|
174
|
-
* @param {Function} apiController
|
|
175
|
-
* @param {Object} apiUtils - Local utils (validation & serialisation) from target API version
|
|
176
|
-
* @param {String} [apiType] - Content or Admin API access
|
|
177
|
-
* @return {Function}
|
|
178
|
-
*/
|
|
179
|
-
const pipeline = (apiController, apiUtils, apiType) => {
|
|
180
|
-
const keys = Object.keys(apiController);
|
|
181
|
-
|
|
182
|
-
// CASE: api controllers are objects with configuration.
|
|
183
|
-
// We have to ensure that we expose a functional interface e.g. `api.posts.add` has to be available.
|
|
184
|
-
return keys.reduce((obj, key) => {
|
|
185
|
-
const docName = apiController.docName;
|
|
186
|
-
const method = key;
|
|
187
|
-
|
|
188
|
-
const apiImpl = _.cloneDeep(apiController)[key];
|
|
189
|
-
|
|
190
|
-
obj[key] = function wrapper() {
|
|
191
|
-
const apiConfig = {docName, method};
|
|
192
|
-
let options;
|
|
193
|
-
let data;
|
|
194
|
-
let frame;
|
|
195
|
-
|
|
196
|
-
if (arguments.length === 2) {
|
|
197
|
-
data = arguments[0];
|
|
198
|
-
options = arguments[1];
|
|
199
|
-
} else if (arguments.length === 1) {
|
|
200
|
-
options = arguments[0] || {};
|
|
201
|
-
} else {
|
|
202
|
-
options = {};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// CASE: http helper already creates it's own frame.
|
|
206
|
-
if (!(options instanceof shared.Frame)) {
|
|
207
|
-
debug(`Internal API request for ${docName}.${method}`);
|
|
208
|
-
frame = new shared.Frame({
|
|
209
|
-
body: data,
|
|
210
|
-
options: _.omit(options, 'context'),
|
|
211
|
-
context: options.context || {}
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
frame.configure({
|
|
215
|
-
options: apiImpl.options,
|
|
216
|
-
data: apiImpl.data
|
|
217
|
-
});
|
|
218
|
-
} else {
|
|
219
|
-
frame = options;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// CASE: api controller *can* be a single function, but it's not recommended to disable the framework.
|
|
223
|
-
if (typeof apiImpl === 'function') {
|
|
224
|
-
debug('ctrl function call');
|
|
225
|
-
return apiImpl(frame);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
frame.apiType = apiType;
|
|
229
|
-
frame.docName = docName;
|
|
230
|
-
frame.method = method;
|
|
231
|
-
|
|
232
|
-
return Promise.resolve()
|
|
233
|
-
.then(() => {
|
|
234
|
-
return STAGES.validation.input(apiUtils, apiConfig, apiImpl, frame);
|
|
235
|
-
})
|
|
236
|
-
.then(() => {
|
|
237
|
-
return STAGES.serialisation.input(apiUtils, apiConfig, apiImpl, frame);
|
|
238
|
-
})
|
|
239
|
-
.then(() => {
|
|
240
|
-
return STAGES.permissions(apiUtils, apiConfig, apiImpl, frame);
|
|
241
|
-
})
|
|
242
|
-
.then(() => {
|
|
243
|
-
return STAGES.query(apiUtils, apiConfig, apiImpl, frame);
|
|
244
|
-
})
|
|
245
|
-
.then((response) => {
|
|
246
|
-
return STAGES.serialisation.output(response, apiUtils, apiConfig, apiImpl, frame);
|
|
247
|
-
})
|
|
248
|
-
.then(() => {
|
|
249
|
-
return frame.response;
|
|
250
|
-
});
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
Object.assign(obj[key], apiImpl);
|
|
254
|
-
return obj;
|
|
255
|
-
}, {});
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
module.exports = pipeline;
|
|
259
|
-
module.exports.STAGES = STAGES;
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
const debug = require('@tryghost/debug')('api:shared:serializers:handle');
|
|
2
|
-
const Promise = require('bluebird');
|
|
3
|
-
const {sequence} = require('@tryghost/promise');
|
|
4
|
-
const errors = require('@tryghost/errors');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @description Shared input serialization handler.
|
|
8
|
-
*
|
|
9
|
-
* The shared input handler runs the request through all the validation steps.
|
|
10
|
-
*
|
|
11
|
-
* 1. Shared serialization
|
|
12
|
-
* 2. API serialization
|
|
13
|
-
*
|
|
14
|
-
* @param {Object} apiConfig - Docname + method of the ctrl
|
|
15
|
-
* @param {Object} apiSerializers - Target API serializers
|
|
16
|
-
* @param {Object} frame
|
|
17
|
-
*/
|
|
18
|
-
module.exports.input = (apiConfig, apiSerializers, frame) => {
|
|
19
|
-
debug('input');
|
|
20
|
-
|
|
21
|
-
const tasks = [];
|
|
22
|
-
const sharedSerializers = require('./input');
|
|
23
|
-
|
|
24
|
-
if (!apiConfig) {
|
|
25
|
-
return Promise.reject(new errors.IncorrectUsageError());
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (!apiSerializers) {
|
|
29
|
-
return Promise.reject(new errors.IncorrectUsageError());
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// ##### SHARED ALL SERIALIZATION
|
|
33
|
-
|
|
34
|
-
tasks.push(function serializeAllShared() {
|
|
35
|
-
return sharedSerializers.all.all(apiConfig, frame);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
if (sharedSerializers.all[apiConfig.method]) {
|
|
39
|
-
tasks.push(function serializeAllShared() {
|
|
40
|
-
return sharedSerializers.all[apiConfig.method](apiConfig, frame);
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// ##### API VERSION RESOURCE SERIALIZATION
|
|
45
|
-
|
|
46
|
-
if (apiSerializers.all) {
|
|
47
|
-
tasks.push(function serializeOptionsShared() {
|
|
48
|
-
return apiSerializers.all(apiConfig, frame);
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (apiSerializers[apiConfig.docName]) {
|
|
53
|
-
if (apiSerializers[apiConfig.docName].all) {
|
|
54
|
-
tasks.push(function serializeOptionsShared() {
|
|
55
|
-
return apiSerializers[apiConfig.docName].all(apiConfig, frame);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (apiSerializers[apiConfig.docName][apiConfig.method]) {
|
|
60
|
-
tasks.push(function serializeOptionsShared() {
|
|
61
|
-
return apiSerializers[apiConfig.docName][apiConfig.method](apiConfig, frame);
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
debug(tasks);
|
|
67
|
-
return sequence(tasks);
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const getBestMatchSerializer = function (apiSerializers, docName, method) {
|
|
71
|
-
if (apiSerializers[docName] && apiSerializers[docName][method]) {
|
|
72
|
-
debug(`Calling ${docName}.${method}`);
|
|
73
|
-
return apiSerializers[docName][method].bind(apiSerializers[docName]);
|
|
74
|
-
} else if (apiSerializers[docName] && apiSerializers[docName].all) {
|
|
75
|
-
debug(`Calling ${docName}.all`);
|
|
76
|
-
return apiSerializers[docName].all.bind(apiSerializers[docName]);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
debug(`Returning as-is`);
|
|
80
|
-
return false;
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* @description Shared output serialization handler.
|
|
85
|
-
*
|
|
86
|
-
* The shared output handler runs the request through all the validation steps.
|
|
87
|
-
*
|
|
88
|
-
* 1. Shared serialization
|
|
89
|
-
* 2. API serialization
|
|
90
|
-
*
|
|
91
|
-
* @param {Object} response - API response
|
|
92
|
-
* @param {Object} apiConfig - Docname + method of the ctrl
|
|
93
|
-
* @param {Object} apiSerializers - Target API serializers
|
|
94
|
-
* @param {Object} frame
|
|
95
|
-
*/
|
|
96
|
-
module.exports.output = (response = {}, apiConfig, apiSerializers, frame) => {
|
|
97
|
-
debug('output');
|
|
98
|
-
|
|
99
|
-
const tasks = [];
|
|
100
|
-
|
|
101
|
-
if (!apiConfig) {
|
|
102
|
-
return Promise.reject(new errors.IncorrectUsageError());
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (!apiSerializers) {
|
|
106
|
-
return Promise.reject(new errors.IncorrectUsageError());
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// ##### API VERSION RESOURCE SERIALIZATION
|
|
110
|
-
|
|
111
|
-
if (apiSerializers.all && apiSerializers.all.before) {
|
|
112
|
-
tasks.push(function allSerializeBefore() {
|
|
113
|
-
return apiSerializers.all.before(response, apiConfig, frame);
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const customSerializer = getBestMatchSerializer(apiSerializers, apiConfig.docName, apiConfig.method);
|
|
118
|
-
const defaultSerializer = getBestMatchSerializer(apiSerializers, 'default', apiConfig.method);
|
|
119
|
-
|
|
120
|
-
if (customSerializer) {
|
|
121
|
-
// CASE: custom serializer exists
|
|
122
|
-
tasks.push(function doCustomSerializer() {
|
|
123
|
-
return customSerializer(response, apiConfig, frame);
|
|
124
|
-
});
|
|
125
|
-
} else if (defaultSerializer) {
|
|
126
|
-
// CASE: Fall back to default serializer
|
|
127
|
-
tasks.push(function doDefaultSerializer() {
|
|
128
|
-
return defaultSerializer(response, apiConfig, frame);
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (apiSerializers.all && apiSerializers.all.after) {
|
|
133
|
-
tasks.push(function allSerializeAfter() {
|
|
134
|
-
return apiSerializers.all.after(apiConfig, frame);
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
debug(tasks);
|
|
139
|
-
return sequence(tasks);
|
|
140
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
const debug = require('@tryghost/debug')('api:shared:serializers:input:all');
|
|
2
|
-
const _ = require('lodash');
|
|
3
|
-
const utils = require('../../utils');
|
|
4
|
-
|
|
5
|
-
const INTERNAL_OPTIONS = ['transacting', 'forUpdate'];
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* @description Shared serializer for all requests.
|
|
9
|
-
*
|
|
10
|
-
* Transforms certain options from API notation into model readable language/notation.
|
|
11
|
-
*
|
|
12
|
-
* e.g. API uses "include", but model layer uses "withRelated".
|
|
13
|
-
*/
|
|
14
|
-
module.exports = {
|
|
15
|
-
all(apiConfig, frame) {
|
|
16
|
-
debug('serialize all');
|
|
17
|
-
|
|
18
|
-
if (frame.options.include) {
|
|
19
|
-
frame.options.withRelated = utils.options.trimAndLowerCase(frame.options.include);
|
|
20
|
-
delete frame.options.include;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (frame.options.fields) {
|
|
24
|
-
frame.options.columns = utils.options.trimAndLowerCase(frame.options.fields);
|
|
25
|
-
delete frame.options.fields;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (frame.options.formats) {
|
|
29
|
-
frame.options.formats = utils.options.trimAndLowerCase(frame.options.formats);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (frame.options.formats && frame.options.columns) {
|
|
33
|
-
frame.options.columns = frame.options.columns.concat(frame.options.formats);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (!frame.options.context.internal) {
|
|
37
|
-
debug('omit internal options');
|
|
38
|
-
frame.options = _.omit(frame.options, INTERNAL_OPTIONS);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = {};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
const _ = require('lodash');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @description Helper function to prepare params for internal usages.
|
|
5
|
-
*
|
|
6
|
-
* e.g. "a,B,c" -> ["a", "b", "c"]
|
|
7
|
-
*
|
|
8
|
-
* @param {String} params
|
|
9
|
-
* @return {Array}
|
|
10
|
-
*/
|
|
11
|
-
const trimAndLowerCase = (params) => {
|
|
12
|
-
params = params || '';
|
|
13
|
-
|
|
14
|
-
if (_.isString(params)) {
|
|
15
|
-
params = params.split(',');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return params.map((item) => {
|
|
19
|
-
return item.trim().toLowerCase();
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
module.exports.trimAndLowerCase = trimAndLowerCase;
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
const debug = require('@tryghost/debug')('api:shared:validators:handle');
|
|
2
|
-
const Promise = require('bluebird');
|
|
3
|
-
const errors = require('@tryghost/errors');
|
|
4
|
-
const {sequence} = require('@tryghost/promise');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @description Shared input validation handler.
|
|
8
|
-
*
|
|
9
|
-
* The shared validation handler runs the request through all the validation steps.
|
|
10
|
-
*
|
|
11
|
-
* 1. Shared validation
|
|
12
|
-
* 2. API validation
|
|
13
|
-
*
|
|
14
|
-
* @param {Object} apiConfig - Docname + method of the ctrl
|
|
15
|
-
* @param {Object} apiValidators - Target API validators
|
|
16
|
-
* @param {Object} frame
|
|
17
|
-
*/
|
|
18
|
-
module.exports.input = (apiConfig, apiValidators, frame) => {
|
|
19
|
-
debug('input begin');
|
|
20
|
-
|
|
21
|
-
const tasks = [];
|
|
22
|
-
const sharedValidators = require('./input');
|
|
23
|
-
|
|
24
|
-
if (!apiValidators) {
|
|
25
|
-
return Promise.reject(new errors.IncorrectUsageError());
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (!apiConfig) {
|
|
29
|
-
return Promise.reject(new errors.IncorrectUsageError());
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// ##### SHARED ALL VALIDATION
|
|
33
|
-
|
|
34
|
-
tasks.push(function allShared() {
|
|
35
|
-
return sharedValidators.all.all(apiConfig, frame);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
if (sharedValidators.all[apiConfig.method]) {
|
|
39
|
-
tasks.push(function allShared() {
|
|
40
|
-
return sharedValidators.all[apiConfig.method](apiConfig, frame);
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// ##### API VERSION VALIDATION
|
|
45
|
-
|
|
46
|
-
if (apiValidators.all) {
|
|
47
|
-
tasks.push(function allAPIVersion() {
|
|
48
|
-
return apiValidators.all[apiConfig.method](apiConfig, frame);
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (apiValidators[apiConfig.docName]) {
|
|
53
|
-
if (apiValidators[apiConfig.docName].all) {
|
|
54
|
-
tasks.push(function docNameAll() {
|
|
55
|
-
return apiValidators[apiConfig.docName].all(apiConfig, frame);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (apiValidators[apiConfig.docName][apiConfig.method]) {
|
|
60
|
-
tasks.push(function docNameMethod() {
|
|
61
|
-
return apiValidators[apiConfig.docName][apiConfig.method](apiConfig, frame);
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
debug('input ready');
|
|
67
|
-
return sequence(tasks);
|
|
68
|
-
};
|