summaryrefslogtreecommitdiff
path: root/src/app/db/service/base/methods.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/db/service/base/methods.js')
-rw-r--r--src/app/db/service/base/methods.js217
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();
+ };
+}