Skip to content

Commit

Permalink
Merge pull request #889 from linea-it/userquery_base
Browse files Browse the repository at this point in the history
Userquery base
  • Loading branch information
linea-relmanager authored Nov 17, 2017
2 parents a7b8d76 + bb645c5 commit 3691a7d
Show file tree
Hide file tree
Showing 290 changed files with 677 additions and 205 deletions.
4 changes: 3 additions & 1 deletion api/dri/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,13 @@

# UserQuery API
router.register(r'userquery_query', userquery_views.QueryViewSet)
router.register(r'userquery_sample', userquery_views.SampleViewSet)
router.register(r'userquery_job', userquery_views.JobViewSet)
router.register(r'userquery_table', userquery_views.TableViewSet)
router.register(r'userquery_validate', userquery_views.QueryValidate, base_name='validate_query')
router.register(r'userquery_preview', userquery_views.QueryPreview, base_name='preview_query')
router.register(r'userquery_create_table', userquery_views.CreateTable, base_name='create_table')
router.register(r'userquery_table', userquery_views.TableProperties, base_name='table')
router.register(r'userquery_properties', userquery_views.TableProperties, base_name='table')

# Aladin API
router.register(r'aladin/image', aladin_views.ImageViewSet)
Expand Down
9 changes: 8 additions & 1 deletion api/userquery/create_table_as.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from common.notify import Notify
from userquery.models import Job
from userquery.models import Table


class CreateTableAs:
Expand Down Expand Up @@ -63,6 +64,12 @@ def _create_table_by_job_id(self):
try:
db.create_table_raw_sql(self.table_name, self.job.sql_sentence, schema=self.schema, timeout=self.timeout)
self.is_table_successfully_created = True

table = Table(table_name=self.table_name,
display_name=self.job.display_name,
owner=self.job.owner,
schema=self.schema)
table.save()
except Exception as e:
self.error_message = str(e)
self.logger.debug("CreateTableAs Error: %s" % self.error_message)
Expand Down Expand Up @@ -93,7 +100,7 @@ def _notify_by_email_finish(self):
body = render_to_string("job_notification_finish.html", {
"username": self.user.username,
"url": url,
"table_name": self.job.table_name
"table_name": self.table_name
})

Notify().send_email(subject, body, self.user.email)
Expand Down
24 changes: 24 additions & 0 deletions api/userquery/migrations/0018_auto_20171116_1212.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2017-11-16 12:12
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('userquery', '0017_auto_20171114_1214'),
]

operations = [
migrations.RemoveField(
model_name='query',
name='is_validate',
),
migrations.AddField(
model_name='query',
name='is_sample',
field=models.BooleanField(default=False, verbose_name='Is a sample query'),
),
]
20 changes: 20 additions & 0 deletions api/userquery/migrations/0019_auto_20171116_1425.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2017-11-16 14:25
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('userquery', '0018_auto_20171116_1212'),
]

operations = [
migrations.AlterField(
model_name='job',
name='table_name',
field=models.CharField(max_length=128, verbose_name='Name'),
),
]
32 changes: 32 additions & 0 deletions api/userquery/migrations/0020_auto_20171116_1858.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2017-11-16 18:58
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),
('userquery', '0019_auto_20171116_1425'),
]

operations = [
migrations.CreateModel(
name='Table',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('table_name', models.CharField(max_length=128, unique=True, verbose_name='Name')),
('display_name', models.CharField(max_length=128, verbose_name='Display name')),
('schema', models.CharField(max_length=128, null=True, verbose_name='Schema')),
('owner', models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Owner')),
],
),
migrations.RemoveField(
model_name='job',
name='table_name',
),
]
20 changes: 15 additions & 5 deletions api/userquery/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@ class Query(models.Model):
help_text='Last Edition Date')
sql_sentence = models.CharField(
max_length=2048, null=False, verbose_name='Sql Sentence')
is_validate = models.BooleanField(
default=False, verbose_name='Is Query Validated')
is_sample = models.BooleanField(
default=False, verbose_name='Is a sample query')
is_public = models.BooleanField(
default=False, verbose_name='Is Public',
help_text='Is Public default True')
# TODO: missing release and database - Use foreign key;

def __str__(self):
return self.name
Expand All @@ -40,8 +39,6 @@ class Job(models.Model):
('ok', 'Done'),
('er', 'Error'),
)
table_name = models.CharField(
max_length=128, null=False, unique=True, verbose_name='Name')
display_name = models.CharField(
max_length=128, null=False, verbose_name='Name')
owner = models.ForeignKey(
Expand All @@ -66,3 +63,16 @@ class Job(models.Model):
default='st',
verbose_name='Status'
)


