forked from openlp/openlp
Fix up tests
This commit is contained in:
parent
ced77e4ec3
commit
6cd384e028
@ -127,28 +127,32 @@ from PyQt4 import QtCore
|
|||||||
from openlp.core.lib import Registry, Settings, PluginStatus, StringContent
|
from openlp.core.lib import Registry, Settings, PluginStatus, StringContent
|
||||||
from openlp.core.utils import AppLocation, translate
|
from openlp.core.utils import AppLocation, translate
|
||||||
|
|
||||||
from cherrypy._cpcompat import md5, sha, ntob
|
from cherrypy._cpcompat import sha, ntob
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def sha_password_encrypter(password):
|
def sha_password_encrypter(password):
|
||||||
|
"""
|
||||||
|
Create an encrypted password for the given password.
|
||||||
|
"""
|
||||||
return sha(ntob(password)).hexdigest()
|
return sha(ntob(password)).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def fetch_password(username):
|
def fetch_password(username):
|
||||||
|
"""
|
||||||
|
Fetch the password for a provided user.
|
||||||
|
"""
|
||||||
if username != Settings().value(u'remotes/user id'):
|
if username != Settings().value(u'remotes/user id'):
|
||||||
return None
|
return None
|
||||||
print "fetch password", username
|
return sha_password_encrypter(Settings().value(u'remotes/password'))
|
||||||
return sha(ntob(Settings().value(u'remotes/password'))).hexdigest()
|
|
||||||
|
|
||||||
|
|
||||||
class HttpServer(object):
|
class HttpServer(object):
|
||||||
"""
|
"""
|
||||||
Ability to control OpenLP via a web browser.
|
Ability to control OpenLP via a web browser.
|
||||||
|
This class controls the Cherrypy server and configuration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_cp_config = {
|
_cp_config = {
|
||||||
'tools.sessions.on': True,
|
'tools.sessions.on': True,
|
||||||
'tools.auth.on': True
|
'tools.auth.on': True
|
||||||
@ -167,7 +171,7 @@ class HttpServer(object):
|
|||||||
Start the http server based on configuration.
|
Start the http server based on configuration.
|
||||||
"""
|
"""
|
||||||
log.debug(u'Start CherryPy server')
|
log.debug(u'Start CherryPy server')
|
||||||
# Define to security levels and add the router code
|
# Define to security levels and inject the router code
|
||||||
self.root = self.Public()
|
self.root = self.Public()
|
||||||
self.root.files = self.Files()
|
self.root.files = self.Files()
|
||||||
self.root.stage = self.Stage()
|
self.root.stage = self.Stage()
|
||||||
@ -180,6 +184,9 @@ class HttpServer(object):
|
|||||||
cherrypy.engine.start()
|
cherrypy.engine.start()
|
||||||
|
|
||||||
def define_config(self):
|
def define_config(self):
|
||||||
|
"""
|
||||||
|
Define the configuration of the server.
|
||||||
|
"""
|
||||||
if Settings().value(self.plugin.settings_section + u'/https enabled'):
|
if Settings().value(self.plugin.settings_section + u'/https enabled'):
|
||||||
port = Settings().value(self.plugin.settings_section + u'/https port')
|
port = Settings().value(self.plugin.settings_section + u'/https port')
|
||||||
address = Settings().value(self.plugin.settings_section + u'/ip address')
|
address = Settings().value(self.plugin.settings_section + u'/ip address')
|
||||||
@ -209,14 +216,12 @@ class HttpServer(object):
|
|||||||
u'tools.basic_auth.on': False}}
|
u'tools.basic_auth.on': False}}
|
||||||
return directory_config
|
return directory_config
|
||||||
|
|
||||||
def reload_config(self):
|
|
||||||
cherrypy.tree.mount(self.root, '/', config=self.define_config())
|
|
||||||
cherrypy.config.reset()
|
|
||||||
|
|
||||||
class Public:
|
class Public:
|
||||||
|
"""
|
||||||
|
Main access class with may have security enabled on it.
|
||||||
|
"""
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def default(self, *args, **kwargs):
|
def default(self, *args, **kwargs):
|
||||||
print "public"
|
|
||||||
self.router.request_data = None
|
self.router.request_data = None
|
||||||
if isinstance(kwargs, dict):
|
if isinstance(kwargs, dict):
|
||||||
self.router.request_data = kwargs.get(u'data', None)
|
self.router.request_data = kwargs.get(u'data', None)
|
||||||
@ -224,13 +229,18 @@ class HttpServer(object):
|
|||||||
return self.router.process_http_request(url.path, *args)
|
return self.router.process_http_request(url.path, *args)
|
||||||
|
|
||||||
class Files:
|
class Files:
|
||||||
|
"""
|
||||||
|
Provides access to files and has no security available. These are read only accesses
|
||||||
|
"""
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def default(self, *args, **kwargs):
|
def default(self, *args, **kwargs):
|
||||||
print "files"
|
|
||||||
url = urlparse.urlparse(cherrypy.url())
|
url = urlparse.urlparse(cherrypy.url())
|
||||||
return self.router.process_http_request(url.path, *args)
|
return self.router.process_http_request(url.path, *args)
|
||||||
|
|
||||||
class Stage:
|
class Stage:
|
||||||
|
"""
|
||||||
|
Stageview is read only so security is not relevant and would reduce it's usability
|
||||||
|
"""
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def default(self, *args, **kwargs):
|
def default(self, *args, **kwargs):
|
||||||
url = urlparse.urlparse(cherrypy.url())
|
url = urlparse.urlparse(cherrypy.url())
|
||||||
@ -246,12 +256,11 @@ class HttpServer(object):
|
|||||||
|
|
||||||
class HttpRouter(object):
|
class HttpRouter(object):
|
||||||
"""
|
"""
|
||||||
A single connection, this handles communication between the server and the client.
|
This code is called by the HttpServer upon a request and it processes it based on the routing table.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""
|
"""
|
||||||
Initialise the CherryPy Server
|
Initialise the router
|
||||||
"""
|
"""
|
||||||
self.routes = [
|
self.routes = [
|
||||||
(u'^/$', self.serve_file),
|
(u'^/$', self.serve_file),
|
||||||
@ -275,7 +284,7 @@ class HttpRouter(object):
|
|||||||
|
|
||||||
def process_http_request(self, url_path, *args):
|
def process_http_request(self, url_path, *args):
|
||||||
"""
|
"""
|
||||||
Common function to process HTTP requests where secure or insecure
|
Common function to process HTTP requests
|
||||||
"""
|
"""
|
||||||
response = None
|
response = None
|
||||||
for route, func in self.routes:
|
for route, func in self.routes:
|
||||||
|
@ -8,7 +8,7 @@ from tempfile import mkstemp
|
|||||||
from mock import patch, MagicMock
|
from mock import patch, MagicMock
|
||||||
|
|
||||||
from openlp.core.lib import Settings
|
from openlp.core.lib import Settings
|
||||||
from openlp.plugins.remotes.lib.httpserver import HttpRouter
|
from openlp.plugins.remotes.lib.httpserver import HttpRouter, fetch_password, sha_password_encrypter
|
||||||
from PyQt4 import QtGui
|
from PyQt4 import QtGui
|
||||||
|
|
||||||
__default_settings__ = {
|
__default_settings__ = {
|
||||||
@ -44,6 +44,43 @@ class TestRouter(TestCase):
|
|||||||
del self.application
|
del self.application
|
||||||
os.unlink(self.ini_file)
|
os.unlink(self.ini_file)
|
||||||
|
|
||||||
|
def fetch_password_unknown_test(self):
|
||||||
|
"""
|
||||||
|
Test the fetch password code with an unknown userid
|
||||||
|
"""
|
||||||
|
# GIVEN: A default configuration
|
||||||
|
# WHEN: called with the defined userid
|
||||||
|
password = fetch_password(u'itwinkle')
|
||||||
|
print password
|
||||||
|
|
||||||
|
# THEN: the function should return None
|
||||||
|
self.assertEqual(password, None, u'The result for fetch_password should be None')
|
||||||
|
|
||||||
|
def fetch_password_known_test(self):
|
||||||
|
"""
|
||||||
|
Test the fetch password code with the defined userid
|
||||||
|
"""
|
||||||
|
# GIVEN: A default configuration
|
||||||
|
# WHEN: called with the defined userid
|
||||||
|
password = fetch_password(u'openlp')
|
||||||
|
required_password = sha_password_encrypter(u'password')
|
||||||
|
|
||||||
|
# THEN: the function should return the correct password
|
||||||
|
self.assertEqual(password, required_password, u'The result for fetch_password should be the defined password')
|
||||||
|
|
||||||
|
def sha_password_encrypter_test(self):
|
||||||
|
"""
|
||||||
|
Test hash password function
|
||||||
|
"""
|
||||||
|
# GIVEN: A default configuration
|
||||||
|
# WHEN: called with the defined userid
|
||||||
|
required_password = sha_password_encrypter(u'password')
|
||||||
|
test_value = '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8'
|
||||||
|
|
||||||
|
# THEN: the function should return the correct password
|
||||||
|
self.assertEqual(required_password, test_value,
|
||||||
|
u'The result for sha_password_encrypter should return the correct encrypted password')
|
||||||
|
|
||||||
def process_http_request_test(self):
|
def process_http_request_test(self):
|
||||||
"""
|
"""
|
||||||
Test the router control functionality
|
Test the router control functionality
|
||||||
@ -61,22 +98,3 @@ class TestRouter(TestCase):
|
|||||||
# THEN: the function should have been called only once
|
# THEN: the function should have been called only once
|
||||||
assert mocked_function.call_count == 1, \
|
assert mocked_function.call_count == 1, \
|
||||||
u'The mocked function should have been matched and called once.'
|
u'The mocked function should have been matched and called once.'
|
||||||
|
|
||||||
|
|
||||||
#self.assertFalse()
|
|
||||||
|
|
||||||
# WHEN: We run the function with no input
|
|
||||||
#authenticated = check_credentials(u'', u'')
|
|
||||||
|
|
||||||
# THEN: The authentication will fail with an error message
|
|
||||||
#self.assertEqual(authenticated, u'Incorrect username or password.',
|
|
||||||
# u'The return should be a error message string')
|
|
||||||
|
|
||||||
# WHEN: We run the function with the correct input
|
|
||||||
#authenticated = check_credentials(u'twinkle', u'mongoose')
|
|
||||||
|
|
||||||
# THEN: The authentication will pass.
|
|
||||||
#self.assertEqual(authenticated, None, u'The return should be a None string')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
"""
|
|
||||||
This module contains tests for the lib submodule of the Remotes plugin.
|
|
||||||
"""
|
|
||||||
import os
|
|
||||||
from unittest import TestCase
|
|
||||||
from tempfile import mkstemp
|
|
||||||
from mock import patch, MagicMock
|
|
||||||
|
|
||||||
|
|
||||||
import urllib
|
|
||||||
from BeautifulSoup import BeautifulSoup, NavigableString, Tag
|
|
||||||
|
|
||||||
from openlp.core.lib import Settings
|
|
||||||
from openlp.plugins.remotes.lib import HttpServer
|
|
||||||
from PyQt4 import QtGui
|
|
||||||
|
|
||||||
__default_settings__ = {
|
|
||||||
u'remotes/twelve hour': True,
|
|
||||||
u'remotes/port': 4316,
|
|
||||||
u'remotes/https port': 4317,
|
|
||||||
u'remotes/https enabled': False,
|
|
||||||
u'remotes/user id': u'openlp',
|
|
||||||
u'remotes/password': u'password',
|
|
||||||
u'remotes/authentication enabled': False,
|
|
||||||
u'remotes/ip address': u'0.0.0.0'
|
|
||||||
}
|
|
||||||
|
|
||||||
SESSION_KEY = '_cp_openlp'
|
|
||||||
|
|
||||||
|
|
||||||
class TestRemoteServer(TestCase):
|
|
||||||
"""
|
|
||||||
Test the functions in the :mod:`lib` module.
|
|
||||||
"""
|
|
||||||
def setUp(self):
|
|
||||||
"""
|
|
||||||
Create the UI
|
|
||||||
"""
|
|
||||||
fd, self.ini_file = mkstemp(u'.ini')
|
|
||||||
Settings().set_filename(self.ini_file)
|
|
||||||
self.application = QtGui.QApplication.instance()
|
|
||||||
Settings().extend_default_settings(__default_settings__)
|
|
||||||
self.server = HttpServer(self)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
"""
|
|
||||||
Delete all the C++ objects at the end so that we don't have a segfault
|
|
||||||
"""
|
|
||||||
del self.application
|
|
||||||
os.unlink(self.ini_file)
|
|
||||||
os.unlink(Settings().fileName())
|
|
||||||
self.server.close()
|
|
||||||
|
|
||||||
def check_access_test(self):
|
|
||||||
"""
|
|
||||||
Test the Authentication check routine.
|
|
||||||
"""
|
|
||||||
# GIVEN: A user and password in settings
|
|
||||||
Settings().setValue(u'remotes/user id', u'twinkle')
|
|
||||||
Settings().setValue(u'remotes/password', u'mongoose')
|
|
||||||
|
|
||||||
# WHEN: We run the function with no input
|
|
||||||
authenticated = check_credentials(u'', u'')
|
|
||||||
|
|
||||||
# THEN: The authentication will fail with an error message
|
|
||||||
self.assertEqual(authenticated, u'Incorrect username or password.',
|
|
||||||
u'The return should be a error message string')
|
|
||||||
|
|
||||||
# WHEN: We run the function with the correct input
|
|
||||||
authenticated = check_credentials(u'twinkle', u'mongoose')
|
|
||||||
|
|
||||||
# THEN: The authentication will pass.
|
|
||||||
self.assertEqual(authenticated, None, u'The return should be a None string')
|
|
||||||
|
|
||||||
def check_auth_inactive_test(self):
|
|
||||||
"""
|
|
||||||
Test the Authentication check routine.
|
|
||||||
"""
|
|
||||||
# GIVEN: A access which is secure
|
|
||||||
Settings().setValue(u'remotes/authentication enabled', True)
|
|
||||||
|
|
||||||
# WHEN: We run the function with no input
|
|
||||||
f = urllib.urlopen("http://localhost:4316")
|
|
||||||
soup = BeautifulSoup(f.read())
|
|
||||||
print soup.title.string
|
|
Loading…
Reference in New Issue
Block a user