Skip to content

Commit e2a94a3

Browse files
committed
permission RAML test and stringifies filters in mongo
1 parent ef79dca commit e2a94a3

File tree

8 files changed

+140
-6
lines changed

8 files changed

+140
-6
lines changed

api/dao/containerstorage.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import datetime
2-
2+
import pymongo
33
import bson
44

5-
from . import APIStorageException, APINotFoundException
5+
from . import APIStorageException, APINotFoundException, APIConflictException
66
from . import containerutil
77
from . import hierarchy
88
from .. import config
@@ -401,6 +401,15 @@ class SearchStorage(ContainerStorage):
401401
def __init__(self):
402402
super(SearchStorage, self).__init__('savesearches', use_object_id=True)
403403

404+
def create_el(self, payload):
405+
log.debug(payload)
406+
payload = self._to_mongo(payload)
407+
try:
408+
result = self.dbc.insert_one(payload, bypass_document_validation=True)
409+
except pymongo.errors.DuplicateKeyError:
410+
raise APIConflictException('Object with id {} already exists.'.format(payload['_id']))
411+
return result
412+
404413
def replace_el(self, search):
405414
self.delete_el(search['_id'])
406415
return self.create_el(search)

api/handlers/savesearchhandler.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import bson
2+
from ast import literal_eval
23
from ..web import base
34
from .. import config, validators
45
from ..auth import require_login
@@ -11,6 +12,23 @@
1112
log = config.log
1213
storage = SearchStorage()
1314

15+
16+
def string_filters(payload):
17+
if payload.get('search') and payload['search'].get('filters'):
18+
filters = []
19+
for filter_ in payload['search'].get('filters',[]):
20+
filters.append(str(filter_))
21+
payload['search']['filters'] = filters
22+
return payload
23+
24+
def unstring_filters(payload):
25+
if payload['search'].get('filters'):
26+
filters= []
27+
for filter_ in payload['search'].get('filters',[]):
28+
filters.append(literal_eval(filter_))
29+
payload['search']['filters']= filters
30+
return payload
31+
1432
class SaveSearchHandler(base.RequestHandler):
1533

1634
def __init__(self, request=None, response=None):
@@ -20,6 +38,7 @@ def __init__(self, request=None, response=None):
2038
def post(self):
2139
payload = self.request.json_body
2240
validators.validate_data(payload, 'search-input.json', 'input', 'POST')
41+
payload = string_filters(payload)
2342
payload['permissions'] = [{"_id": self.uid, "access": "admin"}]
2443
payload['creator'] = self.uid
2544
result = storage.create_el(payload)
@@ -36,6 +55,7 @@ def get(self, sid):
3655
result = storage.get_el(sid)
3756
if result is None:
3857
self.abort(404, 'Element {} not found'.format(sid))
58+
unstring_filters(result)
3959
return result
4060

4161
def delete(self, sid):
@@ -52,6 +72,7 @@ def replace_search(self, sid):
5272
payload = self.request.json_body
5373
payload = self._scrub_replace(payload)
5474
validators.validate_data(payload, 'search-input.json', 'input', 'POST')
75+
payload = string_filters(payload)
5576
payload['_id'] = bson.ObjectId(sid)
5677
search = storage.get_container(sid)
5778
payload['permissions'] = search['permissions']
@@ -74,3 +95,4 @@ def _scrub_replace(self, payload):
7495
if payload.get('creator'):
7596
del(payload['creator'])
7697
return payload
98+

raml/examples/output/search-list.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[{
2+
"label": "Test Search",
3+
"_id": "57e452791cff88b85f9f9c23"
4+
}]

raml/examples/output/search.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"label": "Test Search",
3+
"_id": "57e452791cff88b85f9f9c23",
4+
"search": {
5+
"return_type": "file",
6+
"filters": [{"terms": {"file.type":["nifti"]}}]
7+
},
8+
"permissions": [{"access": "admin", "_id": "[email protected]"}],
9+
"creator": "[email protected]"
10+
}

raml/resources/savesearch.raml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ get:
55
200:
66
body:
77
application/json:
8+
example: !include ../examples/output/search-list.json
89
schema: !include ../schemas/output/search-list.json
910
post:
1011
body:
@@ -18,6 +19,15 @@ post:
1819
body:
1920
application/json:
2021
schema: !include ../schemas/output/search-output.json
22+
post:
23+
description: Replace saved search with a new search
24+
body:
25+
application/json:
26+
schema: !include ../schemas/input/search-input.json
27+
/permissions:
28+
type: permissions-list
29+
/{UserId}:
30+
type: permissions-item
2131
delete:
2232
description: Delete a saved search
2333
responses:
@@ -26,4 +36,3 @@ post:
2636
application/json:
2737
schema: !include ../schemas/output/container-delete.json
2838
example: !include ../examples/output/container-delete.json
29-