class Table(models.Model):
table_name = models.CharField(
max_length=128, null=False, unique=True, verbose_name='Name')
display_name = models.CharField(
max_length=128, null=False, verbose_name='Display name')
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
verbose_name='Owner', default=None)
schema = models.CharField(
max_length=128, null=True, verbose_name='Schema')
9 changes: 8 additions & 1 deletion api/userquery/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,11 @@ class IsOwnerOrPublic(permissions.BasePermission):
"""

def has_object_permission(self, request, view, obj):
return obj.owner == request.user or obj.is_public
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return obj.owner == request.user or obj.is_public

# Write permissions are only allowed to the owner of the snippet.
return obj.owner == request.user

17 changes: 15 additions & 2 deletions api/userquery/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ class Meta:
'creation_date',
'last_edition_date',
'sql_sentence',
'is_validate',
'is_public'
)

Expand All @@ -30,7 +29,6 @@ class Meta:
model = Job
fields = (
'id',
'table_name',
'display_name',
'owner',
'start_date_time',
Expand All @@ -39,3 +37,18 @@ class Meta:
'job_status',
'timeout',
)


class TableSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
id = serializers.ReadOnlyField()

class Meta:
model = Table
fields = (
'id',
'table_name',
'display_name',
'owner',
'schema'
)
67 changes: 49 additions & 18 deletions api/userquery/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.db.models import Q
from django.http import HttpResponse
from django.http import JsonResponse
from django.contrib.auth.models import User

from .models import *
from .permissions import IsOwnerOrPublic
Expand All @@ -24,16 +25,38 @@ class QueryViewSet(viewsets.ModelViewSet):
serializer_class = QuerySerializer

authentication_classes = (TokenAuthentication, SessionAuthentication, BasicAuthentication)
permission_classes = (permissions.IsAuthenticated, IsOwnerOrPublic,)
permission_classes = (permissions.IsAuthenticated, IsOwnerOrPublic)

def get_queryset(self):
return self.queryset.filter(Q(owner=self.request.user) |
Q(is_public=True))
return self.queryset.filter((Q(owner=self.request.user) | Q(is_public=True)) &
Q(is_sample=False))

def perform_create(self, serializer):
serializer.save(owner=self.request.user)


class SampleViewSet(viewsets.ModelViewSet):
queryset = Query.objects.filter()
serializer_class = QuerySerializer

authentication_classes = (TokenAuthentication, SessionAuthentication, BasicAuthentication)
permission_classes = (permissions.IsAuthenticated, IsOwnerOrPublic,)

def get_queryset(self):
return self.queryset.filter(is_sample=True)


class TableViewSet(viewsets.ModelViewSet):
queryset = Table.objects.filter()
serializer_class = TableSerializer

authentication_classes = (TokenAuthentication, SessionAuthentication, BasicAuthentication)
permission_classes = (permissions.IsAuthenticated,)

def get_queryset(self):
return self.queryset.filter(owner=self.request.user)


class JobViewSet(viewsets.ModelViewSet):
queryset = Job.objects.all()
serializer_class = JobSerializer
Expand Down Expand Up @@ -72,9 +95,8 @@ def create(self, request):
try:
data = request.data
sql_sentence = data.get("sql_sentence", None)
line_number = data.get("line_number", 10)

# review number of elements to show
line_number = 10
db = DBBase('catalog')
sql = sql_sentence + " " + db.database.get_raw_sql_limit(line_number)
result = db.fetchall_dict(sql)
Expand Down Expand Up @@ -110,18 +132,16 @@ def create(self, request):
if rqv.engine.has_table(table_name, None):
raise Exception("Table exists - choose a different name")

if rqv.is_query_validated():
q.is_validate = True
q.save()
else:
if not rqv.is_query_validated():
raise Exception("Invalid query: %s" % rqv.validation_error_message())

q = Job(table_name=table_name,
display_name=display_name,
q = Job(display_name=display_name,
owner=self.request.user,
sql_sentence=q.sql_sentence)
q.save()
create_table.delay(q.id, request.user.pk, table_name, schema=None, timeout=None)

timeout = self._time_out_query_execution(request)
create_table.delay(q.id, request.user.pk, table_name, schema=None, timeout=timeout)
return HttpResponse(status=200)
except Exception as e:
print(str(e))
Expand All @@ -130,6 +150,14 @@ def create(self, request):
def _is_user_authorized(self, q):
return q.owner == self.request.user or q.is_public

def _time_out_query_execution(self, request):
user = User.objects.get(pk=request.user.pk)
try:
user.groups.get(name='NCSA')
return settings.USER_QUERY_EXECUTION_NCSA_USER_IN_SECONDS
except Exception as e:
return settings.USER_QUERY_EXECUTION_NON_NCSA_USER_IN_SECONDS


class TableProperties(viewsets.ModelViewSet):
http_method_names = ['get', ]
Expand All @@ -138,15 +166,18 @@ class TableProperties(viewsets.ModelViewSet):

def list(self, request):
try:
jobs = Job.objects.filter(Q(owner=request.user) &
Q(job_status='ok'))
tables = Table.objects.filter(owner=request.user)

db = DBBase('catalog')
response = {}
for job in jobs:
response[job.table_name] = db.get_table_columns(job.table_name)
response = []
for table in tables:
response.append({
'display_name':table.display_name,
'table_name':table.table_name,
'cols': db.get_table_columns(table.table_name)
})

return JsonResponse(response)
return JsonResponse(response, safe=False)

except Exception as e:
print(str(e))
Expand Down
2 changes: 1 addition & 1 deletion frontend/build/production/UserQuery/app.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion frontend/build/production/UserQuery/app.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"packages":{"classic":{"css":true,"included":true,"namespace":"Ext","required":true,"requires":["ext","core"],"version":"6.0.1.250"},"cmd":{"current":"6.5.1.240","version":"6.5.0.180"},"common":{"css":true,"included":true,"required":true,"requires":["ext","core","classic","ux"],"version":"1.0.0"},"core":{"css":true,"included":true,"required":true,"requires":["ext","classic"],"version":"6.0.1.250"},"ext":{"css":true,"included":true,"license":"gpl","namespace":"Ext","required":true,"requires":[],"version":"6.0.1.250"},"font-awesome":{"css":true,"included":true,"namespace":"Ext","required":true,"requires":["ext","core","classic","theme-base","theme-neutral","theme-neptune"],"theme":"theme-neptune","version":"6.0.1.250"},"theme-base":{"css":true,"included":true,"namespace":"Ext","required":true,"requires":["ext","core","classic"],"version":"6.0.1.250"},"theme-crisp":{"css":true,"extend":"theme-neptune","included":true,"namespace":"Ext","required":true,"requires":["ext","core","classic","theme-base","theme-neutral","theme-neptune"],"version":"6.0.1.250"},"theme-neptune":{"css":true,"extend":"theme-neutral","included":true,"namespace":"Ext","required":true,"requires":["ext","core","classic","theme-base","theme-neutral"],"version":"6.0.1.250"},"theme-neutral":{"css":true,"extend":"theme-base","included":true,"namespace":"Ext","required":true,"requires":["ext","core","classic","theme-base"],"version":"6.0.1.250"},"ux":{"css":true,"included":true,"namespace":"Ext","required":true,"requires":["ext","core","classic"],"version":"6.0.1.250"}},"js":[{"path":"app.js"}],"css":[{"exclude":["fashion"],"path":"resources/UserQuery-all.css"}],"cache":{"enable":true,"deltas":true},"fashion":{"inliner":{"enable":false}},"name":"UserQuery","namespace":"UserQuery","version":"1.0.0.0","framework":"ext","toolkit":"classic","theme":"theme-crisp","loader":{"cache":"20171110210504","cacheParam":"_dc"},"id":"ec311b0b-1ca2-4f2f-b672-f7e9bf9f9023","hash":"c52e9ab11a73d78f4b71bea913dc6a1a53a97073","profile":"","resources":{"path":"resources"}}
{"packages":{"classic":{"css":true,"included":true,"namespace":"Ext","required":true,"requires":["ext","core"],"version":"6.0.1.250"},"cmd":{"current":"6.5.1.240","version":"6.5.0.180"},"common":{"css":true,"included":true,"required":true,"requires":["ext","core","classic","ux"],"version":"1.0.0"},"core":{"css":true,"included":true,"required":true,"requires":["ext","classic"],"version":"6.0.1.250"},"ext":{"css":true,"included":true,"license":"gpl","namespace":"Ext","required":true,"requires":[],"version":"6.0.1.250"},"font-awesome":{"css":true,"included":true,"namespace":"Ext","required":true,"requires":["ext","core","classic","theme-base","theme-neutral","theme-neptune"],"theme":"theme-neptune","version":"6.0.1.250"},"theme-base":{"css":true,"included":true,"namespace":"Ext","required":true,"requires":["ext","core","classic"],"version":"6.0.1.250"},"theme-crisp":{"css":true,"extend":"theme-neptune","included":true,"namespace":"Ext","required":true,"requires":["ext","core","classic","theme-base","theme-neutral","theme-neptune"],"version":"6.0.1.250"},"theme-neptune":{"css":true,"extend":"theme-neutral","included":true,"namespace":"Ext","required":true,"requires":["ext","core","classic","theme-base","theme-neutral"],"version":"6.0.1.250"},"theme-neutral":{"css":true,"extend":"theme-base","included":true,"namespace":"Ext","required":true,"requires":["ext","core","classic","theme-base"],"version":"6.0.1.250"},"ux":{"css":true,"included":true,"namespace":"Ext","required":true,"requires":["ext","core","classic"],"version":"6.0.1.250"}},"js":[{"path":"app.js"}],"css":[{"exclude":["fashion"],"path":"resources/UserQuery-all.css"}],"cache":{"enable":true,"deltas":true},"fashion":{"inliner":{"enable":false}},"name":"UserQuery","namespace":"UserQuery","version":"1.0.0.0","framework":"ext","toolkit":"classic","theme":"theme-crisp","loader":{"cache":"20171117123507","cacheParam":"_dc"},"id":"ec311b0b-1ca2-4f2f-b672-f7e9bf9f9023","hash":"be3bf2c1d827e4e9d1d94483e73682789f0356a3","profile":"","resources":{"path":"resources"}}
Loading

0 comments on commit 3691a7d

Please sign in to comment.