Skip to content
This repository was archived by the owner on Sep 10, 2025. It is now read-only.
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
7 changes: 0 additions & 7 deletions example_files/blog.yaml

This file was deleted.

25 changes: 0 additions & 25 deletions example_files/example_manifest.yaml

This file was deleted.

37 changes: 7 additions & 30 deletions form_builder/templates/form_builder/CLIP_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,20 @@
<h1>eCLIP (CLIPper) Form Builder</h1>
{{ form.as_p }} <!-- main form -->
</div>

<div class="container">
<hr>
<h2>Add new sample (Full paths only)</h2>
<h2>Add multiple samples</h2>
<div class="row">
<label for="experiment">Experiment name (alphanumeric or underscores only, no spaces)</label>
<div class="col"><input class="form-control" type="text" name="experiment" id="experiment" pattern="[a-zA-Z0-9_]+" list="experiment-select"></div>
<datalist name="experiment-select" id="experiment-select">
{% for fastq in SEfastqs %}
<option value="{{fastq.experiment}}">{{ fastq.experiment }}</option>
{% endfor %}
</datalist>
<label for="sample">Sample name (alphanumeric or underscores only, no spaces)</label>
<div class="col"><input class="form-control" type="text" name="sample" id="sample" pattern="[a-zA-Z0-9_]+" list="sample-select"></div>
<datalist name="sample-select" id="sample-select">
{% for fastq in SEfastqs %}
<option value="{{fastq.sample}}">{{ fastq.sample }}</option>
{% endfor %}
</datalist>
<label for="cells">Cells (alphanumeric or underscores only, no spaces)</label>
<div class="col"><input class="form-control" type="text" name="cells" id="cells" pattern="[a-zA-Z0-9_]+" list="cell-select"></div>
<datalist name="cell-select" id="cell-select">
{% for fastq in SEfastqs %}
<option value="{{fastq.cells}}">{{ fastq.cells }}</option>
{% endfor %}
</datalist>
<label for="experiment">Use the Globus file browser to select one or more files.</label>
<button type="submit" name="experiment" class="info"><a href={{ globus_url }}>Globus</a></button>
</div>
<div class="row">
{% include 'form_builder/fastq_submit.html' %}
</div>
<div class="row my-4">
<div class="col-md">
<button type="submit" name="newItem" value="newItem">Add sample</button>
</div>
<ul>Selected Fastqs:</ul>
{% for fi in files %}
<li>{{fi}}</li>
{% endfor %}
</div>
</div>

<div class="container my-4">
<hr>
{% include 'form_builder/fastq_display.html' %}
Expand Down
3 changes: 2 additions & 1 deletion form_builder/templates/form_builder/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ <h2>Skipper</h2>
<p><a class="btn btn-secondary" href="/skipper" role="button">Build forms &raquo;</a></p>
</div>-->
<div class="col-md-4">
<h2>eCLIP (CLIPper)</h2>
<h2>eCLIP (CLIPper)!</h2>
<p>A pipeline designed to identify genomic locations (peaks) of RNA-bound proteins.</p>
<p><a href="https://github.com/yeolab/eclip">Github</a></p>
<p><a class="btn btn-secondary" href="/clipper" role="button">Build Form &raquo;</a></p>
</div>

<!--<div class="col-md-4">
<h2>rnaseqSE form</h2>
<p>Coming soon...</p>
Expand Down
7 changes: 7 additions & 0 deletions form_builder/templates/form_builder/receive-data.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

<div class="row">
<div class="col">
<h2 class="text-center mt-3 mb-5">wat</h2>
</div>
</div>

1 change: 1 addition & 0 deletions form_builder/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@
#path('skipper/', views.SKIPPER_form, name='SKIPPER_form'),
#path('rnaseqSE/', views.rnaseqSE_form, name='rnaseqSE_form'),
#path('rnaseqPE/', views.rnaseqPE_form, name='rnaseqPE_form'),
path('receive-data/', views.receive_data, name='receive_data'),
]
36 changes: 31 additions & 5 deletions form_builder/views.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,46 @@
# imports
from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from mysite import settings
from .models import SingleEndFastq
from django.shortcuts import render
from .forms import CLIPManifestForm#, SkipperConfigManifestForm
from .utils import *

from django.views.decorators.csrf import csrf_exempt
import yaml
from django.http import HttpResponse
import os


@csrf_exempt
@login_required
def CLIP_form(request):
SEfastqs = SingleEndFastq.objects.filter(submitter=request.user)
files = []
try:
SEfastqs = SingleEndFastq.objects.filter(submitter=request.user)
except Exception as e:
print(e)
SEfastqs = []

