fix the path given by the set-cookie header
This commit is contained in:
parent
138b8ae314
commit
d362a6ceba
|
@ -71,11 +71,11 @@ def get_session_id(session_id):
|
||||||
"""
|
"""
|
||||||
if not session_id:
|
if not session_id:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
checksum = int(session_id[-4:])
|
checksum = int(session_id[-4:])
|
||||||
session_id = session_id[:-4]
|
session_id = session_id[:-4]
|
||||||
|
|
||||||
if checksum == make_checksum(session_id):
|
if checksum == make_checksum(session_id):
|
||||||
return session_id
|
return session_id
|
||||||
return None
|
return None
|
||||||
|
@ -93,32 +93,32 @@ class Auth(JSONComponent):
|
||||||
"""
|
"""
|
||||||
The component that implements authentification into the JSON interface.
|
The component that implements authentification into the JSON interface.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Auth, self).__init__("Auth")
|
super(Auth, self).__init__("Auth")
|
||||||
self.worker = LoopingCall(self._clean_sessions)
|
self.worker = LoopingCall(self._clean_sessions)
|
||||||
self.worker.start(5)
|
self.worker.start(5)
|
||||||
|
|
||||||
def _clean_sessions(self):
|
def _clean_sessions(self):
|
||||||
config = component.get("DelugeWeb").config
|
config = component.get("DelugeWeb").config
|
||||||
session_ids = config["sessions"].keys()
|
session_ids = config["sessions"].keys()
|
||||||
|
|
||||||
now = time.gmtime()
|
now = time.gmtime()
|
||||||
for session_id in session_ids:
|
for session_id in session_ids:
|
||||||
session = config["sessions"][session_id]
|
session = config["sessions"][session_id]
|
||||||
|
|
||||||
if "expires" not in session:
|
if "expires" not in session:
|
||||||
del config["sessions"][session_id]
|
del config["sessions"][session_id]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if time.gmtime(session["expires"]) < now:
|
if time.gmtime(session["expires"]) < now:
|
||||||
del config["sessions"][session_id]
|
del config["sessions"][session_id]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
def _create_session(self, request, login='admin'):
|
def _create_session(self, request, login='admin'):
|
||||||
"""
|
"""
|
||||||
Creates a new session.
|
Creates a new session.
|
||||||
|
|
||||||
:keyword login: the username of the user logging in, currently \
|
:keyword login: the username of the user logging in, currently \
|
||||||
only for future use currently.
|
only for future use currently.
|
||||||
:type login: string
|
:type login: string
|
||||||
|
@ -131,14 +131,13 @@ class Auth(JSONComponent):
|
||||||
session_id = m.hexdigest()
|
session_id = m.hexdigest()
|
||||||
|
|
||||||
config = component.get("DelugeWeb").config
|
config = component.get("DelugeWeb").config
|
||||||
|
|
||||||
expires, expires_str = make_expires(config["session_timeout"])
|
expires, expires_str = make_expires(config["session_timeout"])
|
||||||
checksum = str(make_checksum(session_id))
|
checksum = str(make_checksum(session_id))
|
||||||
|
|
||||||
base = str(component.get("Web").get_config()["base"])
|
|
||||||
request.addCookie('_session_id', session_id + checksum,
|
request.addCookie('_session_id', session_id + checksum,
|
||||||
path=base+"json", expires=expires_str)
|
path=request.base+"json", expires=expires_str)
|
||||||
|
|
||||||
log.debug("Creating session for %s", login)
|
log.debug("Creating session for %s", login)
|
||||||
config = component.get("DelugeWeb").config
|
config = component.get("DelugeWeb").config
|
||||||
|
|
||||||
|
@ -151,7 +150,7 @@ class Auth(JSONComponent):
|
||||||
"expires": expires
|
"expires": expires
|
||||||
}
|
}
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def check_password(self, password):
|
def check_password(self, password):
|
||||||
config = component.get("DelugeWeb").config
|
config = component.get("DelugeWeb").config
|
||||||
if "pwd_md5" in config.config:
|
if "pwd_md5" in config.config:
|
||||||
|
@ -165,14 +164,14 @@ class Auth(JSONComponent):
|
||||||
# the old passwords from the config file.
|
# the old passwords from the config file.
|
||||||
self._change_password(password)
|
self._change_password(password)
|
||||||
del config.config["pwd_md5"]
|
del config.config["pwd_md5"]
|
||||||
|
|
||||||
# Remove the older password if there is now.
|
# Remove the older password if there is now.
|
||||||
if "old_pwd_md5" in config.config:
|
if "old_pwd_md5" in config.config:
|
||||||
del config.config["old_pwd_salt"]
|
del config.config["old_pwd_salt"]
|
||||||
del config.config["old_pwd_md5"]
|
del config.config["old_pwd_md5"]
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
elif "old_pwd_md5" in config.config:
|
elif "old_pwd_md5" in config.config:
|
||||||
# We are using the 1.1 webui auth method
|
# We are using the 1.1 webui auth method
|
||||||
log.debug("Received a password via the 1.1 auth method")
|
log.debug("Received a password via the 1.1 auth method")
|
||||||
|
@ -181,13 +180,13 @@ class Auth(JSONComponent):
|
||||||
m.update(decodestring(config["old_pwd_salt"]))
|
m.update(decodestring(config["old_pwd_salt"]))
|
||||||
m.update(password)
|
m.update(password)
|
||||||
if m.digest() == decodestring(config["old_pwd_md5"]):
|
if m.digest() == decodestring(config["old_pwd_md5"]):
|
||||||
|
|
||||||
# We want to move the password over to sha1 and remove
|
# We want to move the password over to sha1 and remove
|
||||||
# the old passwords from the config file.
|
# the old passwords from the config file.
|
||||||
self._change_password(password)
|
self._change_password(password)
|
||||||
del config.config["old_pwd_salt"]
|
del config.config["old_pwd_salt"]
|
||||||
del config.config["old_pwd_md5"]
|
del config.config["old_pwd_md5"]
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
elif "pwd_sha1" in config.config:
|
elif "pwd_sha1" in config.config:
|
||||||
|
@ -204,25 +203,25 @@ class Auth(JSONComponent):
|
||||||
# access.
|
# access.
|
||||||
log.debug("Failed to detect the login method")
|
log.debug("Failed to detect the login method")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def check_request(self, request, method=None, level=None):
|
def check_request(self, request, method=None, level=None):
|
||||||
"""
|
"""
|
||||||
Check to ensure that a request is authorised to call the specified
|
Check to ensure that a request is authorised to call the specified
|
||||||
method of authentication level.
|
method of authentication level.
|
||||||
|
|
||||||
:param request: The HTTP request in question
|
:param request: The HTTP request in question
|
||||||
:type request: twisted.web.http.Request
|
:type request: twisted.web.http.Request
|
||||||
:keyword method: Check the specified method
|
:keyword method: Check the specified method
|
||||||
:type method: function
|
:type method: function
|
||||||
:keyword level: Check the specified auth level
|
:keyword level: Check the specified auth level
|
||||||
:type level: integer
|
:type level: integer
|
||||||
|
|
||||||
:raises: Exception
|
:raises: Exception
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config = component.get("DelugeWeb").config
|
config = component.get("DelugeWeb").config
|
||||||
session_id = get_session_id(request.getCookie("_session_id"))
|
session_id = get_session_id(request.getCookie("_session_id"))
|
||||||
|
|
||||||
if session_id not in config["sessions"]:
|
if session_id not in config["sessions"]:
|
||||||
auth_level = AUTH_LEVEL_NONE
|
auth_level = AUTH_LEVEL_NONE
|
||||||
session_id = None
|
session_id = None
|
||||||
|
@ -233,34 +232,33 @@ class Auth(JSONComponent):
|
||||||
session["expires"] = expires
|
session["expires"] = expires
|
||||||
|
|
||||||
_session_id = request.getCookie("_session_id")
|
_session_id = request.getCookie("_session_id")
|
||||||
base = str(component.get("Web").get_config()["base"])
|
|
||||||
request.addCookie('_session_id', _session_id,
|
request.addCookie('_session_id', _session_id,
|
||||||
path=base+"json", expires=expires_str)
|
path=request.base+"json", expires=expires_str)
|
||||||
|
|
||||||
if method:
|
if method:
|
||||||
if not hasattr(method, "_json_export"):
|
if not hasattr(method, "_json_export"):
|
||||||
raise Exception("Not an exported method")
|
raise Exception("Not an exported method")
|
||||||
|
|
||||||
method_level = getattr(method, "_json_auth_level")
|
method_level = getattr(method, "_json_auth_level")
|
||||||
if method_level is None:
|
if method_level is None:
|
||||||
raise Exception("Method has no auth level")
|
raise Exception("Method has no auth level")
|
||||||
|
|
||||||
level = method_level
|
level = method_level
|
||||||
|
|
||||||
if level is None:
|
if level is None:
|
||||||
raise Exception("No level specified to check against")
|
raise Exception("No level specified to check against")
|
||||||
|
|
||||||
request.auth_level = auth_level
|
request.auth_level = auth_level
|
||||||
request.session_id = session_id
|
request.session_id = session_id
|
||||||
|
|
||||||
if auth_level < level:
|
if auth_level < level:
|
||||||
raise AuthError("Not authenticated")
|
raise AuthError("Not authenticated")
|
||||||
|
|
||||||
def _change_password(self, new_password):
|
def _change_password(self, new_password):
|
||||||
"""
|
"""
|
||||||
Change the password. This is to allow the UI to change/reset a
|
Change the password. This is to allow the UI to change/reset a
|
||||||
password.
|
password.
|
||||||
|
|
||||||
:param new_password: the password to change to
|
:param new_password: the password to change to
|
||||||
:type new_password: string
|
:type new_password: string
|
||||||
"""
|
"""
|
||||||
|
@ -272,12 +270,12 @@ class Auth(JSONComponent):
|
||||||
config["pwd_salt"] = salt
|
config["pwd_salt"] = salt
|
||||||
config["pwd_sha1"] = s.hexdigest()
|
config["pwd_sha1"] = s.hexdigest()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@export
|
@export
|
||||||
def change_password(self, old_password, new_password):
|
def change_password(self, old_password, new_password):
|
||||||
"""
|
"""
|
||||||
Change the password.
|
Change the password.
|
||||||
|
|
||||||
:param old_password: the current password
|
:param old_password: the current password
|
||||||
:type old_password: string
|
:type old_password: string
|
||||||
:param new_password: the password to change to
|
:param new_password: the password to change to
|
||||||
|
@ -286,22 +284,22 @@ class Auth(JSONComponent):
|
||||||
if not self.check_password(old_password):
|
if not self.check_password(old_password):
|
||||||
return False
|
return False
|
||||||
return self._change_password(new_password)
|
return self._change_password(new_password)
|
||||||
|
|
||||||
@export(AUTH_LEVEL_NONE)
|
@export(AUTH_LEVEL_NONE)
|
||||||
def check_session(self, session_id=None):
|
def check_session(self, session_id=None):
|
||||||
"""
|
"""
|
||||||
Check a session to see if it's still valid.
|
Check a session to see if it's still valid.
|
||||||
|
|
||||||
:returns: True if the session is valid, False if not.
|
:returns: True if the session is valid, False if not.
|
||||||
:rtype: booleon
|
:rtype: booleon
|
||||||
"""
|
"""
|
||||||
return __request__.session_id is not None
|
return __request__.session_id is not None
|
||||||
|
|
||||||
@export
|
@export
|
||||||
def delete_session(self):
|
def delete_session(self):
|
||||||
"""
|
"""
|
||||||
Removes a session.
|
Removes a session.
|
||||||
|
|
||||||
:param session_id: the id for the session to remove
|
:param session_id: the id for the session to remove
|
||||||
:type session_id: string
|
:type session_id: string
|
||||||
"""
|
"""
|
||||||
|
@ -309,18 +307,18 @@ class Auth(JSONComponent):
|
||||||
config = component.get("DelugeWeb").config
|
config = component.get("DelugeWeb").config
|
||||||
del config["sessions"][__request__.session_id]
|
del config["sessions"][__request__.session_id]
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@export(AUTH_LEVEL_NONE)
|
@export(AUTH_LEVEL_NONE)
|
||||||
def login(self, password):
|
def login(self, password):
|
||||||
"""
|
"""
|
||||||
Test a password to see if it's valid.
|
Test a password to see if it's valid.
|
||||||
|
|
||||||
:param password: the password to test
|
:param password: the password to test
|
||||||
:type password: string
|
:type password: string
|
||||||
:returns: a session id or False
|
:returns: a session id or False
|
||||||
:rtype: string or False
|
:rtype: string or False
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self.check_password(password):
|
if self.check_password(password):
|
||||||
return self._create_session(__request__)
|
return self._create_session(__request__)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -518,13 +518,31 @@ class TopLevel(resource.Resource):
|
||||||
self.__scripts.remove(script)
|
self.__scripts.remove(script)
|
||||||
self.__debug_scripts.remove(script)
|
self.__debug_scripts.remove(script)
|
||||||
|
|
||||||
|
|
||||||
def getChild(self, path, request):
|
def getChild(self, path, request):
|
||||||
if path == "":
|
if path == "":
|
||||||
return self
|
return self
|
||||||
else:
|
else:
|
||||||
return resource.Resource.getChild(self, path, request)
|
return resource.Resource.getChild(self, path, request)
|
||||||
|
|
||||||
|
def getChildWithDefault(self, path, request):
|
||||||
|
# Calculate the request base
|
||||||
|
header = request.getHeader('x-deluge-base')
|
||||||
|
base = header if header else component.get("DelugeWeb").base
|
||||||
|
|
||||||
|
# validate the base parameter
|
||||||
|
if not base:
|
||||||
|
base = '/'
|
||||||
|
|
||||||
|
if base[0] != '/':
|
||||||
|
base = '/' + base
|
||||||
|
|
||||||
|
if base[-1] != '/':
|
||||||
|
base += '/'
|
||||||
|
|
||||||
|
request.base = base.encode('idna')
|
||||||
|
|
||||||
|
return resource.Resource.getChildWithDefault(self, path, request)
|
||||||
|
|
||||||
def render(self, request):
|
def render(self, request):
|
||||||
debug = False
|
debug = False
|
||||||
if 'debug' in request.args:
|
if 'debug' in request.args:
|
||||||
|
@ -555,25 +573,12 @@ class TopLevel(resource.Resource):
|
||||||
template = Template(filename=rpath("index.html"))
|
template = Template(filename=rpath("index.html"))
|
||||||
request.setHeader("content-type", "text/html; charset=utf-8")
|
request.setHeader("content-type", "text/html; charset=utf-8")
|
||||||
|
|
||||||
header = request.getHeader('x-deluge-base')
|
|
||||||
base = header if header else component.get("DelugeWeb").base
|
|
||||||
|
|
||||||
# validate the base parameter
|
|
||||||
if not base:
|
|
||||||
base = '/'
|
|
||||||
|
|
||||||
if base[0] != '/':
|
|
||||||
base = '/' + base
|
|
||||||
|
|
||||||
if base[-1] != '/':
|
|
||||||
base += '/'
|
|
||||||
|
|
||||||
web_config = component.get("Web").get_config()
|
web_config = component.get("Web").get_config()
|
||||||
web_config["base"] = base
|
web_config["base"] = request.base
|
||||||
config = dict([(key, web_config[key]) for key in UI_CONFIG_KEYS])
|
config = dict([(key, web_config[key]) for key in UI_CONFIG_KEYS])
|
||||||
js_config = common.json.dumps(config)
|
js_config = common.json.dumps(config)
|
||||||
return template.render(scripts=scripts, stylesheets=self.stylesheets,
|
return template.render(scripts=scripts, stylesheets=self.stylesheets,
|
||||||
debug=debug, base=base, js_config=js_config)
|
debug=debug, base=request.base, js_config=js_config)
|
||||||
|
|
||||||
class ServerContextFactory:
|
class ServerContextFactory:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue