diff --git a/supysonic/config.py b/supysonic/config.py index 0e602b8..f82487c 100644 --- a/supysonic/config.py +++ b/supysonic/config.py @@ -18,7 +18,6 @@ import tempfile class DefaultConfig(object): DEBUG = False - SECRET_KEY = os.urandom(128) tempdir = os.path.join(tempfile.gettempdir(), 'supysonic') BASE = { diff --git a/supysonic/web.py b/supysonic/web.py index ac5259d..1af92d8 100644 --- a/supysonic/web.py +++ b/supysonic/web.py @@ -8,10 +8,11 @@ # # Distributed under terms of the GNU AGPLv3 license. +import io import mimetypes from flask import Flask -from os import makedirs, path +from os import makedirs, path, urandom from pony.orm import db_session from .config import IniConfig @@ -24,13 +25,13 @@ def create_application(config = None): app = Flask(__name__) app.config.from_object('supysonic.config.DefaultConfig') - if not config: + if not config: # pragma: nocover config = IniConfig.from_common_locations() app.config.from_object(config) # Set loglevel logfile = app.config['WEBAPP']['log_file'] - if logfile: + if logfile: # pragma: nocover import logging from logging.handlers import TimedRotatingFileHandler handler = TimedRotatingFileHandler(logfile, when = 'midnight') @@ -59,7 +60,18 @@ def create_application(config = None): # Test for the cache directory cache_path = app.config['WEBAPP']['cache_dir'] if not path.exists(cache_path): - makedirs(cache_path) + makedirs(cache_path) # pragma: nocover + + # Read or create secret key + secret_path = path.join(cache_path, 'secret') + if path.exists(secret_path): + with io.open(secret_path, 'rb') as f: + app.secret_key = f.read() + else: + secret = urandom(128) + with io.open(secret_path, 'wb') as f: + f.write(secret) + app.secret_key = secret # Import app sections if app.config['WEBAPP']['mount_webui']: diff --git a/tests/base/__init__.py b/tests/base/__init__.py index 30098d4..2f4630e 100644 --- a/tests/base/__init__.py +++ b/tests/base/__init__.py @@ -14,6 +14,7 @@ from .test_config import ConfigTestCase from .test_db import DbTestCase from .test_lastfm import LastFmTestCase from .test_scanner import ScannerTestCase +from .test_secret import SecretTestCase from .test_watcher import suite as watcher_suite def suite(): @@ -25,6 +26,7 @@ def suite(): suite.addTest(watcher_suite()) suite.addTest(unittest.makeSuite(CLITestCase)) suite.addTest(unittest.makeSuite(LastFmTestCase)) + suite.addTest(unittest.makeSuite(SecretTestCase)) return suite diff --git a/tests/base/test_secret.py b/tests/base/test_secret.py new file mode 100644 index 0000000..8f186cc --- /dev/null +++ b/tests/base/test_secret.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# coding: utf-8 +# +# This file is part of Supysonic. +# Supysonic is a Python implementation of the Subsonic server API. +# +# Copyright (C) 2018 Alban 'spl0k' FĂ©ron +# +# Distributed under terms of the GNU AGPLv3 license. + +import os +import unittest +import shutil +import tempfile + +from supysonic.db import init_database, release_database +from supysonic.web import create_application + +from ..testbase import TestConfig + +class SecretTestCase(unittest.TestCase): + def setUp(self): + self.__dbfile = tempfile.mkstemp()[1] + self.__dir = tempfile.mkdtemp() + self.config = TestConfig(False, False) + self.config.BASE['database_uri'] = 'sqlite:///' + self.__dbfile + self.config.WEBAPP['cache_dir'] = self.__dir + + init_database(self.config.BASE['database_uri'], True) + release_database() + + def tearDown(self): + shutil.rmtree(self.__dir) + os.remove(self.__dbfile) + + + def test_key(self): + app1 = create_application(self.config) + release_database() + + app2 = create_application(self.config) + release_database() + + self.assertEqual(app1.secret_key, app2.secret_key) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/testbase.py b/tests/testbase.py index d93b477..8d3dad8 100644 --- a/tests/testbase.py +++ b/tests/testbase.py @@ -8,7 +8,6 @@ # Distributed under terms of the GNU AGPLv3 license. import inspect -import io import os import shutil import unittest