Skip to content
Snippets Groups Projects
Commit 2411fbdc authored by Branson Craig Stephens's avatar Branson Craig Stephens
Browse files

Made changes to store permission info on the Event objects themselves. This...

Made changes to store permission info on the Event objects themselves. This speeds up some searches by an order of magnitude with respect to guardian's get_objects_for_user.
parent 3660bc92
No related branches found
No related tags found
No related merge requests found
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'Event.perms'
db.add_column(u'gracedb_event', 'perms',
self.gf('django.db.models.fields.TextField')(null=True),
keep_default=False)
def backwards(self, orm):
# Deleting field 'Event.perms'
db.delete_column(u'gracedb_event', 'perms')
models = {
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'gracedb.approval': {
'Meta': {'object_name': 'Approval'},
'approvedEvent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gracedb.Event']"}),
'approver': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'approvingCollaboration': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
u'gracedb.coincinspiralevent': {
'Meta': {'ordering': "['-id']", 'object_name': 'CoincInspiralEvent', '_ormbases': [u'gracedb.Event']},
'combined_far': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'end_time': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'end_time_ns': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
u'event_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['gracedb.Event']", 'unique': 'True', 'primary_key': 'True'}),
'false_alarm_rate': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'ifos': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '20'}),
'mass': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'mchirp': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'minimum_duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'snr': ('django.db.models.fields.FloatField', [], {'null': 'True'})
},
u'gracedb.event': {
'Meta': {'ordering': "['-id']", 'object_name': 'Event'},
'analysisType': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'far': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'gpstime': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gracedb.Group']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'instruments': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '20'}),
'labels': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['gracedb.Label']", 'through': u"orm['gracedb.Labelling']", 'symmetrical': 'False'}),
'likelihood': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'nevents': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'perms': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'submitter': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'uid': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '20'})
},
u'gracedb.eventlog': {
'Meta': {'ordering': "['-created', '-N']", 'unique_together': "(('event', 'N'),)", 'object_name': 'EventLog'},
'N': ('django.db.models.fields.IntegerField', [], {}),
'comment': ('django.db.models.fields.TextField', [], {}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gracedb.Event']"}),
'file_version': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'filename': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'issuer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
},
u'gracedb.grbevent': {
'Meta': {'ordering': "['-id']", 'object_name': 'GrbEvent', '_ormbases': [u'gracedb.Event']},
'author_ivorn': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'author_shortname': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'coord_system': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'dec': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'error_radius': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
u'event_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['gracedb.Event']", 'unique': 'True', 'primary_key': 'True'}),
'how_description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'how_reference_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}),
'ivorn': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'observatory_location_id': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'ra': ('django.db.models.fields.FloatField', [], {'null': 'True'})
},
u'gracedb.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '20'})
},
u'gracedb.label': {
'Meta': {'object_name': 'Label'},
'defaultColor': ('django.db.models.fields.CharField', [], {'default': "'black'", 'max_length': '20'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
},
u'gracedb.labelling': {
'Meta': {'object_name': 'Labelling'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gracedb.Event']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gracedb.Label']"})
},
u'gracedb.multiburstevent': {
'Meta': {'ordering': "['-id']", 'object_name': 'MultiBurstEvent', '_ormbases': [u'gracedb.Event']},
'amplitude': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'bandwidth': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'central_freq': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'confidence': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
u'event_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['gracedb.Event']", 'unique': 'True', 'primary_key': 'True'}),
'false_alarm_rate': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'ifos': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '20'}),
'ligo_angle': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'ligo_angle_sig': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'ligo_axis_dec': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'ligo_axis_ra': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'peak_time': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'peak_time_ns': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'snr': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'start_time': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'start_time_ns': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'})
},
u'gracedb.singleinspiral': {
'Gamma0': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma1': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma2': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma3': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma4': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma5': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma6': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma7': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma8': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma9': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Meta': {'object_name': 'SingleInspiral'},
'alpha': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'alpha1': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'alpha2': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'alpha3': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'alpha4': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'alpha5': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'alpha6': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'amplitude': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'bank_chisq': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'bank_chisq_dof': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'beta': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'channel': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'chi': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'chisq': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'chisq_dof': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'coa_phase': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'cont_chisq': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'cont_chisq_dof': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'eff_distance': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'end_time': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'end_time_gmst': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'end_time_ns': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'eta': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['gracedb.Event']"}),
'event_duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'f_final': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ifo': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True'}),
'impulse_time': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'impulse_time_ns': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'kappa': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'mass1': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'mass2': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'mchirp': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'mtotal': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'psi0': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'psi3': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'rsqveto_duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'search': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True'}),
'sigmasq': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'snr': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'tau0': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'tau2': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'tau3': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'tau4': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'tau5': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'template_duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'ttotal': ('django.db.models.fields.FloatField', [], {'null': 'True'})
},
u'gracedb.tag': {
'Meta': {'object_name': 'Tag'},
'displayName': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'eventlogs': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['gracedb.EventLog']", 'symmetrical': 'False'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['gracedb']
\ No newline at end of file
This diff is collapsed.
......@@ -4,6 +4,9 @@ from django.core.urlresolvers import reverse
from model_utils.managers import InheritanceManager
from django.contrib.auth.models import User as DjangoUser
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
from guardian.models import GroupObjectPermission
import datetime
......@@ -19,6 +22,8 @@ import glue.ligolw.table
import glue.ligolw.lsctables
from glue.lal import LIGOTimeGPS
import json
log = logging.getLogger('gracedb.models')
# XXX ER2.utils. utils is in project directory. ugh.
......@@ -99,6 +104,15 @@ class Event(models.Model):
labels = models.ManyToManyField(Label, through="Labelling")
# This field will store a JSON-serialized list of permissions, of the
# form <group name>_can_<permission codename>
# This obviously duplicates information that is already in the database
# in the form of GroupObjectPermission objects. Such duplication is
# normally a bad thing, as it can lead to divergence. But we're going
# to try really hard to avoid that. And it may help speed up the
# searches quite considerably.
perms = models.TextField(null=True)
class Meta:
ordering = ["-id"]
......@@ -221,6 +235,24 @@ class Event(models.Model):
loglist.append(log)
return loglist
# A method to update the permissions according to the permission objects in
# the database.
def refresh_perms(self):
# Content type is 'Event', obvs.
content_type = ContentType.objects.get(app_label='gracedb', model='event')
# Get all of the GroupObjectPermissions for this object id and content type
group_object_perms = GroupObjectPermission.objects.filter(object_pk=self.id,
content_type=content_type)
perm_strings = []
# Make a list of permission strings
for obj in group_object_perms:
perm_strings.append('%s_can_%s' % (obj.group.name, obj.permission.codename.split('_')[0]))
# Serialize as json.
self.perms = json.dumps(perm_strings)
# Fool! Save yourself!
self.save()
class EventLog(models.Model):
class Meta:
ordering = ['-created','-N']
......
......@@ -6,6 +6,7 @@ from django.shortcuts import render_to_response
from django.conf import settings
from gracedb.models import Event
from gracedb.views import filter_events_for_user
from django.db.models import Q
import os, json
......@@ -152,6 +153,8 @@ def gstlalcbc_report(request, format=""):
rawquery = request.POST['query']
if form.is_valid():
objects = form.cleaned_data['query']
objects = filter_events_for_user(objects, request.user, 'view')
object_list = list(objects)
# Try upcasting to CoincInspiralEvents
......
......@@ -48,6 +48,16 @@ GRACEDB_DATA_DIR = settings.GRACEDB_DATA_DIR
import json
import datetime
from django.db.models import Q
# This auth filter relies on the storage of perm info on the event itself.
def filter_events_for_user(events, user, shortname):
auth_filter = Q()
for group in user.groups.all():
perm_string = '%s_can_%s' % (group.name, shortname)
auth_filter = auth_filter | Q(perms__contains=perm_string)
return events.filter(auth_filter)
def index(request):
# assert request.user
......@@ -256,13 +266,17 @@ def _createEventFromForm(request, form):
event.save()
saved = True # in case we have to undo this.
# Create permissions on new event
# Create permissions objects for the new event
assign_default_event_perms(event)
# XXX In case this is a subclass, let's check and assign default
# perms on the underlying Event as well.
if not type(event) is Event:
assign_default_event_perms(Event.objects.get(id=event.id))
underlying_event = Event.objects.get(id=event.id)
assign_default_event_perms(underlying_event)
underlying_event.refresh_perms()
else:
event.refresh_perms()
# Create data directory/directories
# Save uploaded file.
......@@ -679,6 +693,7 @@ def cli_search(request):
form = SimpleSearchForm(request.POST)
if form.is_valid():
objects = form.cleaned_data['query']
objects = filter_events_for_user(objects, request.user, 'view')
if 'ligolw' in request.POST or 'ligolw' in request.GET:
from glue.ligolw import utils
......@@ -724,7 +739,6 @@ def cli_search(request):
response.write(msg)
return response
def assembleLigoLw(objects):
from glue.ligolw import ligolw
# lsctables MUST be loaded before utils.
......@@ -798,7 +812,10 @@ def search(request, format=""):
# Filter objects according to user permissions.
# NOTE: This is bad. Creates a complete list of pks to which the user has
# access for a given content type. Then filters according to this list.
objects = get_objects_for_user(request.user, 'gracedb.view_event', objects)
#objects = get_objects_for_user(request.user, 'gracedb.view_event', objects)
# Instead, use the alternative that uses perm info residing on the event itself.
objects = filter_events_for_user(objects, request.user, 'view')
if format == "json":
return HttpResponse("Not Implemented")
......@@ -953,6 +970,9 @@ def oldsearch(request):
# Need this because events with multiple labels can appear multiple times!
objects = objects.distinct()
# Filter for user.
objects = filter_events_for_user(objects, request.user, 'view')
if objects.count() == 1:
title = "Query Results. %s event" % objects.count()
else:
......@@ -1160,7 +1180,8 @@ def latest(request):
context['rawquery'] = request.GET.get('query') or request.POST.get('query') or ""
if form.is_valid():
objects = form.cleaned_data['query'][0:50]
objects = form.cleaned_data['query']
objects = filter_events_for_user(objects, request.user, 'view')[0:50]
context['objects'] = map(limit, objects)
context['error'] = False
else:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment