feat: progress to revision restore

This commit is contained in:
James
2021-12-22 16:25:19 -05:00
parent 189bc21e48
commit 210488ba4e
2 changed files with 144 additions and 20 deletions

View File

@@ -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}.`;
}

View File

@@ -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;
}