mirror of
https://github.com/vale981/grapher
synced 2025-03-06 10:01:40 -05:00
144 lines
No EOL
4.1 KiB
JavaScript
144 lines
No EOL
4.1 KiB
JavaScript
import createGraph from '../query/lib/createGraph.js';
|
|
import recursiveCompose from '../query/lib/recursiveCompose.js';
|
|
import hypernova from '../query/hypernova/hypernova.js';
|
|
import ExposureConfigSchema from './exposure.config.schema.js';
|
|
import enforceMaxDepth from './lib/enforceMaxDepth.js';
|
|
import enforceMaxLimit from './lib/enforceMaxLimit.js';
|
|
import restrictFieldsFn from './lib/restrictFields.js';
|
|
import restrictLinks from './lib/restrictLinks.js';
|
|
|
|
let globalConfig = {};
|
|
|
|
export default class Exposure {
|
|
static setConfig(config) {
|
|
ExposureConfigSchema.clean(config);
|
|
ExposureConfigSchema.validate(config);
|
|
|
|
_.extend(globalConfig, config);
|
|
}
|
|
|
|
static getConfig() {
|
|
return globalConfig;
|
|
}
|
|
|
|
static restrictFields(...args) {
|
|
return restrictFieldsFn(...args);
|
|
}
|
|
|
|
constructor(collection, config = {}) {
|
|
collection.__isExposedForGrapher = true;
|
|
collection.__exposure = this;
|
|
|
|
this.collection = collection;
|
|
this.name = `exposure_${collection._name}`;
|
|
|
|
this.config = config;
|
|
this._validateAndClean();
|
|
|
|
this.initSecurity();
|
|
|
|
if (config.publication) {
|
|
this.initPublication();
|
|
}
|
|
|
|
if (config.method) {
|
|
this.initMethod();
|
|
}
|
|
|
|
if (!config.method && !config.publication) {
|
|
throw new Meteor.Error('weird', 'If you want to expose your collection you need to specify at least one of ["method", "publication"] options to true')
|
|
}
|
|
|
|
this.initCountMethod();
|
|
}
|
|
|
|
_validateAndClean() {
|
|
if (typeof(this.config) === 'function') {
|
|
const firewall = this.config;
|
|
this.config = {firewall};
|
|
}
|
|
|
|
ExposureConfigSchema.clean(this.config);
|
|
ExposureConfigSchema.validate(this.config);
|
|
|
|
this.config = _.extend({}, Exposure.getConfig(), this.config);
|
|
}
|
|
|
|
initPublication() {
|
|
const collection = this.collection;
|
|
const config = this.config;
|
|
|
|
Meteor.publishComposite(this.name, function (body) {
|
|
const rootNode = createGraph(collection, body);
|
|
|
|
enforceMaxDepth(rootNode, config.maxDepth);
|
|
restrictLinks(rootNode, this.userId);
|
|
|
|
return recursiveCompose(rootNode, this.userId);
|
|
});
|
|
}
|
|
|
|
initMethod() {
|
|
const collection = this.collection;
|
|
const config = this.config;
|
|
|
|
Meteor.methods({
|
|
[this.name](body) {
|
|
this.unblock();
|
|
|
|
const rootNode = createGraph(collection, body);
|
|
enforceMaxDepth(rootNode, config.maxDepth);
|
|
|
|
restrictLinks(rootNode, this.userId);
|
|
|
|
return hypernova(rootNode, this.userId);
|
|
}
|
|
});
|
|
}
|
|
|
|
initCountMethod() {
|
|
const collection = this.collection;
|
|
const config = this.config;
|
|
|
|
Meteor.methods({
|
|
[this.name + '.count'](body) {
|
|
this.unblock();
|
|
|
|
return collection.find(body.$filters || {}, {}, this.userId).count();
|
|
}
|
|
})
|
|
}
|
|
|
|
initSecurity() {
|
|
const collection = this.collection;
|
|
const {firewall, maxLimit, restrictedFields} = this.config;
|
|
const find = collection.find.bind(collection);
|
|
const findOne = collection.findOne.bind(collection);
|
|
|
|
collection.firewall = (filters, options, userId) => {
|
|
if (userId !== undefined) {
|
|
if (firewall) {
|
|
firewall.call({collection: collection}, filters, options, userId);
|
|
}
|
|
|
|
enforceMaxLimit(options, maxLimit);
|
|
|
|
if (restrictedFields) {
|
|
Exposure.restrictFields(filters, options, restrictedFields);
|
|
}
|
|
}
|
|
};
|
|
|
|
collection.find = (filters = {}, options = {}, userId = undefined) => {
|
|
collection.firewall(filters, options, userId);
|
|
|
|
return find(filters, options);
|
|
};
|
|
|
|
collection.findOne = (filters = {}, options = {}, userId = undefined) => {
|
|
collection.firewall(filters, options, userId);
|
|
|
|
return findOne(filters, options);
|
|
}
|
|
}
|
|
}; |