raml/schemas/output/search-list.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"type":"object",
66
"allOf":[{"$ref":"../definitions/search.json#/definitions/search-output"}],
77
"required":[
8-
"_id", "label", "permissions", "search"
8+
"_id", "label"
99
]
1010
}
1111
}

test/integration_tests/abao/abao_test_hooks.js

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ var delete_project_id = '';
2424
var device_id = 'bootstrapper_Bootstrapper';
2525
var injected_api_key = 'XZpXI40Uk85eozjQkU1zHJ6yZHpix+j0mo1TMeGZ4dPzIqVPVGPmyfeK';
2626
var search_id = '';
27+
var delete_search_id = '';
28+
var user_id = '[email protected]'
2729

2830
// Tests we're skipping, fix these
2931

@@ -1474,7 +1476,7 @@ hooks.before("POST /savesearches -> 200", function(test, done) {
14741476
done();
14751477
})
14761478
hooks.after("POST /savesearches -> 200", function(test, done) {
1477-
search_id = test.response.body['_id'];
1479+
delete_search_id = test.response.body['_id'];
14781480
done();
14791481
})
14801482

@@ -1485,6 +1487,11 @@ hooks.before("POST /savesearches -> 400", function(test, done) {
14851487
done();
14861488
})
14871489

1490+
hooks.after("GET /savesearches -> 200", function(test, done) {
1491+
search_id = test.response.body[0]._id;
1492+
done();
1493+
})
1494+
14881495
hooks.before("GET /savesearches/{SearchId} -> 200", function(test, done) {
14891496
test.request.params = {
14901497
SearchId: search_id
@@ -1516,9 +1523,69 @@ hooks.before("POST /savesearches/{SearchId} -> 400", function(test, done) {
15161523
done();
15171524
})
15181525

1519-
hooks.before("DELETE /savesearches/{SearchId} -> 200", function(test, done) {
1526+
hooks.before("POST /savesearches/{SearchId}/permissions -> 200", function(test, done) {
1527+
test.request.params = {
1528+
SearchId: search_id
1529+
};
1530+
test.request.body = {
1531+
"access" : "admin",
1532+
"_id": user_id
1533+
};
1534+
done();
1535+
})
1536+
1537+
hooks.before("POST /savesearches/{SearchId}/permissions -> 400", function(test, done) {
15201538
test.request.params = {
15211539
SearchId: search_id
15221540
};
1541+
test.request.body = {
1542+
"not-access" : "admin",
1543+
"not_id": user_id
1544+
};
1545+
done();
1546+
})
1547+
1548+
hooks.before("GET /savesearches/{SearchId}/permissions/{UserId} -> 200", function(test, done) {
1549+
test.request.params = {
1550+
SearchId: search_id,
1551+
UserId: user_id
1552+
};
1553+
done();
1554+
})
1555+
1556+
hooks.before("PUT /savesearches/{SearchId}/permissions/{UserId} -> 200", function(test, done) {
1557+
test.request.params = {
1558+
SearchId: search_id,
1559+
UserId: user_id
1560+
};
1561+
test.request.body = {
1562+
"access" : "ro"
1563+
};
1564+
done();
1565+
})
1566+
1567+
hooks.before("PUT /savesearches/{SearchId}/permissions/{UserId} -> 400", function(test, done) {
1568+
test.request.params = {
1569+
SearchId: search_id,
1570+
UserId: user_id
1571+
};
1572+
test.request.body = {
1573+
"access" : "not_an_access_level"
1574+
};
1575+
done();
1576+
})
1577+
1578+
hooks.before("DELETE /savesearches/{SearchId}/permissions/{UserId} -> 200", function(test, done) {
1579+
test.request.params = {
1580+
SearchId: search_id,
1581+
UserId: user_id
1582+
};
1583+
done();
1584+
})
1585+
1586+
hooks.before("DELETE /savesearches/{SearchId} -> 200", function(test, done) {
1587+
test.request.params = {
1588+
SearchId: delete_search_id
1589+
};
15231590
done();
15241591
})

test/integration_tests/abao/load_fixture.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,19 @@ def main():
8181
})
8282
assert r.ok
8383

84+
# create a saved search
85+
r = as_root.post('/savesearches', json={
86+
"label": "Test Search",
87+
"search": {
88+
"return_type": "file",
89+
"filters": [{"terms": {"file.type":["nifti"]}}]
90+
},
91+
})
92+
assert r.ok
93+
r = as_root.get('/savesearches')
94+
assert r.ok
95+
assert r.json()[0]['label'] == 'Test Search'
96+
8497
# list projects
8598
# depends on 'upload file to test-project-1/test-session-1/test-acquisition-1'
8699
r = as_root.get('/projects')

0 commit comments

Comments
 (0)