feat: progress to revision restore
This commit is contained in:
@@ -19,18 +19,18 @@ const Restore: React.FC<Props> = ({ collection, global, className, revisionID, o
|
||||
const [processing, setProcessing] = useState(false);
|
||||
|
||||
let fetchURL = `${serverURL}${api}`;
|
||||
let redirectURL = `${serverURL}${admin}`;
|
||||
let redirectURL: string;
|
||||
let restoreMessage: string;
|
||||
|
||||
if (collection) {
|
||||
fetchURL += `/${collection.slug}/revisions/${revisionID}`;
|
||||
redirectURL += `/collections/${collection.slug}/${originalDocID}`;
|
||||
fetchURL = `${fetchURL}/${collection.slug}/revisions/${revisionID}`;
|
||||
redirectURL = `${admin}/collections/${collection.slug}/${originalDocID}`;
|
||||
restoreMessage = `You are about to restore this ${collection.labels.singular} document to the state that it was in on ${revisionDate}.`;
|
||||
}
|
||||
|
||||
if (global) {
|
||||
fetchURL += `/globals/${global.slug}/revisions/${revisionID}`;
|
||||
redirectURL += `/globals/${global.slug}`;
|
||||
fetchURL = `${fetchURL}/globals/${global.slug}/revisions/${revisionID}`;
|
||||
redirectURL = `${admin}/globals/${global.slug}`;
|
||||
restoreMessage = `You are about to restore the global ${global.label} to the state that it was in on ${revisionDate}.`;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
import httpStatus from 'http-status';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
import { Collection } from '../config/types';
|
||||
import { APIError } from '../../errors';
|
||||
import { TypeWithRevision } from '../../revisions/types';
|
||||
import { APIError, Forbidden, NotFound } from '../../errors';
|
||||
import executeAccess from '../../auth/executeAccess';
|
||||
import { Payload } from '../../index';
|
||||
import { hasWhereAccessResult } from '../../auth/types';
|
||||
import { Where } from '../../types';
|
||||
import { TypeWithID } from '../../globals/config/types';
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
|
||||
|
||||
export type Arguments = {
|
||||
collection: Collection
|
||||
@@ -17,11 +21,20 @@ export type Arguments = {
|
||||
depth?: number
|
||||
}
|
||||
|
||||
async function restoreRevision<T extends TypeWithRevision<T> = any>(this: Payload, args: Arguments): Promise<T> {
|
||||
async function restoreRevision<T extends TypeWithID = any>(this: Payload, args: Arguments): Promise<T> {
|
||||
const {
|
||||
collection,
|
||||
collection: {
|
||||
Model,
|
||||
config: collectionConfig,
|
||||
},
|
||||
id,
|
||||
// overrideAccess = false,
|
||||
overrideAccess = false,
|
||||
showHiddenFields,
|
||||
depth,
|
||||
req: {
|
||||
locale,
|
||||
},
|
||||
req,
|
||||
} = args;
|
||||
|
||||
if (!id) {
|
||||
@@ -29,22 +42,133 @@ async function restoreRevision<T extends TypeWithRevision<T> = any>(this: Payloa
|
||||
}
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Retrieve revision
|
||||
// Retrieve original raw revision to get parent ID
|
||||
// /////////////////////////////////////
|
||||
|
||||
const revision = await this.findRevisionByID({
|
||||
...args,
|
||||
collection: collection.config.slug,
|
||||
const RevisionModel = this.revisions[collectionConfig.slug];
|
||||
|
||||
let rawRevision = await RevisionModel.findOne({
|
||||
_id: id,
|
||||
});
|
||||
|
||||
const result = await this.update({
|
||||
...args,
|
||||
id: revision.parent,
|
||||
collection: collection.config.slug,
|
||||
data: revision.revision,
|
||||
locale: args.req.locale,
|
||||
if (!rawRevision) {
|
||||
throw new NotFound();
|
||||
}
|
||||
|
||||
rawRevision = rawRevision.toJSON({ virtuals: true });
|
||||
|
||||
const parentDocID = rawRevision.parent;
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Access
|
||||
// /////////////////////////////////////
|
||||
|
||||
const accessResults = !overrideAccess ? await executeAccess({ req, id: parentDocID }, collectionConfig.access.update) : true;
|
||||
const hasWherePolicy = hasWhereAccessResult(accessResults);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Retrieve document
|
||||
// /////////////////////////////////////
|
||||
|
||||
const queryToBuild: { where: Where } = {
|
||||
where: {
|
||||
and: [
|
||||
{
|
||||
id: {
|
||||
equals: parentDocID,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
if (hasWhereAccessResult(accessResults)) {
|
||||
(queryToBuild.where.and as Where[]).push(accessResults);
|
||||
}
|
||||
|
||||
const query = await Model.buildQuery(queryToBuild, locale);
|
||||
|
||||
const doc = await Model.findOne(query);
|
||||
|
||||
if (!doc && !hasWherePolicy) throw new NotFound();
|
||||
if (!doc && hasWherePolicy) throw new Forbidden();
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Update
|
||||
// /////////////////////////////////////
|
||||
|
||||
let result = await Model.findByIdAndUpdate(
|
||||
{ _id: parentDocID },
|
||||
rawRevision.revision,
|
||||
{ new: true },
|
||||
);
|
||||
|
||||
result = result.toJSON({ virtuals: true });
|
||||
|
||||
// custom id type reset
|
||||
result.id = result._id;
|
||||
result = JSON.stringify(result);
|
||||
result = JSON.parse(result);
|
||||
result = sanitizeInternalFields(result);
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
result = await this.performFieldOperations(collectionConfig, {
|
||||
id: parentDocID,
|
||||
depth,
|
||||
req,
|
||||
data: result,
|
||||
hook: 'afterRead',
|
||||
operation: 'update',
|
||||
overrideAccess,
|
||||
flattenLocales: true,
|
||||
showHiddenFields,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterRead - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({
|
||||
req,
|
||||
doc: result,
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterChange - Fields
|
||||
// /////////////////////////////////////
|
||||
|
||||
result = await this.performFieldOperations(collectionConfig, {
|
||||
data: result,
|
||||
hook: 'afterChange',
|
||||
operation: 'update',
|
||||
req,
|
||||
id: parentDocID,
|
||||
depth,
|
||||
overrideAccess,
|
||||
showHiddenFields,
|
||||
});
|
||||
|
||||
// /////////////////////////////////////
|
||||
// afterChange - Collection
|
||||
// /////////////////////////////////////
|
||||
|
||||
await collectionConfig.hooks.afterChange.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
result = await hook({
|
||||
doc: result,
|
||||
req,
|
||||
operation: 'update',
|
||||
}) || result;
|
||||
}, Promise.resolve());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user