diff --git a/SampleService.html b/SampleService.html
index 745c9325..bce8dc9a 100644
--- a/SampleService.html
+++ b/SampleService.html
@@ -1 +1 @@
-
SampleServicemoduleSampleService{typedefintboolean;
typedefinttimestamp;
typedefstringuser;
typedefstringnode_id;
typedefstringsamplenode_type;
typedefstringsample_id;
typedefstringlink_id;
typedefstringsample_name;
typedefintversion;
typedefstringmetadata_key;
typedefstringmetadata_value_key;
typedefstringws_upa;
typedefstringdata_id;
typedefstructure{}SampleNode; typedefstructure{}Sample; typedefstructure{}SampleACLs; typedefstructure{}SampleAddress; typedefstructure{intprior_version;
}CreateSampleParams; typedefstructure{}GetSampleParams; typedefstructure{}GetSampleACLsParams; typedefstructure{}ReplaceSampleACLsParams; typedefstructure{intprefix;
}GetMetadataKeyStaticMetadataParams; typedefstructure{}GetMetadataKeyStaticMetadataResults; typedefstructure{}CreateDataLinkParams; typedefstructure{}DataLink; typedefstructure{}CreateDataLinkResults; typedefstructure{}ExpireDataLinkParams; typedefstructure{}GetDataLinksFromSampleParams; typedefstructure{}GetDataLinksFromSampleResults; typedefstructure{}GetDataLinksFromDataParams; typedefstructure{}GetDataLinksFromDataResults; typedefstructure{}GetSampleViaDataParams; typedefstructure{}GetDataLinkParams; };
\ No newline at end of file
+SampleServicemoduleSampleService{typedefintboolean;
typedefinttimestamp;
typedefstringuser;
typedefstringnode_id;
typedefstringsamplenode_type;
typedefstringsample_id;
typedefstringlink_id;
typedefstringsample_name;
typedefintversion;
typedefstringmetadata_key;
typedefstringmetadata_value_key;
typedefstringws_upa;
typedefstringdata_id;
typedefstructure{}SampleNode; typedefstructure{}Sample; typedefstructure{}SampleACLs; typedefstructure{}SampleAddress; typedefstructure{intprior_version;
}CreateSampleParams; typedefstructure{}GetSampleParams; typedefstructure{}GetSampleACLsParams; typedefstructure{}ReplaceSampleACLsParams; typedefstructure{intprefix;
}GetMetadataKeyStaticMetadataParams; typedefstructure{}GetMetadataKeyStaticMetadataResults; typedefstructure{}CreateDataLinkParams; typedefstructure{}DataLink; typedefstructure{}CreateDataLinkResults; typedefstructure{}ExpireDataLinkParams; typedefstructure{}GetDataLinksFromSampleParams; typedefstructure{}GetDataLinksFromSampleResults; typedefstructure{}GetDataLinksFromDataParams; typedefstructure{}GetDataLinksFromDataResults; typedefstructure{}GetSampleViaDataParams; typedefstructure{}GetDataLinkParams; };
\ No newline at end of file
diff --git a/SampleService.spec b/SampleService.spec
index 90d5c0b8..a4dcb7e8 100644
--- a/SampleService.spec
+++ b/SampleService.spec
@@ -399,7 +399,7 @@ module SampleService {
The user must have read permissions to the workspace data.
*/
funcdef get_data_links_from_data(GetDataLinksFromDataParams params)
- returns(GetDataLinksFromDataResults results) authentication required;
+ returns(GetDataLinksFromDataResults results) authentication optional;
/* get_sample_via_data parameters.
diff --git a/TODO.md b/TODO.md
index ea92a353..49cf755b 100644
--- a/TODO.md
+++ b/TODO.md
@@ -15,7 +15,6 @@
* cache known good users
* cache user roles
* support anonymous users
- * get links from data
* get sample via data
* remove self from acls (read/write)
* change sample owner
diff --git a/lib/SampleService/SampleServiceImpl.py b/lib/SampleService/SampleServiceImpl.py
index 3855c4b5..4de54300 100644
--- a/lib/SampleService/SampleServiceImpl.py
+++ b/lib/SampleService/SampleServiceImpl.py
@@ -53,7 +53,7 @@ class SampleService:
######################################### noqa
VERSION = "0.1.0-alpha18"
GIT_URL = "https://github.com/mrcreosote/sample_service.git"
- GIT_COMMIT_HASH = "dc5bc302aea67790951dacca3df989fc25017ed5"
+ GIT_COMMIT_HASH = "85b101160fee573bac94636d9829c61683f5a654"
#BEGIN_CLASS_HEADER
#END_CLASS_HEADER
@@ -622,11 +622,11 @@ def get_data_links_from_data(self, ctx, params):
upa = _get_upa_from_object(params)
dt = _get_datetime_from_epochmillseconds_in_object(params, 'effective_time')
admin = _check_admin(
- self._user_lookup, ctx[_CTX_TOKEN], _AdminPermission.READ,
+ self._user_lookup, ctx.get(_CTX_TOKEN), _AdminPermission.READ,
# pretty annoying to test ctx.log_info is working, do it manually
'get_data_links_from_data', ctx.log_info, skip_check=not params.get('as_admin'))
links, ts = self._samples.get_links_from_data(
- _UserID(ctx[_CTX_USER]), upa, dt, as_admin=admin)
+ _get_user_from_object(ctx, _CTX_USER), upa, dt, as_admin=admin)
results = {'links': _links_to_dicts(links),
'effective_time': _datetime_to_epochmilliseconds(ts)
}
diff --git a/lib/SampleService/SampleServiceServer.py b/lib/SampleService/SampleServiceServer.py
index 6ae801bf..d0e8ce22 100644
--- a/lib/SampleService/SampleServiceServer.py
+++ b/lib/SampleService/SampleServiceServer.py
@@ -379,7 +379,7 @@ def __init__(self):
self.rpc_service.add(impl_SampleService.get_data_links_from_data,
name='SampleService.get_data_links_from_data',
types=[dict])
- self.method_authentication['SampleService.get_data_links_from_data'] = 'required' # noqa
+ self.method_authentication['SampleService.get_data_links_from_data'] = 'optional' # noqa
self.rpc_service.add(impl_SampleService.get_sample_via_data,
name='SampleService.get_sample_via_data',
types=[dict])
diff --git a/test/SampleService_test.py b/test/SampleService_test.py
index 4bdfc72c..01a0244b 100644
--- a/test/SampleService_test.py
+++ b/test/SampleService_test.py
@@ -2854,19 +2854,10 @@ def test_get_links_from_data(sample_port, workspace):
{'id': id2, 'version': 2, 'node': 'foo3', 'upa': '1/2/2', 'dataid': 'column2'})
# get links from object 1/2/2
- ret = requests.post(url, headers=get_authorized_headers(TOKEN3), json={
- 'method': 'SampleService.get_data_links_from_data',
- 'version': '1.1',
- 'id': '42',
- 'params': [{'upa': '1/2/2'}]
- })
- # print(ret.text)
- assert ret.ok is True
+ ret = _get_links_from_data(url, TOKEN3, {'upa': '1/2/2'})
- assert len(ret.json()['result']) == 1
- assert len(ret.json()['result'][0]) == 2
- assert_ms_epoch_close_to_now(ret.json()['result'][0]['effective_time'])
- res = ret.json()['result'][0]['links']
+ assert_ms_epoch_close_to_now(ret['effective_time'])
+ res = ret['links']
expected_links = [
{
'linkid': lid1,
@@ -2901,19 +2892,10 @@ def test_get_links_from_data(sample_port, workspace):
assert link in res
# get links from object 1/1/1
- ret = requests.post(url, headers=get_authorized_headers(TOKEN3), json={
- 'method': 'SampleService.get_data_links_from_data',
- 'version': '1.1',
- 'id': '42',
- 'params': [{'upa': '1/1/1'}]
- })
- # print(ret.text)
- assert ret.ok is True
+ ret = _get_links_from_data(url, TOKEN3, {'upa': '1/1/1'})
- assert len(ret.json()['result']) == 1
- assert len(ret.json()['result'][0]) == 2
- assert_ms_epoch_close_to_now(ret.json()['result'][0]['effective_time'])
- res = ret.json()['result'][0]['links']
+ assert_ms_epoch_close_to_now(ret['effective_time'])
+ res = ret['links']
assert_ms_epoch_close_to_now(res[0]['created'])
del res[0]['created']
assert res == [
@@ -2931,18 +2913,25 @@ def test_get_links_from_data(sample_port, workspace):
]
# get links from object 1/2/1
- ret = requests.post(url, headers=get_authorized_headers(TOKEN3), json={
+ ret = _get_links_from_data(url, TOKEN3, {'upa': '1/2/1'})
+
+ assert_ms_epoch_close_to_now(ret['effective_time'])
+ assert ret['links'] == []
+
+
+def _get_links_from_data(url, token, params, print_resp=False):
+ ret = requests.post(url, headers=get_authorized_headers(token), json={
'method': 'SampleService.get_data_links_from_data',
'version': '1.1',
'id': '42',
- 'params': [{'upa': '1/2/1'}]
+ 'params': [params]
})
- # print(ret.text)
+ if print_resp:
+ print(ret.text)
assert ret.ok is True
assert len(ret.json()['result']) == 1
assert len(ret.json()['result'][0]) == 2
- assert_ms_epoch_close_to_now(ret.json()['result'][0]['effective_time'])
- assert ret.json()['result'][0]['links'] == []
+ return ret.json()['result'][0]
def test_get_links_from_data_expired(sample_port, workspace):
@@ -3072,34 +3061,25 @@ def test_get_links_from_data_public_read(sample_port, workspace):
# create links
lid = _create_link(url, TOKEN1, USER1, {'id': id_, 'version': 1, 'node': 'foo', 'upa': '1/1/1'})
- # get links from object, user 4 has no explicit perms
- ret = requests.post(url, headers=get_authorized_headers(TOKEN4), json={
- 'method': 'SampleService.get_data_links_from_data',
- 'version': '1.1',
- 'id': '42',
- 'params': [{'upa': '1/1/1'}]
- })
- # print(ret.text)
- assert ret.ok is True
+ for token in [None, TOKEN4]: # anon user, user 4 has no explicit perms
+ ret = _get_links_from_data(url, token, {'upa': '1/1/1'})
- assert len(ret.json()['result']) == 1
- assert len(ret.json()['result'][0]) == 2
- assert_ms_epoch_close_to_now(ret.json()['result'][0]['effective_time'])
- assert len(ret.json()['result'][0]['links']) == 1
- link = ret.json()['result'][0]['links'][0]
- assert_ms_epoch_close_to_now(link['created'])
- del link['created']
- assert link == {
- 'linkid': lid,
- 'id': id_,
- 'version': 1,
- 'node': 'foo',
- 'upa': '1/1/1',
- 'dataid': None,
- 'createdby': USER1,
- 'expiredby': None,
- 'expired': None
- }
+ assert_ms_epoch_close_to_now(ret['effective_time'])
+ assert len(ret['links']) == 1
+ link = ret['links'][0]
+ assert_ms_epoch_close_to_now(link['created'])
+ del link['created']
+ assert link == {
+ 'linkid': lid,
+ 'id': id_,
+ 'version': 1,
+ 'node': 'foo',
+ 'upa': '1/1/1',
+ 'dataid': None,
+ 'createdby': USER1,
+ 'expiredby': None,
+ 'expired': None
+ }
def test_get_links_from_data_as_admin(sample_port, workspace):
@@ -3179,6 +3159,9 @@ def test_get_links_from_data_fail(sample_port, workspace):
_get_link_from_data_fail(
sample_port, TOKEN4, {'upa': '1/1/1'},
'Sample service error code 20000 Unauthorized: User user4 cannot read upa 1/1/1')
+ _get_link_from_data_fail(
+ sample_port, None, {'upa': '1/1/1'},
+ 'Sample service error code 20000 Unauthorized: Anonymous users cannot read upa 1/1/1')
_get_link_from_data_fail(
sample_port, TOKEN3, {'upa': '1/2/1'},
'Sample service error code 50040 No such workspace data: Object 1/2/1 does not exist')
@@ -3188,6 +3171,10 @@ def test_get_links_from_data_fail(sample_port, workspace):
sample_port, TOKEN4, {'upa': '1/1/1', 'as_admin': 1},
'Sample service error code 20000 Unauthorized: User user4 does not have the necessary ' +
'administration privileges to run method get_data_links_from_data')
+ _get_link_from_data_fail(
+ sample_port, None, {'upa': '1/1/1', 'as_admin': 1},
+ 'Sample service error code 20000 Unauthorized: Anonymous users may not act ' +
+ 'as service administrators.')
_get_link_from_data_fail(
sample_port, TOKEN3, {'upa': '1/1/2', 'as_admin': 1},
'Sample service error code 50040 No such workspace data: Object 1/1/2 does not exist')