|
1 | 1 | import { greaterThan, inArray, node, relation } from 'cypher-query-builder';
|
2 | 2 | import { ACTIVE, filter, matchProjectSens, path } from '~/core/database/query';
|
3 |
| -import { ProjectListInput } from './dto'; |
| 3 | +import { ProjectFilters } from './dto'; |
4 | 4 |
|
5 |
| -export const projectListFilter = (input: ProjectListInput) => |
6 |
| - filter.builder(input.filter ?? {}, { |
7 |
| - type: filter.stringListBaseNodeProp(), |
8 |
| - status: filter.stringListProp(), |
9 |
| - onlyMultipleEngagements: |
10 |
| - ({ value, query }) => |
11 |
| - () => |
12 |
| - value |
13 |
| - ? query |
14 |
| - .match([ |
15 |
| - node('node'), |
16 |
| - relation('out', '', 'engagement', ACTIVE), |
17 |
| - node('engagement', 'Engagement'), |
18 |
| - ]) |
19 |
| - .with('node, count(engagement) as engagementCount') |
20 |
| - .where({ engagementCount: greaterThan(1) }) |
21 |
| - : null, |
22 |
| - step: filter.stringListProp(), |
23 |
| - createdAt: filter.dateTimeBaseNodeProp(), |
24 |
| - modifiedAt: filter.dateTimeProp(), |
25 |
| - mine: filter.pathExistsWhenTrue([ |
26 |
| - node('requestingUser'), |
27 |
| - relation('in', '', 'user'), |
28 |
| - node('', 'ProjectMember'), |
29 |
| - relation('in', '', 'member'), |
30 |
| - node('node'), |
31 |
| - ]), |
32 |
| - pinned: filter.isPinned, |
33 |
| - presetInventory: filter.propVal(), |
34 |
| - partnerId: filter.pathExists((id) => [ |
35 |
| - node('node'), |
36 |
| - relation('out', '', 'partnership', ACTIVE), |
37 |
| - node('', 'Partnership'), |
38 |
| - relation('out', '', 'partner', ACTIVE), |
39 |
| - node('', 'Partner', { id }), |
40 |
| - ]), |
41 |
| - userId: ({ value }) => ({ |
42 |
| - userId: [ |
43 |
| - // TODO We can leak if the project includes this person, if the |
44 |
| - // requesting user does not have access to view the project's members. |
45 |
| - path([ |
46 |
| - node('node'), |
47 |
| - relation('out', '', 'member', ACTIVE), |
48 |
| - node('', 'ProjectMember'), |
49 |
| - relation('out', '', 'user', ACTIVE), |
50 |
| - node('', 'User', { id: value }), |
51 |
| - ]), |
52 |
| - // TODO does it make sense to include interns in this filter? |
53 |
| - path([ |
54 |
| - node('node'), |
55 |
| - relation('out', '', 'engagement', ACTIVE), |
56 |
| - node('', 'Engagement'), |
57 |
| - relation('out', '', 'intern', ACTIVE), |
58 |
| - node('', 'User', { id: value }), |
59 |
| - ]), |
60 |
| - ], |
61 |
| - }), |
62 |
| - languageId: filter.pathExists((id) => [ |
63 |
| - node('node'), |
64 |
| - relation('out', '', 'engagement', ACTIVE), |
65 |
| - node('', 'LanguageEngagement'), |
66 |
| - relation('out', '', 'language', ACTIVE), |
67 |
| - node('', 'Language', { id }), |
68 |
| - ]), |
69 |
| - sensitivity: |
70 |
| - ({ value, query }) => |
71 |
| - () => |
72 |
| - value |
73 |
| - ? query |
74 |
| - .apply(matchProjectSens('node')) |
75 |
| - .with('*') |
76 |
| - .where({ sensitivity: inArray(value) }) |
77 |
| - : query, |
78 |
| - }); |
| 5 | +export const projectFilters = filter.define(() => ProjectFilters, { |
| 6 | + type: filter.stringListBaseNodeProp(), |
| 7 | + status: filter.stringListProp(), |
| 8 | + onlyMultipleEngagements: |
| 9 | + ({ value, query }) => |
| 10 | + () => |
| 11 | + value |
| 12 | + ? query |
| 13 | + .match([ |
| 14 | + node('node'), |
| 15 | + relation('out', '', 'engagement', ACTIVE), |
| 16 | + node('engagement', 'Engagement'), |
| 17 | + ]) |
| 18 | + .with('node, count(engagement) as engagementCount') |
| 19 | + .where({ engagementCount: greaterThan(1) }) |
| 20 | + : null, |
| 21 | + step: filter.stringListProp(), |
| 22 | + createdAt: filter.dateTimeBaseNodeProp(), |
| 23 | + modifiedAt: filter.dateTimeProp(), |
| 24 | + mine: filter.pathExistsWhenTrue([ |
| 25 | + node('requestingUser'), |
| 26 | + relation('in', '', 'user'), |
| 27 | + node('', 'ProjectMember'), |
| 28 | + relation('in', '', 'member'), |
| 29 | + node('node'), |
| 30 | + ]), |
| 31 | + pinned: filter.isPinned, |
| 32 | + presetInventory: filter.propVal(), |
| 33 | + partnerId: filter.pathExists((id) => [ |
| 34 | + node('node'), |
| 35 | + relation('out', '', 'partnership', ACTIVE), |
| 36 | + node('', 'Partnership'), |
| 37 | + relation('out', '', 'partner', ACTIVE), |
| 38 | + node('', 'Partner', { id }), |
| 39 | + ]), |
| 40 | + userId: ({ value }) => ({ |
| 41 | + userId: [ |
| 42 | + // TODO We can leak if the project includes this person, if the |
| 43 | + // requesting user does not have access to view the project's members. |
| 44 | + path([ |
| 45 | + node('node'), |
| 46 | + relation('out', '', 'member', ACTIVE), |
| 47 | + node('', 'ProjectMember'), |
| 48 | + relation('out', '', 'user', ACTIVE), |
| 49 | + node('', 'User', { id: value }), |
| 50 | + ]), |
| 51 | + // TODO does it make sense to include interns in this filter? |
| 52 | + path([ |
| 53 | + node('node'), |
| 54 | + relation('out', '', 'engagement', ACTIVE), |
| 55 | + node('', 'Engagement'), |
| 56 | + relation('out', '', 'intern', ACTIVE), |
| 57 | + node('', 'User', { id: value }), |
| 58 | + ]), |
| 59 | + ], |
| 60 | + }), |
| 61 | + languageId: filter.pathExists((id) => [ |
| 62 | + node('node'), |
| 63 | + relation('out', '', 'engagement', ACTIVE), |
| 64 | + node('', 'LanguageEngagement'), |
| 65 | + relation('out', '', 'language', ACTIVE), |
| 66 | + node('', 'Language', { id }), |
| 67 | + ]), |
| 68 | + sensitivity: |
| 69 | + ({ value, query }) => |
| 70 | + () => |
| 71 | + value |
| 72 | + ? query |
| 73 | + .apply(matchProjectSens('node')) |
| 74 | + .with('*') |
| 75 | + .where({ sensitivity: inArray(value) }) |
| 76 | + : query, |
| 77 | +}); |
0 commit comments