diff options
Diffstat (limited to 'src/app/db/service/base/methods.js')
| -rw-r--r-- | src/app/db/service/base/methods.js | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/src/app/db/service/base/methods.js b/src/app/db/service/base/methods.js new file mode 100644 index 0000000..be84d0c --- /dev/null +++ b/src/app/db/service/base/methods.js @@ -0,0 +1,217 @@ +/** + * Service API methods + * @module app/db/service/base/methods + */ + +import * as db from "app/db/query"; +import { reduceValidColumns } from "app/db/helpers"; +import { PERMISSIONS } from "app/constants"; +import debugModule from "debug"; + +/** + * Export methods for dealing with multiple records + */ +export { showMany, updateMany, destroyMany } from "app/db/service/base/many"; + +/** + * Debug logger + */ +const debug = debugModule("shoebox:service"); + +/** + * API to filter and paginate lists of resources + */ +export function index(service) { + const { columns } = service; + return async function indexMiddleware(request, response, next) { + const { query: userQuery, params, permission, user } = request; + const { paginate } = service.options; + const queryBuilder = service.queryBuilder; + const query = { + ...userQuery, + ...params, + }; + const withRelated = userQuery.related ? userQuery.related.split(",") : []; + if (permission === PERMISSIONS.ALLOW_FOR_OWNER) { + query.user_id = user.user_id; + } + let data, pagination; + let promises = [ + db.index({ + Model: service.Model, + query, + paginate, + user, + columns, + queryBuilder, + withRelated, + }), + ]; + if (paginate) { + promises.push( + db.count({ + Model: service.Model, + query, + paginate, + user, + columns, + queryBuilder, + }) + ); + } else { + promises.push(new Promise((resolve) => resolve({}))); + } + try { + [data, pagination] = await Promise.all(promises); + } catch (error) { + debug(`${service.resource} Index error`); + debug(error); + console.error(error); + return next(error); + } + response.locals = { + data, + pagination, + query, + }; + next(); + }; +} + +/** + * API to query for a single record by ID + */ +export function show(service) { + return async function showMiddleware(request, response, next) { + const { user, permission, query } = request; + const withRelated = query.related ? query.related.split(",") : []; + let data; + try { + data = await db.show({ + Model: service.Model, + objectID: parseInt(request.params.id), + withRelated, + }); + } catch (error) { + debug(`${service.resource} Show error`); + debug(error); + return next(error); + } + if (!data) { + response.locals = {}; + next(); + } else if ( + permission === PERMISSIONS.ALLOW_FOR_OWNER && + data.get("user_id") !== user.user_id + ) { + next(new Error("PermissionsError")); + } else { + response.locals = { data }; + next(); + } + }; +} + +/** + * API to insert a new record + */ +export function create(service) { + return async function createMiddleware(request, response, next) { + const body = reduceValidColumns( + request.body, + service.columns, + service.options.privateFields + ); + if (service.options.parent) { + service.idAttributes.forEach((idAttribute) => { + if (idAttribute in request.params && idAttribute in service.columns) { + body[idAttribute] = request.params[idAttribute]; + } + }); + } + let data; + try { + data = await db.create({ Model: service.Model, data: body }); + } catch (error) { + debug(`${service.resource} create error`); + console.error(error); + return next(error); + } + response.locals = { data }; + next(); + }; +} + +/** + * API to update a single record + */ +export function update(service) { + return async function updateMiddleware(request, response, next) { + const { data: instance } = response.locals; + const { user, permission } = request; + if ( + permission === PERMISSIONS.ALLOW_FOR_OWNER && + instance.get("user_id") !== user.user_id + ) { + return next(new Error("PermissionsError")); + } + const body = reduceValidColumns( + request.body, + service.columns, + service.options.privateFields + ); + let data; + try { + data = await db.update({ + instance, + data: body, + }); + } catch (error) { + debug(`${service.resource} update error`); + debug(error); + next(new Error(error)); + } + response.locals = { data }; + next(); + }; +} + +/** + * API to sort records + */ +export function sort(service) { + return async function sortMiddleware(request, response, next) { + const { ids } = request.body; + const items = await db.showIDs({ + Model: service.Model, + ids, + }); + for (let item of items) { + item.set("sort_order", ids.indexOf(item.id)); + } + await Promise.all(items.map((item) => item.save())); + response.locals.success = true; + next(); + }; +} + +/** + * API to destroy a single record + */ +export function destroy(service) { + return async function destroyMiddleware(request, response, next) { + try { + await db.destroy({ + Model: service.Model, + objectID: request.params.id, + }); + } catch (error) { + debug(`${service.resource} destroy error`); + console.error(error); + return next(new Error(error)); + } + response.locals.success = true; + response.locals.id = request.params.id; + next(); + }; +} |
