mirror of
https://github.com/directus/directus.git
synced 2026-01-30 08:47:57 -05:00
Add item singleton support
This commit is contained in:
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* Check if you're allowed to add an additional item when POSTing to a singleton
|
||||
*/
|
||||
|
||||
import { RequestHandler } from 'express';
|
||||
import asyncHandler from 'express-async-handler';
|
||||
import database from '../database';
|
||||
import { ItemLimitException } from '../exceptions';
|
||||
|
||||
const validateCollection: RequestHandler = asyncHandler(async (req, res, next) => {
|
||||
if (!req.collection) return next();
|
||||
|
||||
const collectionInfo = await database
|
||||
.select('single')
|
||||
.from('directus_collections')
|
||||
.where({ collection: req.collection })
|
||||
.first();
|
||||
|
||||
if (!collectionInfo) return next();
|
||||
|
||||
if (collectionInfo.single === false) return next();
|
||||
|
||||
const { count } = await database.count('*').as('count').from(req.collection).first();
|
||||
|
||||
if (Number(count) === 0) return next();
|
||||
|
||||
throw new ItemLimitException(
|
||||
`You can only create a single item in singleton "${req.collection}"`
|
||||
);
|
||||
});
|
||||
|
||||
export default validateCollection;
|
||||
@@ -3,19 +3,22 @@ import asyncHandler from 'express-async-handler';
|
||||
import * as ItemsService from '../services/items';
|
||||
import sanitizeQuery from '../middleware/sanitize-query';
|
||||
import validateCollection from '../middleware/validate-collection';
|
||||
import validateSingleton from '../middleware/validate-singleton';
|
||||
import validateQuery from '../middleware/validate-query';
|
||||
import * as MetaService from '../services/meta';
|
||||
import { RouteNotFoundException } from '../exceptions';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.post(
|
||||
'/:collection',
|
||||
validateCollection,
|
||||
validateSingleton,
|
||||
sanitizeQuery,
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
if (req.single) {
|
||||
throw new RouteNotFoundException(req.path);
|
||||
}
|
||||
|
||||
const primaryKey = await ItemsService.createItem(req.collection, req.body, {
|
||||
ip: req.ip,
|
||||
userAgent: req.get('user-agent'),
|
||||
@@ -35,7 +38,9 @@ router.get(
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
const [records, meta] = await Promise.all([
|
||||
ItemsService.readItems(req.collection, req.sanitizedQuery),
|
||||
req.single
|
||||
? ItemsService.readSingleton(req.collection, req.sanitizedQuery)
|
||||
: ItemsService.readItems(req.collection, req.sanitizedQuery),
|
||||
MetaService.getMetaForQuery(req.collection, req.sanitizedQuery),
|
||||
]);
|
||||
|
||||
@@ -52,6 +57,10 @@ router.get(
|
||||
sanitizeQuery,
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
if (req.single) {
|
||||
throw new RouteNotFoundException(req.path);
|
||||
}
|
||||
|
||||
const record = await ItemsService.readItem(
|
||||
req.collection,
|
||||
req.params.pk,
|
||||
@@ -64,12 +73,38 @@ router.get(
|
||||
})
|
||||
);
|
||||
|
||||
router.patch(
|
||||
'/:collection',
|
||||
validateCollection,
|
||||
sanitizeQuery,
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
if (req.single === false) {
|
||||
throw new RouteNotFoundException(req.path);
|
||||
}
|
||||
|
||||
await ItemsService.upsertSingleton(req.collection, req.body, {
|
||||
ip: req.ip,
|
||||
userAgent: req.get('user-agent'),
|
||||
user: req.user,
|
||||
});
|
||||
|
||||
const item = await ItemsService.readSingleton(req.collection, req.sanitizedQuery);
|
||||
|
||||
return res.json({ data: item || null });
|
||||
})
|
||||
);
|
||||
|
||||
router.patch(
|
||||
'/:collection/:pk',
|
||||
validateCollection,
|
||||
sanitizeQuery,
|
||||
validateQuery,
|
||||
asyncHandler(async (req, res) => {
|
||||
if (req.single) {
|
||||
throw new RouteNotFoundException(req.path);
|
||||
}
|
||||
|
||||
const primaryKey = await ItemsService.updateItem(req.collection, req.params.pk, req.body, {
|
||||
ip: req.ip,
|
||||
userAgent: req.get('user-agent'),
|
||||
|
||||
@@ -173,3 +173,36 @@ export const deleteItem = async (
|
||||
.delete()
|
||||
.where({ [primaryKeyField]: pk });
|
||||
};
|
||||
|
||||
export const readSingleton = async (collection: string, query: Query = {}) => {
|
||||
const records = await readItems(collection, { ...query, limit: 1 });
|
||||
const record = records[0];
|
||||
|
||||
if (!record) {
|
||||
const columns = await schemaInspector.columnInfo(collection);
|
||||
const defaults = {};
|
||||
|
||||
for (const column of columns) {
|
||||
defaults[column.name] = column.default_value;
|
||||
}
|
||||
|
||||
return defaults;
|
||||
}
|
||||
|
||||
return record;
|
||||
};
|
||||
|
||||
export const upsertSingleton = async (
|
||||
collection: string,
|
||||
data: Record<string, any>,
|
||||
accountability: Accountability
|
||||
) => {
|
||||
const primaryKeyField = await schemaInspector.primary(collection);
|
||||
const record = await database.select(primaryKeyField).from(collection).limit(1).first();
|
||||
|
||||
if (record) {
|
||||
return await updateItem(collection, record.id, data, accountability);
|
||||
}
|
||||
|
||||
return await createItem(collection, data, accountability);
|
||||
};
|
||||
|
||||
@@ -1,36 +1,11 @@
|
||||
import { Query } from '../types/query';
|
||||
import * as ItemsService from './items';
|
||||
import { Accountability } from '../types';
|
||||
import database, { schemaInspector } from '../database';
|
||||
|
||||
export const readSettings = async (query: Query) => {
|
||||
const settings = await ItemsService.readItems('directus_settings', {
|
||||
...query,
|
||||
limit: 1,
|
||||
});
|
||||
|
||||
const settingsObj = settings[0];
|
||||
|
||||
if (!settingsObj) {
|
||||
const settingsColumns = await schemaInspector.columnInfo('directus_settings');
|
||||
const defaults = {};
|
||||
|
||||
for (const column of settingsColumns) {
|
||||
defaults[column.name] = column.default_value;
|
||||
}
|
||||
|
||||
return defaults;
|
||||
}
|
||||
|
||||
return settingsObj;
|
||||
return await ItemsService.readSingleton('directus_settings', query);
|
||||
};
|
||||
|
||||
export const updateSettings = async (data: Record<string, any>, accountability: Accountability) => {
|
||||
const record = await database.select('id').from('directus_settings').limit(1).first();
|
||||
|
||||
if (record) {
|
||||
return await ItemsService.updateItem('directus_settings', record.id, data, accountability);
|
||||
}
|
||||
|
||||
return await ItemsService.createItem('directus_settings', data, accountability);
|
||||
return await ItemsService.upsertSingleton('directus_settings', data, accountability);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user