More updates to authentication

This commit is contained in:
Tim Bentley 2013-03-11 21:00:00 +00:00
parent c62dab074e
commit 5c79832bcc
5 changed files with 46 additions and 86 deletions

View File

@ -36,6 +36,7 @@ from PyQt4 import QtGui
from openlp.core.lib import Registry
class SettingsTab(QtGui.QWidget):
"""
SettingsTab is a helper widget for plugins to define Tabs for the settings

View File

@ -860,8 +860,6 @@ class SlideController(DisplayController):
"""
Go to the requested slide
"""
if not self.service_item or not message[0]:
return
index = int(message[0])
if not self.service_item:
return

View File

@ -34,24 +34,24 @@ http://tools.cherrypy.org/wiki/AuthenticationAndAccessRestrictions
"""
import cherrypy
import urlparse
import logging
from openlp.core.lib import Settings
SESSION_KEY = '_cp_openlp'
log = logging.getLogger(__name__)
def check_credentials(user_name, password):
"""
Verifies credentials for username and password.
Returns None on success or a string describing the error on failure
"""
# @todo make from config
print "check_credentials"
if user_name == 'openlp' and password == 'openlp':
if user_name == Settings().value(u'remotes/user id') and password == Settings().value(u'remotes/password'):
return None
else:
return u"Incorrect username or password."
# if u.password != md5.new(password).hexdigest():
# return u"Incorrect password"
def check_auth(*args, **kwargs):
@ -60,17 +60,14 @@ def check_auth(*args, **kwargs):
is not None, a login is required and the entry is evaluated as a list of
conditions that the user must fulfill
"""
print "check_auth"
conditions = cherrypy.request.config.get('auth.require', None)
print urlparse.urlparse(cherrypy.url()), conditions
print conditions
if not Settings().value(u'remotes/authentication enabled'):
return None
if conditions is not None:
username = cherrypy.session.get(SESSION_KEY)
print username
if username:
cherrypy.request.login = username
for condition in conditions:
print "c ", condition
# A condition is just a callable that returns true or false
if not condition():
raise cherrypy.HTTPRedirect("/auth/login")
@ -97,49 +94,6 @@ def require_auth(*conditions):
return decorate
# Conditions are callables that return True
# if the user fulfills the conditions they define, False otherwise
#
# They can access the current username as cherrypy.request.login
#
# Define those at will however suits the application.
#def member_of(groupname):
# def check():
# # replace with actual check if <username> is in <groupname>
# return cherrypy.request.login == 'joe' and groupname == 'admin'
# return check
#def name_is(reqd_username):
# return lambda: reqd_username == cherrypy.request.login
#def any_of(*conditions):
# """
# Returns True if any of the conditions match
# """
# def check():
# for c in conditions:
# if c():
# return True
# return False
# return check
# By default all conditions are required, but this might still be
# needed if you want to use it inside of an any_of(...) condition
#def all_of(*conditions):
# """
# Returns True if all of the conditions match
# """
# def check():
# for c in conditions:
# if not c():
# return False
# return True
# return check
# Controller to provide login and logout actions
class AuthController(object):
def on_login(self, username):
@ -156,14 +110,26 @@ class AuthController(object):
"""
Provides a login form
"""
return """<html><body>
<form method="post" action="/auth/login">
<input type="hidden" name="from_page" value="%(from_page)s" />
%(msg)s<br />
Username: <input type="text" name="username" value="%(username)s" /><br />
Password: <input type="password" name="password" /><br />
<input type="submit" value="Log in" />
</body></html>""" % locals()
return """<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, minimum-scale=1, maximum-scale=1" />
<title>User Login</title>
<link rel="stylesheet" href="/files/jquery.mobile.css" />
<link rel="stylesheet" href="/files/openlp.css" />
<link rel="shortcut icon" type="image/x-icon" href="/files/images/favicon.ico">
<script type="text/javascript" src="/files/jquery.js"></script>
<script type="text/javascript" src="/files/openlp.js"></script>
<script type="text/javascript" src="/files/jquery.mobile.js"></script>
</head>
<body>
<form method="post" action="/auth/login">
<input type="hidden" name="from_page" value="%(from_page)s" />
%(msg)s<br/>
Username: <input type="text" name="username" value="%(username)s" /><br />
Password: <input type="password" name="password" /><br />
<input type="submit" value="Log in" />
</body></html>""" % locals()
@cherrypy.expose
def login(self, username=None, password=None, from_page="/"):

View File

