diff --git a/Makefile b/Makefile
index 4c7ffc96..2a110690 100644
--- a/Makefile
+++ b/Makefile
@@ -27,7 +27,7 @@ compile:
# Don't compile server automatically, overwrites fixes to error handling
# Temporarily add the next line to the command line args if recompiliation is needed to add
# methods.
-# --pysrvname $(SERVICE_CAPS).$(SERVICE_CAPS)Server \
+# --pysrvname $(SERVICE_CAPS).$(SERVICE_CAPS)Server \
kb-sdk compile $(SPEC_FILE) \
--out $(LIB_DIR) \
diff --git a/SampleService.html b/SampleService.html
index 68688ec7..6eb1f563 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 ed4a275e..8d10e11e 100644
--- a/SampleService.spec
+++ b/SampleService.spec
@@ -167,7 +167,7 @@ module SampleService {
} GetSampleParams;
/* Get a sample. If the version is omitted the most recent sample is returned. */
- funcdef get_sample(GetSampleParams params) returns (Sample sample) authentication required;
+ funcdef get_sample(GetSampleParams params) returns (Sample sample) authentication optional;
/* get_sample_acls parameters.
id - the ID of the sample to retrieve.
diff --git a/TODO.md b/TODO.md
index dccdaeca..2bacad8a 100644
--- a/TODO.md
+++ b/TODO.md
@@ -15,7 +15,6 @@
* cache known good users
* cache user roles
* support anonymous users
- * get sample
* get sample acls
* get links from sample
* get links from data
diff --git a/lib/SampleService/SampleServiceImpl.py b/lib/SampleService/SampleServiceImpl.py
index 20e3180e..9ec38b32 100644
--- a/lib/SampleService/SampleServiceImpl.py
+++ b/lib/SampleService/SampleServiceImpl.py
@@ -20,7 +20,8 @@
get_upa_from_object as _get_upa_from_object,
get_data_unit_id_from_object as _get_data_unit_id_from_object,
get_admin_request_from_object as _get_admin_request_from_object,
- datetime_to_epochmilliseconds as _datetime_to_epochmilliseconds
+ datetime_to_epochmilliseconds as _datetime_to_epochmilliseconds,
+ get_user_from_object as _get_user_from_object,
)
from SampleService.core.acls import AdminPermission as _AdminPermission
from SampleService.core.sample import SampleAddress as _SampleAddress
@@ -52,7 +53,7 @@ class SampleService:
######################################### noqa
VERSION = "0.1.0-alpha18"
GIT_URL = "https://github.com/mrcreosote/sample_service.git"
- GIT_COMMIT_HASH = "208af320923599cab027cf022167238bb78ce785"
+ GIT_COMMIT_HASH = "a1e16589e20404b119283c8bc42a0dcc97982dfc"
#BEGIN_CLASS_HEADER
#END_CLASS_HEADER
@@ -220,10 +221,11 @@ def get_sample(self, ctx, params):
# return variables are: sample
#BEGIN get_sample
id_, ver = _get_sample_address_from_object(params)
- admin = _check_admin(self._user_lookup, ctx[_CTX_TOKEN], _AdminPermission.READ,
+ admin = _check_admin(self._user_lookup, ctx.get(_CTX_TOKEN), _AdminPermission.READ,
# pretty annoying to test ctx.log_info is working, do it manually
'get_sample', ctx.log_info, skip_check=not params.get('as_admin'))
- s = self._samples.get_sample(id_, _UserID(ctx[_CTX_USER]), ver, as_admin=admin)
+ s = self._samples.get_sample(
+ id_, _get_user_from_object(ctx, _CTX_USER), ver, as_admin=admin)
sample = _sample_to_dict(s)
#END get_sample
diff --git a/lib/SampleService/SampleServiceServer.py b/lib/SampleService/SampleServiceServer.py
index 380ba1eb..67418529 100644
--- a/lib/SampleService/SampleServiceServer.py
+++ b/lib/SampleService/SampleServiceServer.py
@@ -351,7 +351,7 @@ def __init__(self):
self.rpc_service.add(impl_SampleService.get_sample,
name='SampleService.get_sample',
types=[dict])
- self.method_authentication['SampleService.get_sample'] = 'required' # noqa
+ self.method_authentication['SampleService.get_sample'] = 'optional' # noqa
self.rpc_service.add(impl_SampleService.get_sample_acls,
name='SampleService.get_sample_acls',
types=[dict])
diff --git a/test/SampleService_test.py b/test/SampleService_test.py
index 5c354f3a..d93e9b80 100644
--- a/test/SampleService_test.py
+++ b/test/SampleService_test.py
@@ -440,7 +440,10 @@ def test_status(sample_port):
def get_authorized_headers(token):
- return {'authorization': token, 'accept': 'application/json'}
+ headers = {'accept': 'application/json'}
+ if token is not None:
+ headers['authorization'] = token
+ return headers
def _check_kafka_messages(kafka, expected_msgs, topic=KAFKA_TOPIC, print_res=False):
@@ -741,28 +744,29 @@ def test_get_sample_public_read(sample_port):
_replace_acls(url, id_, TOKEN1, {'public_read': 1})
- s = _get_sample(url, TOKEN4, id_)
- assert_ms_epoch_close_to_now(s['save_date'])
- del s['save_date']
- assert s == {
- 'id': id_,
- 'version': 1,
- 'user': 'user1',
- 'name': 'mysample',
- 'node_tree': [{'id': 'root',
- 'parent': None,
- 'type': 'BioReplicate',
- 'meta_controlled': {},
- 'meta_user': {}
- },
- {'id': 'foo',
- 'parent': 'root',
- 'type': 'TechReplicate',
- 'meta_controlled': {},
- 'meta_user': {}
- }
- ]
- }
+ for token in [TOKEN4, None]: # unauthed user and anonymous user
+ s = _get_sample(url, token, id_)
+ assert_ms_epoch_close_to_now(s['save_date'])
+ del s['save_date']
+ assert s == {
+ 'id': id_,
+ 'version': 1,
+ 'user': 'user1',
+ 'name': 'mysample',
+ 'node_tree': [{'id': 'root',
+ 'parent': None,
+ 'type': 'BioReplicate',
+ 'meta_controlled': {},
+ 'meta_user': {}
+ },
+ {'id': 'foo',
+ 'parent': 'root',
+ 'type': 'TechReplicate',
+ 'meta_controlled': {},
+ 'meta_user': {}
+ }
+ ]
+ }
def _get_sample(url, token, id_):
@@ -1049,18 +1053,19 @@ def test_get_sample_fail_permissions(sample_port):
assert ret.json()['result'][0]['version'] == 1
id_ = ret.json()['result'][0]['id']
- ret = requests.post(url, headers=get_authorized_headers(TOKEN2), json={
- 'method': 'SampleService.get_sample',
- 'version': '1.1',
- 'id': '42',
- 'params': [{'id': id_}]
- })
-
- # print(ret.text)
- assert ret.status_code == 500
- assert ret.json()['error']['message'] == (
+ _get_sample_fail(
+ url, TOKEN2, {'id': id_},
f'Sample service error code 20000 Unauthorized: User user2 cannot read sample {id_}')
+ _get_sample_fail(
+ url, None, {'id': id_},
+ f'Sample service error code 20000 Unauthorized: Anonymous users cannot read sample {id_}')
+
+ _get_sample_fail(
+ url, None, {'id': id_, 'as_admin': 1},
+ 'Sample service error code 20000 Unauthorized: Anonymous users ' +
+ 'may not act as service administrators.')
+
def test_get_sample_fail_admin_permissions(sample_port):
url = f'http://localhost:{sample_port}'
@@ -1083,19 +1088,25 @@ def test_get_sample_fail_admin_permissions(sample_port):
assert ret.json()['result'][0]['version'] == 1
id_ = ret.json()['result'][0]['id']
+ _get_sample_fail(
+ url, TOKEN4, {'id': id_, 'as_admin': 1},
+ 'Sample service error code 20000 Unauthorized: User user4 does not have the ' +
+ 'necessary administration privileges to run method get_sample')
+
+
+def _get_sample_fail(url, token, params, expected):
+
# user 4 has no admin permissions
- ret = requests.post(url, headers=get_authorized_headers(TOKEN4), json={
+ ret = requests.post(url, headers=get_authorized_headers(token), json={
'method': 'SampleService.get_sample',
'version': '1.1',
'id': '42',
- 'params': [{'id': id_, 'as_admin': 1}]
+ 'params': [params]
})
# print(ret.text)
assert ret.status_code == 500
- assert ret.json()['error']['message'] == (
- 'Sample service error code 20000 Unauthorized: User user4 does not have the ' +
- 'necessary administration privileges to run method get_sample')
+ assert ret.json()['error']['message'] == expected
def test_get_and_replace_acls(sample_port, kafka):