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

John conroy/switch auth globus groups #2239

Merged
merged 5 commits into from
Nov 17, 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
1 change: 1 addition & 0 deletions CHANGELOG-switch-auth-globus-groups.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Switch Globus authentication from Globus Nexus to Globus Groups.
4 changes: 2 additions & 2 deletions context/.storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ export const parameters = {
}

const mockEndpoints = {};
const mockNexusToken=""
const mockGroupsToken=""

export const decorators = [
(Story) => (
<Providers endpoints={mockEndpoints} nexusToken={mockNexusToken}>
<Providers endpoints={mockEndpoints} groupsToken={mockGroupsToken}>
<Story />
</Providers>
),
Expand Down
10 changes: 5 additions & 5 deletions context/app/api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ class VitessceConfLiftedUUID:


class ApiClient():
def __init__(self, url_base=None, nexus_token=None):
def __init__(self, url_base=None, groups_token=None):
self.url_base = url_base
self.nexus_token = nexus_token
self.groups_token = groups_token

def _request(self, url, body_json=None):
headers = {'Authorization': 'Bearer ' + self.nexus_token} if self.nexus_token else {}
headers = {'Authorization': 'Bearer ' + self.groups_token} if self.groups_token else {}
try:
response = (
requests.post(url, headers=headers, json=body_json)
Expand Down Expand Up @@ -109,7 +109,7 @@ def get_entity(self, uuid=None, hbm_id=None):
body_json=query)

hits = response_json['hits']['hits']
return _get_entity_from_hits(hits, has_token=self.nexus_token, uuid=uuid, hbm_id=hbm_id)
return _get_entity_from_hits(hits, has_token=self.groups_token, uuid=uuid, hbm_id=hbm_id)

def get_latest_entity_uuid(self, uuid, type):
lowercase_type = type.lower()
Expand Down Expand Up @@ -147,7 +147,7 @@ def get_vitessce_conf_cells_and_lifted_uuid(self, entity):
if isinstance(Builder, NullViewConfBuilder):
vc = Builder()
else:
vc = Builder(entity, self.nexus_token)
vc = Builder(entity, self.groups_token)
return VitessceConfLiftedUUID(vc.get_conf_cells(), None)
except Exception:
message = f'Building vitessce conf threw error: {traceback.format_exc()}'
Expand Down
24 changes: 12 additions & 12 deletions context/app/api/vitessce_confs/assay_confs.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def get_conf_cells(self):
for tile in sorted(found_tiles):
vc = SPRMJSONViewConfBuilder(
entity=self._entity,
nexus_token=self._nexus_token,
groups_token=self._groups_token,
is_mock=self._is_mock,
base_name=tile,
imaging_path=CODEX_TILE_DIR
Expand All @@ -149,8 +149,8 @@ class RNASeqViewConfBuilder(AbstractScatterplotViewConfBuilder):
from h5ad-to-arrow.cwl (August 2020 release).
"""

def __init__(self, entity, nexus_token, is_mock=False):
super().__init__(entity, nexus_token, is_mock)
def __init__(self, entity, groups_token, is_mock=False):
super().__init__(entity, groups_token, is_mock)
# All "file" Vitessce objects that do not have wrappers.
self._files = [
{
Expand All @@ -172,8 +172,8 @@ class ATACSeqViewConfBuilder(AbstractScatterplotViewConfBuilder):
from h5ad-to-arrow.cwl.
"""

def __init__(self, entity, nexus_token, is_mock=False):
super().__init__(entity, nexus_token, is_mock)
def __init__(self, entity, groups_token, is_mock=False):
super().__init__(entity, groups_token, is_mock)
# All "file" Vitessce objects that do not have wrappers.
self._files = [
{
Expand Down Expand Up @@ -210,7 +210,7 @@ def get_conf_cells(self):
for region in sorted(found_regions):
vc = SPRMAnnDataViewConfBuilder(
entity=self._entity,
nexus_token=self._nexus_token,
groups_token=self._groups_token,
is_mock=self._is_mock,
base_name=region,
imaging_path=STITCHED_IMAGE_DIR,
Expand All @@ -234,8 +234,8 @@ class RNASeqAnnDataZarrViewConfBuilder(ViewConfBuilder):
https://portal.hubmapconsortium.org/browse/dataset/e65175561b4b17da5352e3837aa0e497
"""

def __init__(self, entity, nexus_token, is_mock=False):
super().__init__(entity, nexus_token, is_mock)
def __init__(self, entity, groups_token, is_mock=False):
super().__init__(entity, groups_token, is_mock)
# Spatially resolved RNA-seq assays require some special handling,
# and others do not.
self._is_spatial = False
Expand Down Expand Up @@ -290,8 +290,8 @@ class SpatialRNASeqAnnDataZarrViewConfBuilder(RNASeqAnnDataZarrViewConfBuilder):
https://portal.hubmapconsortium.org/browse/dataset/e65175561b4b17da5352e3837aa0e497
"""

def __init__(self, entity, nexus_token, is_mock=False):
super().__init__(entity, nexus_token, is_mock)
def __init__(self, entity, groups_token, is_mock=False):
super().__init__(entity, groups_token, is_mock)
# Spatially resolved RNA-seq assays require some special handling,
# and others do not.
self._is_spatial = True
Expand Down Expand Up @@ -322,8 +322,8 @@ class IMSViewConfBuilder(ImagePyramidViewConfBuilder):
of all the channels separated out.
"""

def __init__(self, entity, nexus_token, is_mock=False):
super().__init__(entity, nexus_token, is_mock)
def __init__(self, entity, groups_token, is_mock=False):
super().__init__(entity, groups_token, is_mock)
# Do not show the separated mass-spec images.
self.image_pyramid_regex = (
re.escape(IMAGE_PYRAMID_DIR) + r"(?!/ometiffs/separate/)"
Expand Down
51 changes: 27 additions & 24 deletions context/app/api/vitessce_confs/base_confs.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,19 @@ def get_conf_cells(self):


class ViewConfBuilder:
def __init__(self, entity=None, nexus_token=None, is_mock=False):
def __init__(self, entity=None, groups_token=None, is_mock=False):
"""Object for building the vitessce configuration.
:param dict entity: Entity response from search index (from the entity API)
:param str nexus_token: Nexus token for use in authenticating API
:param str groups_token: Groups token for use in authenticating API
:param bool is_mock: Wether or not this class is being mocked.

>>> vc = ViewConfBuilder(entity={"uuid": "uuid"}, nexus_token='nexus_token', is_mock=True)
>>> vc = ViewConfBuilder(
... entity={"uuid": "uuid"}, groups_token='groups_token', is_mock=True)

"""

self._uuid = entity["uuid"]
self._nexus_token = nexus_token
self._groups_token = groups_token
self._entity = entity
self._is_mock = is_mock
self._files = []
Expand All @@ -54,12 +55,13 @@ def _replace_url_in_file(self, file):
:param dict file: File dict which will have its rel_path replaced by url
:rtype: dict The file with rel_path replaced by url
>>> from pprint import pprint
>>> vc = ViewConfBuilder(entity={"uuid": "uuid"}, nexus_token='nexus_token', is_mock=True)
>>> vc = ViewConfBuilder(
... entity={"uuid": "uuid"}, groups_token='groups_token', is_mock=True)
>>> file = { 'data_type': 'CELLS', 'file_type': 'cells.json', 'rel_path': 'cells.json' }
>>> pprint(vc._replace_url_in_file(file))
{'data_type': 'CELLS',\n\
'file_type': 'cells.json',\n\
'url': 'https://example.com/uuid/cells.json?token=nexus_token'}
'url': 'https://example.com/uuid/cells.json?token=groups_token'}
"""

return {
Expand All @@ -71,20 +73,21 @@ def _replace_url_in_file(self, file):
def _build_assets_url(self, rel_path, use_token=True):
"""Create a url for an asset.
:param str rel_path: The path off of which the url should be built
:param bool use_token: Whether or not to append a nexus token to the URL, default True
:param bool use_token: Whether or not to append a groups token to the URL, default True
:rtype: dict The file with rel_path replaced by url

>>> vc = ViewConfBuilder(entity={"uuid": "uuid"}, nexus_token='nexus_token', is_mock=True)
>>> vc = ViewConfBuilder(
... entity={"uuid": "uuid"}, groups_token='groups_token', is_mock=True)
>>> vc._build_assets_url("rel_path/to/clusters.ome.tiff")
'https://example.com/uuid/rel_path/to/clusters.ome.tiff?token=nexus_token'
'https://example.com/uuid/rel_path/to/clusters.ome.tiff?token=groups_token'

"""
if not self._is_mock:
assets_endpoint = current_app.config["ASSETS_ENDPOINT"]
else:
assets_endpoint = MOCK_URL
base_url = urllib.parse.urljoin(assets_endpoint, f"{self._uuid}/{rel_path}")
token_param = urllib.parse.urlencode({"token": self._nexus_token})
token_param = urllib.parse.urlencode({"token": self._groups_token})
return f"{base_url}?{token_param}" if use_token else base_url

def _get_request_init(self):
Expand All @@ -93,14 +96,14 @@ def _get_request_init(self):
not the above _build_assets_url function.

>>> entity = {"uuid": "uuid", "status": "QA"}
>>> vc = ViewConfBuilder(entity=entity, nexus_token='nexus_token', is_mock=True)
>>> vc = ViewConfBuilder(entity=entity, groups_token='groups_token', is_mock=True)
>>> vc._get_request_init()
{'headers': {'Authorization': 'Bearer nexus_token'}}
{'headers': {'Authorization': 'Bearer groups_token'}}
>>> entity = {"uuid": "uuid", "status": "Published"}
>>> vc = ViewConfBuilder(entity=entity, nexus_token='nexus_token', is_mock=True)
>>> vc = ViewConfBuilder(entity=entity, groups_token='groups_token', is_mock=True)
>>> assert vc._get_request_init() is None # None because dataset is Published (public)
"""
request_init = {"headers": {"Authorization": f"Bearer {self._nexus_token}"}}
request_init = {"headers": {"Authorization": f"Bearer {self._groups_token}"}}
# Extra headers outside of a select few cause extra CORS-preflight requests which
# can slow down the webpage. If the dataset is published, we don't need to use
# heaeder to authenticate access to the assets API.
Expand All @@ -113,7 +116,7 @@ def _get_file_paths(self):

>>> files = [{ "rel_path": "path/to/file" }, { "rel_path": "path/to/other_file" }]
>>> entity = {"uuid": "uuid", "files": files}
>>> vc = ViewConfBuilder(entity=entity, nexus_token='nexus_token', is_mock=True)
>>> vc = ViewConfBuilder(entity=entity, groups_token='groups_token', is_mock=True)
>>> vc._get_file_paths()
['path/to/file', 'path/to/other_file']
"""
Expand All @@ -130,11 +133,11 @@ def _get_img_and_offset_url(self, img_path, img_dir):

>>> from pprint import pprint
>>> vc = AbstractImagingViewConfBuilder(entity={ "uuid": "uuid" },\
nexus_token='nexus_token', is_mock=True)
groups_token='groups_token', is_mock=True)
>>> pprint(vc._get_img_and_offset_url("rel_path/to/clusters.ome.tiff",\
"rel_path/to"))
('https://example.com/uuid/rel_path/to/clusters.ome.tiff?token=nexus_token',\n\
'https://example.com/uuid/output_offsets/clusters.offsets.json?token=nexus_token')
('https://example.com/uuid/rel_path/to/clusters.ome.tiff?token=groups_token',\n\
'https://example.com/uuid/output_offsets/clusters.offsets.json?token=groups_token')

"""
img_url = self._build_assets_url(img_path)
Expand All @@ -159,13 +162,13 @@ def _setup_view_config_raster(self, vc, dataset, disable_3d=[]):


class ImagePyramidViewConfBuilder(AbstractImagingViewConfBuilder):
def __init__(self, entity, nexus_token, is_mock=False):
def __init__(self, entity, groups_token, is_mock=False):
"""Wrapper class for creating a standard view configuration for image pyramids,
i.e for high resolution viz-lifted imaging datasets like
https://portal.hubmapconsortium.org/browse/dataset/dc289471333309925e46ceb9bafafaf4
"""
self.image_pyramid_regex = IMAGE_PYRAMID_DIR
super().__init__(entity, nexus_token, is_mock)
super().__init__(entity, groups_token, is_mock)

def get_conf_cells(self):
file_paths_found = self._get_file_paths()
Expand Down Expand Up @@ -269,9 +272,9 @@ class SPRMJSONViewConfBuilder(SPRMViewConfBuilder):
https://portal.hubmapconsortium.org/browse/dataset/dc31a6d06daa964299224e9c8d6cafb3
"""

def __init__(self, entity, nexus_token, is_mock=False, **kwargs):
def __init__(self, entity, groups_token, is_mock=False, **kwargs):
# All "file" Vitessce objects that do not have wrappers.
super().__init__(entity, nexus_token, is_mock)
super().__init__(entity, groups_token, is_mock)
# These are both something like R001_X009_Y009 because
# there is no mask used here or shared name with the mask data.
self._base_name = kwargs["base_name"]
Expand Down Expand Up @@ -348,8 +351,8 @@ class SPRMAnnDataViewConfBuilder(SPRMViewConfBuilder):
of the image and mask relative to image_pyramid_regex
"""

def __init__(self, entity, nexus_token, is_mock=False, **kwargs):
super().__init__(entity, nexus_token, is_mock)
def __init__(self, entity, groups_token, is_mock=False, **kwargs):
super().__init__(entity, groups_token, is_mock)
self._base_name = kwargs["base_name"]
self._mask_name = kwargs["mask_name"]
self._image_name = kwargs["image_name"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
"name": "Visualization Files",
"files": [
{
"url": "https://example.com/210d118a14c8624b6bb9610a9062656e/output/umap_coords_clusters.cells.json?token=nexus_token",
"url": "https://example.com/210d118a14c8624b6bb9610a9062656e/output/umap_coords_clusters.cells.json?token=groups_token",
"type": "cells",
"fileType": "cells.json"
},
{
"url": "https://example.com/210d118a14c8624b6bb9610a9062656e/output/umap_coords_clusters.cell-sets.json?token=nexus_token",
"url": "https://example.com/210d118a14c8624b6bb9610a9062656e/output/umap_coords_clusters.cell-sets.json?token=groups_token",
"type": "cell-sets",
"fileType": "cell-sets.json"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
},
"requestInit": {
"headers": {
"Authorization": "Bearer nexus_token"
"Authorization": "Bearer groups_token"
}
}
},
Expand Down Expand Up @@ -67,7 +67,7 @@
],
"requestInit": {
"headers": {
"Authorization": "Bearer nexus_token"
"Authorization": "Bearer groups_token"
}
}
},
Expand All @@ -80,7 +80,7 @@
},
"requestInit": {
"headers": {
"Authorization": "Bearer nexus_token"
"Authorization": "Bearer groups_token"
}
}
},
Expand All @@ -95,19 +95,19 @@
{
"name": "reg1_stitched_expressions",
"type": "ome-tiff",
"url": "https://example.com/2f8d43199ca3167e991b320038024b77/ometiff-pyramids/stitched/expressions/reg1_stitched_expressions.ome.tiff?token=nexus_token",
"url": "https://example.com/2f8d43199ca3167e991b320038024b77/ometiff-pyramids/stitched/expressions/reg1_stitched_expressions.ome.tiff?token=groups_token",
"metadata": {
"isBitmask": false,
"omeTiffOffsetsUrl": "https://example.com/2f8d43199ca3167e991b320038024b77/output_offsets/stitched/expressions/reg1_stitched_expressions.offsets.json?token=nexus_token"
"omeTiffOffsetsUrl": "https://example.com/2f8d43199ca3167e991b320038024b77/output_offsets/stitched/expressions/reg1_stitched_expressions.offsets.json?token=groups_token"
}
},
{
"name": "reg1_stitched_mask",
"type": "ome-tiff",
"url": "https://example.com/2f8d43199ca3167e991b320038024b77/ometiff-pyramids/stitched/mask/reg1_stitched_mask.ome.tiff?token=nexus_token",
"url": "https://example.com/2f8d43199ca3167e991b320038024b77/ometiff-pyramids/stitched/mask/reg1_stitched_mask.ome.tiff?token=groups_token",
"metadata": {
"isBitmask": true,
"omeTiffOffsetsUrl": "https://example.com/2f8d43199ca3167e991b320038024b77/output_offsets/stitched/mask/reg1_stitched_mask.offsets.json?token=nexus_token"
"omeTiffOffsetsUrl": "https://example.com/2f8d43199ca3167e991b320038024b77/output_offsets/stitched/mask/reg1_stitched_mask.offsets.json?token=groups_token"
}
}
]
Expand Down Expand Up @@ -229,7 +229,7 @@
},
"requestInit": {
"headers": {
"Authorization": "Bearer nexus_token"
"Authorization": "Bearer groups_token"
}
}
},
Expand Down Expand Up @@ -269,7 +269,7 @@
],
"requestInit": {
"headers": {
"Authorization": "Bearer nexus_token"
"Authorization": "Bearer groups_token"
}
}
},
Expand All @@ -282,7 +282,7 @@
},
"requestInit": {
"headers": {
"Authorization": "Bearer nexus_token"
"Authorization": "Bearer groups_token"
}
}
},
Expand All @@ -297,19 +297,19 @@
{
"name": "reg2_stitched_expressions",
"type": "ome-tiff",
"url": "https://example.com/2f8d43199ca3167e991b320038024b77/ometiff-pyramids/stitched/expressions/reg2_stitched_expressions.ome.tiff?token=nexus_token",
"url": "https://example.com/2f8d43199ca3167e991b320038024b77/ometiff-pyramids/stitched/expressions/reg2_stitched_expressions.ome.tiff?token=groups_token",
"metadata": {
"isBitmask": false,
"omeTiffOffsetsUrl": "https://example.com/2f8d43199ca3167e991b320038024b77/output_offsets/stitched/expressions/reg2_stitched_expressions.offsets.json?token=nexus_token"
"omeTiffOffsetsUrl": "https://example.com/2f8d43199ca3167e991b320038024b77/output_offsets/stitched/expressions/reg2_stitched_expressions.offsets.json?token=groups_token"
}
},
{
"name": "reg2_stitched_mask",
"type": "ome-tiff",
"url": "https://example.com/2f8d43199ca3167e991b320038024b77/ometiff-pyramids/stitched/mask/reg2_stitched_mask.ome.tiff?token=nexus_token",
"url": "https://example.com/2f8d43199ca3167e991b320038024b77/ometiff-pyramids/stitched/mask/reg2_stitched_mask.ome.tiff?token=groups_token",
"metadata": {
"isBitmask": true,
"omeTiffOffsetsUrl": "https://example.com/2f8d43199ca3167e991b320038024b77/output_offsets/stitched/mask/reg2_stitched_mask.offsets.json?token=nexus_token"
"omeTiffOffsetsUrl": "https://example.com/2f8d43199ca3167e991b320038024b77/output_offsets/stitched/mask/reg2_stitched_mask.offsets.json?token=groups_token"
}
}
]
Expand Down
Loading