Return species information as part of the flowcell json information.
authorDiane Trout <diane@caltech.edu>
Wed, 23 Sep 2009 19:09:58 +0000 (19:09 +0000)
committerDiane Trout <diane@caltech.edu>
Wed, 23 Sep 2009 19:09:58 +0000 (19:09 +0000)
Additionally instead of using django authentication use an apikey
for authenticating access to the json data.

Currently the apikey is just a value stored in the settings.py file
(DEFAULT_API_KEY), but in the future could be linked to users.

htsworkflow/frontend/auth.py [new file with mode: 0644]
htsworkflow/frontend/experiments/experiments.py
htsworkflow/frontend/experiments/fixtures/test_flowcells.json
htsworkflow/frontend/experiments/tests.py
htsworkflow/frontend/samples/fixtures/initial_data.json
htsworkflow/frontend/samples/fixtures/test_samples.json
htsworkflow/frontend/samples/tests.py
htsworkflow/frontend/samples/views.py
htsworkflow/frontend/settings.py

diff --git a/htsworkflow/frontend/auth.py b/htsworkflow/frontend/auth.py
new file mode 100644 (file)
index 0000000..4df771b
--- /dev/null
@@ -0,0 +1,22 @@
+"""
+Define some alternate authentication methods
+"""
+from django.core.exceptions import PermissionDenied
+
+from htsworkflow.frontend import settings
+
+apidata = {'apiid': u'0', 'apikey': settings.DEFAULT_API_KEY}
+
+def require_api_key(request):
+    # make sure we have the api component
+    if not (request.REQUEST.has_key('apiid') or request.REQUEST.has_key('apikey')):
+        raise PermissionDenied
+
+    # make sure the id and key are right
+    if request.REQUEST['apiid'] == apidata['apiid'] and \
+       request.REQUEST['apikey'] == apidata['apikey']:
+        return True
+    else:
+        raise PermissionDenied
+        
+    
index f9144b01095e979a96a83cc7d09f91878df7b2d3..331bdde59a2e57a42fd66d633eac580c40e1660b 100755 (executable)
@@ -16,6 +16,7 @@ from django.http import HttpResponse, Http404
 from htsworkflow.frontend import settings
 from htsworkflow.frontend.experiments.models import FlowCell, DataRun
 from htsworkflow.frontend.samples.models import Library
 from htsworkflow.frontend import settings
 from htsworkflow.frontend.experiments.models import FlowCell, DataRun
 from htsworkflow.frontend.samples.models import Library
+from htsworkflow.frontend.auth import require_api_key
 
 def flowcell_information(flowcell_id):
     """
 
 def flowcell_information(flowcell_id):
     """
@@ -35,6 +36,7 @@ def flowcell_information(flowcell_id):
             'lane_number': int(lane.lane_number),
             'library_name': lane.library.library_name,
             'library_id': lane.library.library_id,
             'lane_number': int(lane.lane_number),
             'library_name': lane.library.library_name,
             'library_id': lane.library.library_id,
