Auto-generate a secret key for django and store in the config file.
authorDiane Trout <diane@caltech.edu>
Wed, 27 Jun 2012 21:44:18 +0000 (14:44 -0700)
committerDiane Trout <diane@caltech.edu>
Wed, 27 Jun 2012 21:44:18 +0000 (14:44 -0700)
This way I can keep checking settings.py in.

Also since I implemented this be re-writing the settings file
I thought I'd clean out some of how we were storing some of our
previous default values. (Removed the hard coded - [defaults] section)
so they dont end up cluttering the users config file.

Since I removed the default for the linking hard disk tool
I changed the script to complain more helpfully if it can't find
the setting.

htsworkflow/settings.py
htsworkflow/util/api.py
htsworkflow/util/test/test_api.py [new file with mode: 0644]
scripts/htsw-record-runfolder

index dce9b2b36418863cf35327153992c9d16419be44..7af5ac484f5e612dde288e3e4519215a031c9e83 100644 (file)
@@ -9,8 +9,11 @@ The options understood by this module are (with their defaults):
   [frontend]
   email_host=localhost
   email_port=25
-  database_engine=sqlite3
-  database_name=/path/to/db
+  database=<section_name>
+
+  [database_name]
+  engine=sqlite3
+  name=/path/to/database
 
   [admins]
   #name1=email1
@@ -31,6 +34,8 @@ import htsworkflow
 import django
 from django.conf import global_settings
 
+from htsworkflow.util.api import make_django_secret_key
+
 HTSWORKFLOW_ROOT = os.path.abspath(os.path.split(htsworkflow.__file__)[0])
 
 # make epydoc happy
@@ -53,23 +58,18 @@ def options_to_dict(dest, section_name):
       dest[name] = options.get(section_name, name)
 
 # define your defaults here
-options = ConfigParser.SafeConfigParser(
-           { 'email_host': 'localhost',
-             'email_port': '25',
-             'database_engine': 'sqlite3',
-             'database_name':
-                  os.path.join(HTSWORKFLOW_ROOT, '..', 'fctracker.db'),
-             'time_zone': 'America/Los_Angeles',
-             'default_pm': '5',
-             'link_flowcell_storage_device_url': "http://localhost:8000/inventory/lts/link/",
-             'printer1_host': '127.0.0.1',
-             'printer1_port': '9100',
-             'printer2_host': '127.0.0.1',
-             'printer2_port': '9100',
-           })
-
-options.read([os.path.expanduser("~/.htsworkflow.ini"),
-              '/etc/htsworkflow.ini',])
+options = ConfigParser.SafeConfigParser()
+
+def save_options(filename, options):
+    try:
+        ini_stream = open(filename, 'w')
+        options.write(ini_stream)
+        ini_stream.close()
+    except IOError, e:
+        LOGGER.debug("Error saving setting: %s" % (str(e)))
+
+INI_FILE = options.read([os.path.expanduser("~/.htsworkflow.ini"),
+                         '/etc/htsworkflow.ini',])
 
 # OptionParser will use the dictionary passed into the config parser as
 # 'Default' values in any section. However it still needs an empty section
@@ -91,14 +91,17 @@ options_to_list(options, ADMINS, 'frontend', 'admins')
 MANAGERS = []
 options_to_list(options, MANAGERS, 'frontend', 'managers')
 
-DEFAULT_PM=int(options.get('frontend', 'default_pm'))
+if options.has_option('front', 'default_pm'):
+    DEFAULT_PM=int(options.get('frontend', 'default_pm'))
+else:
+    DEFAULT_PM=5
 
 AUTHENTICATION_BACKENDS = (
   'htsworkflow.frontend.samples.auth_backend.HTSUserModelBackend', )
 CUSTOM_USER_MODEL = 'samples.HTSUser'
 
