Fix some clean config dir issues.

Moved some auth stuff to `deluge.common` because they're also used on the GTK UI.
Now, if a user starts deluge in classic mode and tries to change it to client/daemon mode, he see's a dialog stating that the current session will be stopped. If he answers no, nothing is done, the classic mode pref is set back as it was. If he answers yes, all components are stopped and client is disconnected. At this stage the user can open the connection manager to start the daemon and connect.
If the user starts in client/daemon mode and switches to classic mode he see's a dialog stating that deluge must be restarted.
The GTK UI connection manager now loads it's default config with the localclient username and password. If not present in the auth file, the auth file will be recreated.
This commit is contained in:
Pedro Algarvio 2011-04-27 22:06:13 +01:00
parent 18b27d4b49
commit 9fa8748432
7 changed files with 132 additions and 71 deletions

View file

@ -631,3 +631,43 @@ class VersionSplit(object):
v1 = [self.version, self.suffix or 'z', self.dev]
v2 = [ver.version, ver.suffix or 'z', ver.dev]
return cmp(v1, v2)
# Common AUTH stuff
AUTH_LEVEL_NONE = 0
AUTH_LEVEL_READONLY = 1
AUTH_LEVEL_NORMAL = 5
AUTH_LEVEL_ADMIN = 10
AUTH_LEVEL_DEFAULT = AUTH_LEVEL_NORMAL
def create_auth_file():
import stat, configmanager
auth_file = configmanager.get_config_dir("auth")
# Check for auth file and create if necessary
if not os.path.exists(auth_file):
fd = open(auth_file, "w")
fd.flush()
os.fsync(fd.fileno())
fd.close()
# Change the permissions on the file so only this user can read/write it
os.chmod(auth_file, stat.S_IREAD | stat.S_IWRITE)
def create_localclient_account():
import configmanager, random
auth_file = configmanager.get_config_dir("auth")
if not os.path.exists(auth_file):
create_auth_file()
try:
from hashlib import sha1 as sha_hash
except ImportError:
from sha import new as sha_hash
fd = open(auth_file, "w")
fd.write(":".join([
"localclient",
sha_hash(str(random.random())).hexdigest(),
str(AUTH_LEVEL_ADMIN)
]) + '\n')
fd.flush()
os.fsync(fd.fileno())
fd.close()

View file