+            'library_species': lane.library.library_species.scientific_name,
             'pM': float(lane.pM),
         }
     info = {
             'pM': float(lane.pM),
         }
     info = {
@@ -56,11 +58,12 @@ def flowcell_information(flowcell_id):
     
     return info
 
     
     return info
 
-@login_required    
 def flowcell_json(request, fc_id):
     """
     Return a JSON blob containing enough information to generate a config file.
     """
 def flowcell_json(request, fc_id):
     """
     Return a JSON blob containing enough information to generate a config file.
     """
+    require_api_key(request)
+    
     fc_dict = flowcell_information(fc_id)
 
     if fc_dict is None:
     fc_dict = flowcell_information(fc_id)
 
     if fc_dict is None:
index 09876795ac3aa0d3219e083ae590ca1948db8a79..1ce52506e76cbee03c3fb7a38ccfdd8c2ff5df0b 100644 (file)
@@ -92,7 +92,7 @@
             "library_name": "Paired End Pfl #3 MP 7/24/9 a", 
             "creation_date": "2009-08-06", 
             "cell_line": 1, 
             "library_name": "Paired End Pfl #3 MP 7/24/9 a", 
             "creation_date": "2009-08-06", 
             "cell_line": 1, 
-            "library_species": 22
+            "library_species": 2, 
             "library_type": 2, 
             "made_by": "Lorian", 
             "affiliations": [
             "library_type": 2, 
             "made_by": "Lorian", 
             "affiliations": [
index 6f4bc3dbf5e602299dd7d0d6d4ae3d468a9fa37c..a4a53155f7fa3ca88f11a4b44da48ee74305dcb8 100644 (file)
@@ -6,6 +6,7 @@ except ImportError, e:
 from django.test import TestCase
 from htsworkflow.frontend.experiments import models
 from htsworkflow.frontend.experiments import experiments
 from django.test import TestCase
 from htsworkflow.frontend.experiments import models
 from htsworkflow.frontend.experiments import experiments
+from htsworkflow.frontend.auth import apidata
 
 class ExperimentsTestCases(TestCase):
     fixtures = ['test_flowcells.json']
 
 class ExperimentsTestCases(TestCase):
     fixtures = ['test_flowcells.json']
@@ -36,9 +37,10 @@ class ExperimentsTestCases(TestCase):
                 self.failUnlessEqual(lane_dict['library_name'], lane.library.library_name)
                 self.failUnlessEqual(lane_dict['library_id'], lane.library.library_id)
                 self.failUnlessAlmostEqual(lane_dict['pM'], float(lane.pM))
                 self.failUnlessEqual(lane_dict['library_name'], lane.library.library_name)
                 self.failUnlessEqual(lane_dict['library_id'], lane.library.library_id)
                 self.failUnlessAlmostEqual(lane_dict['pM'], float(lane.pM))
+                self.failUnlessEqual(lane_dict['library_species'],
+                                     lane.library.library_species.scientific_name)
                     
                     
-            self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
-            response = self.client.get('/experiments/config/%s/json' % (fc_id,))
+            response = self.client.get('/experiments/config/%s/json' % (fc_id,), apidata)
             # strptime isoformat string = '%Y-%m-%dT%H:%M:%S'
             fc_json = json.loads(response.content)
             self.failUnlessEqual(fc_json['flowcell_id'], fc_id)
             # strptime isoformat string = '%Y-%m-%dT%H:%M:%S'
             fc_json = json.loads(response.content)
             self.failUnlessEqual(fc_json['flowcell_id'], fc_id)
@@ -57,35 +59,38 @@ class ExperimentsTestCases(TestCase):
                 self.failUnlessEqual(lane_dict['library_name'], lane.library.library_name)
                 self.failUnlessEqual(lane_dict['library_id'], lane.library.library_id)
                 self.failUnlessAlmostEqual(lane_dict['pM'], float(lane.pM))
                 self.failUnlessEqual(lane_dict['library_name'], lane.library.library_name)
                 self.failUnlessEqual(lane_dict['library_id'], lane.library.library_id)
                 self.failUnlessAlmostEqual(lane_dict['pM'], float(lane.pM))
+                self.failUnlessEqual(lane_dict['library_species'],
+                                     lane.library.library_species.scientific_name)
 
     def test_invalid_flowcell(self):
         """
         Make sure we get a 404 if we request an invalid flowcell ID
         """
 
     def test_invalid_flowcell(self):
         """
         Make sure we get a 404 if we request an invalid flowcell ID
         """
-        self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
-        response = self.client.get('/experiments/config/nottheone/json')
+        response = self.client.get('/experiments/config/nottheone/json', apidata)
         self.failUnlessEqual(response.status_code, 404)
 
         self.failUnlessEqual(response.status_code, 404)
 
-    def test_not_logged_in(self):
+    def test_no_key(self):
         """
         Require logging in to retrieve meta data
         """
         response = self.client.get(u'/experiments/config/303TUAAXX/json')
         """
         Require logging in to retrieve meta data
         """
         response = self.client.get(u'/experiments/config/303TUAAXX/json')
-        self.failUnlessEqual(response.status_code, 302)
+        self.failUnlessEqual(response.status_code, 403)
 
     def test_library_id(self):
         """
         Library IDs should be flexible, so make sure we can retrive a non-numeric ID
         """
 
     def test_library_id(self):
         """
         Library IDs should be flexible, so make sure we can retrive a non-numeric ID
         """
-        self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
-        response = self.client.get('/experiments/config/303TUAAXX/json')
+        response = self.client.get('/experiments/config/303TUAAXX/json', apidata)
         self.failUnlessEqual(response.status_code, 200)
         flowcell = json.loads(response.content)
 
         self.failUnlessEqual(flowcell['lane_set']['3']['library_id'], 'SL039')
 
         self.failUnlessEqual(response.status_code, 200)
         flowcell = json.loads(response.content)
 
         self.failUnlessEqual(flowcell['lane_set']['3']['library_id'], 'SL039')
 
-        response = self.client.get('/samples/library/SL039/json')
+        response = self.client.get('/samples/library/SL039/json', apidata)
         self.failUnlessEqual(response.status_code, 200)
         library_sl039 = json.loads(response.content)
 
         self.failUnlessEqual(library_sl039['library_id'], 'SL039')
         self.failUnlessEqual(response.status_code, 200)
         library_sl039 = json.loads(response.content)
 
         self.failUnlessEqual(library_sl039['library_id'], 'SL039')
+
+#class RetriveConfigTestCases(TestCase):
+#    fixtures = ['test_flowcells.json']
index dbdcc7a27049b40371c285314c3ff4034b99693f..27eeccfdbcf7214528382c3a4d25cf301d6e2b22 100644 (file)
         "name": "Multiplexed"
      }
   },
         "name": "Multiplexed"
      }
   },
