WiP on permissions
Doesn't run. This commit is just to backup the changes.
This commit is contained in:
parent
5df444f641
commit
89c9615592
37 changed files with 913 additions and 366 deletions
|
@ -1,36 +1,64 @@
|
|||
'use strict';
|
||||
|
||||
const knex = require('../lib/knex');
|
||||
const permissions = require('../lib/permissions');
|
||||
|
||||
async function ajaxList(params, queryFun, columns) {
|
||||
async function ajaxList(params, queryFun, columns, mapFun) {
|
||||
return await knex.transaction(async (tx) => {
|
||||
const query = queryFun(tx);
|
||||
const columnsNames = [];
|
||||
const columnsSelect = [];
|
||||
|
||||
for (const col of columns) {
|
||||
if (typeof col === 'string') {
|
||||
columnsNames.push(col);
|
||||
columnsSelect.push(col);
|
||||
} else {
|
||||
columnsNames.push(col.name);
|
||||
|
||||
if (col.raw) {
|
||||
columnsSelect.push(tx.raw(col.raw));
|
||||
} else if (col.query) {
|
||||
columnsSelect.push(function () { return col.query(this); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (params.operation === 'getBy') {
|
||||
query.whereIn(columns[parseInt(params.column)], params.values);
|
||||
query.select(columns);
|
||||
const query = queryFun(tx);
|
||||
query.whereIn(columnsNames[parseInt(params.column)], params.values);
|
||||
query.select(columnsSelect);
|
||||
|
||||
const rows = await query;
|
||||
const rowsOfArray = rows.map(row => Object.keys(row).map(key => row[key]));
|
||||
return rowsOfArray;
|
||||
|
||||
} else {
|
||||
const recordsTotalQuery = query.clone().count('* as recordsTotal').first();
|
||||
const recordsTotal = (await recordsTotalQuery).recordsTotal;
|
||||
|
||||
query.where(function() {
|
||||
const whereFun = function() {
|
||||
let searchVal = '%' + params.search.value.replace(/\\/g, '\\\\').replace(/([%_])/g, '\\$1') + '%';
|
||||
for (let colIdx = 0; colIdx < params.columns.length; colIdx++) {
|
||||
const col = params.columns[colIdx];
|
||||
if (col.searchable) {
|
||||
this.orWhere(columns[parseInt(col.data)], 'like', searchVal);
|
||||
this.orWhere(columnsNames[parseInt(col.data)], 'like', searchVal);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const recordsFilteredQuery = query.clone().count('* as recordsFiltered').first();
|
||||
/* There are a few SQL peculiarities that make this query a bit weird:
|
||||
- Group by (which is used in getting permissions) don't go well with count(*). Thus we run the actual query
|
||||
as a sub-query and then count the number of results.
|
||||
- SQL does not like if it have columns with the same name in the subquery. This happens multiple tables are joined.
|
||||
To circumvent this, we select only the first column (whatever it is). Since this is not "distinct", it is supposed
|
||||
to give us the right number of rows anyway.
|
||||
*/
|
||||
const recordsTotalQuery = tx.count('* as recordsTotal').from(function () { return queryFun(this).select(columnsSelect[0]).as('records'); }).first();
|
||||
const recordsTotal = (await recordsTotalQuery).recordsTotal;
|
||||
|
||||
const recordsFilteredQuery = tx.count('* as recordsFiltered').from(function () { return queryFun(this).select(columnsSelect[0]).where(whereFun).as('records'); }).first();
|
||||
const recordsFiltered = (await recordsFilteredQuery).recordsFiltered;
|
||||
|
||||
const query = queryFun(tx);
|
||||
query.where(whereFun);
|
||||
|
||||
query.offset(parseInt(params.start));
|
||||
|
||||
const limit = parseInt(params.length);
|
||||
|
@ -38,16 +66,25 @@ async function ajaxList(params, queryFun, columns) {
|
|||
query.limit(limit);
|
||||
}
|
||||
|
||||
query.select(columns);
|
||||
query.select(columnsSelect);
|
||||
|
||||
for (const order of params.order) {
|
||||
query.orderBy(columns[params.columns[order.column].data], order.dir);
|
||||
query.orderBy(columnsNames[params.columns[order.column].data], order.dir);
|
||||
}
|
||||
|
||||
query.options({rowsAsArray:true});
|
||||
|
||||
const rows = await query;
|
||||
const rowsOfArray = rows.map(row => Object.keys(row).map(field => row[field]));
|
||||
const rowsOfArray = rows.map(row => {
|
||||
const arr = Object.keys(row).map(field => row[field]);
|
||||
|
||||
if (mapFun) {
|
||||
const result = mapFun(arr);
|
||||
return result || arr;
|
||||
} else {
|
||||
return arr;
|
||||
}
|
||||
});
|
||||
|
||||
const result = {
|
||||
draw: params.draw,
|
||||
|
@ -61,6 +98,51 @@ async function ajaxList(params, queryFun, columns) {
|
|||
});
|
||||
}
|
||||
|
||||
async function ajaxListWithPermissions(context, fetchSpecs, params, queryFun, columns) {
|
||||
const permCols = [];
|
||||
for (const fetchSpec of fetchSpecs) {
|
||||
const entityType = permissions.getEntityType(fetchSpec.entityTypeId);
|
||||
permCols.push({
|
||||
name: `permissions_${fetchSpec.entityTypeId}`,
|
||||
query: builder => builder
|
||||
.from(entityType.permissionsTable)
|
||||
.select(knex.raw('GROUP_CONCAT(operation SEPARATOR \';\')'))
|
||||
.whereRaw(`${entityType.permissionsTable}.entity = ${entityType.entitiesTable}.id`)
|
||||
.where(`${entityType.permissionsTable}.user`, context.user.id)
|
||||
.as(`permissions_${fetchSpec.entityTypeId}`)
|
||||
});
|
||||
}
|
||||
|
||||
return await ajaxList(
|
||||
params,
|
||||
builder => {
|
||||
let query = queryFun(builder);
|
||||
|
||||
for (const fetchSpec of fetchSpecs) {
|
||||
const entityType = permissions.getEntityType(fetchSpec.entityTypeId);
|
||||
|
||||
query = query.innerJoin(
|
||||
function () {
|
||||
return this.from(entityType.permissionsTable).select('entity').where('user', context.user.id).whereIn('operation', fetchSpec.requiredOperations).as(`permitted__${fetchSpec.entityTypeId}`);
|
||||
},
|
||||
`permitted__${fetchSpec.entityTypeId}.entity`, `${entityType.entitiesTable}.id`)
|
||||
}
|
||||
|
||||
return query;
|
||||
},
|
||||
[
|
||||
...columns,
|
||||
...permCols
|
||||
],
|
||||
data => {
|
||||
for (let idx = 0; idx < fetchSpecs.length; idx++) {
|
||||
data[columns.length + idx] = data[columns.length + idx].split(';');
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ajaxList
|
||||
ajaxList,
|
||||
ajaxListWithPermissions
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue