Start on sort endpoint

This commit is contained in:
rijkvanzanten
2020-08-21 11:29:49 -06:00
parent 53a951fb65
commit a7e0ebfc11
2 changed files with 85 additions and 0 deletions

View File

@@ -3,6 +3,9 @@ import asyncHandler from 'express-async-handler';
import { nanoid } from 'nanoid';
import { InvalidQueryException, InvalidPayloadException } from '../exceptions';
import argon2 from 'argon2';
import collectionExists from '../middleware/collection-exists';
import UtilsService from '../services/utils';
import Joi from 'joi';
const router = Router();
@@ -48,4 +51,23 @@ router.post(
})
);
const SortSchema = Joi.object({
item: Joi.alternatives(Joi.string(), Joi.number()).required(),
to: Joi.alternatives(Joi.string(), Joi.number()).required(),
});
router.post(
'/sort/:collection',
collectionExists,
asyncHandler(async (req, res) => {
const { error } = SortSchema.validate(req.body);
if (error) throw new InvalidPayloadException(error.message);
const service = new UtilsService({ accountability: req.accountability });
await service.sort(req.collection, req.body);
return res.status(200).end();
})
)
export default router;

63
api/src/services/utils.ts Normal file
View File

@@ -0,0 +1,63 @@
import { AbstractServiceOptions, Accountability, PrimaryKey } from "../types";
import database from '../database';
import Knex from 'knex';
import { InvalidPayloadException, ForbiddenException } from '../exceptions';
import SchemaInspector from 'knex-schema-inspector';
export default class UtilsService {
knex: Knex;
accountability: Accountability | null;
constructor(options?: AbstractServiceOptions) {
this.knex = options?.knex || database;
this.accountability = options?.accountability || null;
}
async sort(collection: string, { from, to }: { from: PrimaryKey, to: PrimaryKey }) {
const schemaInspector = SchemaInspector(this.knex);
const sortFieldResponse = await this.knex
.select('sort_field')
.from('directus_collections')
.where({ collection })
.first();
const sortField = sortFieldResponse?.sort_field;
if (!sortField) {
throw new InvalidPayloadException(`Collection "${collection}" doesn't have a sort field.`);
}
if (this.accountability?.admin !== true) {
const permissions = await this.knex.select('fields').from('directus_permissions').where({ role: this.accountability?.role || null, collection }).first();
if (!permissions) {
throw new ForbiddenException();
}
const allowedFields = permissions.fields.split(',');
if (allowedFields[0] !== '*' && allowedFields.includes(sortField) === false) {
throw new ForbiddenException();
}
}
const primaryKeyField = await schemaInspector.primary(collection);
// Make sure all rows have a sort value
const countResponse = await this.knex.count('*').from(collection).whereNull(sortField).first();
if (countResponse?.count && +countResponse.count !== 0) {
const lastSortValueResponse = await this.knex.max(sortField).from(collection).first();
const rowsWithoutSortValue = await this.knex.select(primaryKeyField, sortField).from(collection).whereNull(sortField).orderBy(primaryKeyField);
let lastSortValue = lastSortValueResponse!.max;
for (const row of rowsWithoutSortValue) {
lastSortValue++;
await this.knex(collection).update({ [sortField]: lastSortValue }).where({ [primaryKeyField]: row[primaryKeyField] });
}
}
}
}