Files
directus/api/src/services/utils.ts
Rijk van Zanten b7d87e581a System permissions for app access (#4004)
* Pass relations through schema, instead of individual reads

* Fetch field transforms upfront

* Fix length check

* List if user has app access or not in accountability

* Load permissions up front, merge app access minimal permissions

* Show app access required permissions in permissions overview

* Show system minimal permissions in permissions detail

* Fix app access check in authenticate for jwt use

* Fix minimal permissions for presets

* Remove /permissions/me in favor of root use w/ permissions

* Fix logical nested OR in an AND

* Use root permissions endpoint with filter instead of /me

* Allow filter query on /permissions

* Add system minimal app access permissions into result of /permissions

* Remove stray console log

* Remove stray console.dir

* Set current role as role for minimal permissions

* Fix no-permissions state for user detail

* Add filter items function that allows altering existing result set
2021-02-11 12:50:56 -05:00

102 lines
3.2 KiB
TypeScript

import { AbstractServiceOptions, Accountability, PrimaryKey, SchemaOverview } from '../types';
import database from '../database';
import Knex from 'knex';
import { InvalidPayloadException, ForbiddenException } from '../exceptions';
import { systemCollectionRows } from '../database/system-data/collections';
export class UtilsService {
knex: Knex;
accountability: Accountability | null;
schema: SchemaOverview;
constructor(options: AbstractServiceOptions) {
this.knex = options.knex || database;
this.accountability = options.accountability || null;
this.schema = options.schema;
}
async sort(collection: string, { item, to }: { item: PrimaryKey; to: PrimaryKey }) {
const sortFieldResponse =
(await this.knex.select('sort_field').from('directus_collections').where({ collection }).first()) ||
systemCollectionRows;
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 = this.schema.permissions.find((permission) => {
return permission.collection === collection && permission.action === 'update';
});
if (!permissions) {
throw new ForbiddenException();
}
const allowedFields = permissions.fields ?? [];
if (allowedFields[0] !== '*' && allowedFields.includes(sortField) === false) {
throw new ForbiddenException();
}
}
const primaryKeyField = this.schema.tables[collection].primary;
// Make sure all rows have a sort value
const countResponse = await this.knex.count('* as 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);
let lastSortValue = lastSortValueResponse ? Object.values(lastSortValueResponse)[0] : 0;
for (const row of rowsWithoutSortValue) {
lastSortValue++;
await this.knex(collection)
.update({ [sortField]: lastSortValue })
.where({ [primaryKeyField]: row[primaryKeyField] });
}
}
const targetSortValueResponse = await this.knex
.select(sortField)
.from(collection)
.where({ [primaryKeyField]: to })
.first();
const targetSortValue = targetSortValueResponse[sortField];
const sourceSortValueResponse = await this.knex
.select(sortField)
.from(collection)
.where({ [primaryKeyField]: item })
.first();
const sourceSortValue = sourceSortValueResponse[sortField];
// Set the target item to the new sort value
await this.knex(collection)
.update({ [sortField]: targetSortValue })
.where({ [primaryKeyField]: item });
if (sourceSortValue < targetSortValue) {
await this.knex(collection)
.decrement(sortField, 1)
.where(sortField, '>', sourceSortValue)
.andWhere(sortField, '<=', targetSortValue)
.andWhereNot({ [primaryKeyField]: item });
} else {
await this.knex(collection)
.increment(sortField, 1)
.where(sortField, '>=', targetSortValue)
.andWhere(sortField, '<=', sourceSortValue)
.andWhereNot({ [primaryKeyField]: item });
}
}
}