Add delete flag in configuration (#707)

Adds a `delete` flag to collections in `config.yml`; fixes
#593. Defaults to false. This is mostly for use with files to restrict
users from deleting settings files etc that available via the CMS.
This commit is contained in:
Richard Pullinger 2017-10-30 20:07:54 +00:00 committed by Benaiah Mischenko
parent 1bb2b56366
commit a14f25355e
4 changed files with 20 additions and 3 deletions

View File

@ -27,6 +27,7 @@ collections: # A list of collections the CMS should be able to edit
- name: "settings" - name: "settings"
label: "Settings" label: "Settings"
delete: false # Prevent users from deleting documents in this collection
editor: editor:
preview: false preview: false
files: files:

View File

@ -3,7 +3,7 @@ import TestRepoBackend from "./test-repo/implementation";
import GitHubBackend from "./github/implementation"; import GitHubBackend from "./github/implementation";
import GitGatewayBackend from "./git-gateway/implementation"; import GitGatewayBackend from "./git-gateway/implementation";
import { resolveFormat } from "../formats/formats"; import { resolveFormat } from "../formats/formats";
import { selectListMethod, selectEntrySlug, selectEntryPath, selectAllowNewEntries, selectFolderEntryExtension } from "../reducers/collections"; import { selectListMethod, selectEntrySlug, selectEntryPath, selectAllowNewEntries, selectAllowDeletion, selectFolderEntryExtension } from "../reducers/collections";
import { createEntry } from "../valueObjects/Entry"; import { createEntry } from "../valueObjects/Entry";
import { sanitizeSlug } from "../lib/urlHelper"; import { sanitizeSlug } from "../lib/urlHelper";
@ -246,6 +246,11 @@ class Backend {
deleteEntry(config, collection, slug) { deleteEntry(config, collection, slug) {
const path = selectEntryPath(collection, slug); const path = selectEntryPath(collection, slug);
if (!selectAllowDeletion(collection)) {
throw (new Error("Not allowed to delete entries in this collection"));
}
const commitMessage = `Delete ${ collection.get('label') }${ slug }`; const commitMessage = `Delete ${ collection.get('label') }${ slug }`;
return this.implementation.deleteFile(path, commitMessage); return this.implementation.deleteFile(path, commitMessage);
} }

View File

@ -2,6 +2,7 @@ import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { EDITORIAL_WORKFLOW } from '../../constants/publishModes'; import { EDITORIAL_WORKFLOW } from '../../constants/publishModes';
import { selectUnpublishedEntry, selectEntry } from '../../reducers'; import { selectUnpublishedEntry, selectEntry } from '../../reducers';
import { selectAllowDeletion } from "../../reducers/collections";
import { loadUnpublishedEntry, persistUnpublishedEntry } from '../../actions/editorialWorkflow'; import { loadUnpublishedEntry, persistUnpublishedEntry } from '../../actions/editorialWorkflow';
@ -15,11 +16,14 @@ export default function EntryPageHOC(EntryPage) {
function mapStateToProps(state, ownProps) { function mapStateToProps(state, ownProps) {
const { collections } = state; const { collections } = state;
const isEditorialWorkflow = (state.config.get('publish_mode') === EDITORIAL_WORKFLOW); const isEditorialWorkflow = (state.config.get('publish_mode') === EDITORIAL_WORKFLOW);
const returnObj = { isEditorialWorkflow, showDelete: !ownProps.newEntry }; const collection = collections.get(ownProps.match.params.name);
const returnObj = {
isEditorialWorkflow,
showDelete: !ownProps.newEntry && selectAllowDeletion(collection),
};
if (isEditorialWorkflow) { if (isEditorialWorkflow) {
returnObj.showDelete = false; returnObj.showDelete = false;
const slug = ownProps.match.params.slug; const slug = ownProps.match.params.slug;
const collection = collections.get(ownProps.match.params.name);
const unpublishedEntry = selectUnpublishedEntry(state, collection.get('name'), slug); const unpublishedEntry = selectUnpublishedEntry(state, collection.get('name'), slug);
if (unpublishedEntry) { if (unpublishedEntry) {
returnObj.unpublishedEntry = true; returnObj.unpublishedEntry = true;

View File

@ -47,6 +47,9 @@ const selectors = {
allowNewEntries(collection) { allowNewEntries(collection) {
return collection.get('create'); return collection.get('create');
}, },
allowDeletion(collection) {
return collection.get('delete', true);
},
templateName(collection) { templateName(collection) {
return collection.get('name'); return collection.get('name');
}, },
@ -74,6 +77,9 @@ const selectors = {
allowNewEntries() { allowNewEntries() {
return false; return false;
}, },
allowDeletion(collection) {
return collection.get('delete', true);
},
templateName(collection, slug) { templateName(collection, slug) {
return slug; return slug;
}, },
@ -86,6 +92,7 @@ export const selectEntryPath = (collection, slug) => selectors[collection.get('t
export const selectEntrySlug = (collection, path) => selectors[collection.get('type')].entrySlug(collection, path); export const selectEntrySlug = (collection, path) => selectors[collection.get('type')].entrySlug(collection, path);
export const selectListMethod = collection => selectors[collection.get('type')].listMethod(); export const selectListMethod = collection => selectors[collection.get('type')].listMethod();
export const selectAllowNewEntries = collection => selectors[collection.get('type')].allowNewEntries(collection); export const selectAllowNewEntries = collection => selectors[collection.get('type')].allowNewEntries(collection);
export const selectAllowDeletion = collection => selectors[collection.get('type')].allowDeletion(collection);
export const selectTemplateName = (collection, slug) => selectors[collection.get('type')].templateName(collection, slug); export const selectTemplateName = (collection, slug) => selectors[collection.get('type')].templateName(collection, slug);
export const selectInferedField = (collection, fieldName) => { export const selectInferedField = (collection, fieldName) => {
const inferableField = INFERABLE_FIELDS[fieldName]; const inferableField = INFERABLE_FIELDS[fieldName];