@ -130,6 +130,7 @@ from openlp.plugins.remotes.lib.httpauth import AuthController, require_auth
log = logging.getLogger(__name__)
class HttpServer(object):
"""
Ability to control OpenLP via a web browser.
@ -156,10 +157,19 @@ class HttpServer(object):
clients. Listen out for socket connections.
"""
log.debug(u'Start CherryPy server')
port = Settings().value(self.plugin.settingsSection + u'/port')
address = Settings().value(self.plugin.settingsSection + u'/ip address')
server_config = {u'server.socket_host': str(address),
u'server.socket_port': port}
if Settings().value(self.plugin.settingsSection + u'/https enabled'):
port = Settings().value(self.plugin.settingsSection + u'/https port')
address = Settings().value(self.plugin.settingsSection + u'/ip address')
shared_data = AppLocation.get_directory(AppLocation.SharedData)
server_config = {u'server.socket_host': str(address),
u'server.socket_port': port,
u'server.ssl_certificate': os.path.join(shared_data, u'openlp.crt'),
u'server.ssl_private_key': os.path.join(shared_data, u'openlp.key')}
else:
port = Settings().value(self.plugin.settingsSection + u'/port')
address = Settings().value(self.plugin.settingsSection + u'/ip address')
server_config = {u'server.socket_host': str(address),
u'server.socket_port': port}
cherrypy.config.update(server_config)
cherrypy.config.update({'environment': 'embedded'})
cherrypy.config.update({'engine.autoreload_on': False})
@ -231,10 +241,8 @@ class HttpConnection(object):
"""
Handles the requests for the main url. This is secure depending on settings in config.
"""
print "default"
url = urlparse.urlparse(cherrypy.url())
self.url_params = urlparse.parse_qs(url.query)
print url
# Loop through the routes we set up earlier and execute them
return self._process_http_request(args, kwargs)
@ -243,10 +251,8 @@ class HttpConnection(object):
"""
Handles the requests for the stage url. This is not secure.
"""
print "Stage"
url = urlparse.urlparse(cherrypy.url())
self.url_params = urlparse.parse_qs(url.query)
print url
return self._process_http_request(args, kwargs)
@cherrypy.expose
@ -254,24 +260,20 @@ class HttpConnection(object):
"""
Handles the requests for the files url. This is not secure.
"""
print "files"
url = urlparse.urlparse(cherrypy.url())
self.url_params = urlparse.parse_qs(url.query)
print url
return self._process_http_request(args, kwargs)
def _process_http_request(self, args, kwargs):
"""
Common function to process HTTP requests where secure or insecure
"""
print "common handler"
url = urlparse.urlparse(cherrypy.url())
self.url_params = urlparse.parse_qs(url.query)
response = None
for route, func in self.routes:
match = re.match(route, url.path)
if match:
print 'Route "%s" matched "%s"', route, url.path, func
log.debug('Route "%s" matched "%s"', route, url.path)
args = []
for param in match.groups():
@ -474,11 +476,8 @@ class HttpConnection(object):
# This slot expects an int within a list.
id = data[u'request'][u'id']
Registry().execute(event, [id])
else:
Registry().execute(event, [0])
json_data = {u'results': {u'success': True}}
cherrypy.response.headers['Content-Type'] = u'application/json'
print json.dumps(json_data)
return json.dumps(json_data)
def service(self, action):
@ -545,7 +544,6 @@ class HttpConnection(object):
"""
Go live on an item of type ``plugin``.
"""
print "go_live"
try:
id = json.loads(self.url_params[u'data'][0])[u'request'][u'id']
except KeyError, ValueError:
@ -577,7 +575,7 @@ class HttpConnection(object):
def _http_not_found(self):
cherrypy.response.status = 404
cherrypy.response.body = ["<html><body>Sorry, an error occured</body></html>"]
cherrypy.response.body = ["<html><body>Sorry, an error occurred </body></html>"]
def _get_service_manager(self):
"""

View File

@ -56,15 +56,13 @@ class RemoteTab(SettingsTab):
self.address_label.setObjectName(u'address_label')
self.address_edit = QtGui.QLineEdit(self.server_settings_group_box)
self.address_edit.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed)
self.address_edit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(u'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'),
self.address_edit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(u'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'),
self))
self.address_edit.setObjectName(u'address_edit')
self.server_settings_layout.addRow(self.address_label, self.address_edit)
self.twelve_hour_check_box = QtGui.QCheckBox(self.server_settings_group_box)
self.twelve_hour_check_box.setObjectName(u'twelve_hour_check_box')
self.server_settings_layout.addRow(self.twelve_hour_check_box)
self.leftLayout.addWidget(self.server_settings_group_box)
self.http_settings_group_box = QtGui.QGroupBox(self.leftColumn)
self.http_settings_group_box.setObjectName(u'http_settings_group_box')
@ -75,7 +73,6 @@ class RemoteTab(SettingsTab):
self.port_spin_box = QtGui.QSpinBox(self.http_settings_group_box)
self.port_spin_box.setMaximum(32767)
self.port_spin_box.setObjectName(u'port_spin_box')
self.http_setting_layout.addRow(self.port_label, self.port_spin_box)
self.remote_url_label = QtGui.QLabel(self.http_settings_group_box)
self.remote_url_label.setObjectName(u'remote_url_label')
@ -244,7 +241,7 @@ class RemoteTab(SettingsTab):
Settings().setValue(self.settingsSection + u'/user id', self.user_id.text())
Settings().setValue(self.settingsSection + u'/password', self.password.text())
if changed:
Registry().register_function(u'remotes_config_updated')
Registry().execute(u'remotes_config_updated')
def on_twelve_hour_check_box_changed(self, check_state):