Skip to content

Commit e84819b

Browse files
committed
0.0.5 #2
1 parent ac07ee9 commit e84819b

File tree

3 files changed

+182
-45
lines changed

3 files changed

+182
-45
lines changed

README.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ Methods and temporary storage of information about the rules of selection / inhe
108108
#### collection.select.allow
109109
> (graph: Mongo.Collection, selector: Selector)
110110
111-
It includes listening to this graph changes and the graph transferred to the selector.
111+
Adds listening to this graph changes and the graph transferred to the selector.
112112

113113
Reacting to changes in their support this graph in an integrity.
114114

@@ -137,12 +137,38 @@ From what part of the link in a given `selector.graph` will continue the selecti
137137
138138
On what will expend the selection started from `from`.
139139

140+
#### collection.select.deny
141+
> (graph: Mongo.Collection, selector: Selector)
142+
143+
Adds listening graph which prevents the presence of links in this graph.
144+
145+
Reacting to changes in their support this graph in an integrity.
146+
147+
You can call this method several times. For example, it is possible to prohibit the intersection with a few graphs.
148+
149+
##### Graph
150+
> Mongo.Collection
151+
152+
Collection-graph whose links will be used as paths for selection.
153+
154+
##### Selector
155+
> Object
156+
157+
###### field
158+
> "source"|"target"
159+
160+
The field pointing in this graph to the selected documents.
161+
140162
## Soon
141163
- [ ] `Selector.query?` `Object` mongodb query condition to enable or disable selection from root link, to support management of the selection from database
142164
- [ ] `collection.select.deny(graph: Mongo.Collection)` to be able to stop the selection of one graph by crossing with other graph with root link relevant to query
143165

144166
## Versions
145167

168+
### 0.0.5
169+
* [#2](https://github.com/meteor-shuttler/selector/issues/2)
170+
* `graph.select.deny` for deny selection where there are links in another graph
171+
146172
### 0.0.2
147173
* [#1](https://github.com/meteor-shuttler/selector/issues/1)
148174

package.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package.describe({
22
name: 'shuttler:selector',
3-
version: '0.0.4',
3+
version: '0.0.5',
44
summary: 'Selectors in links of documents by links in graphs.',
55
git: 'https://github.com/meteor-shuttler/selector',
66
documentation: 'README.md'

selector.js

Lines changed: 154 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Shuttler.SelectorFunctionSchema = new SimpleSchema({
1+
Shuttler.SelectorSelectAllowSchema = new SimpleSchema({
22
field: {
33
type: String,
44
allowedValues: ["source", "target"]
@@ -15,6 +15,12 @@ Shuttler.SelectorFunctionSchema = new SimpleSchema({
1515
}
1616
}
1717
});
18+
Shuttler.SelectorSelectDenySchema = new SimpleSchema({
19+
field: {
20+
type: String,
21+
allowedValues: ["source", "target"]
22+
}
23+
});
1824
Shuttler.SelectedDocumentSchema = new SimpleSchema({
1925
from: {
2026
type: Shuttler.Ref.Schema,
@@ -61,9 +67,67 @@ Mongo.Collection.prototype.attachSelect = function() {
6167
this.select = {}
6268

6369
this.select._allowed = [];
70+
this.select._allowedField = { source: false, target: false };
71+
72+
var generateShortNamesSelectAllow = function(selector) {
73+
return {
74+
So: selector.field, // selected changes field
75+
Ta: selector.field=='source'?'target':'source', // target of selection
76+
Fr: selector.from, // path from
77+
To: selector.to // path to
78+
};
79+
};
80+
81+
var isipv = {
82+
fromLink: function(short, paths, selected, path) {
83+
insertSelectedIntoPathCore(short, paths, selected, path, path['_'+short.To], path.Ref(), selected._id);
84+
},
85+
toLink: function(short, paths, selected, path) {
86+
insertSelectedIntoPathCore(short, paths, selected, path, path.Ref(), path['_'+short.Fr], selected._id);
87+
},
88+
else: function(short, paths, selected, path) {
89+
insertSelectedIntoPathCore(short, paths, selected, path, path['_'+short.To], path['_'+short.Fr], selected._id);
90+
}
91+
};
92+
93+
// from -> to
94+
var insertSelectedIntoPathVariantsHash = {
95+
'link': { 'source': isipv.fromLink, 'target': isipv.fromLink },
96+
'source': { 'target': isipv.else, 'link': isipv.toLink },
97+
'target': { 'source': isipv.else, 'link': isipv.toLink },
98+
};
99+
100+
var insertSelectedIntoPathCore = function(short, paths, selected, path, so, from, prev) {
101+
for (var d in collection.select._denied) {
102+
if (collection.select._denied[d].find({
103+
$or: [
104+
{ '_source.id': so.id, '_source.collection': so.collection },
105+
{ '_target.id': so.id, '_target.collection': so.collection }
106+
]
107+
}).count()) return undefined;
108+
}
109+
if (!collection.find({
110+
['_'+short.Ta+'.id']: selected['_'+short.Ta].id, ['_'+short.Ta+'.collection']: selected['_'+short.Ta].collection,
111+
['_'+short.So+'.id']: so.id, ['_'+short.So+'.collection']: so.collection,
112+
'_selected.path.id': path?path._id:undefined, '_selected.path.collection': path?paths._name:undefined,
113+
'_selected.from.id': from?from.id:undefined, '_selected.from.collection': from?from.collection:undefined,
114+
'_selected.prev': prev?prev:undefined,
115+
'_selected.root': selected.root()
116+
}).count()){
117+
collection.insert({
118+
['_'+short.Ta]: selected['_'+short.Ta], ['_'+short.So]: so,
119+
'_selected': {
120+
path: path?path.Ref():undefined,
121+
from: from?from:undefined,
122+
prev: prev?prev:undefined,
123+
root: selected.root()
124+
}
125+
});
126+
}
127+
};
64128

65129
this.select.allow = function(graph, selector) {
66-
var context = Shuttler.SelectorFunctionSchema.newContext();
130+
var context = Shuttler.SelectorSelectAllowSchema.newContext();
67131
if (!context.validate(selector)) {
68132
throw new Meteor.Error(context.keyErrorMessage(context.invalidKeys()[0].name));
69133
}
@@ -73,46 +137,12 @@ Mongo.Collection.prototype.attachSelect = function() {
73137
var selects = collection;
74138

75139
collection.select._allowed.push({ graph: graph, selector: selector });
140+
collection.select._allowedField[selector.field] = true;
76141

77-
var So = selector.field; // selected changes field
78-
var Ta = selector.field=='source'?'target':'source'; // target of selection
79-
var Fr = selector.from; // path from
80-
var To = selector.to; // path to
81-
82-
var insertSelectedIntoPathCore = function(selected, path, so, from, prev) {
83-
if (!selects.find({
84-
['_'+Ta+'.id']: selected['_'+Ta].id, ['_'+Ta+'.collection']: selected['_'+Ta].collection,
85-
['_'+So+'.id']: so.id, ['_'+So+'.collection']: so.collection,
86-
'_selected.path.id': path?path._id:undefined, '_selected.path.collection': path?paths._name:undefined,
87-
'_selected.from.id': from?from.id:undefined, '_selected.from.collection': from?from.collection:undefined,
88-
'_selected.prev': prev?prev:undefined,
89-
'_selected.root': selected.root()
90-
}).count()){
91-
selects.insert({
92-
['_'+Ta]: selected['_'+Ta], ['_'+So]: so,
93-
'_selected': {
94-
path: path?path.Ref():undefined,
95-
from: from?from:undefined,
96-
prev: prev?prev:undefined,
97-
root: selected.root()
98-
}
99-
});
100-
}
101-
};
142+
var short = generateShortNamesSelectAllow(selector);
143+
let { So, Ta, Fr, To } = short;
102144

103-
if (Fr == 'link') {
104-
var insertSelectedIntoPath = function(selected, path) {
105-
insertSelectedIntoPathCore(selected, path, path['_'+To], path.Ref(), selected._id);
106-
};
107-
} else if (To == 'link') {
108-
var insertSelectedIntoPath = function(selected, path) {
109-
insertSelectedIntoPathCore(selected, path, path.Ref(), path['_'+Fr], selected._id);
110-
};
111-
} else {
112-
var insertSelectedIntoPath = function(selected, path) {
113-
insertSelectedIntoPathCore(selected, path, path['_'+To], path['_'+Fr], selected._id);
114-
};
115-
}
145+
var insertSelectedIntoPath = insertSelectedIntoPathVariantsHash[Fr][To];
116146

117147
if (Fr == 'link') {
118148
var findEachPaths = function(selected, handler) {
@@ -139,10 +169,10 @@ Mongo.Collection.prototype.attachSelect = function() {
139169
selects.after.link[So](function(userId, selected, fieldNames, modifier, options) {
140170
var selected = selects._transform(selected);
141171
if (selected.root() == selected._id) {
142-
insertSelectedIntoPathCore(selected, undefined, selected['_'+So], undefined, undefined);
172+
insertSelectedIntoPathCore(short, paths, selected, undefined, selected['_'+So], undefined, undefined);
143173
} else {
144174
findEachPaths(selected, function(path) {
145-
insertSelectedIntoPath(selected, path);
175+
insertSelectedIntoPath(short, paths, selected, path);
146176
});
147177
}
148178
});
@@ -191,8 +221,89 @@ Mongo.Collection.prototype.attachSelect = function() {
191221
paths.after.link(function(userId, path, fieldNames, modifier, options) {
192222
var path = paths._transform(path);
193223
findEachSelected(path, function(selected) {
194-
insertSelectedIntoPath(selected, path);
224+
insertSelectedIntoPath(short, paths, selected, path);
195225
});
196226
});
197227
};
228+
229+
this.select._denied = [];
230+
231+
var generateShortNamesSelectDeny = function(selector) {
232+
return {
233+
So: selector.field, // selected changes field
234+
Ta: selector.field=='source'?'target':'source' // target of selection
235+
};
236+
};
237+
238+
this.select.deny = function(graph, selector) {
239+
var context = Shuttler.SelectorSelectDenySchema.newContext();
240+
if (!context.validate(selector)) {
241+
throw new Meteor.Error(context.keyErrorMessage(context.invalidKeys()[0].name));
242+
}
243+
244+
if (!(graph instanceof Mongo.Collection)) throw new Meteor.Error('Graph must be a Mongo.Collection');
245+
collection.select._denied.push(graph);
246+
247+
var dShort = generateShortNamesSelectDeny(selector);
248+
249+
var deny = graph;
250+
var allow = collection;
251+
252+
deny.after.unlink[dShort.So](function(userId, denied, fieldNames, modifier, options) {
253+
var denied = deny._transform(denied);
254+
255+
lodash.each(collection.select._allowed, function(_a) {
256+
var _aShort = generateShortNamesSelectAllow(_a.selector);
257+
258+
if (_aShort.To == 'link') {
259+
_a.graph.find({
260+
_id: denied['_'+dShort.So].id
261+
}).forEach(function(path) {
262+
allow.links.find[_aShort.So](path['_'+_aShort.Fr], { '_selected': { $exists: true } }).forEach(function(a) {
263+
insertSelectedIntoPathVariantsHash[_aShort.Fr][_aShort.To](_aShort, _a.graph, a, path);
264+
});
265+
});
266+
} else {
267+
_a.graph.find({
268+
['_'+_aShort.To+'.id']: denied['_'+dShort.So].id,
269+
['_'+_aShort.To+'.collection']: denied['_'+dShort.So].collection
270+
}).forEach(function(path) {
271+
if (_aShort.Fr == 'link') {
272+
allow.links.find[_aShort.So](path, { '_selected': { $exists: true } }).forEach(function(a) {
273+
insertSelectedIntoPathVariantsHash[_aShort.Fr][_aShort.To](_aShort, _a.graph, a, path);
274+
});
275+
} else {
276+
allow.links.find[_aShort.So](path['_'+_aShort.Fr], { '_selected': { $exists: true } }).forEach(function(a) {
277+
insertSelectedIntoPathVariantsHash[_aShort.Fr][_aShort.To](_aShort, _a.graph, a, path);
278+
});
279+
}
280+
});
281+
}
282+
283+
284+
allow.links.find[_aShort.So](denied['_'+dShort.So], { '_selected': { $exists: false } }).forEach(function(allowed) {
285+
insertSelectedIntoPathCore(_aShort, _a.graph, allowed, undefined, allowed['_'+_aShort.So], undefined, undefined);
286+
});
287+
});
288+
});
289+
290+
deny.after.link[dShort.So](function(userId, denied, fieldNames, modifier, options) {
291+
var denied = deny._transform(denied);
292+
293+
if (collection.select._allowedField.source) {
294+
allow.remove({
295+
'_selected': { $exists: true },
296+
['_source.id']: denied['_'+dShort.So].id,
297+
['_source.collection']: denied['_'+dShort.So].collection
298+
});
299+
}
300+
if (collection.select._allowedField.target) {
301+
allow.remove({
302+
'_selected': { $exists: true },
303+
['_target.id']: denied['_'+dShort.So].id,
304+
['_target.collection']: denied['_'+dShort.So].collection
305+
});
306+
}
307+
});
308+
}
198309
};

0 commit comments

Comments
 (0)