Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List all available mapsets (issue 162) #249

Merged
merged 10 commits into from
Oct 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/actinia_core/models/response_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,28 @@ class SimpleResponseModel(Schema):
required = ["status", "message"]


class MapsetListResponseModel(Schema):
"""Response schema that is used to list all mapsets available to the user.

"""
type = 'object'
properties = {
'status': {
'type': 'string',
'description': 'The status of the request'
},
'available_mapsets': {
'type': 'array',
'items': {'type': 'string'},
'description': ('The names of all available mapsets with'
' corresponding locations in the global database')
}
}
required = ["status", "available_mapsets"]
example = {"status": "success", "available_mapsets":
["nc_spm_08/PERMANENT", "latlong_wgs84/PERMANENT"]}


class LockedMapsetListResponseModel(Schema):
"""Response schema that is used to list all locked mapsets.

Expand Down
81 changes: 70 additions & 11 deletions src/actinia_core/rest/mapsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
Mapset resources for information across all locations

* List all mapset locks
* TODO: List all mapsets in all locations
* List all mapsets in all locations available to a user
"""

from flask import jsonify, make_response
Expand All @@ -36,10 +36,11 @@
from actinia_core.core.common.api_logger import log_api_call
from actinia_core.core.common.config import global_config
from actinia_core.core.redis_lock import RedisLockingInterface
from actinia_core.core.redis_user import RedisUserInterface
from actinia_core.models.response_models import SimpleResponseModel, \
LockedMapsetListResponseModel
MapsetListResponseModel, LockedMapsetListResponseModel
from .user_auth import check_user_permissions
from .user_auth import very_admin_role
# from .user_auth import very_admin_role
# from .common.response_models import MapsetInfoModel


Expand All @@ -53,23 +54,37 @@ class AllMapsetsListingResourceAdmin(ResourceBase):
""" Get all locked mapsets
"""
decorators = [log_api_call, check_user_permissions,
very_admin_role, auth.login_required]
auth.login_required]

@swagger.doc({
'tags': ['Mapsets'],
'description': 'Get all locked mapsets. '
'Minimum required user role: admin.',
'description': 'List available or locked mapsets.',
'parameters': [
{
'in': 'path',
'name': 'mapsets',
'type': 'string',
'description': "List all mapsets in the global database available "
"to the authenticated user."
},
{
'in': 'path',
'name': 'status',
'type': 'string',
'description': ("If set to 'locked', list all locked mapsets across"
" all locations.")
'description': ("If set to 'locked', list all locked mapsets across "
"all locations. Minimum required user role: admin.")
},
{
'in': 'path',
'name': 'user',
'type': 'string',
'description': ("List all mapsets in the global database available "
"to the specified user. "
"Minimum required user role: admin")
}],
'responses': {
'200': {
'description': 'Get a list of (locked) mapsets ',
'description': 'Returns a list of available (or locked) mapsets ',
'schema': LockedMapsetListResponseModel
},
'500': {
Expand All @@ -79,8 +94,16 @@ class AllMapsetsListingResourceAdmin(ResourceBase):
}
})
def get(self):

if 'status' in request.args:
if request.args['status'] == "locked":
if self.user.has_superadmin_role() is False:
return make_response(jsonify(SimpleResponseModel(
status="error",
message=("Unable to list locked mapsets You are not authorized"
" for this request. "
"Minimum required user role: superadmin")
)), 401)
redis_interface = RedisLockingInterface()
kwargs = dict()
kwargs["host"] = global_config.REDIS_SERVER_URL
Expand Down Expand Up @@ -108,5 +131,41 @@ def get(self):
message="Unable to list locked mapsets: Exception %s"
% (str(e)))), 500)
else:
# TODO: https://github.com/mundialis/actinia_core/issues/162
pass
redis_interface = RedisUserInterface()
kwargs = dict()
kwargs["host"] = global_config.REDIS_SERVER_URL
kwargs["port"] = global_config.REDIS_SERVER_PORT
if (global_config.REDIS_SERVER_PW
and global_config.REDIS_SERVER_PW is not None):
kwargs["password"] = global_config.REDIS_SERVER_PW
redis_interface.connect(**kwargs)
if "user" in request.args:
user = request.args["user"]
if self.user.has_superadmin_role() is False:
redis_interface.disconnect()
return make_response(jsonify(SimpleResponseModel(
status="error",
message=(f"Unable to list mapsets for user {user}: You are not"
" authorized for this request. "
"Minimum required user role: superadmin")
)), 401)
else:
user = self.user.get_id()
locs_mapsets = (redis_interface.get_credentials(user)["permissions"]
["accessible_datasets"])
redis_interface.disconnect()
mapsets = []
for location in locs_mapsets:
for mapset in locs_mapsets[location]:
mapsets.append(f"{location}/{mapset}")
try:
return make_response(jsonify(MapsetListResponseModel(
status="success",
available_mapsets=mapsets,
)), 200)

