forked from NationalSecurityAgency/lemongraph
-
Notifications
You must be signed in to change notification settings - Fork 0
/
RESTAPI
224 lines (187 loc) · 8.29 KB
/
RESTAPI
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/graph
GET (Accept: application/json, application/x-msgpack)
Can be filtered by supplying query parameters 'user' and 'role' - see below
If no queries ('q') are supplied:
returns listing of available graphs, including a the contents of 'meta' and a few other magic fields
Else, iterates over list of graphs and executes queries - see below:
returns a list such that the first entry is:
[query patterns]
and subsequent entries are:
[<graph>, <query index>, chain]
POST (Accept: application/json, application/x-msgpack)
(Content-Type: application/json, application/x-msgpack)
body should be object w/ the optional kv pairs below
{
"seed": true, // mark any referenced nodes/edges as seeds (nodes are assigned depth=0)
"meta": {}, // same structure as POST /graph, merges graph-level kv pairs
'chains': [], // list of node[->edge->node]* object chains
'nodes': [], // list of nodes
'edges': [], // list of edges
}
all node objects must have:
a) type/value combo
all edge objects referenced in chains must have:
a) type[/value] (optional value defaults to empty string)
all edge objects referenced in edges must have:
a) type[/value] (optional value defaults to empty string)
b) src and tgt attributes, with node objects as values (as above, must have type/value attributes)
Nodes and edges will be created as necessary if type/value or type/value/src/tgt combos do not already exist
Any supplied 'depth' property on a node is silently ignored (use seed flag to set node depth=0).
Any supplied 'cost' property on an edge is silently ignored if either is true:
a) cost < 0 or cost > 1
b) cost > target edge's current cost
/graph/<uuid>
HEAD
GET (Accept: application/json, application/x-msgpack, application/octet-stream)
if application/octet-stream:
dumps binary lemongraph snapshot, ignores QUERY_STRING parameters
elif application/x-msgpack or application/json:
QUERY_STRING parameters:
q=<pattern> (see LemonGraph/MatchLGQL.py for query pattern docs)
crawl=<string> ('0' or not '0')
start=<x> (x > 0)
stop=<y> (y > 0)
limit=<z> (z >= 0)
w/out supplied q, the other options are meaningless
without supplied q:
return a full graph dump - only valid for application/json
(I have not settled on a streaming format for application/x-msgpack)
only other param employed is 'stop' - dumped graph will include
changes up to and including supplied ID
with both q and crawl supplied, and crawl is not '0':
return sub-graph[s] - only valid for application/json
traverse graph, using chain data returned from queries as starting points
only other param employed is 'stop' - dumped sub-graph[s] will include
changes up to and including supplied ID
otherwise:
if limit:
limit all query responses to that many chains
if start && stop:
evaluate streaming query over ID range [start, stop]
elif start:
evaluate streaming query over ID range [start, inf)
eilf stop:
evaluate ad-hoc query as of position
streams a single lists of lists:
first entry is a sorted list of the requested query patterns
remaining entries are tuples of query pattern index and matching chain
POST (Content-Type: application/json, application/x-msgpack)
target graph must exist already, unless 'create' is in the query parameters (no value required)
body should be object w/ the optional kv pairs below
{
"seed": true, // mark any referenced nodes/edges as seeds (nodes are assigned depth=0)
"meta": {}, // same structure as POST /graph, merges graph-level kv pairs
'chains': [], // list of node[->edge->node]* object chains
'nodes': [], // list of nodes
'edges': [], // list of edges
}
all node objects must have at minimum either of:
a) type/value combo
b) ID (node must exist already)
all edge objects referenced in chains must have at minimum either of:
a) type[/value] (optional value defaults to empty string)
b) ID (edge must exist already)
all edge objects referenced in edges must have at minimum either of:
a) type[/value] (optional value defaults to empty string), along with:
1) src and tgt attributes, with node objects as values (as above, must have ID or type/value attributes)
b) ID (edge must exist already)
When not referenced by ID, nodes and edges will be created as necessary if type/value or type/value/src/tgt combos do not already exist
Any supplied 'depth' property on a node is silently ignored (use seed flag to set node depth=0).
Any supplied 'cost' property on an edge is silently ignored if either is true:
a) cost < 0 or cost > 1
b) cost > target edge's current cost
PUT (application/octet-stream)
expects graph binary as input
DELETE
Deletes given graph.
/graph/<uuid>/meta
GET (Accept: application/json, application/x-msgpack)
PUT (Content-Type: application/json, application/x-msgpack)
/graph/<uuid>/status
HEAD
GET (Accept: application/json, application/x-msgpack)
/reset/<uuid>
PUT
Clears entire graph db and re-inserts the first POST marked as seed data, if present.
Payload should be empty.
/graph/<uuid>/node/<id>
GET (Accept: application/json, application/x-msgpack)
PUT (Content-Type: application/json, application/x-msgpack)
/graph/<uuid>/edge/<id>
GET (Accept: application/json, application/x-msgpack)
PUT (Content-Type: application/json, application/x-msgpack)
/graph/exec
POST (Content-Type: application/python)
Post python script body that at minimum defines a handler function like so:
def handler(txns_uuids, headers, **kwargs):
pass
After loading, it will be called with:
* a generator that yields tuples of read-only transaction handle and matching uuid
* the response headers object
* and any supplied QUERY_STRING parameters as named parameters
Optionally filter graphs by supplying user and role parameters (they will be excluded from the kwargs fed to the handler)
/graph/<uuid>/exec
POST (Content-Type: application/python)
Post python script body that at minimum defines a handler function like so:
def handler(txn, uuid, headers, **kwargs):
pass
After loading, it will be called with:
* a read-only transaction handle
* the graph uuid
* the response headers object
* and any supplied QUERY_STRING parameters as named parameters
/graph/<uuid>/seeds
GET (Accept: application/json, application/x-msgpack)
Returns ordered list of posted payloads that were marked as seeds.
/kv/<uuid> - non-logged key/value pairs
GET (Accept: application/json, application/x-msgpack)
Retrieves dictionary
PUT (Content-Type: application/json, application/x-msgpack)
Overwrites dictionary
POST (Content-Type: application/json, application/x-msgpack)
Merges dictionary
DELETE
Deletes dictionary
/kv/<uuid>/<key> - non-logged key/value pairs
GET (Accept: application/json, application/x-msgpack)
Retrieves specific dictionary key
PUT (Content-Type: application/json, application/x-msgpack)
Overwrites specific dictionary key
POST (Content-Type: application/json, application/x-msgpack)
Merges specific dictionary key
DELETE
Deletes specific dictionary key
/view/<uuid>
GET
Returns html that presents a graph using D3
/d3/<uuid>
GET
Streams D3-friendly json dump of graph
Magic Meta Keys:
If present, several meta keys are harvested, transformed, and cached
by the top-level graph tracking layer:
'enabled':
bool(value) is cached, defaulting: true
'priority':
clamped to be in numeric range [0-255], default: 100
'roles':
if dictionary:
keys are users
values can be either:
a) strings of one or more words
b) dictionaries of:
role: boolean
For example, here are the two styles:
{
"alice" : "reader writer",
"bob": { "reader": true, "writer": false }
}
This data is indexed such that you can pull:
* a list of graphs that Alice has any active role:
/graph?user=alice
* a list of graphs that Bob is either a reader or a writer for:
/graph?user=bob&role=reader&role=writer
In addition, if user & optionally role arguments are supplied, any HTTP request to /graph/<uuid>
or deeper will enforce either:
a) if specified, that the supplied user is a member of at least one of the supplied roles
b) else if no roles are supplied, that the supplied user is a member of at least one role