Skip to content

Commit

Permalink
Merge pull request #691 from isb-cgc/isb-cgc-prod-sp
Browse files Browse the repository at this point in the history
Sprint 28
  • Loading branch information
s-paquette authored Jul 31, 2018
2 parents 3f44c87 + fddeb52 commit 3a24001
Show file tree
Hide file tree
Showing 15 changed files with 3,300 additions and 619 deletions.
876 changes: 876 additions & 0 deletions accounts/dcf_support.py

Large diffs are not rendered by default.

979 changes: 979 additions & 0 deletions accounts/dcf_views.py

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions accounts/migrations/0016_auto_20180524_1033.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.10 on 2018-05-24 17:33
from __future__ import unicode_literals

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('accounts', '0015_googleproject_active'),
]

operations = [
migrations.CreateModel(
name='DCFToken',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('nih_username', models.TextField()),
('nih_username_lower', models.CharField(max_length=128)),
('dcf_user', models.CharField(max_length=128)),
('access_token', models.TextField()),
('refresh_token', models.TextField()),
('user_token', models.TextField()),
('decoded_jwt', models.TextField()),
('expires_at', models.DateTimeField()),
('refresh_expires_at', models.DateTimeField()),
('google_id', models.TextField(null=True)),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.AlterUniqueTogether(
name='dcftoken',
unique_together=set([('user', 'nih_username_lower')]),
),
]
24 changes: 24 additions & 0 deletions accounts/migrations/0017_auto_20180629_1416.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.10 on 2018-06-29 21:16
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('accounts', '0016_auto_20180524_1033'),
]

operations = [
migrations.AlterField(
model_name='bucket',
name='bucket_name',
field=models.CharField(max_length=155, null=True, unique=True),
),
migrations.AlterUniqueTogether(
name='bqdataset',
unique_together=set([('google_project', 'dataset_name')]),
),
]
22 changes: 21 additions & 1 deletion accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def active_service_accounts(self):

class Bucket(models.Model):
google_project = models.ForeignKey(GoogleProject, null=False)
bucket_name = models.CharField(null=True,max_length=155)
bucket_name = models.CharField(null=True,max_length=155, unique=True)
bucket_permissions = models.TextField(null=True)

def __str__(self):
Expand All @@ -94,6 +94,9 @@ class BqDataset(models.Model):
google_project = models.ForeignKey(GoogleProject, null=False)
dataset_name = models.CharField(null=False, max_length=155)

class Meta:
unique_together = (("google_project", "dataset_name"),)


class AuthorizedDataset(models.Model):
name = models.CharField(max_length=256, null=False)
Expand Down Expand Up @@ -157,3 +160,20 @@ class ServiceAccountAuthorizedDatasets(models.Model):
service_account = models.ForeignKey(ServiceAccount, null=False)
authorized_dataset = models.ForeignKey(AuthorizedDataset, null=False)
authorized_date = models.DateTimeField(auto_now=True)


class DCFToken(models.Model):
user = models.OneToOneField(User, null=False)
nih_username = models.TextField(null=False)
nih_username_lower = models.CharField(max_length=128, null=False) # Must be limited to include in constraint
dcf_user = models.CharField(max_length=128, null=False)
access_token = models.TextField(null=False)
refresh_token = models.TextField(null=False)
user_token = models.TextField(null=False)
decoded_jwt = models.TextField(null=False)
expires_at = models.DateTimeField(null=False)
refresh_expires_at = models.DateTimeField(null=False)
google_id = models.TextField(null=True)

class Meta:
unique_together = (("user", "nih_username_lower"),)
877 changes: 655 additions & 222 deletions accounts/sa_utils.py

Large diffs are not rendered by default.

13 changes: 12 additions & 1 deletion accounts/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from django.conf.urls import url, include
from allauth.socialaccount.providers.google import urls as google_urls, views as google_views

from . import views
from . import views, dcf_views


