Joey Baker 79b9fc1242 Change: permissions must always be an array
This allows us to set different configs per model. I should have thought
of this usecase when I first did permissions.
2016-07-22 11:50:08 -07:00

263 lines
6.0 KiB
JavaScript

import joi from 'joi';
import error from './error';
import _ from 'lodash';
import { parseInclude, parseWhere } from './utils';
import { notFound } from 'boom';
import * as associations from './associations/index';
const createAll = ({ server, model, prefix, config }) => {
Object.keys(methods).forEach((method) => {
methods[method]({ server, model, prefix, config });
});
};
export { associations };
/*
The `models` option, becomes `permissions`, and can look like:
```
models: ['cat', 'dog']
```
or
```
models: {
cat: ['list', 'get']
, dog: true // all
}
```
*/
export default (server, model, { prefix, defaultConfig: config, models: permissions }) => {
const modelName = model._singular;
if (!permissions) {
createAll({ server, model, prefix, config });
} else if (!Array.isArray(permissions)) {
throw new Error('hapi-sequelize-crud: `models` property must be an array');
} else if (permissions.includes(modelName)) {
createAll({ server, model, prefix, config });
} else {
const permissionOptions = permissions.filter((permission) => {
return permission.model === modelName;
});
permissionOptions.forEach((permissionOption) => {
if (_.isPlainObject(permissionOption)) {
const permissionConfig = permissionOption.config || config;
if (permissionOption.methods) {
permissionOption.methods.forEach((method) => {
methods[method]({
server,
model,
prefix,
config: permissionConfig,
});
});
} else {
createAll({ server, model, prefix, config: permissionConfig });
}
}
});
}
};
export const list = ({ server, model, prefix, config }) => {
server.route({
method: 'GET',
path: `${prefix}/${model._plural}`,
@error
async handler(request, reply) {
const include = parseInclude(request);
const where = parseWhere(request);
if (include instanceof Error) return void reply(include);
const list = await model.findAll({
where, include,
});
reply(list);
},
config,
});
};
export const get = ({ server, model, prefix, config }) => {
server.route({
method: 'GET',
path: `${prefix}/${model._singular}/{id?}`,
@error
async handler(request, reply) {
const include = parseInclude(request);
const where = parseWhere(request);
const { id } = request.params;
if (id) where[model.primaryKeyField] = id;
const instance = await model.findOne({ where, include });
if (!instance) return void reply(notFound(`${id} not found.`));
reply(instance);
},
config: _.defaultsDeep({
validate: {
params: joi.object().keys({
id: joi.any(),
}),
},
}, config),
});
};
export const scope = ({ server, model, prefix, config }) => {
const scopes = Object.keys(model.options.scopes);
server.route({
method: 'GET',
path: `${prefix}/${model._plural}/{scope}`,
@error
async handler(request, reply) {
const include = parseInclude(request);
const where = parseWhere(request);
const list = await model.scope(request.params.scope).findAll({ include, where });
reply(list);
},
config: _.defaultsDeep({
validate: {
params: joi.object().keys({
scope: joi.string().valid(...scopes),
}),
},
}, config),
});
};
export const create = ({ server, model, prefix, config }) => {
server.route({
method: 'POST',
path: `${prefix}/${model._singular}`,
@error
async handler(request, reply) {
const instance = await model.create(request.payload);
reply(instance);
},
config,
});
};
export const destroy = ({ server, model, prefix, config }) => {
server.route({
method: 'DELETE',
path: `${prefix}/${model._singular}/{id?}`,
@error
async handler(request, reply) {
const where = parseWhere(request);
if (request.params.id) where[model.primaryKeyField] = request.params.id;
const list = await model.findAll({ where });
await Promise.all(list.map(instance => instance.destroy()));
reply(list.length === 1 ? list[0] : list);
},
config,
});
};
export const destroyAll = ({ server, model, prefix, config }) => {
server.route({
method: 'DELETE',
path: `${prefix}/${model._plural}`,
@error
async handler(request, reply) {
const where = parseWhere(request);
const list = await model.findAll({ where });
await Promise.all(list.map(instance => instance.destroy()));
reply(list.length === 1 ? list[0] : list);
},
config,
});
};
export const destroyScope = ({ server, model, prefix, config }) => {
const scopes = Object.keys(model.options.scopes);
server.route({
method: 'DELETE',
path: `${prefix}/${model._plural}/{scope}`,
@error
async handler(request, reply) {
const include = parseInclude(request);
const where = parseWhere(request);
const list = await model.scope(request.params.scope).findAll({ include, where });
await Promise.all(list.map(instance => instance.destroy()));
reply(list);
},
config: _.defaultsDeep({
validate: {
params: joi.object().keys({
scope: joi.string().valid(...scopes),
}),
},
}, config),
});
};
export const update = ({ server, model, prefix, config }) => {
server.route({
method: 'PUT',
path: `${prefix}/${model._singular}/{id}`,
@error
async handler(request, reply) {
const { id } = request.params;
const instance = await model.findOne({
where: {
id,
},
});
if (!instance) return void reply(notFound(`${id} not found.`));
await instance.update(request.payload);
reply(instance);
},
config: _.defaultsDeep({
validate: {
payload: joi.object().required(),
},
}, config),
});
};
const methods = {
list, get, scope, create, destroy, destroyAll, destroyScope, update,
};