if request.method == 'POST':
form = CLIPManifestForm(request.POST)
data = make_CLIP_form(form, request)
if data:
return data
else:
if request.GET.get('endpoint'):
base_url = '/projects/ps-yeolab5/seqdata' + request.GET.get('path')
for key in request.GET.keys():
if key.startswith('file'):
files.append(os.path.join(base_url, request.GET.get(key)))
form = CLIPManifestForm()

return render(request, 'form_builder/CLIP_form.html', {'form': form,
'SEfastqs': SEfastqs})
context = {
'form': form,
'SEfastqs': SEfastqs,
'files': files,
'globus_url': "https://app.globus.org/file-manager?method=GET&origin_id=d9358457-3f23-4b35-bbae-68d2f4190545&origin_path=%2F&action=http://localhost:8000/clipper/"
}
return render(request, 'form_builder/CLIP_form.html', context=context)

'''
@login_required
Expand Down Expand Up @@ -142,3 +160,11 @@ def index_view(request):
context = {'LOGIN_URL': settings.LOGIN_URL}
template = 'form_builder/index.html'
return render(request, template, context)


@csrf_exempt
def receive_data(request):
print('post', request.POST)

context = {}
return render(request, 'form_builder/receive-data.html', context)
2 changes: 0 additions & 2 deletions globus_portal_framework/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,3 @@
'get_helper_page_url', 'is_file',

]

default_app_config = 'globus_portal_framework.apps.GlobusPortalFrameworkConfig'
37 changes: 20 additions & 17 deletions globus_portal_framework/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,41 @@
https://docs.globus.org/api/auth
"""
import logging
import urllib
from social_core.backends.globus import (
GlobusOpenIdConnect as GlobusOpenIdConnectBase
)
from social_core.exceptions import AuthForbidden
from globus_portal_framework.gclients import (
get_service_url, GROUPS_SCOPE, GLOBUS_GROUPS_V2_MY_GROUPS
)
import globus_sdk
from globus_sdk.scopes import GroupsScopes
from globus_sdk import config as globus_sdk_config

log = logging.getLogger(__name__)


class GlobusOpenIdConnect(GlobusOpenIdConnectBase):
OIDC_ENDPOINT = get_service_url('auth')

OIDC_ENDPOINT = globus_sdk_config.get_service_url('auth')
GLOBUS_APP_URL = 'https://app.globus.org'
# Fixed by https://github.com/python-social-auth/social-core/pull/577
JWT_ALGORITHMS = ['RS512']

def introspect_token(self, auth_token):
url = urllib.parse.urljoin(self.OIDC_ENDPOINT,
'v2/oauth2/token/introspect')
return self.get_json(
self.OIDC_ENDPOINT + '/v2/oauth2/token/introspect',
url,
method='POST',
data={"token": auth_token,
"include": "session_info,identities_set"},
auth=self.get_key_and_secret()
)

def get_globus_identities(self, auth_token, identities_set):
url = urllib.parse.urljoin(self.OIDC_ENDPOINT,
'/v2/api/identities')
return self.get_json(
self.OIDC_ENDPOINT + '/v2/api/identities',
url,
method='GET',
headers={'Authorization': 'Bearer ' + auth_token},
params={'ids': ','.join(identities_set),
Expand Down Expand Up @@ -128,25 +134,22 @@ def get_user_globus_groups(self, other_tokens):
groups a user belongs. The API is PUBLIC, and no special allowlists
are needed to use it.
"""
groups_scopes = (GroupsScopes.all,
GroupsScopes.view_my_groups_and_memberships)
groups_token = None
for item in other_tokens:
if item.get('scope') == GROUPS_SCOPE:
if item.get('scope') in groups_scopes:
groups_token = item.get('access_token')

if groups_token is None:
raise ValueError(
'You must set the {} scope on {} in order to set an allowed '
'group'.format(GROUPS_SCOPE,
'settings.SOCIAL_AUTH_GLOBUS_SCOPE')
f'You must set one of {groups_scopes} scopes on '
'settings.SOCIAL_AUTH_GLOBUS_SCOPE in order to set an allowed'
)

# Get the allowed group
return self.get_json(
'{}{}'.format(get_service_url('groups'),
GLOBUS_GROUPS_V2_MY_GROUPS),
method='GET',
headers={'Authorization': 'Bearer ' + groups_token}
)
authorizer = globus_sdk.AccessTokenAuthorizer(groups_token)
groups_client = globus_sdk.GroupsClient(authorizer=authorizer)
return groups_client.get_user_groups()

def auth_params(self, state=None):
params = super(GlobusOpenIdConnect, self).auth_params(state)
Expand Down
82 changes: 20 additions & 62 deletions globus_portal_framework/checks.py
Original file line number Diff line number Diff line change
@@ -1,58 +1,17 @@
import logging
from django.core.checks import Error, Warning, register
import os
from django.core.checks import Error, Warning, Info, register
from django.conf import settings
import globus_sdk

from globus_portal_framework.constants import FILTER_TYPES
from globus_portal_framework.gclients import get_globus_environment
from globus_portal_framework.constants import (
FILTER_TYPES, DEFAULT_RESULT_FORMAT_VERSION
)

log = logging.getLogger(__name__)
log.debug('Debugging is active.')


@register()
def check_old_v2_config(app_configs, **kwargs):
warnings = []
title_template = 'Version 0.3.x Update: "{}" is no longer used'
OLD_SETTINGS = {
'ENTRY_SERVICE_VARS':
{'hint': 'These are now defined in SEARCH_INDEXES under "fields"'},
'SEARCH_INDEX':
{'hint': 'This is now defined in SEARCH_INDEXES as "uuid"'},
'SEARCH_SCHEMA':
{'hint': 'The JSON in the search schema file have been moved to '
'SEARCH_INDEXES, see "fields" and "facets"'},
'SEARCH_MAPPER':
{'hint': 'Please replace this with a function in SEARCH_INDEXES '
'"fields" for your index. See the README for examples'},
'SEARCH_ENTRY_FIELD_PATH':
{'hint': 'The framework no longer assumes all data resides under '
'this field, and it has now been removed.'}
}
for name, warn_opts in OLD_SETTINGS.items():
if getattr(settings, name, None):
warnings.append(Warning(title_template.format(name),
hint=warn_opts.get('hint'),
obj=settings)
)
return warnings


@register()
def check_old_apps(app_configs, **kwargs):
installed_apps = getattr(settings, 'INSTALLED_APPS', [])
old_apps = ['globus_portal_framework.search',
'globus_portal_framework.transfer']
if not installed_apps:
return []
warn = '{} is now built in, and no longer needs to be explicitly added'
hint = 'Remove {} from settings.INSTALLED_APPS'
return [Warning(warn.format(oa),
hint=hint.format(oa),
obj=settings)
for oa in old_apps if oa in installed_apps]


@register()
def check_search_indexes(app_configs, **kwargs):
errors = []
Expand All @@ -66,23 +25,23 @@ def check_search_indexes(app_configs, **kwargs):
id = r.data['id']
except globus_sdk.SearchAPIError:
pass
hint = f'Search UUID for "{index_name}" is "{id}".' if id else None
errors.append(Error(
'Could not find "uuid" for settings.SEARCH_INDEXES.{}'
''.format(index_name),
'Could not find "uuid" for '
f'settings.SEARCH_INDEXES.{index_name}',
obj=settings,
hint=('Search UUID for "{}" is "{}".'.format(index_name, id)
if id else None),
hint=hint,
id='globus_portal_framework.settings.E001'
)
)
if idata.get('result_format_version') == '2019-08-27':
rf_version = idata.get('result_format_version')
if rf_version and rf_version != DEFAULT_RESULT_FORMAT_VERSION:
errors.append(Warning(
'Globus Portal Framework does not support '
'result_format_version=="2019-08-27"',
f'result_format_version=="{rf_version}"',
obj=settings,
hint=('Suggested you unset '
'settings.SEARCH_INDEXES.{}.result_format_version'
''.format(index_name)),
hint=('Suggested you unset settings.SEARCH_INDEXES.'
f'{index_name}.result_format_version'),
id='globus_portal_framework.settings.E002'
)
)
Expand All @@ -92,17 +51,16 @@ def check_search_indexes(app_configs, **kwargs):
Warning('SEARCH_INDEXES.{}.filter_match is invalid.'
''.format(index_name),
obj=settings,
hint='Must be one of {}'.format(
tuple(FILTER_TYPES.keys()))
hint=f'Must be one of {tuple(FILTER_TYPES.keys())}'
))
return errors


@register()
def check_globus_env(app_configs, **kwargs):
env = get_globus_environment()
# 'default' is used in Globus SDK v2, 'production' in v3
if env not in ['default', 'production']:
return [Warning('Environment set to "{}", unset with '
'"unset GLOBUS_SDK_ENVIRONMENT"'.format(env))]
env = os.getenv('GLOBUS_SDK_ENVIRONMENT')
if env and env != 'production':
return [Info(f'GLOBUS_SDK_ENVIRONMENT set to "{env}".',
hint='Non-production services may contain experimental '
'features.')]
return []
2 changes: 1 addition & 1 deletion globus_portal_framework/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
'missing'
]
# https://docs.globus.org/api/search/search/#request_documents
DEFAULT_RESULT_FORMAT_VERSION = '2017-09-01'
DEFAULT_RESULT_FORMAT_VERSION = '2019-08-27'

BASE_TEMPLATES = 'globus-portal-framework/v2/'

Expand Down
Loading