urlpatterns = [
Expand All @@ -29,6 +29,17 @@
url(r'^login/$', google_views.oauth2_login, name='account_login'),
# url(r'^nih_login/$', views.nih_login, name='nih_login'),
url(r'^unlink_accounts/', views.unlink_accounts, name='unlink_accounts'),
# Following urls for new DCF flows
url(r'^dcf_login/$', dcf_views.oauth2_login, name='dcf_login'),
url(r'^dcf_simple_logout/$', dcf_views.dcf_simple_logout, name='dcf_simple_logout'),
url(r'^dcf/login/callback/$', dcf_views.oauth2_callback, name='dcf_callback'),
url(r'^dcf_link_callback/$', dcf_views.dcf_link_callback, name='dcf_link_callback'),
url(r'^dcf_link_extend/$', dcf_views.dcf_link_extend, name='dcf_link_extend'),
url(r'^dcf_disconnect_user/$', dcf_views.dcf_disconnect_user, name='dcf_disconnect_user'),
# Following urls for QC and development use. Not used in production
# url(r'^dcf_user_data/$', dcf_views.dcf_get_user_data, name='dcf_get_user_data'),
# url(r'^dcf_unlink/$', dcf_views.dcf_unlink, name='dcf_unlink'),
# url(r'^dcf_link_redo/$', dcf_views.dcf_link_redo, name='dcf_link_redo'),

# Google Cloud Project related
url(r'^users/(?P<user_id>\d+)/gcp_list/$', views.user_gcp_list, name='user_gcp_list'),
Expand Down
46 changes: 42 additions & 4 deletions accounts/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Copyright 2017, Institute for Systems Biology
Copyright 2017-2018, Institute for Systems Biology
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -33,14 +33,14 @@
from google_helpers.storage_service import get_storage_resource
from google_helpers.bigquery.bq_support import BigQuerySupport
from googleapiclient.errors import HttpError
from django.contrib.auth.models import User
from models import *
from projects.models import User_Data_Tables
from django.utils.html import escape
from sa_utils import verify_service_account, register_service_account, \
unregister_all_gcp_sa, unregister_sa_with_id, service_account_dict, \
do_nih_unlink, deactivate_nih_add_to_open

import json
from json import loads as json_loads

logger = logging.getLogger('main_logger')

Expand All @@ -52,6 +52,7 @@

@login_required
def extended_logout_view(request):

response = None
try:
# deactivate NIH_username entry if exists
Expand Down Expand Up @@ -475,6 +476,32 @@ def register_bucket(request, user_id, gcp_id):
# Check bucketname not null
if not bucket_name:
messages.error(request, 'There was no bucket name provided.')
return redirect('gcp_detail', user_id=user_id, gcp_id=gcp_id)
else:
try:
bucket = Bucket.objects.get(bucket_name=bucket_name)
if bucket.google_project.project_id != gcp.project_id:
messages.error(
request,
"A bucket with the name {} has already been registered under a different project.".format(escape(bucket_name)) +
" If you feel you've received this message in error, please contact the administrator."
)
else:
messages.error(
request,
"A bucket with the name {} has already been registered under project {}.".format(escape(bucket_name),gcp.project_id) +
" Buckets can only be registered to a project once. If you feel you've received this message in error, please contact the administrator."
)
return redirect('gcp_detail', user_id=user_id, gcp_id=gcp_id)
except MultipleObjectsReturned:
messages.error(
request,
"More than one bucket with the name {} has already been registered.".format(escape(bucket_name)) +
" Buckets can only be registered once."
)
return redirect('gcp_detail', user_id=user_id, gcp_id=gcp_id)
except ObjectDoesNotExist:
pass

# Check that bucket is in project
try:
Expand All @@ -500,7 +527,7 @@ def register_bucket(request, user_id, gcp_id):
messages.error(request, 'Access to the bucket {0} in Google Cloud Project {1} was denied.'.format(
bucket_name, gcp.project_id))
elif e.resp.get('content-type', '').startswith('application/json'):
err_val = json.loads(e.content).get('error')
err_val = json_loads(e.content).get('error')
if err_val:
e_message = err_val.get('message')
else:
Expand Down Expand Up @@ -545,8 +572,19 @@ def register_bqdataset(request, user_id, gcp_id):
# Check bqdatasetname not null
if not bqdataset_name:
messages.error(request, 'There was no dataset name provided.')
return redirect('gcp_detail', user_id=user_id, gcp_id=gcp_id)
else:
bqdataset_name = bqdataset_name.strip()
try:
BqDataset.objects.get(dataset_name=bqdataset_name,google_project=gcp)
messages.error(request,"A dataset with the name {} has already been registered for project {}.".format(escape(bqdataset_name),gcp.project_id))
return redirect('gcp_detail', user_id=user_id, gcp_id=gcp_id)
except MultipleObjectsReturned:
messages.error(request, "Multiple datasets with the name {} have already been registered for project {}.".format(
escape(bqdataset_name),gcp.project_id))
return redirect('gcp_detail', user_id=user_id, gcp_id=gcp_id)
except ObjectDoesNotExist:
pass

# Check that bqdataset is in project
try:
Expand Down
Loading

0 comments on commit 3a24001

Please sign in to comment.