diff --git a/gracedb/fixtures/test_perms/cbc-lm.xml b/gracedb/fixtures/test_perms/cbc-lm.xml new file mode 100644 index 0000000000000000000000000000000000000000..2d04abd4816a6cc6b3af128ddca78cbc1873fee4 --- /dev/null +++ b/gracedb/fixtures/test_perms/cbc-lm.xml @@ -0,0 +1,112 @@ +<?xml version='1.0' encoding='utf-8'?> +<!DOCTYPE LIGO_LW SYSTEM "http://ldas-sw.ligo.caltech.edu/doc/ligolwAPI/html/ligolw_dtd.txt"> +<LIGO_LW> + <Table Name="sngl_inspiral:table"> + <Column Type="real_4" Name="sngl_inspiral:cont_chisq"/> + <Column Type="real_4" Name="sngl_inspiral:bank_chisq"/> + <Column Type="int_4s" Name="sngl_inspiral:chisq_dof"/> + <Column Type="real_8" Name="sngl_inspiral:end_time_gmst"/> + <Column Type="real_8" Name="sngl_inspiral:event_duration"/> + <Column Type="real_4" Name="sngl_inspiral:chisq"/> + <Column Type="real_4" Name="sngl_inspiral:alpha"/> + <Column Type="real_4" Name="sngl_inspiral:coa_phase"/> + <Column Type="real_4" Name="sngl_inspiral:alpha2"/> + <Column Type="real_4" Name="sngl_inspiral:mchirp"/> + <Column Type="real_4" Name="sngl_inspiral:alpha1"/> + <Column Type="real_4" Name="sngl_inspiral:alpha6"/> + <Column Type="real_4" Name="sngl_inspiral:alpha4"/> + <Column Type="real_4" Name="sngl_inspiral:alpha5"/> + <Column Type="ilwd:char" Name="sngl_inspiral:event_id"/> + <Column Type="real_4" Name="sngl_inspiral:chi"/> + <Column Type="int_4s" Name="sngl_inspiral:cont_chisq_dof"/> + <Column Type="real_4" Name="sngl_inspiral:tau2"/> + <Column Type="real_4" Name="sngl_inspiral:tau3"/> + <Column Type="real_4" Name="sngl_inspiral:tau0"/> + <Column Type="real_4" Name="sngl_inspiral:tau4"/> + <Column Type="real_4" Name="sngl_inspiral:tau5"/> + <Column Type="real_8" Name="sngl_inspiral:template_duration"/> + <Column Type="int_4s" Name="sngl_inspiral:impulse_time"/> + <Column Type="int_4s" Name="sngl_inspiral:impulse_time_ns"/> + <Column Type="real_4" Name="sngl_inspiral:rsqveto_duration"/> + <Column Type="lstring" Name="sngl_inspiral:channel"/> + <Column Type="real_4" Name="sngl_inspiral:mtotal"/> + <Column Type="real_4" Name="sngl_inspiral:alpha3"/> + <Column Type="real_4" Name="sngl_inspiral:Gamma5"/> + <Column Type="real_4" Name="sngl_inspiral:f_final"/> + <Column Type="real_4" Name="sngl_inspiral:beta"/> + <Column Type="ilwd:char" Name="sngl_inspiral:process_id"/> + <Column Type="real_4" Name="sngl_inspiral:snr"/> + <Column Type="int_4s" Name="sngl_inspiral:bank_chisq_dof"/> + <Column Type="real_4" Name="sngl_inspiral:kappa"/> + <Column Type="real_4" Name="sngl_inspiral:eff_distance"/> + <Column Type="real_4" Name="sngl_inspiral:Gamma7"/> + <Column Type="real_4" Name="sngl_inspiral:Gamma6"/> + <Column Type="lstring" Name="sngl_inspiral:search"/> + <Column Type="real_4" Name="sngl_inspiral:Gamma4"/> + <Column Type="real_4" Name="sngl_inspiral:mass1"/> + <Column Type="real_4" Name="sngl_inspiral:Gamma2"/> + <Column Type="real_4" Name="sngl_inspiral:Gamma1"/> + <Column Type="real_4" Name="sngl_inspiral:mass2"/> + <Column Type="real_4" Name="sngl_inspiral:ttotal"/> + <Column Type="real_4" Name="sngl_inspiral:Gamma0"/> + <Column Type="real_4" Name="sngl_inspiral:Gamma9"/> + <Column Type="real_4" Name="sngl_inspiral:Gamma8"/> + <Column Type="real_4" Name="sngl_inspiral:Gamma3"/> + <Column Type="real_4" Name="sngl_inspiral:eta"/> + <Column Type="real_4" Name="sngl_inspiral:psi0"/> + <Column Type="int_4s" Name="sngl_inspiral:end_time"/> + <Column Type="real_4" Name="sngl_inspiral:amplitude"/> + <Column Type="real_4" Name="sngl_inspiral:psi3"/> + <Column Type="int_4s" Name="sngl_inspiral:end_time_ns"/> + <Column Type="lstring" Name="sngl_inspiral:ifo"/> + <Column Type="real_8" Name="sngl_inspiral:sigmasq"/> + <Stream Name="sngl_inspiral:table" Type="Local" Delimiter=","> + 111117.7,46.05555,0,13.37498739211096,0.000244140625,0,0,-2.222122,0,1.161378,0,0,0,0,"sngl_inspiral:event_id:0",0,112837,1.459517,0.9047917,26.94421,0.04901026,0,27.54793872301135,971609248,861816406,0,"DMT-STRAIN",2.698323,0,426.13315,1629.595,0,"process:process_id:0",5.561541,15,0,57.40068,0,0,"FindChirpSPtwoPN",-212.24567,1.533016,7010.147,-2963.2476,1.165307,27.54794,174532.62,0,0,115.9822,0.2453574,0,971609248,0,0,861816406,"H1",101911.765625, + 109975.2,32.12224,0,13.37498868415753,0.000244140625,0,0,-2.353283,0,1.15963,0,0,0,0,"sngl_inspiral:event_id:1",0,112935,1.504488,0.9970195,27.01193,0.05250296,0,27.57190592010491,971609248,866455078,0,"DMT-STRAIN",2.965915,0,386.59695,1482.569,0,"process:process_id:0",5.63967,15,0,49.10112,0,0,"FindChirpSPtwoPN",-201.89705,2.083082,6643.8418,-2951.074,0.8828334,27.57191,170850.05,0,0,115.80309,0.2090584,0,971609248,0,0,866455078,"L1",76681.4296875 + </Stream> + </Table> + <Table Name="coinc_inspiral:table"> + <Column Type="real_8" Name="coinc_inspiral:false_alarm_rate"/> + <Column Type="real_8" Name="coinc_inspiral:mchirp"/> + <Column Type="ilwd:char" Name="coinc_inspiral:coinc_event_id"/> + <Column Type="real_8" Name="coinc_inspiral:combined_far"/> + <Column Type="real_8" Name="coinc_inspiral:mass"/> + <Column Type="int_4s" Name="coinc_inspiral:end_time"/> + <Column Type="real_8" Name="coinc_inspiral:snr"/> + <Column Type="int_4s" Name="coinc_inspiral:end_time_ns"/> + <Column Type="lstring" Name="coinc_inspiral:ifos"/> + <Stream Name="coinc_inspiral:table" Type="Local" Delimiter=","> + 2.075093374861122,1.160504,"coinc_event:coinc_event_id:0",2.075093374861122,2.8321192,971609248,7.121797825164989,861816406,"H1,L1" + </Stream> + </Table> + <Table Name="coinc_definer:table"> + <Column Type="lstring" Name="coinc_definer:search"/> + <Column Type="lstring" Name="coinc_definer:description"/> + <Column Type="ilwd:char" Name="coinc_definer:coinc_def_id"/> + <Column Type="int_4u" Name="coinc_definer:search_coinc_type"/> + <Stream Name="coinc_definer:table" Type="Local" Delimiter=","> + "inspiral","sngl_inspiral<-->sngl_inspiral coincidences","coinc_definer:coinc_def_id:1",0 + </Stream> + </Table> + <Table Name="coinc_event:table"> + <Column Type="ilwd:char" Name="coinc_event:coinc_event_id"/> + <Column Type="lstring" Name="coinc_event:instruments"/> + <Column Type="int_4u" Name="coinc_event:nevents"/> + <Column Type="ilwd:char" Name="coinc_event:process_id"/> + <Column Type="ilwd:char" Name="coinc_event:coinc_def_id"/> + <Column Type="ilwd:char" Name="coinc_event:time_slide_id"/> + <Column Type="real_8" Name="coinc_event:likelihood"/> + <Stream Name="coinc_event:table" Type="Local" Delimiter=","> + "coinc_event:coinc_event_id:0","H1,L1",3,"process:process_id:2","coinc_definer:coinc_def_id:1",,, + </Stream> + </Table> + <Table Name="coinc_event_map:table"> + <Column Type="ilwd:char" Name="coinc_event_map:event_id"/> + <Column Type="char_v" Name="coinc_event_map:table_name"/> + <Column Type="ilwd:char" Name="coinc_event_map:coinc_event_id"/> + <Stream Name="coinc_event_map:table" Type="Local" Delimiter=","> + "sngl_inspiral:event_id:0","sngl_inspiral","coinc_event:coinc_event_id:0", + "sngl_inspiral:event_id:1","sngl_inspiral","coinc_event:coinc_event_id:0" + </Stream> + </Table> +</LIGO_LW> diff --git a/gracedb/test/test_perms.py b/gracedb/test/test_perms.py index a076f399bf9220991d74cbe6213269309bf3acf8..9f82395fecbacaf4edd5c1be1a78d8114aef7892 100644 --- a/gracedb/test/test_perms.py +++ b/gracedb/test/test_perms.py @@ -1,4 +1,5 @@ from django.test import TestCase +from django.test.utils import override_settings from django.contrib.contenttypes.models import ContentType from django.contrib.auth.models import Permission, Group, User @@ -6,7 +7,11 @@ from guardian.models import GroupObjectPermission from gracedb.models import Event, GrbEvent, CoincInspiralEvent from gracedb.models import MultiBurstEvent +from django.conf import settings + import json +import os +import shutil from urllib import urlencode #------------------------------------------------------------------------------- @@ -14,6 +19,7 @@ from urllib import urlencode # Some utilities #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- +TMP_DATA_DIR = '/tmp/test_perms_data' def get_user(category): if category=='public': @@ -24,7 +30,11 @@ def get_user(category): return User.objects.get(first_name='Albert', last_name='Einstein') elif category=='exec': return User.objects.get(first_name='Spokesy', last_name='McSpokesperson') - + elif category=='gstlal_submitter': + return User.objects.get(last_name='GstLal CBC') + else: + return None + def get_public_coinc_event(): ctype = ContentType.objects.get(model='CoincInspiralEvent') perm = Permission.objects.get(codename='view_coincinspiralevent') @@ -60,6 +70,27 @@ def get_internal_coinc_event(): break return e +# Given a Django test client, attempt to create a CBC, gstlal, +# LowMass event. +EVENT_FILE = os.path.join(settings.ROOT_PATH,'gracedb/fixtures/test_perms/cbc-lm.xml') + +def request_event_creation(client, username): + event_file = open(EVENT_FILE,'r') + url = '/events/create/' + input_dict = { + 'group' : 'CBC', + 'pipeline' : 'gstlal', + 'search' : 'LM', + 'eventFile' : event_file, + } + return client.post(url, input_dict, REMOTE_USER=username) + +#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- +# Test Perms Class +#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- + class TestPerms(TestCase): # I wonder if the order of loading the fixtures will matter? fixtures = [ @@ -159,6 +190,14 @@ class TestPerms(TestCase): for e in Event.objects.all(): e.refresh_perms() + # Lastly, let's create a temporary data dir. + if not os.path.isdir(TMP_DATA_DIR): + os.mkdir(TMP_DATA_DIR) + + def tearDown(self): + # Get rid of that temporary data dir. + shutil.rmtree(TMP_DATA_DIR) + #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- # Tests of view access @@ -255,12 +294,92 @@ class TestPerms(TestCase): # Tests of event annotation #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- - - # Test annotation of events by public users + + # What annotation activities need to be tested? + # - EventLog creation + # /events/GXXXX/log/ + # POST dict keys: comment, tagname (no files through web interface) + # - Tag creation + # /events/GXXXX/log/N/tag/<tagname> + # POST dict keys: displayName + # test DELETE? + # - Labelling + # no way to do this through the web interface + + # Test annotation of events user. + def test_public_log_creation(self): + # Choose any event. The public coinc one will do. + event = get_public_coinc_event() + url = '/events/%s/log/' % event.graceid() + input_dict = { + 'comment' : 'This is a test.', + 'tagname' : 'test_tag', + } + response = self.client.post(url,input_dict, + REMOTE_USER=get_user('public').username) + self.assertEqual(response.status_code, 403) + + def test_public_log_tagging(self): + # Choose any event. The public coinc one will do. + event = get_public_coinc_event() + # Try to add 'test_tag' to the first log entry. + url = '/events/%s/log/1/tag/test_tag' % event.graceid() + input_dict = {'displayName' : None,} + response = self.client.post(url, input_dict, + REMOTE_USER=get_user('public').username) + self.assertEqual(response.status_code, 403) # Test annotation of events by LV-EM users + def test_lvem_log_creation(self): + # Should be able to annotate the public event, but no others + public_coinc_event = get_public_coinc_event() + for e in CoincInspiralEvent.objects.all(): + url = '/events/%s/log/' % e.graceid() + input_dict = { + 'comment' : 'This is a test.', + 'tagname' : 'test_tag', + } + response = self.client.post(url,input_dict, + REMOTE_USER=get_user('lvem').username) + if e.id==public_coinc_event.id: + # Not an AJAX call, so redirects to event page if successful. + self.assertEqual(response.status_code, 302) + else: + self.assertEqual(response.status_code, 403) + + def test_lvem_log_tagging(self): + public_coinc_event = get_public_coinc_event() + for e in CoincInspiralEvent.objects.all(): + # Try to add 'test_tag' to the first log entry. + url = '/events/%s/log/1/tag/test_tag' % e.graceid() + input_dict = {'displayName' : None,} + response = self.client.post(url, input_dict, + REMOTE_USER=get_user('lvem').username) + if e.id==public_coinc_event.id: + self.assertEqual(response.status_code, 302) + else: + self.assertEqual(response.status_code, 403) # Test annotation of events by LIGO users + def test_internal_log_creation(self): + for e in CoincInspiralEvent.objects.all(): + url = '/events/%s/log/' % e.graceid() + input_dict = { + 'comment' : 'This is a test.', + 'tagname' : 'test_tag', + } + response = self.client.post(url,input_dict, + REMOTE_USER=get_user('internal').username) + self.assertEqual(response.status_code, 302) + + def test_internal_log_tagging(self): + for e in CoincInspiralEvent.objects.all(): + # Try to add 'test_tag' to the first log entry. + url = '/events/%s/log/1/tag/test_tag' % e.graceid() + input_dict = {'displayName' : None,} + response = self.client.post(url, input_dict, + REMOTE_USER=get_user('internal').username) + self.assertEqual(response.status_code, 302) #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- @@ -268,10 +387,37 @@ class TestPerms(TestCase): #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- + @override_settings(GRACEDB_DATA_DIR=TMP_DATA_DIR) + def test_event_creation(self): + gstlal_submitter = get_user('gstlal_submitter') + for user in User.objects.all(): + response = request_event_creation(self.client, user.username) + if user.id==gstlal_submitter.id: + self.assertEqual(response.status_code, 200) + else: + self.assertEqual(response.status_code, 403) + +# # Actually, you can only replace an event that you yourself created. +# # Thus, not sure if we really need this. +# def test_event_replacement(self): +# pass + #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- # Test changes to permissions #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- - + def test_perm_creation(self): + for user in User.objects.all(): + # choose any event + event = CoincInspiralEvent.objects.all()[0] + # try POST to permission creation URL + url = '/events/%s/perms' % event.graceid() + input_dict = {} + response = self.client.post(url, input_dict, REMOTE_USER=user.username) + groups = [g.name for g in user.groups.all()] + if not 'executives' in groups: + self.assertEqual(response.status_code, 403) + else: + self.assertEqual(response.status_code, 200)