except Exception as e:
return make_response(jsonify(SimpleResponseModel(
status="error",
message="Unable to list mapsets: Exception %s"
% (str(e)))), 500)
43 changes: 41 additions & 2 deletions tests/test_mapsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@
class MapsetsTestCase(ActiniaResourceTestCaseBase):

test_mapsets = [str(uuid.uuid4()), str(uuid.uuid4())]
test_user = f"test_user_{str(uuid.uuid4())}"
accessible_datasets = {"nc_spm_08": ["PERMANENT"],
"latlong_wgs84": ["PERMANENT"]}
ref_mapsets = []
for location in accessible_datasets:
for mapset in accessible_datasets[location]:
ref_mapsets.append(f"{location}/{mapset}")

@classmethod
def setUpClass(cls):
super(ActiniaResourceTestCaseBase, cls).setUpClass()

# Create test_user
cls.test_user_id, cls.test_user_group, cls.test_user_auth_header = cls.create_user(
name=cls.test_user, role="user",
accessible_datasets=cls.accessible_datasets)

def tearDown(self):
# unlock and delete the test mapsets
Expand All @@ -64,9 +80,9 @@ def test_two_locked_mapsets(self):
for mapset in self.test_mapsets:
self.create_new_mapset(mapset)
rvpost = self.server.post(URL_PREFIX + '/locations/nc_spm_08/mapsets/%s/lock' % mapset,
headers=self.admin_auth_header)
headers=self.root_auth_header)
rv = self.server.get(URL_PREFIX + '/mapsets?status=locked',
headers=self.admin_auth_header)
headers=self.root_auth_header)
self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i" % rv.status_code)
self.assertEqual(rv.mimetype, "application/json", "Wrong mimetype %s" % rv.mimetype)
rvdata = json_load(rv.data)
Expand All @@ -87,6 +103,29 @@ def test_user_error(self):
headers=self.user_auth_header)
self.assertEqual(rv.status_code, 401, "Status code is not 401: %s" % rv.status_code)

def test_user_own_mapsets(self):
"""Test if user can list available mapsets
"""
rv = self.server.get(URL_PREFIX + '/mapsets', headers=self.test_user_auth_header)
self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i" % rv.status_code)
rvdata = json_load(rv.data)
mapsets = rvdata["available_mapsets"]
self.assertEqual(mapsets, self.ref_mapsets, "Mapset list is not equal to reference mapset list")

def test_superadmin_user_mapsets(self):
"""Test if superadmin can list available mapsets from test_user
"""
rv = self.server.get(URL_PREFIX + f'/mapsets?user={self.test_user}', headers=self.root_auth_header)
self.assertEqual(rv.status_code, 200, "HTML status code is wrong %i" % rv.status_code)
rvdata = json_load(rv.data)
mapsets = rvdata["available_mapsets"]
self.assertEqual(mapsets, self.ref_mapsets, "Mapset list is not equal to reference mapset list")

def test_user_user_mapsets(self):
# Test if test_user can list available mapsets from user
rv = self.server.get(URL_PREFIX + f'/mapsets?user={self.test_user}', headers=self.user_auth_header)
self.assertEqual(rv.status_code, 401, "Status code is not 401: %s" % rv.status_code)


if __name__ == '__main__':
unittest.main()