apostrophe 3.13.0 → 3.14.2-alpha.20220401
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/CHANGELOG.md +29 -0
- package/index.js +9 -7
- package/modules/@apostrophecms/asset/index.js +24 -9
- package/modules/@apostrophecms/doc/index.js +11 -3
- package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocContextMenu.vue +0 -7
- package/modules/@apostrophecms/express/index.js +43 -37
- package/modules/@apostrophecms/http/index.js +0 -20
- package/modules/@apostrophecms/i18n/i18n/en.json +2 -0
- package/modules/@apostrophecms/login/index.js +160 -33
- package/modules/@apostrophecms/login/ui/apos/components/TheAposLogin.vue +23 -24
- package/modules/@apostrophecms/login/ui/apos/components/TheAposLoginHeader.vue +1 -1
- package/modules/@apostrophecms/migration/index.js +27 -32
- package/modules/@apostrophecms/page/index.js +134 -80
- package/modules/@apostrophecms/piece-page-type/index.js +1 -1
- package/modules/@apostrophecms/piece-type/index.js +85 -72
- package/modules/@apostrophecms/util/ui/src/http.js +1 -7
- package/package.json +3 -2
- package/test/express.js +2 -26
- package/test/http.js +0 -24
- package/test/login-requirements.js +76 -6
- package/test/login.js +42 -0
- package/test/parked-pages.js +284 -13
- package/test/pieces-page-type.js +63 -0
- package/test/package.json +0 -11
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
:class="themeClass"
|
|
7
7
|
>
|
|
8
8
|
<div class="apos-login__wrapper">
|
|
9
|
-
<transition name="fade-body">
|
|
9
|
+
<transition name="fade-body" mode="out-in">
|
|
10
10
|
<div
|
|
11
|
+
key="1"
|
|
11
12
|
class="apos-login__upper"
|
|
12
13
|
v-if="loaded && phase === 'beforeSubmit'"
|
|
13
14
|
>
|
|
@@ -18,25 +19,19 @@
|
|
|
18
19
|
/>
|
|
19
20
|
|
|
20
21
|
<div class="apos-login__body">
|
|
21
|
-
<form
|
|
22
|
-
@submit.prevent="submit"
|
|
23
|
-
>
|
|
22
|
+
<form @submit.prevent="submit">
|
|
24
23
|
<AposSchema
|
|
25
24
|
:schema="schema"
|
|
26
25
|
v-model="doc"
|
|
27
26
|
/>
|
|
28
|
-
|
|
29
|
-
v-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
@done="requirementDone(requirement, $event)"
|
|
37
|
-
@block="requirementBlock(requirement)"
|
|
38
|
-
/>
|
|
39
|
-
</template>
|
|
27
|
+
<Component
|
|
28
|
+
v-for="requirement in beforeSubmitRequirements"
|
|
29
|
+
:key="requirement.name"
|
|
30
|
+
:is="requirement.component"
|
|
31
|
+
v-bind="getRequirementProps(requirement.name)"
|
|
32
|
+
@done="requirementDone(requirement, $event)"
|
|
33
|
+
@block="requirementBlock(requirement)"
|
|
34
|
+
/>
|
|
40
35
|
<!-- TODO -->
|
|
41
36
|
<!-- <a href="#" class="apos-login__link">Forgot Password</a> -->
|
|
42
37
|
<AposButton
|
|
@@ -53,8 +48,9 @@
|
|
|
53
48
|
</div>
|
|
54
49
|
</div>
|
|
55
50
|
<div
|
|
51
|
+
key="2"
|
|
56
52
|
class="apos-login__upper"
|
|
57
|
-
v-else-if="activeSoloRequirement
|
|
53
|
+
v-else-if="activeSoloRequirement"
|
|
58
54
|
>
|
|
59
55
|
<TheAposLoginHeader
|
|
60
56
|
:env="context.env"
|
|
@@ -64,6 +60,7 @@
|
|
|
64
60
|
/>
|
|
65
61
|
<div class="apos-login__body">
|
|
66
62
|
<Component
|
|
63
|
+
v-if="!fetchingRequirementProps"
|
|
67
64
|
v-bind="getRequirementProps(activeSoloRequirement.name)"
|
|
68
65
|
:is="activeSoloRequirement.component"
|
|
69
66
|
:success="activeSoloRequirement.success"
|
|
@@ -131,7 +128,8 @@ export default {
|
|
|
131
128
|
return this.mounted && this.beforeCreateFinished;
|
|
132
129
|
},
|
|
133
130
|
disabled() {
|
|
134
|
-
return this.doc.hasErrors ||
|
|
131
|
+
return this.doc.hasErrors ||
|
|
132
|
+
!!this.beforeSubmitRequirements.find(requirement => !requirement.done);
|
|
135
133
|
},
|
|
136
134
|
beforeSubmitRequirements() {
|
|
137
135
|
return this.requirements.filter(requirement => requirement.phase === 'beforeSubmit');
|
|
@@ -277,12 +275,14 @@ export default {
|
|
|
277
275
|
location.assign(`${apos.prefix}/`);
|
|
278
276
|
},
|
|
279
277
|
async requirementBlock(requirementBlock) {
|
|
280
|
-
const requirement = this.requirements
|
|
278
|
+
const requirement = this.requirements
|
|
279
|
+
.find(requirement => requirement.name === requirementBlock.name);
|
|
281
280
|
requirement.done = false;
|
|
282
281
|
requirement.value = undefined;
|
|
283
282
|
},
|
|
284
283
|
async requirementDone(requirementDone, value) {
|
|
285
|
-
const requirement = this.requirements
|
|
284
|
+
const requirement = this.requirements
|
|
285
|
+
.find(requirement => requirement.name === requirementDone.name);
|
|
286
286
|
|
|
287
287
|
if (requirement.phase === 'beforeSubmit') {
|
|
288
288
|
requirement.done = true;
|
|
@@ -392,12 +392,11 @@ function getRequirements() {
|
|
|
392
392
|
transition-delay: 0.6s;
|
|
393
393
|
}
|
|
394
394
|
|
|
395
|
-
.fade-leave-active {
|
|
395
|
+
.fade-body-leave-active {
|
|
396
396
|
transition: all 0.25s linear;
|
|
397
|
-
transition-delay: 0;
|
|
398
397
|
}
|
|
399
398
|
|
|
400
|
-
.fade-body-enter-to
|
|
399
|
+
.fade-body-enter-to, .fade-body-leave {
|
|
401
400
|
transform: translateY(0);
|
|
402
401
|
}
|
|
403
402
|
|
|
@@ -459,7 +458,7 @@ function getRequirements() {
|
|
|
459
458
|
max-width: $login-container;
|
|
460
459
|
margin: auto;
|
|
461
460
|
align-items: center;
|
|
462
|
-
justify-content: start;
|
|
461
|
+
justify-content: flex-start;
|
|
463
462
|
}
|
|
464
463
|
|
|
465
464
|
&__project-version {
|
|
@@ -231,41 +231,36 @@ module.exports = {
|
|
|
231
231
|
// Perform the actual migrations. Implementation of
|
|
232
232
|
// the @apostrophecms/migration:migrate task
|
|
233
233
|
async migrate(options) {
|
|
234
|
-
await self.apos.lock.lock(self.__meta.name);
|
|
235
234
|
await self.emit('before');
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
await self.runOne(migration);
|
|
255
|
-
}
|
|
235
|
+
if (self.apos.isNew) {
|
|
236
|
+
// Since the site is brand new (zero documents), we may assume
|
|
237
|
+
// it requires no migrations. Mark them all as "done" but note
|
|
238
|
+
// that they were skipped, just in case we decide that's an issue later
|
|
239
|
+
const at = new Date();
|
|
240
|
+
// Just in case the db has no documents but did
|
|
241
|
+
// start to run migrations on a previous attempt,
|
|
242
|
+
// which causes an occasional unique key error if not
|
|
243
|
+
// corrected for here
|
|
244
|
+
await self.db.removeMany({});
|
|
245
|
+
await self.db.insertMany(self.migrations.map(migration => ({
|
|
246
|
+
_id: migration.name,
|
|
247
|
+
at,
|
|
248
|
+
skipped: true
|
|
249
|
+
})));
|
|
250
|
+
} else {
|
|
251
|
+
for (const migration of self.migrations) {
|
|
252
|
+
await self.runOne(migration);
|
|
256
253
|
}
|
|
257
|
-
// In production, this event is emitted only at the end of the migrate command line task.
|
|
258
|
-
// In dev it is emitted at every startup after the automatic migration.
|
|
259
|
-
//
|
|
260
|
-
// Intentionally emitted regardless of whether the site is new or not.
|
|
261
|
-
//
|
|
262
|
-
// This is the right time to park pages, for instance, because the
|
|
263
|
-
// database is guaranteed to be in a stable state, whether because the
|
|
264
|
-
// site is new or because migrations ran successfully.
|
|
265
|
-
await self.emit('after');
|
|
266
|
-
} finally {
|
|
267
|
-
await self.apos.lock.unlock(self.__meta.name);
|
|
268
254
|
}
|
|
255
|
+
// In production, this event is emitted only at the end of the migrate command line task.
|
|
256
|
+
// In dev it is emitted at every startup after the automatic migration.
|
|
257
|
+
//
|
|
258
|
+
// Intentionally emitted regardless of whether the site is new or not.
|
|
259
|
+
//
|
|
260
|
+
// This is the right time to park pages, for instance, because the
|
|
261
|
+
// database is guaranteed to be in a stable state, whether because the
|
|
262
|
+
// site is new or because migrations ran successfully.
|
|
263
|
+
await self.emit('after');
|
|
269
264
|
},
|
|
270
265
|
async runOne(migration) {
|
|
271
266
|
const info = await self.db.findOne({ _id: migration.name });
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const { klona } = require('klona');
|
|
4
|
+
const expressCacheOnDemand = require('express-cache-on-demand')();
|
|
4
5
|
|
|
5
6
|
module.exports = {
|
|
6
7
|
cascades: [ 'batchOperations' ],
|
|
@@ -47,6 +48,9 @@ module.exports = {
|
|
|
47
48
|
}
|
|
48
49
|
},
|
|
49
50
|
async init(self) {
|
|
51
|
+
const { enableCacheOnDemand = true } = self.apos
|
|
52
|
+
.modules['@apostrophecms/express'].options;
|
|
53
|
+
self.enableCacheOnDemand = enableCacheOnDemand;
|
|
50
54
|
self.typeChoices = self.options.types || [];
|
|
51
55
|
// If "park" redeclares something with a parkedId present in "minimumPark",
|
|
52
56
|
// the later one should win
|
|
@@ -55,9 +59,11 @@ module.exports = {
|
|
|
55
59
|
self.addEditorModal();
|
|
56
60
|
self.enableBrowserData();
|
|
57
61
|
self.addLegacyMigrations();
|
|
62
|
+
self.addMisreplicatedParkedPagesMigration();
|
|
58
63
|
await self.createIndexes();
|
|
59
64
|
},
|
|
60
65
|
restApiRoutes(self) {
|
|
66
|
+
|
|
61
67
|
return {
|
|
62
68
|
// Trees are arranged in a tree, not a list. So this API returns the home page,
|
|
63
69
|
// with _children populated if ?_children=1 is in the query string. An editor can
|
|
@@ -77,95 +83,102 @@ module.exports = {
|
|
|
77
83
|
// If querying for draft pages, you may add ?published=1 to attach a
|
|
78
84
|
// `_publishedDoc` property to each draft that also exists in a published form.
|
|
79
85
|
|
|
80
|
-
|
|
81
|
-
self.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
getAll: [
|
|
87
|
+
...self.enableCacheOnDemand ? [ expressCacheOnDemand ] : [],
|
|
88
|
+
async (req) => {
|
|
89
|
+
self.publicApiCheck(req);
|
|
90
|
+
const all = self.apos.launder.boolean(req.query.all);
|
|
91
|
+
const archived = self.apos.launder.booleanOrNull(req.query.archived);
|
|
92
|
+
const flat = self.apos.launder.boolean(req.query.flat);
|
|
93
|
+
const autocomplete = self.apos.launder.string(req.query.autocomplete);
|
|
86
94
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
95
|
+
if (autocomplete.length) {
|
|
96
|
+
if (!self.apos.permission.can(req, 'edit', '@apostrophecms/any-page-type')) {
|
|
97
|
+
throw self.apos.error('forbidden');
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
// For consistency with the pieces REST API we
|
|
101
|
+
// use a results property when returning a flat list
|
|
102
|
+
results: await self.getRestQuery(req).limit(10).relationships(false)
|
|
103
|
+
.areas(false).toArray()
|
|
104
|
+
};
|
|
90
105
|
}
|
|
91
|
-
return {
|
|
92
|
-
// For consistency with the pieces REST API we
|
|
93
|
-
// use a results property when returning a flat list
|
|
94
|
-
results: await self.getRestQuery(req).limit(10).relationships(false)
|
|
95
|
-
.areas(false).toArray()
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
106
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
107
|
+
if (all) {
|
|
108
|
+
if (!self.apos.permission.can(req, 'edit', '@apostrophecms/any-page-type')) {
|
|
109
|
+
throw self.apos.error('forbidden');
|
|
110
|
+
}
|
|
111
|
+
const page = await self.getRestQuery(req).and({ level: 0 }).children({
|
|
112
|
+
depth: 1000,
|
|
113
|
+
archived,
|
|
114
|
+
orphan: null,
|
|
115
|
+
relationships: false,
|
|
116
|
+
areas: false,
|
|
117
|
+
permission: false,
|
|
118
|
+
withPublished: self.apos.launder.boolean(req.query.withPublished),
|
|
119
|
+
project: self.getAllProjection()
|
|
120
|
+
}).toObject();
|
|
113
121
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
if (!page) {
|
|
123
|
+
throw self.apos.error('notfound');
|
|
124
|
+
}
|
|
117
125
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
126
|
+
if (flat) {
|
|
127
|
+
const result = [];
|
|
128
|
+
flatten(result, page);
|
|
121
129
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
130
|
+
return {
|
|
131
|
+
// For consistency with the pieces REST API we
|
|
132
|
+
// use a results property when returning a flat list
|
|
133
|
+
results: result
|
|
134
|
+
};
|
|
135
|
+
} else {
|
|
136
|
+
return page;
|
|
137
|
+
}
|
|
127
138
|
} else {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (!result) {
|
|
133
|
-
throw self.apos.error('notfound');
|
|
134
|
-
}
|
|
139
|
+
const result = await self.getRestQuery(req).and({ level: 0 }).toObject();
|
|
140
|
+
if (!result) {
|
|
141
|
+
throw self.apos.error('notfound');
|
|
142
|
+
}
|
|
135
143
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
144
|
+
// Attach `_url` and `_urls` properties to the home page
|
|
145
|
+
self.apos.attachment.all(result, { annotate: true });
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
140
148
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
149
|
+
function flatten(result, node) {
|
|
150
|
+
const children = node._children;
|
|
151
|
+
node._children = _.map(node._children, '_id');
|
|
152
|
+
result.push(node);
|
|
153
|
+
_.each(children || [], function(child) {
|
|
154
|
+
flatten(result, child);
|
|
155
|
+
});
|
|
148
156
|
|
|
157
|
+
}
|
|
149
158
|
}
|
|
150
|
-
|
|
159
|
+
],
|
|
151
160
|
// _id may be a page _id, or the convenient shorthands
|
|
152
161
|
// `_home` or `_archive`
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
162
|
+
|
|
163
|
+
getOne: [
|
|
164
|
+
...self.enableCacheOnDemand ? [ expressCacheOnDemand ] : [],
|
|
165
|
+
async (req, _id) => {
|
|
166
|
+
_id = self.inferIdLocaleAndMode(req, _id);
|
|
167
|
+
// Edit access to draft is sufficient to fetch either
|
|
168
|
+
self.publicApiCheck(req);
|
|
169
|
+
const criteria = self.getIdCriteria(_id);
|
|
170
|
+
const result = await self.getRestQuery(req).and(criteria).toObject();
|
|
171
|
+
if (!result) {
|
|
172
|
+
throw self.apos.error('notfound');
|
|
173
|
+
}
|
|
174
|
+
if (self.apos.launder.boolean(req.query['render-areas']) === true) {
|
|
175
|
+
await self.apos.area.renderDocsAreas(req, [ result ]);
|
|
176
|
+
}
|
|
177
|
+
// Attach `_url` and `_urls` properties
|
|
178
|
+
self.apos.attachment.all(result, { annotate: true });
|
|
179
|
+
return result;
|
|
164
180
|
}
|
|
165
|
-
|
|
166
|
-
self.apos.attachment.all(result, { annotate: true });
|
|
167
|
-
return result;
|
|
168
|
-
},
|
|
181
|
+
],
|
|
169
182
|
// POST a new page to the site. The schema fields should be part of the JSON request body.
|
|
170
183
|
//
|
|
171
184
|
// You may pass `_targetId` and `_position` to specify the location in the page tree.
|
|
@@ -576,7 +589,14 @@ database.`);
|
|
|
576
589
|
},
|
|
577
590
|
'apostrophe:ready': {
|
|
578
591
|
addServeRoute() {
|
|
579
|
-
self.apos.app.get('*',
|
|
592
|
+
self.apos.app.get('*',
|
|
593
|
+
(req, res, next) => {
|
|
594
|
+
return self.enableCacheOnDemand
|
|
595
|
+
? expressCacheOnDemand(req, res, next)
|
|
596
|
+
: next();
|
|
597
|
+
},
|
|
598
|
+
self.serve
|
|
599
|
+
);
|
|
580
600
|
}
|
|
581
601
|
}
|
|
582
602
|
};
|
|
@@ -1298,9 +1318,6 @@ database.`);
|
|
|
1298
1318
|
if (!options) {
|
|
1299
1319
|
options = {};
|
|
1300
1320
|
}
|
|
1301
|
-
const manager = self.apos.doc.getManager(page.type);
|
|
1302
|
-
await manager.emit('beforeUpdate', req, page, options);
|
|
1303
|
-
await manager.emit('beforeSave', req, page, options);
|
|
1304
1321
|
await self.apos.doc.update(req, page, options);
|
|
1305
1322
|
return page;
|
|
1306
1323
|
},
|
|
@@ -2171,7 +2188,44 @@ database.`);
|
|
|
2171
2188
|
}
|
|
2172
2189
|
}
|
|
2173
2190
|
},
|
|
2174
|
-
...require('./lib/legacy-migrations')(self)
|
|
2191
|
+
...require('./lib/legacy-migrations')(self),
|
|
2192
|
+
addMisreplicatedParkedPagesMigration() {
|
|
2193
|
+
self.apos.migration.add('misreplicated-parked-pages', async () => {
|
|
2194
|
+
const parkedPages = await self.apos.doc.db.find({
|
|
2195
|
+
parkedId: {
|
|
2196
|
+
$ne: null
|
|
2197
|
+
}
|
|
2198
|
+
}).toArray();
|
|
2199
|
+
const locales = [ self.apos.i18n.defaultLocale, ...Object.keys(self.apos.i18n.locales) ];
|
|
2200
|
+
const parkedIds = [ ...new Set(parkedPages.map(page => page.parkedId)) ];
|
|
2201
|
+
for (const parkedId of parkedIds) {
|
|
2202
|
+
let aposDocId;
|
|
2203
|
+
for (const locale of locales) {
|
|
2204
|
+
for (const mode of [ 'draft', 'published' ]) {
|
|
2205
|
+
const page = parkedPages.find(page => (page.parkedId === parkedId) && (page.aposLocale === `${locale}:${mode}`));
|
|
2206
|
+
if (!page) {
|
|
2207
|
+
continue;
|
|
2208
|
+
}
|
|
2209
|
+
if (!aposDocId) {
|
|
2210
|
+
aposDocId = page.aposDocId;
|
|
2211
|
+
} else {
|
|
2212
|
+
if (page.aposDocId !== aposDocId) {
|
|
2213
|
+
await self.apos.doc.db.removeOne({
|
|
2214
|
+
_id: page._id
|
|
2215
|
+
});
|
|
2216
|
+
await self.apos.doc.db.insertOne({
|
|
2217
|
+
...page,
|
|
2218
|
+
_id: `${aposDocId}:${locale}:${mode}`,
|
|
2219
|
+
aposDocId,
|
|
2220
|
+
path: page.path.replace(page.aposDocId, aposDocId)
|
|
2221
|
+
});
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
});
|
|
2228
|
+
}
|
|
2175
2229
|
};
|
|
2176
2230
|
},
|
|
2177
2231
|
helpers(self) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
|
+
const expressCacheOnDemand = require('express-cache-on-demand')();
|
|
2
3
|
|
|
3
4
|
module.exports = {
|
|
4
5
|
extend: '@apostrophecms/doc-type',
|
|
@@ -164,79 +165,91 @@ module.exports = {
|
|
|
164
165
|
self.addManagerModal();
|
|
165
166
|
self.addEditorModal();
|
|
166
167
|
},
|
|
167
|
-
restApiRoutes
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
168
|
+
restApiRoutes(self) {
|
|
169
|
+
const { enableCacheOnDemand = true } = self.apos
|
|
170
|
+
.modules['@apostrophecms/express'].options;
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
getAll: [
|
|
174
|
+
...enableCacheOnDemand ? [ expressCacheOnDemand ] : [],
|
|
175
|
+
async (req) => {
|
|
176
|
+
self.publicApiCheck(req);
|
|
177
|
+
const query = self.getRestQuery(req);
|
|
178
|
+
if (!query.get('perPage')) {
|
|
179
|
+
query.perPage(
|
|
180
|
+
self.options.perPage
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
const result = {};
|
|
184
|
+
// Also populates totalPages when perPage is present
|
|
185
|
+
const count = await query.toCount();
|
|
186
|
+
if (self.apos.launder.boolean(req.query.count)) {
|
|
187
|
+
return {
|
|
188
|
+
count
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
result.pages = query.get('totalPages');
|
|
192
|
+
result.currentPage = query.get('page') || 1;
|
|
193
|
+
result.results = await query.toArray();
|
|
194
|
+
if (self.apos.launder.boolean(req.query['render-areas']) === true) {
|
|
195
|
+
await self.apos.area.renderDocsAreas(req, result.results);
|
|
196
|
+
}
|
|
197
|
+
if (query.get('choicesResults')) {
|
|
198
|
+
result.choices = query.get('choicesResults');
|
|
199
|
+
}
|
|
200
|
+
if (query.get('countsResults')) {
|
|
201
|
+
result.counts = query.get('countsResults');
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
],
|
|
206
|
+
getOne: [
|
|
207
|
+
...enableCacheOnDemand ? [ expressCacheOnDemand ] : [],
|
|
208
|
+
async (req, _id) => {
|
|
209
|
+
_id = self.inferIdLocaleAndMode(req, _id);
|
|
210
|
+
self.publicApiCheck(req);
|
|
211
|
+
const doc = await self.getRestQuery(req).and({ _id }).toObject();
|
|
212
|
+
if (!doc) {
|
|
213
|
+
throw self.apos.error('notfound');
|
|
214
|
+
}
|
|
215
|
+
if (self.apos.launder.boolean(req.query['render-areas']) === true) {
|
|
216
|
+
await self.apos.area.renderDocsAreas(req, [ doc ]);
|
|
217
|
+
}
|
|
218
|
+
self.apos.attachment.all(doc, { annotate: true });
|
|
219
|
+
return doc;
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
async post(req) {
|
|
223
|
+
self.publicApiCheck(req);
|
|
224
|
+
if (req.body._newInstance) {
|
|
225
|
+
const newInstance = self.newInstance();
|
|
226
|
+
newInstance._previewable = self.addUrlsViaModule && (await self.addUrlsViaModule.readyToAddUrlsToPieces(req, self.name));
|
|
227
|
+
delete newInstance._url;
|
|
228
|
+
return newInstance;
|
|
229
|
+
}
|
|
230
|
+
return await self.convertInsertAndRefresh(req, req.body);
|
|
231
|
+
},
|
|
232
|
+
async put(req, _id) {
|
|
233
|
+
_id = self.inferIdLocaleAndMode(req, _id);
|
|
234
|
+
self.publicApiCheck(req);
|
|
235
|
+
return self.convertUpdateAndRefresh(req, req.body, _id);
|
|
236
|
+
},
|
|
237
|
+
async delete(req, _id) {
|
|
238
|
+
_id = self.inferIdLocaleAndMode(req, _id);
|
|
239
|
+
self.publicApiCheck(req);
|
|
240
|
+
const piece = await self.findOneForEditing(req, {
|
|
241
|
+
_id
|
|
242
|
+
});
|
|
243
|
+
return self.delete(req, piece);
|
|
244
|
+
},
|
|
245
|
+
async patch(req, _id) {
|
|
246
|
+
_id = self.inferIdLocaleAndMode(req, _id);
|
|
247
|
+
self.publicApiCheck(req);
|
|
248
|
+
return self.convertPatchAndRefresh(req, req.body, _id);
|
|
218
249
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
_id = self.inferIdLocaleAndMode(req, _id);
|
|
223
|
-
self.publicApiCheck(req);
|
|
224
|
-
return self.convertUpdateAndRefresh(req, req.body, _id);
|
|
225
|
-
},
|
|
226
|
-
async delete(req, _id) {
|
|
227
|
-
_id = self.inferIdLocaleAndMode(req, _id);
|
|
228
|
-
self.publicApiCheck(req);
|
|
229
|
-
const piece = await self.findOneForEditing(req, {
|
|
230
|
-
_id
|
|
231
|
-
});
|
|
232
|
-
return self.delete(req, piece);
|
|
233
|
-
},
|
|
234
|
-
async patch(req, _id) {
|
|
235
|
-
_id = self.inferIdLocaleAndMode(req, _id);
|
|
236
|
-
self.publicApiCheck(req);
|
|
237
|
-
return self.convertPatchAndRefresh(req, req.body, _id);
|
|
238
|
-
}
|
|
239
|
-
}),
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
},
|
|
240
253
|
apiRoutes(self) {
|
|
241
254
|
return {
|
|
242
255
|
get: {
|