Skip to content
Draft
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
19 changes: 19 additions & 0 deletions globus_portal_framework/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,22 @@ def check_allowed_groups(app_configs, **kwargs):
errors.append(e)

return errors


@register
def check_gpreview(app_configs, **kwargs):
"""Simplistic check: GLOBUS_PREVIEW_COLLECTIONS must be a dict of {uuid: https_url}"""
s = getattr(settings, 'GLOBUS_PREVIEW_COLLECTIONS', {})

catchall = [
Error('GLOBUS_PREVIEW_COLLECTIONS must be a dict of {uuid: https_url}',
obj=s, id='globus_portal_framework.settings.E005')
]

if not isinstance(s, dict):
return catchall

for k, v in s.items():
if len(k.replace('-', '')) != 32 or not v.startswith('https'):
return catchall
return []
7 changes: 7 additions & 0 deletions globus_portal_framework/exc.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ def __init__(self, **kwargs):
self.message = 'Preview is unable to display binary data.'


class PreviewCollectionError(GlobusPortalException):
DEFAULT_MESSAGE = 'Could not determine how to access the specified collection for Preview Mode'
def __init__(self, message=DEFAULT_MESSAGE, **kwargs):
super().__init__(message=message, **kwargs)
self.code = 'BadPreviewConfig'


class ExpiredGlobusToken(GlobusPortalException):
def __init__(self, token_name='', **kwargs):
super().__init__(**kwargs)
Expand Down
2 changes: 1 addition & 1 deletion globus_portal_framework/gclients.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def is_globus_user(user):
return False


def load_globus_access_token(user: "django.contrib.auth.models.User", token_name: str):
def load_globus_access_token(user: "django.contrib.auth.models.User", token_name: str) -> t.Union[str, None]:
"""
Load a globus user access token using a provided lookup by resource server.
Scopes MUST have already been configured in settings.py, and additionally
Expand Down
67 changes: 67 additions & 0 deletions globus_portal_framework/gpreview.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""
Functions related to the "file preview" functionality
"""
import logging
import typing as t
from urllib.parse import urljoin

from django.conf import settings
from django.urls import reverse

from globus_portal_framework.exc import PreviewCollectionError

log = logging.getLogger(__name__)


def get_https_url(collection_uuid: str) -> t.Union[str, None]:
"""
Get the HTTPS server URL associated with a collection UUID

Enforces an assumption that the site is only allowed to talk to (authenticated) collections that
are whitelisted in app settings
"""
whitelist = getattr(settings, 'GLOBUS_PREVIEW_COLLECTIONS', {})
try:
return whitelist[collection_uuid]
except KeyError:
raise PreviewCollectionError(message=f'No HTTPS URL available for collection UUID {collection_uuid}')


def get_render_options(url: str=None,
collection_id: str=None, path: str=None,
is_authenticated: bool=False,
render_mode: str='auto'):
"""
Generate "render options" used by the client-side preview feature.

Translates collection id + path into URLs based on info in app config
"""
token_endpoint = None

if not url and not collection_id and not path:
# There's nothing to render, and it makes sense to hide the render widget on page
raise PreviewCollectionError(message='Please specify how to locate the file')

if (collection_id and path) and not url:
# Translate collection IDs into "where is the file and how to access it"
try:
base = get_https_url(collection_id)
except PreviewCollectionError as e:
log.error(f'Preview mode requested a file from unrecognized storage collection: "{collection_id}". Check GLOBUS_PREVIEW_COLLECTIONS setting.')
raise e

url = urljoin(base, path)

# Now that we know it's a globus collections, answer the question:
# "How does the renderer get globus access credentials?" (if appropriate)
if is_authenticated:
token_endpoint = reverse('get-token', kwargs={'collection_id': collection_id})

return {
'url': url,
'render_mode': render_mode,

# null if file is public
'collection_id': collection_id,
'token_endpoint': token_endpoint,
}
Empty file.
Loading