@ -42,17 +42,14 @@ import logging
import deluge.component as component
import deluge.configmanager as configmanager
from deluge.common import (AUTH_LEVEL_ADMIN, AUTH_LEVEL_NONE, AUTH_LEVEL_NORMAL,
AUTH_LEVEL_READONLY, AUTH_LEVEL_DEFAULT,
create_auth_file, create_localclient_account)
from deluge.error import AuthManagerError, AuthenticationRequired, BadLoginError
log = logging.getLogger(__name__)
AUTH_LEVEL_NONE = 0
AUTH_LEVEL_READONLY = 1
AUTH_LEVEL_NORMAL = 5
AUTH_LEVEL_ADMIN = 10
AUTH_LEVEL_DEFAULT = AUTH_LEVEL_NORMAL
AUTH_LEVELS_MAPPING = {
'NONE': AUTH_LEVEL_NONE,
'READONLY': AUTH_LEVEL_READONLY,
@ -218,28 +215,13 @@ class AuthManager(component.Component):
self.__load_auth_file()
def __create_localclient_account(self):
"""
Returns the string.
"""
# We create a 'localclient' account with a random password
try:
from hashlib import sha1 as sha_hash
except ImportError:
from sha import new as sha_hash
self.__auth["localclient"] = Account(
"localclient",
sha_hash(str(random.random())).hexdigest(),
AUTH_LEVEL_ADMIN
)
def __load_auth_file(self):
save_and_reload = False
auth_file = configmanager.get_config_dir("auth")
# Check for auth file and create if necessary
if not os.path.exists(auth_file):
self.__create_auth_file()
self.__create_localclient_account()
create_auth_file()
create_localclient_account()
self.write_auth_file()
auth_file_modification_time = os.stat(auth_file).st_mtime
@ -295,7 +277,7 @@ class AuthManager(component.Component):
self.__auth[username] = Account(username, password, authlevel)
if "localclient" not in self.__auth:
self.__create_localclient_account()
create_localclient_account()
self.write_auth_file()
if save_and_reload:
@ -303,14 +285,3 @@ class AuthManager(component.Component):
self.write_auth_file()
self.__auth_modification_time = auth_file_modification_time
def __create_auth_file(self):
auth_file = configmanager.get_config_dir("auth")
# Check for auth file and create if necessary
if not os.path.exists(auth_file):
fd = open(auth_file, "w")
fd.flush()
os.fsync(fd.fileno())
fd.close()
# Change the permissions on the file so only this user can read/write it
os.chmod(auth_file, stat.S_IREAD | stat.S_IWRITE)

View file

@ -54,7 +54,9 @@ class Daemon(object):
if os.path.isfile(deluge.configmanager.get_config_dir("deluged.pid")):
# Get the PID and the port of the supposedly running daemon
try:
(pid, port) = open(deluge.configmanager.get_config_dir("deluged.pid")).read().strip().split(";")
(pid, port) = open(
deluge.configmanager.get_config_dir("deluged.pid")
).read().strip().split(";")
pid = int(pid)
port = int(port)
except ValueError:
@ -93,7 +95,10 @@ class Daemon(object):
else:
# This is a deluged!
s.close()
raise deluge.error.DaemonRunningError("There is a deluge daemon running with this config directory!")
raise deluge.error.DaemonRunningError(
"There is a deluge daemon running with this config "
"directory!"
)
# Initialize gettext
try:

View file

@ -515,6 +515,7 @@ class DaemonClassicProxy(DaemonProxy):
self.__daemon.core.eventmanager.register_event_handler(event, handler)
def disconnect(self):
self.connected = False
self.__daemon = None
def call(self, method, *args, **kwargs):

View file

@ -407,26 +407,28 @@ def get_localhost_auth():
:rtype: tuple
"""
auth_file = deluge.configmanager.get_config_dir("auth")
if os.path.exists(auth_file):
for line in open(auth_file):
if line.startswith("#"):
# This is a comment line
continue
line = line.strip()
try:
lsplit = line.split(":")
except Exception, e:
log.error("Your auth file is malformed: %s", e)
continue
if not os.path.exists(auth_file):
from deluge.common import create_localclient_account
create_localclient_account()
if len(lsplit) == 2:
username, password = lsplit
elif len(lsplit) == 3:
username, password, level = lsplit
else:
log.error("Your auth file is malformed: Incorrect number of fields!")
continue
for line in open(auth_file):
if line.startswith("#"):
# This is a comment line
continue
line = line.strip()
try:
lsplit = line.split(":")
except Exception, e:
log.error("Your auth file is malformed: %s", e)
continue
if username == "localclient":
return (username, password)
return ("", "")
if len(lsplit) == 2:
username, password = lsplit
elif len(lsplit) == 3:
username, password, level = lsplit
else:
log.error("Your auth file is malformed: Incorrect number of fields!")
continue
if username == "localclient":
return (username, password)

View file

@ -33,6 +33,7 @@
#
#
import os
import gtk
import pkg_resources
import time
@ -56,11 +57,6 @@ log = logging.getLogger(__name__)
DEFAULT_HOST = "127.0.0.1"
DEFAULT_PORT = 58846
DEFAULT_CONFIG = {
"hosts": [(hashlib.sha1(str(time.time())).hexdigest(), DEFAULT_HOST,
DEFAULT_PORT, "localclient", "")]
}
HOSTLIST_COL_ID = 0
HOSTLIST_COL_HOST = 1
HOSTLIST_COL_PORT = 2
@ -99,15 +95,11 @@ class ConnectionManager(component.Component):
def __init__(self):
component.Component.__init__(self, "ConnectionManager")
self.gtkui_config = ConfigManager("gtkui.conf")
self.config = ConfigManager("hostlist.conf.1.2", DEFAULT_CONFIG)
self.config.run_converter((0, 1), 2, self.__migrate_config_1_to_2)
self.running = False
# Component overrides
def start(self):
pass
self.config = self.__load_config()
def stop(self):
# Close this dialog when we are shutting down
@ -117,6 +109,26 @@ class ConnectionManager(component.Component):
def shutdown(self):
pass
def __load_config(self):
auth_file = deluge.configmanager.get_config_dir("auth")
if not os.path.exists(auth_file):
from deluge.common import create_localclient_account
create_localclient_account()
localclient_username, localclient_password = get_localhost_auth()
DEFAULT_CONFIG = {
"hosts": [(
hashlib.sha1(str(time.time())).hexdigest(),
DEFAULT_HOST,
DEFAULT_PORT,
localclient_username,
localclient_password
)]
}
config = ConfigManager("hostlist.conf.1.2", DEFAULT_CONFIG)
config.run_converter((0, 1), 2, self.__migrate_config_1_to_2)
return config
# Public methods
def show(self):
"""

View file

@ -546,6 +546,8 @@ class Preferences(component.Component):
except ImportError:
from sha import new as sha_hash
classic_mode_was_set = self.gtkui_config["classic_mode"]
# Get the values from the dialog
new_core_config = {}
new_gtkui_config = {}
@ -666,8 +668,10 @@ class Preferences(component.Component):
self.glade.get_widget("txt_tray_password").get_text()).hexdigest()
if passhex != "c07eb5a8c0dc7bb81c217b67f11c3b7a5e95ffd7":
new_gtkui_config["tray_password"] = passhex
new_gtkui_config["classic_mode"] = \
self.glade.get_widget("chk_classic_mode").get_active()
new_gtkui_in_classic_mode = self.glade.get_widget("chk_classic_mode").get_active()
new_gtkui_config["classic_mode"] = new_gtkui_in_classic_mode
new_gtkui_config["show_rate_in_title"] = \
self.glade.get_widget("chk_show_rate_in_title").get_active()
@ -763,6 +767,32 @@ class Preferences(component.Component):
# Re-show the dialog to make sure everything has been updated
self.show()
if classic_mode_was_set==True and new_gtkui_in_classic_mode==False:
def on_response(response):
if response == gtk.RESPONSE_NO:
# Set each changed config value in the core
self.gtkui_config["classic_mode"] = True
client.core.set_config({"classic_mode": True})
client.force_call(True)
# Update the configuration
self.core_config.update({"classic_mode": True})
self.glade.get_widget("chk_classic_mode").set_active(True)
else:
client.disconnect()
if client.is_classicmode():
component.stop()
dialog = dialogs.YesNoDialog(
_("Attention"),
_("Your current session will be stopped. Continue?")
)
dialog.run().addCallback(on_response)
elif classic_mode_was_set==False and new_gtkui_in_classic_mode==True:
dialog = dialogs.InformationDialog(
_("Attention"),
_("You must now restart the deluge UI")
)
dialog.run()
def hide(self):
self.glade.get_widget("port_img").hide()
self.pref_dialog.hide()