-EMAIL_HOST = options.get('frontend', 'email_host')
-EMAIL_PORT = int(options.get('frontend', 'email_port'))
+EMAIL_HOST = options.get('frontend', 'email_host', 'localhost')
+EMAIL_PORT = int(options.get('frontend', 'email_port', 25))
 
 if options.has_option('frontend', 'notification_sender'):
     NOTIFICATION_SENDER = options.get('frontend', 'notification_sender')
@@ -134,7 +137,10 @@ elif options.has_option(database_section, 'password'):
 # although not all variations may be possible on all operating systems.
 # If running in a Windows environment this must be set to the same as your
 # system time zone.
-TIME_ZONE = options.get('frontend', 'time_zone')
+if options.has_option('frontend', 'time_zone'):
+  TIME_ZONE = options.get('frontend', 'time_zone')
+else:
+  TIME_ZONE = 'America/Los_Angeles'
 
 # Language code for this installation. All choices can be found here:
 # http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
@@ -161,7 +167,10 @@ MEDIA_URL = '/static/'
 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'
+if not options.has_option('frontend', 'secret'):
+    options.set('frontend', 'secret_key', make_django_secret_key(458))
+    save_options(INI_FILE[0], options)
+SECRET_KEY = options.get('frontend', 'secret_key')
 
 # some of our urls need an api key
 DEFAULT_API_KEY = 'n7HsXGHIi0vp9j5u4TIRJyqAlXYc4wrH'
@@ -232,7 +241,11 @@ if options.has_option('frontend', 'results_dir'):
 else:
     RESULT_HOME_DIR='/tmp'
 
-LINK_FLOWCELL_STORAGE_DEVICE_URL = options.get('frontend', 'link_flowcell_storage_device_url')
+if options.has_option('frontend', 'link_flowcell_storage_device_url'):
+    LINK_FLOWCELL_STORAGE_DEVICE_URL = options.get('frontend',
+                                                   'link_flowcell_storage_device_url')
+else:
+    LINK_FLOWCELL_STORAGE_DEVICE_URL = None
 # PORT 9100 is default for Zebra tabletop/desktop printers
 # PORT 6101 is default for Zebra mobile printers
 BCPRINTER_PRINTER1_HOST = options.get('bcprinter', 'printer1_host')
index 6ac2bb28c4f57b9732426a88bcd76a4564276d21..76ee84dc318005fea7281d6b838244fb869b811f 100644 (file)
@@ -1,6 +1,8 @@
 """Common functions for accessing the HTS Workflow REST API
 """
+import base64
 from ConfigParser import SafeConfigParser
+import random
 import logging
 
 # try to deal with python <2.6
@@ -143,24 +145,38 @@ def retrieve_info(url, apidata):
     return json.loads(contents)
 
 class HtswApi(object):
-  def __init__(self, root_url, authdata):
-    self.root_url = root_url
-    self.authdata = authdata
+    def __init__(self, root_url, authdata):
+        self.root_url = root_url
+        self.authdata = authdata
 
-  def get_flowcell(self, flowcellId):
-    url = flowcell_url(self.root_url, flowcellId)
-    return retrieve_info(url, self.authdata)
+    def get_flowcell(self, flowcellId):
+        url = flowcell_url(self.root_url, flowcellId)
+        return retrieve_info(url, self.authdata)
 
-  def get_library(self, libraryId):
-    url = library_url(self.root_url, libraryId)
-    return retrieve_info(url, self.authdata)
+    def get_library(self, libraryId):
+        url = library_url(self.root_url, libraryId)
+        return retrieve_info(url, self.authdata)
 
-  def get_lanes_for_user(self, user):
-    url = lanes_for_user(self.root_url, user)
-    return retrieve_info(url, self.authdata)
+    def get_lanes_for_user(self, user):
+        url = lanes_for_user(self.root_url, user)
+        return retrieve_info(url, self.authdata)
 