-  {
-     "model": "samples.Species",
-     "pk": 1,
-     "fields": {
-        "scientific_name": "Mus musculus",
-        "common_name": "mouse"
-     }
-  },
   {
      "model": "samples.Species",
      "pk": 2,
   {
      "model": "samples.Species",
      "pk": 2,
         "common_name": ""
      }
   },
         "common_name": ""
      }
   },
+  {
+     "model": "samples.Species",
+     "pk": 6,
+     "fields": {
+        "scientific_name": "Arabidopsis thaliana"
+     }
+  },
   {
      "model": "samples.Species",
      "pk": 8,
   {
      "model": "samples.Species",
      "pk": 8,
         "scientific_name": "Homo sapiens",
         "common_name": ""
      }
         "scientific_name": "Homo sapiens",
         "common_name": ""
      }
+  },
+  {
+     "model": "samples.Species",
+     "pk": 9,
+     "fields": {
+        "scientific_name": "Mus musculus",
+        "common_name": "mouse"
+     }
+  },
+  {
+     "model": "samples.Species",
+     "pk": 10,
+     "fields": {
+        "scientific_name": "Strongylocentrotus purpuratus"
+     }
   }
   }
-
 ]
 ]
index dba08b6626de4185298f4826a8834b6a9a3cac9d..ae998723b8588ea5e23b7a2201bb96ecd2b26c8e 100644 (file)
@@ -53,7 +53,7 @@
             "library_name": "Paired End Pfl #3 MP 7/24/9 a", 
             "creation_date": "2009-08-06", 
             "cell_line": 1, 
             "library_name": "Paired End Pfl #3 MP 7/24/9 a", 
             "creation_date": "2009-08-06", 
             "cell_line": 1, 
