From 1986c5001aef28327bdfaa5c11b57f09387ba5db Mon Sep 17 00:00:00 2001 From: Diane Trout Date: Wed, 27 Jun 2012 14:44:18 -0700 Subject: [PATCH] Auto-generate a secret key for django and store in the config file. 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 | 63 +++++++++++++++++++------------ htsworkflow/util/api.py | 44 ++++++++++++++------- htsworkflow/util/test/test_api.py | 20 ++++++++++ scripts/htsw-record-runfolder | 31 ++++++++------- 4 files changed, 105 insertions(+), 53 deletions(-) create mode 100644 htsworkflow/util/test/test_api.py diff --git a/htsworkflow/settings.py b/htsworkflow/settings.py index dce9b2b..7af5ac4 100644 --- a/htsworkflow/settings.py +++ b/htsworkflow/settings.py @@ -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= + + [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') diff --git a/htsworkflow/util/api.py b/htsworkflow/util/api.py index 6ac2bb2..76ee84d 100644 --- a/htsworkflow/util/api.py +++ b/htsworkflow/util/api.py @@ -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 index 0000000..4cbe383 --- /dev/null +++ b/htsworkflow/util/test/test_api.py @@ -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') diff --git a/scripts/htsw-record-runfolder b/scripts/htsw-record-runfolder index 42bb614..674cd52 100755 --- a/scripts/htsw-record-runfolder +++ b/scripts/htsw-record-runfolder @@ -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) -- 2.30.2