@webiny/api-headless-cms 0.0.0-unstable.b02d94bba0 → 0.0.0-unstable.b14eaecf38
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/context.js +47 -43
- package/context.js.map +1 -1
- package/crud/contentEntry.crud.d.ts +3 -1
- package/crud/contentEntry.crud.js +829 -817
- package/crud/contentEntry.crud.js.map +1 -1
- package/crud/contentModel/beforeCreate.js +38 -79
- package/crud/contentModel/beforeCreate.js.map +1 -1
- package/crud/contentModel/beforeDelete.d.ts +1 -1
- package/crud/contentModel/beforeDelete.js +1 -5
- package/crud/contentModel/beforeDelete.js.map +1 -1
- package/crud/contentModel/beforeUpdate.js +30 -6
- package/crud/contentModel/beforeUpdate.js.map +1 -1
- package/crud/contentModel/validate/endingAllowed.d.ts +6 -0
- package/crud/contentModel/validate/endingAllowed.js +26 -0
- package/crud/contentModel/validate/endingAllowed.js.map +1 -0
- package/crud/contentModel/validate/isModelEndingAllowed.d.ts +6 -0
- package/crud/contentModel/validate/isModelEndingAllowed.js +24 -0
- package/crud/contentModel/validate/isModelEndingAllowed.js.map +1 -0
- package/crud/contentModel/validate/modelId.d.ts +11 -0
- package/crud/contentModel/validate/modelId.js +36 -0
- package/crud/contentModel/validate/modelId.js.map +1 -0
- package/crud/contentModel/validate/pluralApiName.d.ts +7 -0
- package/crud/contentModel/validate/pluralApiName.js +24 -0
- package/crud/contentModel/validate/pluralApiName.js.map +1 -0
- package/crud/contentModel/validate/singularApiName.d.ts +7 -0
- package/crud/contentModel/validate/singularApiName.js +24 -0
- package/crud/contentModel/validate/singularApiName.js.map +1 -0
- package/crud/contentModel/validateModelFields.js +6 -7
- package/crud/contentModel/validateModelFields.js.map +1 -1
- package/crud/contentModel/validation.d.ts +48 -16
- package/crud/contentModel/validation.js +2 -2
- package/crud/contentModel/validation.js.map +1 -1
- package/crud/contentModel.crud.js +334 -295
- package/crud/contentModel.crud.js.map +1 -1
- package/crud/contentModelGroup.crud.js +170 -142
- package/crud/contentModelGroup.crud.js.map +1 -1
- package/crud/settings.crud.d.ts +1 -1
- package/crud/settings.crud.js +5 -10
- package/crud/settings.crud.js.map +1 -1
- package/graphql/checkEndpointAccess.d.ts +2 -0
- package/graphql/checkEndpointAccess.js +18 -0
- package/graphql/checkEndpointAccess.js.map +1 -0
- package/graphql/createExecutableSchema.d.ts +2 -3
- package/graphql/createExecutableSchema.js.map +1 -1
- package/graphql/createRequestBody.d.ts +2 -0
- package/graphql/createRequestBody.js +14 -0
- package/graphql/createRequestBody.js.map +1 -0
- package/graphql/formatErrorPayload.d.ts +1 -0
- package/graphql/formatErrorPayload.js +25 -0
- package/graphql/formatErrorPayload.js.map +1 -0
- package/graphql/generateSchema.js.map +1 -1
- package/graphql/getSchema.d.ts +17 -0
- package/graphql/getSchema.js +102 -0
- package/graphql/getSchema.js.map +1 -0
- package/graphql/graphQLHandlerFactory.js +6 -150
- package/graphql/graphQLHandlerFactory.js.map +1 -1
- package/graphql/handleRequest.d.ts +11 -0
- package/graphql/handleRequest.js +81 -0
- package/graphql/handleRequest.js.map +1 -0
- package/graphql/schema/contentModelGroups.js +6 -6
- package/graphql/schema/contentModelGroups.js.map +1 -1
- package/graphql/schema/contentModels.js +3 -3
- package/graphql/schema/contentModels.js.map +1 -1
- package/graphqlFields/dynamicZone/dynamicZoneField.d.ts +1 -1
- package/graphqlFields/dynamicZone/dynamicZoneField.js +13 -1
- package/graphqlFields/dynamicZone/dynamicZoneField.js.map +1 -1
- package/graphqlFields/ref.js +7 -7
- package/graphqlFields/ref.js.map +1 -1
- package/index.d.ts +2 -0
- package/index.js +24 -0
- package/index.js.map +1 -1
- package/package.json +22 -22
- package/plugins/CmsModelPlugin.d.ts +13 -7
- package/plugins/CmsModelPlugin.js +21 -6
- package/plugins/CmsModelPlugin.js.map +1 -1
- package/plugins/StorageOperationsCmsModelPlugin.d.ts +23 -0
- package/plugins/StorageOperationsCmsModelPlugin.js +42 -0
- package/plugins/StorageOperationsCmsModelPlugin.js.map +1 -0
- package/plugins/index.d.ts +1 -0
- package/plugins/index.js +11 -0
- package/plugins/index.js.map +1 -1
- package/types.d.ts +46 -47
- package/types.js.map +1 -1
- package/utils/converters/valueKeyStorageConverter.d.ts +1 -5
- package/utils/converters/valueKeyStorageConverter.js +19 -17
- package/utils/converters/valueKeyStorageConverter.js.map +1 -1
- package/utils/createTypeFromFields.js +1 -2
- package/utils/createTypeFromFields.js.map +1 -1
- package/utils/createTypeName.d.ts +0 -2
- package/utils/createTypeName.js +2 -10
- package/utils/createTypeName.js.map +1 -1
- package/utils/incrementEntryIdVersion.d.ts +5 -0
- package/utils/incrementEntryIdVersion.js +29 -0
- package/utils/incrementEntryIdVersion.js.map +1 -0
|
@@ -6,22 +6,21 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.createContentEntryCrud = exports.STATUS_UNPUBLISHED = exports.STATUS_PUBLISHED = exports.STATUS_DRAFT = void 0;
|
|
8
8
|
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
|
|
9
|
+
var _merge = _interopRequireDefault(require("lodash/merge"));
|
|
9
10
|
var _mdbid = _interopRequireDefault(require("mdbid"));
|
|
11
|
+
var _error = _interopRequireDefault(require("@webiny/error"));
|
|
10
12
|
var _handlerGraphql = require("@webiny/handler-graphql");
|
|
11
13
|
var _entryDataValidation = require("./contentEntry/entryDataValidation");
|
|
12
|
-
var _error = _interopRequireDefault(require("@webiny/error"));
|
|
13
14
|
var _pubsub = require("@webiny/pubsub");
|
|
14
15
|
var _beforeCreate = require("./contentEntry/beforeCreate");
|
|
15
16
|
var _beforeUpdate = require("./contentEntry/beforeUpdate");
|
|
16
17
|
var _utils = require("@webiny/utils");
|
|
17
18
|
var _afterDelete = require("./contentEntry/afterDelete");
|
|
18
19
|
var _referenceFieldsMapping = require("./contentEntry/referenceFieldsMapping");
|
|
19
|
-
var _merge = _interopRequireDefault(require("lodash/merge"));
|
|
20
20
|
var _permissions = require("../utils/permissions");
|
|
21
21
|
var _access = require("../utils/access");
|
|
22
22
|
var _ownership = require("../utils/ownership");
|
|
23
23
|
var _entryStorage = require("../utils/entryStorage");
|
|
24
|
-
var _valueKeyStorageConverter = require("../utils/converters/valueKeyStorageConverter");
|
|
25
24
|
var _searchableFields = require("./contentEntry/searchableFields");
|
|
26
25
|
/**
|
|
27
26
|
* Package mdbid does not have types.
|
|
@@ -181,11 +180,9 @@ const createContentEntryCrud = params => {
|
|
|
181
180
|
storageOperations,
|
|
182
181
|
context,
|
|
183
182
|
getIdentity,
|
|
184
|
-
getTenant
|
|
183
|
+
getTenant,
|
|
184
|
+
getLocale
|
|
185
185
|
} = params;
|
|
186
|
-
const {
|
|
187
|
-
plugins
|
|
188
|
-
} = context;
|
|
189
186
|
const getCreatedBy = () => {
|
|
190
187
|
const identity = getIdentity();
|
|
191
188
|
return {
|
|
@@ -283,189 +280,847 @@ const createContentEntryCrud = params => {
|
|
|
283
280
|
/**
|
|
284
281
|
* A helper to delete the entire entry.
|
|
285
282
|
*/
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
entry
|
|
290
|
-
} = params;
|
|
291
|
-
try {
|
|
292
|
-
await onEntryBeforeDelete.publish({
|
|
293
|
-
entry,
|
|
294
|
-
model
|
|
295
|
-
});
|
|
296
|
-
await storageOperations.entries.delete(model, {
|
|
297
|
-
entry
|
|
298
|
-
});
|
|
299
|
-
await onEntryAfterDelete.publish({
|
|
300
|
-
entry,
|
|
301
|
-
model
|
|
302
|
-
});
|
|
303
|
-
} catch (ex) {
|
|
304
|
-
await onEntryDeleteError.publish({
|
|
305
|
-
entry,
|
|
283
|
+
const deleteEntryHelper = async params => {
|
|
284
|
+
return context.benchmark.measure("headlessCms.crud.entries.deleteEntry", async () => {
|
|
285
|
+
const {
|
|
306
286
|
model,
|
|
307
|
-
error: ex
|
|
308
|
-
});
|
|
309
|
-
throw new _error.default(ex.message || "Could not delete entry.", ex.code || "DELETE_ERROR", {
|
|
310
287
|
entry
|
|
311
|
-
}
|
|
312
|
-
|
|
288
|
+
} = params;
|
|
289
|
+
try {
|
|
290
|
+
await onEntryBeforeDelete.publish({
|
|
291
|
+
entry,
|
|
292
|
+
model
|
|
293
|
+
});
|
|
294
|
+
await storageOperations.entries.delete(model, {
|
|
295
|
+
entry
|
|
296
|
+
});
|
|
297
|
+
await onEntryAfterDelete.publish({
|
|
298
|
+
entry,
|
|
299
|
+
model
|
|
300
|
+
});
|
|
301
|
+
} catch (ex) {
|
|
302
|
+
await onEntryDeleteError.publish({
|
|
303
|
+
entry,
|
|
304
|
+
model,
|
|
305
|
+
error: ex
|
|
306
|
+
});
|
|
307
|
+
throw new _error.default(ex.message || "Could not delete entry.", ex.code || "DELETE_ERROR", {
|
|
308
|
+
entry
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
});
|
|
313
312
|
};
|
|
314
313
|
/**
|
|
315
314
|
* A helper to get entries by revision IDs
|
|
316
315
|
*/
|
|
317
|
-
const getEntriesByIds = async (
|
|
316
|
+
const getEntriesByIds = async (model, ids) => {
|
|
317
|
+
return context.benchmark.measure("headlessCms.crud.entries.getEntriesByIds", async () => {
|
|
318
|
+
const permission = await checkEntryPermissions({
|
|
319
|
+
rwd: "r"
|
|
320
|
+
});
|
|
321
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
322
|
+
const entries = await storageOperations.entries.getByIds(model, {
|
|
323
|
+
ids
|
|
324
|
+
});
|
|
325
|
+
return entries.filter(entry => (0, _ownership.validateOwnership)(context, permission, entry));
|
|
326
|
+
});
|
|
327
|
+
};
|
|
328
|
+
const getEntryById = async (model, id) => {
|
|
329
|
+
const where = {
|
|
330
|
+
id
|
|
331
|
+
};
|
|
332
|
+
await onEntryBeforeGet.publish({
|
|
333
|
+
where,
|
|
334
|
+
model
|
|
335
|
+
});
|
|
336
|
+
const [entry] = await getEntriesByIds(model, [id]);
|
|
337
|
+
if (!entry) {
|
|
338
|
+
throw new _handlerGraphql.NotFoundError(`Entry by ID "${id}" not found.`);
|
|
339
|
+
}
|
|
340
|
+
return entry;
|
|
341
|
+
};
|
|
342
|
+
const getPublishedEntriesByIds = async (model, ids) => {
|
|
318
343
|
const permission = await checkEntryPermissions({
|
|
319
344
|
rwd: "r"
|
|
320
345
|
});
|
|
321
|
-
await (0, _access.checkModelAccess)(context,
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
346
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
347
|
+
const entries = await storageOperations.entries.getPublishedByIds(model, {
|
|
348
|
+
ids
|
|
349
|
+
});
|
|
350
|
+
return entries.filter(entry => (0, _ownership.validateOwnership)(context, permission, entry));
|
|
351
|
+
};
|
|
352
|
+
const getLatestEntriesByIds = async (model, ids) => {
|
|
353
|
+
const permission = await checkEntryPermissions({
|
|
354
|
+
rwd: "r"
|
|
325
355
|
});
|
|
326
|
-
|
|
356
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
357
|
+
const entries = await storageOperations.entries.getLatestByIds(model, {
|
|
327
358
|
ids
|
|
328
359
|
});
|
|
329
360
|
return entries.filter(entry => (0, _ownership.validateOwnership)(context, permission, entry));
|
|
330
361
|
};
|
|
331
|
-
|
|
362
|
+
const getEntry = async (model, params) => {
|
|
363
|
+
await checkEntryPermissions({
|
|
364
|
+
rwd: "r"
|
|
365
|
+
});
|
|
366
|
+
const {
|
|
367
|
+
where,
|
|
368
|
+
sort
|
|
369
|
+
} = params;
|
|
370
|
+
await onEntryBeforeGet.publish({
|
|
371
|
+
where,
|
|
372
|
+
model
|
|
373
|
+
});
|
|
374
|
+
const [items] = await listEntries(model, {
|
|
375
|
+
where,
|
|
376
|
+
sort,
|
|
377
|
+
limit: 1
|
|
378
|
+
});
|
|
379
|
+
const item = items.shift();
|
|
380
|
+
if (!item) {
|
|
381
|
+
throw new _handlerGraphql.NotFoundError(`Entry not found!`);
|
|
382
|
+
}
|
|
383
|
+
return item;
|
|
384
|
+
};
|
|
385
|
+
const getEntryRevisions = async (model, entryId) => {
|
|
386
|
+
return storageOperations.entries.getRevisions(model, {
|
|
387
|
+
id: entryId
|
|
388
|
+
});
|
|
389
|
+
};
|
|
390
|
+
const listEntries = async (model, params) => {
|
|
391
|
+
const permission = await checkEntryPermissions({
|
|
392
|
+
rwd: "r"
|
|
393
|
+
});
|
|
394
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
395
|
+
const {
|
|
396
|
+
where: initialWhere,
|
|
397
|
+
limit: initialLimit
|
|
398
|
+
} = params;
|
|
399
|
+
const limit = initialLimit && initialLimit > 0 ? initialLimit : 50;
|
|
332
400
|
/**
|
|
333
|
-
*
|
|
401
|
+
* We always assign tenant and locale because we do not allow one model to have content through multiple tenants.
|
|
334
402
|
*/
|
|
335
|
-
|
|
336
|
-
onAfterEntryCreate: onEntryAfterCreate,
|
|
337
|
-
onBeforeEntryCreateRevision: onEntryBeforeCreateRevision,
|
|
338
|
-
onAfterEntryCreateRevision: onEntryRevisionAfterCreate,
|
|
339
|
-
onBeforeEntryUpdate: onEntryBeforeUpdate,
|
|
340
|
-
onAfterEntryUpdate: onEntryAfterUpdate,
|
|
341
|
-
onBeforeEntryDelete: onEntryBeforeDelete,
|
|
342
|
-
onAfterEntryDelete: onEntryAfterDelete,
|
|
343
|
-
onBeforeEntryDeleteRevision: onEntryRevisionBeforeDelete,
|
|
344
|
-
onAfterEntryDeleteRevision: onEntryRevisionAfterDelete,
|
|
345
|
-
onBeforeEntryPublish: onEntryBeforePublish,
|
|
346
|
-
onAfterEntryPublish: onEntryAfterPublish,
|
|
347
|
-
onBeforeEntryUnpublish: onEntryBeforeUnpublish,
|
|
348
|
-
onAfterEntryUnpublish: onEntryAfterUnpublish,
|
|
349
|
-
onBeforeEntryGet: onEntryBeforeGet,
|
|
350
|
-
onBeforeEntryList: onEntryBeforeList,
|
|
403
|
+
const where = (0, _objectSpread2.default)({}, initialWhere);
|
|
351
404
|
/**
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
* Create
|
|
405
|
+
* Possibly only get records which are owned by current user.
|
|
406
|
+
* Or if searching for the owner set that value - in the case that user can see other entries than their own.
|
|
355
407
|
*/
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
408
|
+
const ownedBy = permission.own ? getIdentity().id : where.ownedBy;
|
|
409
|
+
if (ownedBy !== undefined) {
|
|
410
|
+
where.ownedBy = ownedBy;
|
|
411
|
+
}
|
|
359
412
|
/**
|
|
360
|
-
*
|
|
413
|
+
* Where must contain either latest or published keys.
|
|
414
|
+
* We cannot list entries without one of those
|
|
361
415
|
*/
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
416
|
+
if (where.latest && where.published) {
|
|
417
|
+
throw new _error.default("Cannot list entries that are both published and latest.", "LIST_ENTRIES_ERROR", {
|
|
418
|
+
where
|
|
419
|
+
});
|
|
420
|
+
} else if (!where.latest && !where.published) {
|
|
421
|
+
throw new _error.default("Cannot list entries if we do not have latest or published defined.", "LIST_ENTRIES_ERROR", {
|
|
422
|
+
where
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
const fields = (0, _searchableFields.getSearchableFields)({
|
|
426
|
+
fields: model.fields,
|
|
427
|
+
plugins: context.plugins,
|
|
428
|
+
input: params.fields || []
|
|
429
|
+
});
|
|
430
|
+
try {
|
|
431
|
+
await onEntryBeforeList.publish({
|
|
432
|
+
where,
|
|
433
|
+
model
|
|
434
|
+
});
|
|
435
|
+
const {
|
|
436
|
+
hasMoreItems,
|
|
437
|
+
totalCount,
|
|
438
|
+
cursor,
|
|
439
|
+
items
|
|
440
|
+
} = await storageOperations.entries.list(model, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, params), {}, {
|
|
441
|
+
limit,
|
|
442
|
+
where,
|
|
443
|
+
fields
|
|
444
|
+
}));
|
|
445
|
+
const meta = {
|
|
446
|
+
hasMoreItems,
|
|
447
|
+
totalCount,
|
|
448
|
+
/**
|
|
449
|
+
* Cursor should be null if there are no more items to load.
|
|
450
|
+
* Just make sure of that, disregarding what is returned from the storageOperations.entries.list method.
|
|
451
|
+
*/
|
|
452
|
+
cursor: hasMoreItems ? cursor : null
|
|
453
|
+
};
|
|
454
|
+
return [items, meta];
|
|
455
|
+
} catch (ex) {
|
|
456
|
+
throw new _error.default("Error while fetching entries from storage.", "LIST_ENTRIES_ERROR", {
|
|
457
|
+
params,
|
|
458
|
+
error: {
|
|
459
|
+
message: ex.message,
|
|
460
|
+
code: ex.code,
|
|
461
|
+
data: ex.data
|
|
462
|
+
},
|
|
463
|
+
model,
|
|
464
|
+
fields
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
const createEntry = async (model, inputData) => {
|
|
469
|
+
await checkEntryPermissions({
|
|
470
|
+
rwd: "w"
|
|
471
|
+
});
|
|
472
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
473
|
+
|
|
365
474
|
/**
|
|
366
|
-
*
|
|
475
|
+
* Make sure we only work with fields that are defined in the model.
|
|
367
476
|
*/
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
477
|
+
const initialInput = mapAndCleanCreateInputData(model, inputData);
|
|
478
|
+
await (0, _entryDataValidation.validateModelEntryData)({
|
|
479
|
+
context,
|
|
480
|
+
model,
|
|
481
|
+
data: initialInput
|
|
482
|
+
});
|
|
483
|
+
const input = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
|
|
484
|
+
context,
|
|
485
|
+
model,
|
|
486
|
+
input: initialInput,
|
|
487
|
+
validateEntries: true
|
|
488
|
+
});
|
|
489
|
+
const locale = getLocale();
|
|
490
|
+
const owner = getCreatedBy();
|
|
491
|
+
const {
|
|
492
|
+
id,
|
|
493
|
+
entryId,
|
|
494
|
+
version
|
|
495
|
+
} = createEntryId(inputData);
|
|
371
496
|
/**
|
|
372
|
-
*
|
|
497
|
+
* There is a possibility that user sends an ID in the input, so we will use that one.
|
|
498
|
+
* There is no check if the ID is unique or not, that is up to the user.
|
|
373
499
|
*/
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
500
|
+
const entry = {
|
|
501
|
+
webinyVersion: context.WEBINY_VERSION,
|
|
502
|
+
tenant: getTenant().id,
|
|
503
|
+
entryId,
|
|
504
|
+
id,
|
|
505
|
+
modelId: model.modelId,
|
|
506
|
+
locale: locale.code,
|
|
507
|
+
createdOn: new Date().toISOString(),
|
|
508
|
+
savedOn: new Date().toISOString(),
|
|
509
|
+
createdBy: owner,
|
|
510
|
+
ownedBy: owner,
|
|
511
|
+
modifiedBy: null,
|
|
512
|
+
version,
|
|
513
|
+
locked: false,
|
|
514
|
+
status: STATUS_DRAFT,
|
|
515
|
+
values: input
|
|
516
|
+
};
|
|
517
|
+
let storageEntry = null;
|
|
518
|
+
try {
|
|
519
|
+
await onEntryBeforeCreate.publish({
|
|
520
|
+
entry,
|
|
521
|
+
input,
|
|
522
|
+
model
|
|
523
|
+
});
|
|
524
|
+
storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
|
|
525
|
+
const result = await storageOperations.entries.create(model, {
|
|
526
|
+
entry,
|
|
527
|
+
storageEntry
|
|
528
|
+
});
|
|
529
|
+
await onEntryAfterCreate.publish({
|
|
530
|
+
entry,
|
|
531
|
+
storageEntry: result,
|
|
532
|
+
model,
|
|
533
|
+
input
|
|
534
|
+
});
|
|
535
|
+
return result;
|
|
536
|
+
} catch (ex) {
|
|
537
|
+
await onEntryCreateError.publish({
|
|
538
|
+
error: ex,
|
|
539
|
+
entry,
|
|
540
|
+
model,
|
|
541
|
+
input
|
|
542
|
+
});
|
|
543
|
+
throw new _error.default(ex.message || "Could not create content entry.", ex.code || "CREATE_ENTRY_ERROR", ex.data || {
|
|
544
|
+
error: ex,
|
|
545
|
+
input,
|
|
546
|
+
entry,
|
|
547
|
+
storageEntry
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
const createEntryRevisionFrom = async (model, sourceId, inputData) => {
|
|
552
|
+
const permission = await checkEntryPermissions({
|
|
553
|
+
rwd: "w"
|
|
554
|
+
});
|
|
555
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
556
|
+
|
|
377
557
|
/**
|
|
378
|
-
*
|
|
558
|
+
* Make sure we only work with fields that are defined in the model.
|
|
379
559
|
*/
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
onEntryRevisionDeleteError,
|
|
560
|
+
const input = mapAndCleanUpdatedInputData(model, inputData);
|
|
561
|
+
|
|
383
562
|
/**
|
|
384
|
-
*
|
|
563
|
+
* Entries are identified by a common parent ID + Revision number.
|
|
385
564
|
*/
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
565
|
+
const {
|
|
566
|
+
id: uniqueId
|
|
567
|
+
} = (0, _utils.parseIdentifier)(sourceId);
|
|
568
|
+
const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
|
|
569
|
+
id: sourceId
|
|
570
|
+
});
|
|
571
|
+
const latestStorageEntry = await storageOperations.entries.getLatestRevisionByEntryId(model, {
|
|
572
|
+
id: uniqueId
|
|
573
|
+
});
|
|
574
|
+
if (!originalStorageEntry) {
|
|
575
|
+
throw new _handlerGraphql.NotFoundError(`Entry "${sourceId}" of model "${model.modelId}" was not found.`);
|
|
576
|
+
}
|
|
577
|
+
|
|
389
578
|
/**
|
|
390
|
-
*
|
|
579
|
+
* We need to convert data from DB to its original form before using it further.
|
|
391
580
|
*/
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
581
|
+
const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
|
|
582
|
+
const initialValues = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry.values), input);
|
|
583
|
+
await (0, _entryDataValidation.validateModelEntryData)({
|
|
584
|
+
context,
|
|
585
|
+
model,
|
|
586
|
+
data: initialValues,
|
|
587
|
+
entry: originalEntry
|
|
588
|
+
});
|
|
589
|
+
const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
|
|
590
|
+
context,
|
|
591
|
+
model,
|
|
592
|
+
input: initialValues,
|
|
593
|
+
validateEntries: false
|
|
594
|
+
});
|
|
595
|
+
(0, _ownership.checkOwnership)(context, permission, originalEntry);
|
|
596
|
+
const identity = getIdentity();
|
|
597
|
+
const latestId = latestStorageEntry ? latestStorageEntry.id : sourceId;
|
|
598
|
+
const {
|
|
599
|
+
id,
|
|
600
|
+
version: nextVersion
|
|
601
|
+
} = increaseEntryIdVersion(latestId);
|
|
602
|
+
const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
|
|
603
|
+
id,
|
|
604
|
+
version: nextVersion,
|
|
605
|
+
savedOn: new Date().toISOString(),
|
|
606
|
+
createdOn: new Date().toISOString(),
|
|
607
|
+
createdBy: {
|
|
608
|
+
id: identity.id,
|
|
609
|
+
displayName: identity.displayName,
|
|
610
|
+
type: identity.type
|
|
611
|
+
},
|
|
612
|
+
modifiedBy: null,
|
|
613
|
+
locked: false,
|
|
614
|
+
publishedOn: undefined,
|
|
615
|
+
status: STATUS_DRAFT,
|
|
616
|
+
values
|
|
617
|
+
});
|
|
618
|
+
let storageEntry = null;
|
|
619
|
+
try {
|
|
620
|
+
await onEntryBeforeCreateRevision.publish({
|
|
621
|
+
input,
|
|
622
|
+
entry,
|
|
623
|
+
original: originalEntry,
|
|
624
|
+
model
|
|
625
|
+
});
|
|
626
|
+
storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
|
|
627
|
+
const result = await storageOperations.entries.createRevisionFrom(model, {
|
|
628
|
+
entry,
|
|
629
|
+
storageEntry
|
|
630
|
+
});
|
|
631
|
+
await onEntryRevisionAfterCreate.publish({
|
|
632
|
+
input,
|
|
633
|
+
entry,
|
|
634
|
+
model,
|
|
635
|
+
original: originalEntry,
|
|
636
|
+
storageEntry: result
|
|
637
|
+
});
|
|
638
|
+
return result;
|
|
639
|
+
} catch (ex) {
|
|
640
|
+
await onEntryCreateRevisionError.publish({
|
|
641
|
+
entry,
|
|
642
|
+
original: originalEntry,
|
|
643
|
+
model,
|
|
644
|
+
input,
|
|
645
|
+
error: ex
|
|
646
|
+
});
|
|
647
|
+
throw new _error.default(ex.message || "Could not create entry from existing one.", ex.code || "CREATE_FROM_REVISION_ERROR", {
|
|
648
|
+
error: ex,
|
|
649
|
+
entry,
|
|
650
|
+
storageEntry,
|
|
651
|
+
originalEntry,
|
|
652
|
+
originalStorageEntry
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
const updateEntry = async (model, id, inputData, metaInput) => {
|
|
657
|
+
const permission = await checkEntryPermissions({
|
|
658
|
+
rwd: "w"
|
|
659
|
+
});
|
|
660
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
661
|
+
|
|
395
662
|
/**
|
|
396
|
-
*
|
|
663
|
+
* Make sure we only work with fields that are defined in the model.
|
|
397
664
|
*/
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
onEntryUnpublishError,
|
|
401
|
-
onEntryBeforeGet,
|
|
402
|
-
onEntryBeforeList,
|
|
665
|
+
const input = mapAndCleanUpdatedInputData(model, inputData);
|
|
666
|
+
|
|
403
667
|
/**
|
|
404
|
-
*
|
|
668
|
+
* The entry we are going to update.
|
|
405
669
|
*/
|
|
406
|
-
|
|
670
|
+
const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
|
|
671
|
+
id
|
|
672
|
+
});
|
|
673
|
+
if (!originalStorageEntry) {
|
|
674
|
+
throw new _handlerGraphql.NotFoundError(`Entry "${id}" of model "${model.modelId}" was not found.`);
|
|
675
|
+
}
|
|
676
|
+
if (originalStorageEntry.locked) {
|
|
677
|
+
throw new _error.default(`Cannot update entry because it's locked.`, "CONTENT_ENTRY_UPDATE_ERROR");
|
|
678
|
+
}
|
|
679
|
+
const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
|
|
680
|
+
await (0, _entryDataValidation.validateModelEntryData)({
|
|
681
|
+
context,
|
|
682
|
+
model,
|
|
683
|
+
data: input,
|
|
684
|
+
entry: originalEntry
|
|
685
|
+
});
|
|
686
|
+
(0, _ownership.checkOwnership)(context, permission, originalEntry);
|
|
687
|
+
const initialValues = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry.values), input);
|
|
688
|
+
const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
|
|
689
|
+
context,
|
|
690
|
+
model,
|
|
691
|
+
input: initialValues,
|
|
692
|
+
validateEntries: false
|
|
693
|
+
});
|
|
407
694
|
/**
|
|
408
|
-
*
|
|
695
|
+
* If users wants to remove a key from meta values, they need to send meta key with the null value.
|
|
409
696
|
*/
|
|
410
|
-
|
|
411
|
-
const where = {
|
|
412
|
-
id
|
|
413
|
-
};
|
|
414
|
-
const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
|
|
415
|
-
model: initialModel,
|
|
416
|
-
plugins
|
|
417
|
-
});
|
|
418
|
-
await onEntryBeforeGet.publish({
|
|
419
|
-
where,
|
|
420
|
-
model
|
|
421
|
-
});
|
|
422
|
-
const [entry] = await getEntriesByIds(model, [id]);
|
|
423
|
-
if (!entry) {
|
|
424
|
-
throw new _handlerGraphql.NotFoundError(`Entry by ID "${id}" not found.`);
|
|
425
|
-
}
|
|
426
|
-
return entry;
|
|
427
|
-
},
|
|
697
|
+
const meta = createEntryMeta(metaInput, originalEntry.meta);
|
|
428
698
|
/**
|
|
429
|
-
*
|
|
699
|
+
* We always send the full entry to the hooks and storage operations update.
|
|
430
700
|
*/
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
701
|
+
const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
|
|
702
|
+
savedOn: new Date().toISOString(),
|
|
703
|
+
modifiedBy: getCreatedBy(),
|
|
704
|
+
values,
|
|
705
|
+
meta,
|
|
706
|
+
status: transformEntryStatus(originalEntry.status)
|
|
707
|
+
});
|
|
708
|
+
let storageEntry = null;
|
|
709
|
+
try {
|
|
710
|
+
await onEntryBeforeUpdate.publish({
|
|
711
|
+
entry,
|
|
712
|
+
model,
|
|
713
|
+
input,
|
|
714
|
+
original: originalEntry
|
|
434
715
|
});
|
|
435
|
-
await (0,
|
|
436
|
-
const
|
|
437
|
-
|
|
438
|
-
|
|
716
|
+
storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
|
|
717
|
+
const result = await storageOperations.entries.update(model, {
|
|
718
|
+
entry,
|
|
719
|
+
storageEntry
|
|
439
720
|
});
|
|
440
|
-
|
|
441
|
-
|
|
721
|
+
await onEntryAfterUpdate.publish({
|
|
722
|
+
entry,
|
|
723
|
+
storageEntry: result,
|
|
724
|
+
model,
|
|
725
|
+
input,
|
|
726
|
+
original: originalEntry
|
|
442
727
|
});
|
|
443
|
-
return
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
rwd: "r"
|
|
728
|
+
return result;
|
|
729
|
+
} catch (ex) {
|
|
730
|
+
await onEntryUpdateError.publish({
|
|
731
|
+
entry,
|
|
732
|
+
model,
|
|
733
|
+
input,
|
|
734
|
+
error: ex
|
|
451
735
|
});
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
736
|
+
throw new _error.default(ex.message || "Could not update existing entry.", ex.code || "UPDATE_ERROR", {
|
|
737
|
+
error: ex,
|
|
738
|
+
entry,
|
|
739
|
+
storageEntry,
|
|
740
|
+
originalEntry,
|
|
741
|
+
input
|
|
456
742
|
});
|
|
457
|
-
|
|
458
|
-
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
const republishEntry = async (model, id) => {
|
|
746
|
+
await checkEntryPermissions({
|
|
747
|
+
rwd: "w"
|
|
748
|
+
});
|
|
749
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
750
|
+
/**
|
|
751
|
+
* Fetch the entry from the storage.
|
|
752
|
+
*/
|
|
753
|
+
const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
|
|
754
|
+
id
|
|
755
|
+
});
|
|
756
|
+
if (!originalStorageEntry) {
|
|
757
|
+
throw new _handlerGraphql.NotFoundError(`Entry "${id}" was not found!`);
|
|
758
|
+
}
|
|
759
|
+
const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
|
|
760
|
+
/**
|
|
761
|
+
* We can only process published entries.
|
|
762
|
+
*/
|
|
763
|
+
if (originalEntry.status !== "published") {
|
|
764
|
+
throw new _error.default("Entry with given ID is not published!", "NOT_PUBLISHED_ERROR", {
|
|
765
|
+
id,
|
|
766
|
+
original: originalEntry
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
|
|
770
|
+
context,
|
|
771
|
+
model,
|
|
772
|
+
input: originalEntry.values,
|
|
773
|
+
validateEntries: false
|
|
774
|
+
});
|
|
775
|
+
const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
|
|
776
|
+
savedOn: new Date().toISOString(),
|
|
777
|
+
webinyVersion: context.WEBINY_VERSION,
|
|
778
|
+
values
|
|
779
|
+
});
|
|
780
|
+
const storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
|
|
781
|
+
/**
|
|
782
|
+
* First we need to update existing entry.
|
|
783
|
+
*/
|
|
784
|
+
try {
|
|
785
|
+
await storageOperations.entries.update(model, {
|
|
786
|
+
entry,
|
|
787
|
+
storageEntry
|
|
788
|
+
});
|
|
789
|
+
} catch (ex) {
|
|
790
|
+
throw new _error.default("Could not update existing entry with new data while re-publishing.", "REPUBLISH_UPDATE_ERROR", {
|
|
791
|
+
entry
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Then we move onto publishing it again.
|
|
796
|
+
*/
|
|
797
|
+
try {
|
|
798
|
+
await onEntryBeforeRepublish.publish({
|
|
799
|
+
entry,
|
|
800
|
+
model
|
|
801
|
+
});
|
|
802
|
+
const result = await storageOperations.entries.publish(model, {
|
|
803
|
+
entry,
|
|
804
|
+
storageEntry
|
|
805
|
+
});
|
|
806
|
+
await onEntryAfterRepublish.publish({
|
|
807
|
+
entry,
|
|
808
|
+
model,
|
|
809
|
+
storageEntry
|
|
810
|
+
});
|
|
811
|
+
return result;
|
|
812
|
+
} catch (ex) {
|
|
813
|
+
await onEntryRepublishError.publish({
|
|
814
|
+
entry,
|
|
815
|
+
model,
|
|
816
|
+
error: ex
|
|
817
|
+
});
|
|
818
|
+
throw new _error.default("Could not publish existing entry while re-publishing.", "REPUBLISH_PUBLISH_ERROR", {
|
|
819
|
+
entry
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
const deleteEntryRevision = async (model, revisionId) => {
|
|
824
|
+
const permission = await checkEntryPermissions({
|
|
825
|
+
rwd: "d"
|
|
826
|
+
});
|
|
827
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
828
|
+
const {
|
|
829
|
+
id: entryId,
|
|
830
|
+
version
|
|
831
|
+
} = (0, _utils.parseIdentifier)(revisionId);
|
|
832
|
+
const storageEntryToDelete = await storageOperations.entries.getRevisionById(model, {
|
|
833
|
+
id: revisionId
|
|
834
|
+
});
|
|
835
|
+
const latestStorageEntry = await storageOperations.entries.getLatestRevisionByEntryId(model, {
|
|
836
|
+
id: entryId
|
|
837
|
+
});
|
|
838
|
+
const previousStorageEntry = await storageOperations.entries.getPreviousRevision(model, {
|
|
839
|
+
entryId,
|
|
840
|
+
version: version
|
|
841
|
+
});
|
|
842
|
+
if (!storageEntryToDelete) {
|
|
843
|
+
throw new _handlerGraphql.NotFoundError(`Entry "${revisionId}" was not found!`);
|
|
844
|
+
}
|
|
845
|
+
(0, _ownership.checkOwnership)(context, permission, storageEntryToDelete);
|
|
846
|
+
const latestEntryRevisionId = latestStorageEntry ? latestStorageEntry.id : null;
|
|
847
|
+
const entryToDelete = await (0, _entryStorage.entryFromStorageTransform)(context, model, storageEntryToDelete);
|
|
848
|
+
/**
|
|
849
|
+
* If targeted record is the latest entry record and there is no previous one, we need to run full delete with hooks.
|
|
850
|
+
* At this point deleteRevision hooks are not fired.
|
|
851
|
+
*/
|
|
852
|
+
if (entryToDelete.id === latestEntryRevisionId && !previousStorageEntry) {
|
|
853
|
+
return await deleteEntryHelper({
|
|
854
|
+
model,
|
|
855
|
+
entry: entryToDelete
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* If targeted record is latest entry revision, set the previous one as the new latest
|
|
860
|
+
*/
|
|
861
|
+
let entryToSetAsLatest = null;
|
|
862
|
+
let storageEntryToSetAsLatest = null;
|
|
863
|
+
if (entryToDelete.id === latestEntryRevisionId && previousStorageEntry) {
|
|
864
|
+
entryToSetAsLatest = await (0, _entryStorage.entryFromStorageTransform)(context, model, previousStorageEntry);
|
|
865
|
+
storageEntryToSetAsLatest = previousStorageEntry;
|
|
866
|
+
}
|
|
867
|
+
try {
|
|
868
|
+
await onEntryRevisionBeforeDelete.publish({
|
|
869
|
+
entry: entryToDelete,
|
|
870
|
+
model
|
|
871
|
+
});
|
|
872
|
+
await storageOperations.entries.deleteRevision(model, {
|
|
873
|
+
entry: entryToDelete,
|
|
874
|
+
storageEntry: storageEntryToDelete,
|
|
875
|
+
latestEntry: entryToSetAsLatest,
|
|
876
|
+
latestStorageEntry: storageEntryToSetAsLatest
|
|
877
|
+
});
|
|
878
|
+
await onEntryRevisionAfterDelete.publish({
|
|
879
|
+
entry: entryToDelete,
|
|
880
|
+
model
|
|
881
|
+
});
|
|
882
|
+
} catch (ex) {
|
|
883
|
+
await onEntryRevisionDeleteError.publish({
|
|
884
|
+
entry: entryToDelete,
|
|
885
|
+
model,
|
|
886
|
+
error: ex
|
|
887
|
+
});
|
|
888
|
+
throw new _error.default(ex.message, ex.code || "DELETE_REVISION_ERROR", {
|
|
889
|
+
error: ex,
|
|
890
|
+
entry: entryToDelete,
|
|
891
|
+
storageEntry: storageEntryToDelete,
|
|
892
|
+
latestEntry: entryToSetAsLatest,
|
|
893
|
+
latestStorageEntry: storageEntryToSetAsLatest
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
const deleteEntry = async (model, entryId) => {
|
|
898
|
+
const permission = await checkEntryPermissions({
|
|
899
|
+
rwd: "d"
|
|
900
|
+
});
|
|
901
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
902
|
+
const storageEntry = await storageOperations.entries.getLatestRevisionByEntryId(model, {
|
|
903
|
+
id: entryId
|
|
904
|
+
});
|
|
905
|
+
if (!storageEntry) {
|
|
906
|
+
throw new _handlerGraphql.NotFoundError(`Entry "${entryId}" was not found!`);
|
|
907
|
+
}
|
|
908
|
+
(0, _ownership.checkOwnership)(context, permission, storageEntry);
|
|
909
|
+
const entry = await (0, _entryStorage.entryFromStorageTransform)(context, model, storageEntry);
|
|
910
|
+
return await deleteEntryHelper({
|
|
911
|
+
model,
|
|
912
|
+
entry
|
|
913
|
+
});
|
|
914
|
+
};
|
|
915
|
+
const publishEntry = async (model, id) => {
|
|
916
|
+
const permission = await checkEntryPermissions({
|
|
917
|
+
pw: "p"
|
|
918
|
+
});
|
|
919
|
+
await (0, _access.checkModelAccess)(context, model);
|
|
920
|
+
const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
|
|
921
|
+
id
|
|
922
|
+
});
|
|
923
|
+
if (!originalStorageEntry) {
|
|
924
|
+
throw new _handlerGraphql.NotFoundError(`Entry "${id}" in the model "${model.modelId}" was not found.`);
|
|
925
|
+
}
|
|
926
|
+
(0, _ownership.checkOwnership)(context, permission, originalStorageEntry);
|
|
927
|
+
const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
|
|
928
|
+
const currentDate = new Date().toISOString();
|
|
929
|
+
const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
|
|
930
|
+
status: STATUS_PUBLISHED,
|
|
931
|
+
locked: true,
|
|
932
|
+
savedOn: currentDate,
|
|
933
|
+
publishedOn: currentDate
|
|
934
|
+
});
|
|
935
|
+
let storageEntry = null;
|
|
936
|
+
try {
|
|
937
|
+
await onEntryBeforePublish.publish({
|
|
938
|
+
entry,
|
|
939
|
+
model
|
|
940
|
+
});
|
|
941
|
+
storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
|
|
942
|
+
const result = await storageOperations.entries.publish(model, {
|
|
943
|
+
entry,
|
|
944
|
+
storageEntry
|
|
945
|
+
});
|
|
946
|
+
await onEntryAfterPublish.publish({
|
|
947
|
+
entry,
|
|
948
|
+
storageEntry: result,
|
|
949
|
+
model
|
|
950
|
+
});
|
|
951
|
+
return result;
|
|
952
|
+
} catch (ex) {
|
|
953
|
+
await onEntryPublishError.publish({
|
|
954
|
+
entry,
|
|
955
|
+
model,
|
|
956
|
+
error: ex
|
|
957
|
+
});
|
|
958
|
+
throw new _error.default(ex.message || "Could not publish entry.", ex.code || "PUBLISH_ERROR", {
|
|
959
|
+
error: ex,
|
|
960
|
+
entry,
|
|
961
|
+
storageEntry,
|
|
962
|
+
originalEntry,
|
|
963
|
+
originalStorageEntry
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
};
|
|
967
|
+
const unpublishEntry = async (model, id) => {
|
|
968
|
+
const permission = await checkEntryPermissions({
|
|
969
|
+
pw: "u"
|
|
970
|
+
});
|
|
971
|
+
const {
|
|
972
|
+
id: entryId
|
|
973
|
+
} = (0, _utils.parseIdentifier)(id);
|
|
974
|
+
const originalStorageEntry = await storageOperations.entries.getPublishedRevisionByEntryId(model, {
|
|
975
|
+
id: entryId
|
|
976
|
+
});
|
|
977
|
+
if (!originalStorageEntry) {
|
|
978
|
+
throw new _handlerGraphql.NotFoundError(`Entry "${id}" of model "${model.modelId}" was not found.`);
|
|
979
|
+
}
|
|
980
|
+
if (originalStorageEntry.id !== id) {
|
|
981
|
+
throw new _error.default(`Entry is not published.`, "UNPUBLISH_ERROR", {
|
|
982
|
+
entry: originalStorageEntry
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
(0, _ownership.checkOwnership)(context, permission, originalStorageEntry);
|
|
986
|
+
const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
|
|
987
|
+
const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
|
|
988
|
+
status: STATUS_UNPUBLISHED
|
|
989
|
+
});
|
|
990
|
+
let storageEntry = null;
|
|
991
|
+
try {
|
|
992
|
+
await onEntryBeforeUnpublish.publish({
|
|
993
|
+
entry,
|
|
994
|
+
model
|
|
995
|
+
});
|
|
996
|
+
storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
|
|
997
|
+
const result = await storageOperations.entries.unpublish(model, {
|
|
998
|
+
entry,
|
|
999
|
+
storageEntry
|
|
1000
|
+
});
|
|
1001
|
+
await onEntryAfterUnpublish.publish({
|
|
1002
|
+
entry,
|
|
1003
|
+
storageEntry: result,
|
|
1004
|
+
model
|
|
1005
|
+
});
|
|
1006
|
+
return result;
|
|
1007
|
+
} catch (ex) {
|
|
1008
|
+
await onEntryUnpublishError.publish({
|
|
1009
|
+
entry,
|
|
1010
|
+
model,
|
|
1011
|
+
error: ex
|
|
1012
|
+
});
|
|
1013
|
+
throw new _error.default(ex.message || "Could not unpublish entry.", ex.code || "UNPUBLISH_ERROR", {
|
|
1014
|
+
originalEntry,
|
|
1015
|
+
originalStorageEntry,
|
|
1016
|
+
entry,
|
|
1017
|
+
storageEntry
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
};
|
|
1021
|
+
return {
|
|
1022
|
+
/**
|
|
1023
|
+
* Deprecated - will be removed in 5.35.0
|
|
1024
|
+
*/
|
|
1025
|
+
onBeforeEntryCreate: onEntryBeforeCreate,
|
|
1026
|
+
onAfterEntryCreate: onEntryAfterCreate,
|
|
1027
|
+
onBeforeEntryCreateRevision: onEntryBeforeCreateRevision,
|
|
1028
|
+
onAfterEntryCreateRevision: onEntryRevisionAfterCreate,
|
|
1029
|
+
onBeforeEntryUpdate: onEntryBeforeUpdate,
|
|
1030
|
+
onAfterEntryUpdate: onEntryAfterUpdate,
|
|
1031
|
+
onBeforeEntryDelete: onEntryBeforeDelete,
|
|
1032
|
+
onAfterEntryDelete: onEntryAfterDelete,
|
|
1033
|
+
onBeforeEntryDeleteRevision: onEntryRevisionBeforeDelete,
|
|
1034
|
+
onAfterEntryDeleteRevision: onEntryRevisionAfterDelete,
|
|
1035
|
+
onBeforeEntryPublish: onEntryBeforePublish,
|
|
1036
|
+
onAfterEntryPublish: onEntryAfterPublish,
|
|
1037
|
+
onBeforeEntryUnpublish: onEntryBeforeUnpublish,
|
|
1038
|
+
onAfterEntryUnpublish: onEntryAfterUnpublish,
|
|
1039
|
+
onBeforeEntryGet: onEntryBeforeGet,
|
|
1040
|
+
onBeforeEntryList: onEntryBeforeList,
|
|
1041
|
+
/**
|
|
1042
|
+
* Released in 5.34.0
|
|
1043
|
+
*
|
|
1044
|
+
* Create
|
|
1045
|
+
*/
|
|
1046
|
+
onEntryBeforeCreate,
|
|
1047
|
+
onEntryAfterCreate,
|
|
1048
|
+
onEntryCreateError,
|
|
1049
|
+
/**
|
|
1050
|
+
* Create revision
|
|
1051
|
+
*/
|
|
1052
|
+
onEntryRevisionBeforeCreate: onEntryBeforeCreateRevision,
|
|
1053
|
+
onEntryRevisionAfterCreate,
|
|
1054
|
+
onEntryRevisionCreateError: onEntryCreateRevisionError,
|
|
1055
|
+
/**
|
|
1056
|
+
* Update
|
|
1057
|
+
*/
|
|
1058
|
+
onEntryBeforeUpdate,
|
|
1059
|
+
onEntryAfterUpdate,
|
|
1060
|
+
onEntryUpdateError,
|
|
1061
|
+
/**
|
|
1062
|
+
* Delete whole entry
|
|
1063
|
+
*/
|
|
1064
|
+
onEntryBeforeDelete,
|
|
1065
|
+
onEntryAfterDelete,
|
|
1066
|
+
onEntryDeleteError,
|
|
1067
|
+
/**
|
|
1068
|
+
* Delete entry revision
|
|
1069
|
+
*/
|
|
1070
|
+
onEntryRevisionBeforeDelete,
|
|
1071
|
+
onEntryRevisionAfterDelete,
|
|
1072
|
+
onEntryRevisionDeleteError,
|
|
1073
|
+
/**
|
|
1074
|
+
* Publish
|
|
1075
|
+
*/
|
|
1076
|
+
onEntryBeforePublish,
|
|
1077
|
+
onEntryAfterPublish,
|
|
1078
|
+
onEntryPublishError,
|
|
1079
|
+
/**
|
|
1080
|
+
* Republish
|
|
1081
|
+
*/
|
|
1082
|
+
onEntryBeforeRepublish,
|
|
1083
|
+
onEntryAfterRepublish,
|
|
1084
|
+
onEntryRepublishError,
|
|
1085
|
+
/**
|
|
1086
|
+
* Unpublish
|
|
1087
|
+
*/
|
|
1088
|
+
onEntryBeforeUnpublish,
|
|
1089
|
+
onEntryAfterUnpublish,
|
|
1090
|
+
onEntryUnpublishError,
|
|
1091
|
+
onEntryBeforeGet,
|
|
1092
|
+
onEntryBeforeList,
|
|
1093
|
+
/**
|
|
1094
|
+
* Get entries by exact revision IDs from the database.
|
|
1095
|
+
*/
|
|
1096
|
+
getEntriesByIds,
|
|
1097
|
+
/**
|
|
1098
|
+
* Get a single entry by revision ID from the database.
|
|
1099
|
+
*/
|
|
1100
|
+
async getEntryById(model, id) {
|
|
1101
|
+
return context.benchmark.measure("headlessCms.crud.entries.getEntryById", async () => {
|
|
1102
|
+
return getEntryById(model, id);
|
|
1103
|
+
});
|
|
1104
|
+
},
|
|
1105
|
+
/**
|
|
1106
|
+
* Get published revisions by entry IDs.
|
|
1107
|
+
*/
|
|
1108
|
+
async getPublishedEntriesByIds(model, ids) {
|
|
1109
|
+
return context.benchmark.measure("headlessCms.crud.entries.getPublishedEntriesByIds", async () => {
|
|
1110
|
+
return getPublishedEntriesByIds(model, ids);
|
|
459
1111
|
});
|
|
460
|
-
return entries.filter(entry => (0, _ownership.validateOwnership)(context, permission, entry));
|
|
461
1112
|
},
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
1113
|
+
/**
|
|
1114
|
+
* Get the latest revisions by entry IDs.
|
|
1115
|
+
*/
|
|
1116
|
+
async getLatestEntriesByIds(model, ids) {
|
|
1117
|
+
return context.benchmark.measure("headlessCms.crud.entries.getLatestEntriesByIds", async () => {
|
|
1118
|
+
return getLatestEntriesByIds(model, ids);
|
|
466
1119
|
});
|
|
467
|
-
|
|
468
|
-
|
|
1120
|
+
},
|
|
1121
|
+
async getEntryRevisions(model, entryId) {
|
|
1122
|
+
return context.benchmark.measure("headlessCms.crud.entries.getEntryRevisions", async () => {
|
|
1123
|
+
return getEntryRevisions(model, entryId);
|
|
469
1124
|
});
|
|
470
1125
|
},
|
|
471
1126
|
/**
|
|
@@ -473,118 +1128,20 @@ const createContentEntryCrud = params => {
|
|
|
473
1128
|
*
|
|
474
1129
|
* @internal
|
|
475
1130
|
*/
|
|
476
|
-
async getEntry(
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
});
|
|
480
|
-
const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
|
|
481
|
-
model: initialModel,
|
|
482
|
-
plugins
|
|
483
|
-
});
|
|
484
|
-
const {
|
|
485
|
-
where,
|
|
486
|
-
sort
|
|
487
|
-
} = params;
|
|
488
|
-
await onEntryBeforeGet.publish({
|
|
489
|
-
where,
|
|
490
|
-
model
|
|
491
|
-
});
|
|
492
|
-
const [items] = await this.listEntries(model, {
|
|
493
|
-
where,
|
|
494
|
-
sort,
|
|
495
|
-
limit: 1
|
|
1131
|
+
async getEntry(model, params) {
|
|
1132
|
+
return context.benchmark.measure("headlessCms.crud.entries.getEntry", async () => {
|
|
1133
|
+
return getEntry(model, params);
|
|
496
1134
|
});
|
|
497
|
-
if (items.length === 0) {
|
|
498
|
-
throw new _handlerGraphql.NotFoundError(`Entry not found!`);
|
|
499
|
-
}
|
|
500
|
-
return items[0];
|
|
501
1135
|
},
|
|
502
1136
|
/**
|
|
503
1137
|
* @description Should not be used directly. Internal use only!
|
|
504
1138
|
*
|
|
505
1139
|
* @internal
|
|
506
1140
|
*/
|
|
507
|
-
async listEntries(
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
});
|
|
511
|
-
await (0, _access.checkModelAccess)(context, initialModel);
|
|
512
|
-
const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
|
|
513
|
-
model: initialModel,
|
|
514
|
-
plugins
|
|
515
|
-
});
|
|
516
|
-
const {
|
|
517
|
-
where: initialWhere,
|
|
518
|
-
limit: initialLimit
|
|
519
|
-
} = params;
|
|
520
|
-
const limit = initialLimit && initialLimit > 0 ? initialLimit : 50;
|
|
521
|
-
/**
|
|
522
|
-
* We always assign tenant and locale because we do not allow one model to have content through multiple tenants.
|
|
523
|
-
*/
|
|
524
|
-
const where = (0, _objectSpread2.default)({}, initialWhere);
|
|
525
|
-
/**
|
|
526
|
-
* Possibly only get records which are owned by current user.
|
|
527
|
-
* Or if searching for the owner set that value - in the case that user can see other entries than their own.
|
|
528
|
-
*/
|
|
529
|
-
const ownedBy = permission.own ? getIdentity().id : where.ownedBy;
|
|
530
|
-
if (ownedBy !== undefined) {
|
|
531
|
-
where.ownedBy = ownedBy;
|
|
532
|
-
}
|
|
533
|
-
/**
|
|
534
|
-
* Where must contain either latest or published keys.
|
|
535
|
-
* We cannot list entries without one of those
|
|
536
|
-
*/
|
|
537
|
-
if (where.latest && where.published) {
|
|
538
|
-
throw new _error.default("Cannot list entries that are both published and latest.", "LIST_ENTRIES_ERROR", {
|
|
539
|
-
where
|
|
540
|
-
});
|
|
541
|
-
} else if (!where.latest && !where.published) {
|
|
542
|
-
throw new _error.default("Cannot list entries if we do not have latest or published defined.", "LIST_ENTRIES_ERROR", {
|
|
543
|
-
where
|
|
544
|
-
});
|
|
545
|
-
}
|
|
546
|
-
const fields = (0, _searchableFields.getSearchableFields)({
|
|
547
|
-
fields: model.fields,
|
|
548
|
-
plugins: context.plugins,
|
|
549
|
-
input: params.fields || []
|
|
1141
|
+
async listEntries(model, params) {
|
|
1142
|
+
return context.benchmark.measure("headlessCms.crud.entries.listEntries", async () => {
|
|
1143
|
+
return listEntries(model, params);
|
|
550
1144
|
});
|
|
551
|
-
try {
|
|
552
|
-
await onEntryBeforeList.publish({
|
|
553
|
-
where,
|
|
554
|
-
model
|
|
555
|
-
});
|
|
556
|
-
const {
|
|
557
|
-
hasMoreItems,
|
|
558
|
-
totalCount,
|
|
559
|
-
cursor,
|
|
560
|
-
items
|
|
561
|
-
} = await storageOperations.entries.list(model, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, params), {}, {
|
|
562
|
-
limit,
|
|
563
|
-
where,
|
|
564
|
-
fields
|
|
565
|
-
}));
|
|
566
|
-
const meta = {
|
|
567
|
-
hasMoreItems,
|
|
568
|
-
totalCount,
|
|
569
|
-
/**
|
|
570
|
-
* Cursor should be null if there are no more items to load.
|
|
571
|
-
* Just make sure of that, disregarding what is returned from the storageOperations.entries.list method.
|
|
572
|
-
*/
|
|
573
|
-
cursor: hasMoreItems ? cursor : null
|
|
574
|
-
};
|
|
575
|
-
return [items, meta];
|
|
576
|
-
} catch (ex) {
|
|
577
|
-
throw new _error.default("Error while fetching entries from storage.", "LIST_ENTRIES_ERROR", {
|
|
578
|
-
params,
|
|
579
|
-
error: {
|
|
580
|
-
message: ex.message,
|
|
581
|
-
code: ex.code,
|
|
582
|
-
data: ex.data
|
|
583
|
-
},
|
|
584
|
-
model,
|
|
585
|
-
fields
|
|
586
|
-
});
|
|
587
|
-
}
|
|
588
1145
|
},
|
|
589
1146
|
async listLatestEntries(model, params) {
|
|
590
1147
|
const where = (params === null || params === void 0 ? void 0 : params.where) || {};
|
|
@@ -606,594 +1163,49 @@ const createContentEntryCrud = params => {
|
|
|
606
1163
|
})
|
|
607
1164
|
}));
|
|
608
1165
|
},
|
|
609
|
-
async createEntry(
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
});
|
|
613
|
-
await (0, _access.checkModelAccess)(context, initialModel);
|
|
614
|
-
const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
|
|
615
|
-
model: initialModel,
|
|
616
|
-
plugins
|
|
617
|
-
});
|
|
618
|
-
|
|
619
|
-
/**
|
|
620
|
-
* Make sure we only work with fields that are defined in the model.
|
|
621
|
-
*/
|
|
622
|
-
const initialInput = mapAndCleanCreateInputData(model, inputData);
|
|
623
|
-
await (0, _entryDataValidation.validateModelEntryData)({
|
|
624
|
-
context,
|
|
625
|
-
model,
|
|
626
|
-
data: initialInput
|
|
627
|
-
});
|
|
628
|
-
const input = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
|
|
629
|
-
context,
|
|
630
|
-
model,
|
|
631
|
-
input: initialInput,
|
|
632
|
-
validateEntries: true
|
|
1166
|
+
async createEntry(model, input) {
|
|
1167
|
+
return context.benchmark.measure("headlessCms.crud.entries.createEntry", async () => {
|
|
1168
|
+
return createEntry(model, input);
|
|
633
1169
|
});
|
|
634
|
-
const locale = this.getLocale();
|
|
635
|
-
const owner = getCreatedBy();
|
|
636
|
-
const {
|
|
637
|
-
id,
|
|
638
|
-
entryId,
|
|
639
|
-
version
|
|
640
|
-
} = createEntryId(inputData);
|
|
641
|
-
/**
|
|
642
|
-
* There is a possibility that user sends an ID in the input, so we will use that one.
|
|
643
|
-
* There is no check if the ID is unique or not, that is up to the user.
|
|
644
|
-
*/
|
|
645
|
-
const entry = {
|
|
646
|
-
webinyVersion: context.WEBINY_VERSION,
|
|
647
|
-
tenant: getTenant().id,
|
|
648
|
-
entryId,
|
|
649
|
-
id,
|
|
650
|
-
modelId: model.modelId,
|
|
651
|
-
locale: locale.code,
|
|
652
|
-
createdOn: new Date().toISOString(),
|
|
653
|
-
savedOn: new Date().toISOString(),
|
|
654
|
-
createdBy: owner,
|
|
655
|
-
ownedBy: owner,
|
|
656
|
-
modifiedBy: null,
|
|
657
|
-
version,
|
|
658
|
-
locked: false,
|
|
659
|
-
status: STATUS_DRAFT,
|
|
660
|
-
values: input
|
|
661
|
-
};
|
|
662
|
-
let storageEntry = null;
|
|
663
|
-
try {
|
|
664
|
-
await onEntryBeforeCreate.publish({
|
|
665
|
-
entry,
|
|
666
|
-
input,
|
|
667
|
-
model
|
|
668
|
-
});
|
|
669
|
-
storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
|
|
670
|
-
const result = await storageOperations.entries.create(model, {
|
|
671
|
-
entry,
|
|
672
|
-
storageEntry
|
|
673
|
-
});
|
|
674
|
-
await onEntryAfterCreate.publish({
|
|
675
|
-
entry,
|
|
676
|
-
storageEntry: result,
|
|
677
|
-
model,
|
|
678
|
-
input
|
|
679
|
-
});
|
|
680
|
-
return result;
|
|
681
|
-
} catch (ex) {
|
|
682
|
-
await onEntryCreateError.publish({
|
|
683
|
-
error: ex,
|
|
684
|
-
entry,
|
|
685
|
-
model,
|
|
686
|
-
input
|
|
687
|
-
});
|
|
688
|
-
throw new _error.default(ex.message || "Could not create content entry.", ex.code || "CREATE_ENTRY_ERROR", ex.data || {
|
|
689
|
-
error: ex,
|
|
690
|
-
input,
|
|
691
|
-
entry,
|
|
692
|
-
storageEntry
|
|
693
|
-
});
|
|
694
|
-
}
|
|
695
1170
|
},
|
|
696
|
-
async createEntryRevisionFrom(
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
});
|
|
700
|
-
await (0, _access.checkModelAccess)(context, initialModel);
|
|
701
|
-
const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
|
|
702
|
-
model: initialModel,
|
|
703
|
-
plugins
|
|
704
|
-
});
|
|
705
|
-
|
|
706
|
-
/**
|
|
707
|
-
* Make sure we only work with fields that are defined in the model.
|
|
708
|
-
*/
|
|
709
|
-
const input = mapAndCleanUpdatedInputData(model, inputData);
|
|
710
|
-
|
|
711
|
-
/**
|
|
712
|
-
* Entries are identified by a common parent ID + Revision number.
|
|
713
|
-
*/
|
|
714
|
-
const {
|
|
715
|
-
id: uniqueId
|
|
716
|
-
} = (0, _utils.parseIdentifier)(sourceId);
|
|
717
|
-
const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
|
|
718
|
-
id: sourceId
|
|
719
|
-
});
|
|
720
|
-
const latestStorageEntry = await storageOperations.entries.getLatestRevisionByEntryId(model, {
|
|
721
|
-
id: uniqueId
|
|
722
|
-
});
|
|
723
|
-
if (!originalStorageEntry) {
|
|
724
|
-
throw new _handlerGraphql.NotFoundError(`Entry "${sourceId}" of model "${model.modelId}" was not found.`);
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
/**
|
|
728
|
-
* We need to convert data from DB to its original form before using it further.
|
|
729
|
-
*/
|
|
730
|
-
const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
|
|
731
|
-
const initialValues = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry.values), input);
|
|
732
|
-
await (0, _entryDataValidation.validateModelEntryData)({
|
|
733
|
-
context,
|
|
734
|
-
model,
|
|
735
|
-
data: initialValues,
|
|
736
|
-
entry: originalEntry
|
|
737
|
-
});
|
|
738
|
-
const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
|
|
739
|
-
context,
|
|
740
|
-
model,
|
|
741
|
-
input: initialValues,
|
|
742
|
-
validateEntries: false
|
|
1171
|
+
async createEntryRevisionFrom(model, sourceId, input) {
|
|
1172
|
+
return context.benchmark.measure("headlessCms.crud.entries.createEntryRevisionFrom", async () => {
|
|
1173
|
+
return createEntryRevisionFrom(model, sourceId, input);
|
|
743
1174
|
});
|
|
744
|
-
(0, _ownership.checkOwnership)(context, permission, originalEntry);
|
|
745
|
-
const identity = getIdentity();
|
|
746
|
-
const latestId = latestStorageEntry ? latestStorageEntry.id : sourceId;
|
|
747
|
-
const {
|
|
748
|
-
id,
|
|
749
|
-
version: nextVersion
|
|
750
|
-
} = increaseEntryIdVersion(latestId);
|
|
751
|
-
const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
|
|
752
|
-
id,
|
|
753
|
-
version: nextVersion,
|
|
754
|
-
savedOn: new Date().toISOString(),
|
|
755
|
-
createdOn: new Date().toISOString(),
|
|
756
|
-
createdBy: {
|
|
757
|
-
id: identity.id,
|
|
758
|
-
displayName: identity.displayName,
|
|
759
|
-
type: identity.type
|
|
760
|
-
},
|
|
761
|
-
modifiedBy: null,
|
|
762
|
-
locked: false,
|
|
763
|
-
publishedOn: undefined,
|
|
764
|
-
status: STATUS_DRAFT,
|
|
765
|
-
values
|
|
766
|
-
});
|
|
767
|
-
let storageEntry = null;
|
|
768
|
-
try {
|
|
769
|
-
await onEntryBeforeCreateRevision.publish({
|
|
770
|
-
input,
|
|
771
|
-
entry,
|
|
772
|
-
original: originalEntry,
|
|
773
|
-
model
|
|
774
|
-
});
|
|
775
|
-
storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
|
|
776
|
-
const result = await storageOperations.entries.createRevisionFrom(model, {
|
|
777
|
-
entry,
|
|
778
|
-
storageEntry
|
|
779
|
-
});
|
|
780
|
-
await onEntryRevisionAfterCreate.publish({
|
|
781
|
-
input,
|
|
782
|
-
entry,
|
|
783
|
-
model,
|
|
784
|
-
original: originalEntry,
|
|
785
|
-
storageEntry: result
|
|
786
|
-
});
|
|
787
|
-
return result;
|
|
788
|
-
} catch (ex) {
|
|
789
|
-
await onEntryCreateRevisionError.publish({
|
|
790
|
-
entry,
|
|
791
|
-
original: originalEntry,
|
|
792
|
-
model,
|
|
793
|
-
input,
|
|
794
|
-
error: ex
|
|
795
|
-
});
|
|
796
|
-
throw new _error.default(ex.message || "Could not create entry from existing one.", ex.code || "CREATE_FROM_REVISION_ERROR", {
|
|
797
|
-
error: ex,
|
|
798
|
-
entry,
|
|
799
|
-
storageEntry,
|
|
800
|
-
originalEntry,
|
|
801
|
-
originalStorageEntry
|
|
802
|
-
});
|
|
803
|
-
}
|
|
804
1175
|
},
|
|
805
|
-
async updateEntry(
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
});
|
|
809
|
-
await (0, _access.checkModelAccess)(context, initialModel);
|
|
810
|
-
const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
|
|
811
|
-
model: initialModel,
|
|
812
|
-
plugins
|
|
813
|
-
});
|
|
814
|
-
|
|
815
|
-
/**
|
|
816
|
-
* Make sure we only work with fields that are defined in the model.
|
|
817
|
-
*/
|
|
818
|
-
const input = mapAndCleanUpdatedInputData(model, inputData);
|
|
819
|
-
|
|
820
|
-
/**
|
|
821
|
-
* The entry we are going to update.
|
|
822
|
-
*/
|
|
823
|
-
const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
|
|
824
|
-
id
|
|
825
|
-
});
|
|
826
|
-
if (!originalStorageEntry) {
|
|
827
|
-
throw new _handlerGraphql.NotFoundError(`Entry "${id}" of model "${model.modelId}" was not found.`);
|
|
828
|
-
}
|
|
829
|
-
if (originalStorageEntry.locked) {
|
|
830
|
-
throw new _error.default(`Cannot update entry because it's locked.`, "CONTENT_ENTRY_UPDATE_ERROR");
|
|
831
|
-
}
|
|
832
|
-
const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
|
|
833
|
-
await (0, _entryDataValidation.validateModelEntryData)({
|
|
834
|
-
context,
|
|
835
|
-
model,
|
|
836
|
-
data: input,
|
|
837
|
-
entry: originalEntry
|
|
838
|
-
});
|
|
839
|
-
(0, _ownership.checkOwnership)(context, permission, originalEntry);
|
|
840
|
-
const initialValues = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry.values), input);
|
|
841
|
-
const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
|
|
842
|
-
context,
|
|
843
|
-
model,
|
|
844
|
-
input: initialValues,
|
|
845
|
-
validateEntries: false
|
|
846
|
-
});
|
|
847
|
-
/**
|
|
848
|
-
* If users wants to remove a key from meta values, they need to send meta key with the null value.
|
|
849
|
-
*/
|
|
850
|
-
const meta = createEntryMeta(metaInput, originalEntry.meta);
|
|
851
|
-
/**
|
|
852
|
-
* We always send the full entry to the hooks and storage operations update.
|
|
853
|
-
*/
|
|
854
|
-
const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
|
|
855
|
-
savedOn: new Date().toISOString(),
|
|
856
|
-
modifiedBy: getCreatedBy(),
|
|
857
|
-
values,
|
|
858
|
-
meta,
|
|
859
|
-
status: transformEntryStatus(originalEntry.status)
|
|
1176
|
+
async updateEntry(model, id, input, meta) {
|
|
1177
|
+
return context.benchmark.measure("headlessCms.crud.entries.updateEntry", async () => {
|
|
1178
|
+
return updateEntry(model, id, input, meta);
|
|
860
1179
|
});
|
|
861
|
-
let storageEntry = null;
|
|
862
|
-
try {
|
|
863
|
-
await onEntryBeforeUpdate.publish({
|
|
864
|
-
entry,
|
|
865
|
-
model,
|
|
866
|
-
input,
|
|
867
|
-
original: originalEntry
|
|
868
|
-
});
|
|
869
|
-
storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
|
|
870
|
-
const result = await storageOperations.entries.update(model, {
|
|
871
|
-
entry,
|
|
872
|
-
storageEntry
|
|
873
|
-
});
|
|
874
|
-
await onEntryAfterUpdate.publish({
|
|
875
|
-
entry,
|
|
876
|
-
storageEntry: result,
|
|
877
|
-
model,
|
|
878
|
-
input,
|
|
879
|
-
original: originalEntry
|
|
880
|
-
});
|
|
881
|
-
return result;
|
|
882
|
-
} catch (ex) {
|
|
883
|
-
await onEntryUpdateError.publish({
|
|
884
|
-
entry,
|
|
885
|
-
model,
|
|
886
|
-
input,
|
|
887
|
-
error: ex
|
|
888
|
-
});
|
|
889
|
-
throw new _error.default(ex.message || "Could not update existing entry.", ex.code || "UPDATE_ERROR", {
|
|
890
|
-
error: ex,
|
|
891
|
-
entry,
|
|
892
|
-
storageEntry,
|
|
893
|
-
originalEntry,
|
|
894
|
-
input
|
|
895
|
-
});
|
|
896
|
-
}
|
|
897
1180
|
},
|
|
898
1181
|
/**
|
|
899
1182
|
* Method used internally. Not documented and should not be used in users systems.
|
|
900
1183
|
* @internal
|
|
901
1184
|
*/
|
|
902
|
-
async republishEntry(
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
});
|
|
906
|
-
await (0, _access.checkModelAccess)(context, initialModel);
|
|
907
|
-
const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
|
|
908
|
-
model: initialModel,
|
|
909
|
-
plugins
|
|
910
|
-
});
|
|
911
|
-
/**
|
|
912
|
-
* Fetch the entry from the storage.
|
|
913
|
-
*/
|
|
914
|
-
const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
|
|
915
|
-
id
|
|
916
|
-
});
|
|
917
|
-
if (!originalStorageEntry) {
|
|
918
|
-
throw new _handlerGraphql.NotFoundError(`Entry "${id}" was not found!`);
|
|
919
|
-
}
|
|
920
|
-
const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
|
|
921
|
-
/**
|
|
922
|
-
* We can only process published entries.
|
|
923
|
-
*/
|
|
924
|
-
if (originalEntry.status !== "published") {
|
|
925
|
-
throw new _error.default("Entry with given ID is not published!", "NOT_PUBLISHED_ERROR", {
|
|
926
|
-
id,
|
|
927
|
-
original: originalEntry
|
|
928
|
-
});
|
|
929
|
-
}
|
|
930
|
-
const values = await (0, _referenceFieldsMapping.referenceFieldsMapping)({
|
|
931
|
-
context,
|
|
932
|
-
model,
|
|
933
|
-
input: originalEntry.values,
|
|
934
|
-
validateEntries: false
|
|
935
|
-
});
|
|
936
|
-
const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
|
|
937
|
-
savedOn: new Date().toISOString(),
|
|
938
|
-
webinyVersion: context.WEBINY_VERSION,
|
|
939
|
-
values
|
|
1185
|
+
async republishEntry(model, id) {
|
|
1186
|
+
return context.benchmark.measure("headlessCms.crud.entries.republishEntry", async () => {
|
|
1187
|
+
return republishEntry(model, id);
|
|
940
1188
|
});
|
|
941
|
-
const storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
|
|
942
|
-
/**
|
|
943
|
-
* First we need to update existing entry.
|
|
944
|
-
*/
|
|
945
|
-
try {
|
|
946
|
-
await storageOperations.entries.update(model, {
|
|
947
|
-
entry,
|
|
948
|
-
storageEntry
|
|
949
|
-
});
|
|
950
|
-
} catch (ex) {
|
|
951
|
-
throw new _error.default("Could not update existing entry with new data while re-publishing.", "REPUBLISH_UPDATE_ERROR", {
|
|
952
|
-
entry
|
|
953
|
-
});
|
|
954
|
-
}
|
|
955
|
-
/**
|
|
956
|
-
* Then we move onto publishing it again.
|
|
957
|
-
*/
|
|
958
|
-
try {
|
|
959
|
-
await onEntryBeforeRepublish.publish({
|
|
960
|
-
entry,
|
|
961
|
-
model
|
|
962
|
-
});
|
|
963
|
-
const result = await storageOperations.entries.publish(model, {
|
|
964
|
-
entry,
|
|
965
|
-
storageEntry
|
|
966
|
-
});
|
|
967
|
-
await onEntryAfterRepublish.publish({
|
|
968
|
-
entry,
|
|
969
|
-
model,
|
|
970
|
-
storageEntry
|
|
971
|
-
});
|
|
972
|
-
return result;
|
|
973
|
-
} catch (ex) {
|
|
974
|
-
await onEntryRepublishError.publish({
|
|
975
|
-
entry,
|
|
976
|
-
model,
|
|
977
|
-
error: ex
|
|
978
|
-
});
|
|
979
|
-
throw new _error.default("Could not publish existing entry while re-publishing.", "REPUBLISH_PUBLISH_ERROR", {
|
|
980
|
-
entry
|
|
981
|
-
});
|
|
982
|
-
}
|
|
983
1189
|
},
|
|
984
|
-
async deleteEntryRevision(
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
});
|
|
988
|
-
await (0, _access.checkModelAccess)(context, initialModel);
|
|
989
|
-
const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
|
|
990
|
-
model: initialModel,
|
|
991
|
-
plugins
|
|
992
|
-
});
|
|
993
|
-
const {
|
|
994
|
-
id: entryId,
|
|
995
|
-
version
|
|
996
|
-
} = (0, _utils.parseIdentifier)(revisionId);
|
|
997
|
-
const storageEntryToDelete = await storageOperations.entries.getRevisionById(model, {
|
|
998
|
-
id: revisionId
|
|
1190
|
+
async deleteEntryRevision(model, id) {
|
|
1191
|
+
return context.benchmark.measure("headlessCms.crud.entries.deleteEntryRevision", async () => {
|
|
1192
|
+
return deleteEntryRevision(model, id);
|
|
999
1193
|
});
|
|
1000
|
-
const latestStorageEntry = await storageOperations.entries.getLatestRevisionByEntryId(model, {
|
|
1001
|
-
id: entryId
|
|
1002
|
-
});
|
|
1003
|
-
const previousStorageEntry = await storageOperations.entries.getPreviousRevision(model, {
|
|
1004
|
-
entryId,
|
|
1005
|
-
version: version
|
|
1006
|
-
});
|
|
1007
|
-
if (!storageEntryToDelete) {
|
|
1008
|
-
throw new _handlerGraphql.NotFoundError(`Entry "${revisionId}" was not found!`);
|
|
1009
|
-
}
|
|
1010
|
-
(0, _ownership.checkOwnership)(context, permission, storageEntryToDelete);
|
|
1011
|
-
const latestEntryRevisionId = latestStorageEntry ? latestStorageEntry.id : null;
|
|
1012
|
-
const entryToDelete = await (0, _entryStorage.entryFromStorageTransform)(context, model, storageEntryToDelete);
|
|
1013
|
-
/**
|
|
1014
|
-
* If targeted record is the latest entry record and there is no previous one, we need to run full delete with hooks.
|
|
1015
|
-
* At this point deleteRevision hooks are not fired.
|
|
1016
|
-
*/
|
|
1017
|
-
if (entryToDelete.id === latestEntryRevisionId && !previousStorageEntry) {
|
|
1018
|
-
return await deleteEntry({
|
|
1019
|
-
model,
|
|
1020
|
-
entry: entryToDelete
|
|
1021
|
-
});
|
|
1022
|
-
}
|
|
1023
|
-
/**
|
|
1024
|
-
* If targeted record is latest entry revision, set the previous one as the new latest
|
|
1025
|
-
*/
|
|
1026
|
-
let entryToSetAsLatest = null;
|
|
1027
|
-
let storageEntryToSetAsLatest = null;
|
|
1028
|
-
if (entryToDelete.id === latestEntryRevisionId && previousStorageEntry) {
|
|
1029
|
-
entryToSetAsLatest = await (0, _entryStorage.entryFromStorageTransform)(context, model, previousStorageEntry);
|
|
1030
|
-
storageEntryToSetAsLatest = previousStorageEntry;
|
|
1031
|
-
}
|
|
1032
|
-
try {
|
|
1033
|
-
await onEntryRevisionBeforeDelete.publish({
|
|
1034
|
-
entry: entryToDelete,
|
|
1035
|
-
model
|
|
1036
|
-
});
|
|
1037
|
-
await storageOperations.entries.deleteRevision(model, {
|
|
1038
|
-
entry: entryToDelete,
|
|
1039
|
-
storageEntry: storageEntryToDelete,
|
|
1040
|
-
latestEntry: entryToSetAsLatest,
|
|
1041
|
-
latestStorageEntry: storageEntryToSetAsLatest
|
|
1042
|
-
});
|
|
1043
|
-
await onEntryRevisionAfterDelete.publish({
|
|
1044
|
-
entry: entryToDelete,
|
|
1045
|
-
model
|
|
1046
|
-
});
|
|
1047
|
-
} catch (ex) {
|
|
1048
|
-
await onEntryRevisionDeleteError.publish({
|
|
1049
|
-
entry: entryToDelete,
|
|
1050
|
-
model,
|
|
1051
|
-
error: ex
|
|
1052
|
-
});
|
|
1053
|
-
throw new _error.default(ex.message, ex.code || "DELETE_REVISION_ERROR", {
|
|
1054
|
-
error: ex,
|
|
1055
|
-
entry: entryToDelete,
|
|
1056
|
-
storageEntry: storageEntryToDelete,
|
|
1057
|
-
latestEntry: entryToSetAsLatest,
|
|
1058
|
-
latestStorageEntry: storageEntryToSetAsLatest
|
|
1059
|
-
});
|
|
1060
|
-
}
|
|
1061
1194
|
},
|
|
1062
|
-
async deleteEntry(
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
});
|
|
1066
|
-
await (0, _access.checkModelAccess)(context, initialModel);
|
|
1067
|
-
const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
|
|
1068
|
-
model: initialModel,
|
|
1069
|
-
plugins
|
|
1070
|
-
});
|
|
1071
|
-
const storageEntry = await storageOperations.entries.getLatestRevisionByEntryId(model, {
|
|
1072
|
-
id: entryId
|
|
1073
|
-
});
|
|
1074
|
-
if (!storageEntry) {
|
|
1075
|
-
throw new _handlerGraphql.NotFoundError(`Entry "${entryId}" was not found!`);
|
|
1076
|
-
}
|
|
1077
|
-
(0, _ownership.checkOwnership)(context, permission, storageEntry);
|
|
1078
|
-
const entry = await (0, _entryStorage.entryFromStorageTransform)(context, model, storageEntry);
|
|
1079
|
-
return await deleteEntry({
|
|
1080
|
-
model,
|
|
1081
|
-
entry
|
|
1195
|
+
async deleteEntry(model, entryId) {
|
|
1196
|
+
return context.benchmark.measure("headlessCms.crud.entries.deleteEntry", async () => {
|
|
1197
|
+
return deleteEntry(model, entryId);
|
|
1082
1198
|
});
|
|
1083
1199
|
},
|
|
1084
|
-
async publishEntry(
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
});
|
|
1088
|
-
await (0, _access.checkModelAccess)(context, initialModel);
|
|
1089
|
-
const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
|
|
1090
|
-
model: initialModel,
|
|
1091
|
-
plugins
|
|
1092
|
-
});
|
|
1093
|
-
const originalStorageEntry = await storageOperations.entries.getRevisionById(model, {
|
|
1094
|
-
id
|
|
1095
|
-
});
|
|
1096
|
-
if (!originalStorageEntry) {
|
|
1097
|
-
throw new _handlerGraphql.NotFoundError(`Entry "${id}" in the model "${model.modelId}" was not found.`);
|
|
1098
|
-
}
|
|
1099
|
-
(0, _ownership.checkOwnership)(context, permission, originalStorageEntry);
|
|
1100
|
-
const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
|
|
1101
|
-
const currentDate = new Date().toISOString();
|
|
1102
|
-
const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
|
|
1103
|
-
status: STATUS_PUBLISHED,
|
|
1104
|
-
locked: true,
|
|
1105
|
-
savedOn: currentDate,
|
|
1106
|
-
publishedOn: currentDate
|
|
1200
|
+
async publishEntry(model, id) {
|
|
1201
|
+
return context.benchmark.measure("headlessCms.crud.entries.publishEntry", async () => {
|
|
1202
|
+
return publishEntry(model, id);
|
|
1107
1203
|
});
|
|
1108
|
-
let storageEntry = null;
|
|
1109
|
-
try {
|
|
1110
|
-
await onEntryBeforePublish.publish({
|
|
1111
|
-
entry,
|
|
1112
|
-
model
|
|
1113
|
-
});
|
|
1114
|
-
storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
|
|
1115
|
-
const result = await storageOperations.entries.publish(model, {
|
|
1116
|
-
entry,
|
|
1117
|
-
storageEntry
|
|
1118
|
-
});
|
|
1119
|
-
await onEntryAfterPublish.publish({
|
|
1120
|
-
entry,
|
|
1121
|
-
storageEntry: result,
|
|
1122
|
-
model
|
|
1123
|
-
});
|
|
1124
|
-
return result;
|
|
1125
|
-
} catch (ex) {
|
|
1126
|
-
await onEntryPublishError.publish({
|
|
1127
|
-
entry,
|
|
1128
|
-
model,
|
|
1129
|
-
error: ex
|
|
1130
|
-
});
|
|
1131
|
-
throw new _error.default(ex.message || "Could not publish entry.", ex.code || "PUBLISH_ERROR", {
|
|
1132
|
-
error: ex,
|
|
1133
|
-
entry,
|
|
1134
|
-
storageEntry,
|
|
1135
|
-
originalEntry,
|
|
1136
|
-
originalStorageEntry
|
|
1137
|
-
});
|
|
1138
|
-
}
|
|
1139
1204
|
},
|
|
1140
|
-
async unpublishEntry(
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
});
|
|
1144
|
-
const model = (0, _valueKeyStorageConverter.attachCmsModelFieldConverters)({
|
|
1145
|
-
model: initialModel,
|
|
1146
|
-
plugins
|
|
1147
|
-
});
|
|
1148
|
-
const {
|
|
1149
|
-
id: entryId
|
|
1150
|
-
} = (0, _utils.parseIdentifier)(id);
|
|
1151
|
-
const originalStorageEntry = await storageOperations.entries.getPublishedRevisionByEntryId(model, {
|
|
1152
|
-
id: entryId
|
|
1205
|
+
async unpublishEntry(model, id) {
|
|
1206
|
+
return context.benchmark.measure("headlessCms.crud.entries.unpublishEntry", async () => {
|
|
1207
|
+
return unpublishEntry(model, id);
|
|
1153
1208
|
});
|
|
1154
|
-
if (!originalStorageEntry) {
|
|
1155
|
-
throw new _handlerGraphql.NotFoundError(`Entry "${id}" of model "${model.modelId}" was not found.`);
|
|
1156
|
-
}
|
|
1157
|
-
if (originalStorageEntry.id !== id) {
|
|
1158
|
-
throw new _error.default(`Entry is not published.`, "UNPUBLISH_ERROR", {
|
|
1159
|
-
entry: originalStorageEntry
|
|
1160
|
-
});
|
|
1161
|
-
}
|
|
1162
|
-
(0, _ownership.checkOwnership)(context, permission, originalStorageEntry);
|
|
1163
|
-
const originalEntry = await (0, _entryStorage.entryFromStorageTransform)(context, model, originalStorageEntry);
|
|
1164
|
-
const entry = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, originalEntry), {}, {
|
|
1165
|
-
status: STATUS_UNPUBLISHED
|
|
1166
|
-
});
|
|
1167
|
-
let storageEntry = null;
|
|
1168
|
-
try {
|
|
1169
|
-
await onEntryBeforeUnpublish.publish({
|
|
1170
|
-
entry,
|
|
1171
|
-
model
|
|
1172
|
-
});
|
|
1173
|
-
storageEntry = await (0, _entryStorage.entryToStorageTransform)(context, model, entry);
|
|
1174
|
-
const result = await storageOperations.entries.unpublish(model, {
|
|
1175
|
-
entry,
|
|
1176
|
-
storageEntry
|
|
1177
|
-
});
|
|
1178
|
-
await onEntryAfterUnpublish.publish({
|
|
1179
|
-
entry,
|
|
1180
|
-
storageEntry: result,
|
|
1181
|
-
model
|
|
1182
|
-
});
|
|
1183
|
-
return result;
|
|
1184
|
-
} catch (ex) {
|
|
1185
|
-
await onEntryUnpublishError.publish({
|
|
1186
|
-
entry,
|
|
1187
|
-
model,
|
|
1188
|
-
error: ex
|
|
1189
|
-
});
|
|
1190
|
-
throw new _error.default(ex.message || "Could not unpublish entry.", ex.code || "UNPUBLISH_ERROR", {
|
|
1191
|
-
originalEntry,
|
|
1192
|
-
originalStorageEntry,
|
|
1193
|
-
entry,
|
|
1194
|
-
storageEntry
|
|
1195
|
-
});
|
|
1196
|
-
}
|
|
1197
1209
|
}
|
|
1198
1210
|
};
|
|
1199
1211
|
};
|