-            "library_species": 1
+            "library_species": 9
             "library_type": 2, 
             "made_by": "Lorian", 
             "affiliations": [
             "library_type": 2, 
             "made_by": "Lorian", 
             "affiliations": [
             "library_name": "Paired End Pfl #3 MP 7/24/9", 
             "creation_date": "2009-08-05", 
             "cell_line": 1, 
             "library_name": "Paired End Pfl #3 MP 7/24/9", 
             "creation_date": "2009-08-05", 
             "cell_line": 1, 
-            "library_species": 1
+            "library_species": 8
             "library_type": 2, 
             "made_by": "Lorian", 
             "affiliations": [
             "library_type": 2, 
             "made_by": "Lorian", 
             "affiliations": [
index 595727e13510c0eaa369e668056cef5c005b988d..d85a46672ebc4e8902bce1a53fad6078b604ec34 100644 (file)
@@ -18,6 +18,8 @@ from htsworkflow.frontend.samples.views import \
      library_dict, \
      library_json
 
      library_dict, \
      library_json
 
+from htsworkflow.frontend.auth import apidata
+
 # The django test runner flushes the database between test suites not cases,
 # so to be more compatible with running via nose we flush the database tables
 # of interest before creating our sample data.
 # The django test runner flushes the database between test suites not cases,
 # so to be more compatible with running via nose we flush the database tables
 # of interest before creating our sample data.
@@ -123,9 +125,8 @@ class SampleWebTestCase(TestCase):
 
         for lib in Library.objects.all():
             lib_dict = library_dict(lib.library_id)
 
         for lib in Library.objects.all():
             lib_dict = library_dict(lib.library_id)
-            self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
             url = '/samples/library/%s/json' % (lib.library_id,)
             url = '/samples/library/%s/json' % (lib.library_id,)
-            lib_response = self.client.get(url)
+            lib_response = self.client.get(url, apidata)
             self.failUnlessEqual(lib_response.status_code, 200)
             lib_json = json.loads(lib_response.content)
 
             self.failUnlessEqual(lib_response.status_code, 200)
             lib_json = json.loads(lib_response.content)
 
@@ -164,17 +165,15 @@ class SampleWebTestCase(TestCase):
         """
         Make sure we get a 404 if we request an invalid library id
         """
         """
         Make sure we get a 404 if we request an invalid library id
         """
-        self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
-        response = self.client.get('/samples/library/nottheone/json')
+        response = self.client.get('/samples/library/nottheone/json', apidata)
         self.failUnlessEqual(response.status_code, 404)
 
             
         self.failUnlessEqual(response.status_code, 404)
 
             
-    def test_library_not_logged_in(self):
+    def test_library_no_key(self):
         """
         Make sure we get a 302 if we're not logged in
         """
         response = self.client.get('/samples/library/10981/json')
         """
         Make sure we get a 302 if we're not logged in
         """
         response = self.client.get('/samples/library/10981/json')
-        self.failUnlessEqual(response.status_code, 302)
-        self.client.login(username='test', password='BJOKL5kAj6aFZ6A5')
-        response = self.client.get('/samples/library/10981/json')
+        self.failUnlessEqual(response.status_code, 403)
+        response = self.client.get('/samples/library/10981/json', apidata)
         self.failUnlessEqual(response.status_code, 200)
         self.failUnlessEqual(response.status_code, 200)
index f42c8bce7d53984ed227c696d487898a533ff755..b0a61f42117db2c1758b933041e64f0cb2377cb4 100644 (file)
@@ -7,6 +7,7 @@ try:
 except ImportError, e:
     import simplejson as json
 
 except ImportError, e:
     import simplejson as json
 
+from htsworkflow.frontend.auth import require_api_key
 from htsworkflow.frontend.experiments.models import FlowCell
 from htsworkflow.frontend.samples.changelist import ChangeList
 from htsworkflow.frontend.samples.models import Library
 from htsworkflow.frontend.experiments.models import FlowCell
 from htsworkflow.frontend.samples.changelist import ChangeList
 from htsworkflow.frontend.samples.models import Library
@@ -491,11 +492,11 @@ def library_dict(library_id):
         info['library_type'] = lib.library_type.name
     return info
 
         info['library_type'] = lib.library_type.name
     return info
 
-@login_required
 def library_json(request, library_id):
     """
     Return a json formatted library dictionary
     """
 def library_json(request, library_id):
     """
     Return a json formatted library dictionary
     """
+    require_api_key(request)
     # what validation should we do on library_id?
     
     lib = library_dict(library_id)
     # what validation should we do on library_id?
     
     lib = library_dict(library_id)
index 91eccf967e301615ae535fa6736df7c53d26ed3c..a1412836a7ef59686ca2108a400070bee3dfe2d9 100644 (file)
@@ -141,6 +141,9 @@ ADMIN_MEDIA_PREFIX = '/media/'
 # Make this unique, and don't share it with anybody.
 SECRET_KEY = '(ekv^=gf(j9f(x25@a7r+8)hqlz%&_1!tw^75l%^041#vi=@4n'
 
 # Make this unique, and don't share it with anybody.
 SECRET_KEY = '(ekv^=gf(j9f(x25@a7r+8)hqlz%&_1!tw^75l%^041#vi=@4n'
 
+# some of our urls need an api key
+DEFAULT_API_KEY = 'n7HsXGHIi0vp9j5u4TIRJyqAlXYc4wrH'
+
 # List of callables that know how to import templates from various sources.
 TEMPLATE_LOADERS = (
     'django.template.loaders.filesystem.load_template_source',
 # List of callables that know how to import templates from various sources.
 TEMPLATE_LOADERS = (
     'django.template.loaders.filesystem.load_template_source',