-  def get_url(self, url):
-    return retrieve_info(url, self.authdata)
+    def get_url(self, url):
+        return retrieve_info(url, self.authdata)
+
+def make_django_secret_key(size=216):
+    """return key suitable for use as secret key"""
+    try:
+        source = random.SystemRandom()
+    except AttributeError, e:
+        source = random.random()
+    bits = source.getrandbits(size)
+    chars = []
+    while bits > 0:
+        byte = bits & 0xff
+        chars.append(chr(byte))
+        bits >>= 8
+    return base64.encodestring("".join(chars)).strip()
 
 if __name__ == "__main__":
     from optparse import OptionParser
diff --git a/htsworkflow/util/test/test_api.py b/htsworkflow/util/test/test_api.py
new file mode 100644 (file)
index 0000000..4cbe383
--- /dev/null
@@ -0,0 +1,20 @@
+import copy
+import os
+import unittest
+
+from htsworkflow.util import api
+
+class testApi(unittest.TestCase):
+    def test_make_key(self):
+        k1 = api.make_django_secret_key()
+        k2 = api.make_django_secret_key()
+
+        self.failUnless(len(k1), 85)
+        self.failUnless(len(k2), 85)
+        self.failUnless(k1 != k2)
+
+def suite():
+    return unittest.makeSuite(testApi, 'test')
+
+if __name__ == "__main__":
+    unittest.main(defaultTest='suite')
index 42bb61472d0c941787332e071f72f2422293b77e..674cd52fb918db49e7650d8ae6a8aa716e211722 100755 (executable)
@@ -20,7 +20,7 @@ def extract_flowcell(runfolder_name):
         return match.group('flowcell')
     else:
         return None
-    
+
 def construct_parser():
     """
     """
@@ -33,7 +33,7 @@ def construct_parser():
                       help="device flowcell is being archived to")
     parser.add_option("-s", "--serial", type="string", help="serial num. of archive device")
     parser.add_option("-v", "--verbose", action="store_true", default=False)
-    
+
     return parser
 
 
@@ -43,7 +43,7 @@ def update_db(root_url, flowcells, serial, debug=False):
     """
     for fc in flowcells:
         url = urlparse.urljoin(root_url, '%s/%s/' % (fc, serial))
-        
+
         req = urllib2.Request(url)
         try:
             response = urllib2.urlopen(req)
@@ -52,19 +52,19 @@ def update_db(root_url, flowcells, serial, debug=False):
             if debug:
                 print e.read()
             sys.exit(e.code)
-        
+
         print "DB Update of %s & %s succeeded" % (fc, serial)
         print response.read()
-    
+
 
 def process_args(parser):
     """
     returns flowcell and serial#
     """
     options, args = parser.parse_args()
-    
+
     msg = []
-    
+
     # Only provide device or serial
     if options.device is not None and options.serial is not None:
         parser.error("Please provide only --device or --serial.\n"\
@@ -77,13 +77,16 @@ def process_args(parser):
     else:
         root_url = settings.LINK_FLOWCELL_STORAGE_DEVICE_URL
 
+    if root_url is None:
+        parser.error("Please set path to flowcell storage url")
+
     # if device and serial missing:
     if options.device is None and options.serial is None:
         parser.error('One of --device or --serial is required')
 
     flowcells = []
-    
-    # sanitize args    
+
+    # sanitize args
     for runfolder in args:
         flowcell_id = extract_flowcell(runfolder)
         if flowcell_id is None:
@@ -91,10 +94,10 @@ def process_args(parser):
                          '(got %s)' % (runfolder,))
         else:
             flowcells.append(flowcell_id)
-            
+
     if options.flowcell is not None:
         flowcells.append(options.flowcell)
-        
+
     if len(flowcells) == 0:
         parser.error('please specify a  --flowcell or list of runfolder archives\n'\
                      'for archival. I need something to do.')
@@ -108,15 +111,15 @@ def process_args(parser):
     else:
         msg ="FATAL should not happen error occured; i.e. the best kind!"
         raise ValueError, msg
-    
-    
+
+
 
 def main():
     """
     """
     parser = construct_parser()
     process_args(parser)
-    
+
     #print "Database Updated."
     sys.exit(0)