From b84c487e953ab96bd6140a7073763c15b242e3d3 Mon Sep 17 00:00:00 2001 From: tonio Date: Wed, 9 Jun 2010 09:58:33 +0200 Subject: [PATCH] More work about #57. User password is no more stored inside the session! To finish, I just need a good way to handle http server reboots (and so python code reloading). --- auth/views.py | 8 +++++- extensions/webmail/imap_listing.py | 27 ++++++++++++--------- extensions/webmail/main.py | 12 ++++++++- extensions/webmail/views.py | 39 +++++++++++++++--------------- lib/__init__.py | 2 +- lib/events.py | 3 ++- templates/nlayout.html | 2 +- urls.py | 2 +- 8 files changed, 58 insertions(+), 37 deletions(-) diff --git a/auth/views.py b/auth/views.py index 52d127346..ba167ad68 100755 --- a/auth/views.py +++ b/auth/views.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from django.contrib.auth import authenticate, login +from django.contrib.auth import authenticate, login, logout from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import render_to_response from django.core.urlresolvers import reverse @@ -35,3 +35,9 @@ def dologin(request): return render_to_response("registration/login.html", { "form" : form, "error" : error, "next" : next }) + +def dologout(request): + events.raiseEvent("UserLogout", request=request) + logout(request) + + return HttpResponseRedirect(reverse(dologin)) diff --git a/extensions/webmail/imap_listing.py b/extensions/webmail/imap_listing.py index a85b964e2..572b430ad 100644 --- a/extensions/webmail/imap_listing.py +++ b/extensions/webmail/imap_listing.py @@ -126,13 +126,12 @@ class ConnectionsManager(type): key = None if kwargs.has_key("user"): key = kwargs["user"] - elif len(args): - key = args[0].user.username - if key is None: + else: return None if not cls.instances.has_key(key): cls.instances[key] = None - if cls.instances[key] is None: + if cls.instances[key] is None or cls.instances[key].invalid: + # I hope python's garbage collector will detect this correclty cls.instances[key] = \ super(ConnectionsManager, cls).__call__(*args, **kwargs) return cls.instances[key] @@ -140,15 +139,14 @@ class ConnectionsManager(type): class IMAPconnector(object): __metaclass__ = ConnectionsManager - def __init__(self, request=None, user=None, password=None): + def __init__(self, user=None, password=None): + print "IMAP constructor" + self.criterions = [] self.address = parameters.get("webmail", "IMAP_SERVER") self.port = int(parameters.get("webmail", "IMAP_PORT")) - if request: - status, msg = self.login(request.user.username, - request.session["password"]) - else: - status, msg = self.login(user, password) + self.invalid = False + status, msg = self.login(user, password) if not status: raise Exception(msg) @@ -169,6 +167,11 @@ class IMAPconnector(object): return True, None + def logout(self): + self.m.close() + self.m.logout() + self.invalid = True + def _encodefolder(self, folder): if not folder: return "INBOX" @@ -314,8 +317,8 @@ class ImapListing(EmailListing): defcallback = "wm_updatelisting" reset_wm_url = False - def __init__(self, user, password, **kwargs): - self.mbc = IMAPconnector(user=user, password=password) + def __init__(self, user, **kwargs): + self.mbc = IMAPconnector(user=user) if kwargs.has_key("pattern"): self.parse_search_parameters(kwargs["criteria"], kwargs["pattern"]) diff --git a/extensions/webmail/main.py b/extensions/webmail/main.py index c98835d9c..f399b0cff 100644 --- a/extensions/webmail/main.py +++ b/extensions/webmail/main.py @@ -7,6 +7,7 @@ from mailng.lib import events, parameters def init(): events.register("UserMenuDisplay", menu) events.register("UserLogin", userlogin) + events.register("UserLogout", userlogout) parameters.register("webmail", "IMAP_SERVER", "string", "127.0.0.1", help=_("Address of your IMAP server")) parameters.register("webmail", "IMAP_SECURED", "list_yesno", "no", @@ -51,4 +52,13 @@ def menu(**kwargs): ] def userlogin(**kwargs): - kwargs["request"].session["password"] = kwargs["password"] + from imap_listing import IMAPconnector + + m = IMAPconnector(user=kwargs["request"].user.username, + password=kwargs["password"]) + +def userlogout(**kwargs): + from imap_listing import IMAPconnector + + m = IMAPconnector(user=kwargs["request"].user.username) + m.logout() diff --git a/extensions/webmail/views.py b/extensions/webmail/views.py index b9609a94d..467f53d81 100644 --- a/extensions/webmail/views.py +++ b/extensions/webmail/views.py @@ -47,7 +47,7 @@ def folder(request, name, updatenav=True): optparams["criteria"] = request.session["criteria"] else: optparams["reset"] = True - lst = ImapListing(request.user.username, request.session["password"], + lst = ImapListing(request.user.username, baseurl=name, folder=name, order=order, **optparams) page = lst.paginator.getpage(request.session["page"]) @@ -67,18 +67,19 @@ def folder(request, name, updatenav=True): @login_required @is_not_localadmin() def index(request): - try: - navp = request.session.has_key("navparams") \ - and request.session["navparams"] or {} - lst = ImapListing(request.user.username, request.session["password"], - baseurl="INBOX", navparams=navp, folder="INBOX", - empty=True) - except Exception, exp: - return _render_error(request, {"error" : exp}) + #try: + navp = request.session.has_key("navparams") \ + and request.session["navparams"] or {} + lst = ImapListing(request.user.username, + baseurl="INBOX", navparams=navp, folder="INBOX", + empty=True) + #except Exception, exp: + # return _render_error(request, user_context={"error" : exp}) return lst.render(request) def fetchmail(request, folder, mail_id, all=False): - res = IMAPconnector(request).fetch(start=mail_id, folder=folder, all=all) + res = IMAPconnector(user=request.user.username).fetch(start=mail_id, + folder=folder, all=all) if len(res): return res[0] return None @@ -101,7 +102,7 @@ def viewmail(request, folder, mail_id=None): def getmailcontent(request, folder, mail_id): msg = fetchmail(request, folder, mail_id, True) if "class" in msg.keys() and msg["class"] == "unseen": - IMAPconnector(request).msg_read(folder, mail_id) + IMAPconnector(user=request.user.username).msg_read(folder, mail_id) email = ImapEmail(msg, mode="html", links="1") try: pageid = request.session["page"] @@ -140,14 +141,14 @@ def move(request): for arg in ["msgset", "to"]: if not request.GET.has_key(arg): return - mbc = IMAPconnector(request) + mbc = IMAPconnector(user=request.user.username) mbc.move(request.GET["msgset"], request.session["folder"], request.GET["to"]) return folder(request, request.session["folder"], False) @login_required @is_not_localadmin() def delete(request, fdname, mail_id): - mbc = IMAPconnector(request) + mbc = IMAPconnector(user=request.user.username) mbc.move(mail_id, fdname, "Trash") return folder(request, fdname, False) @@ -156,7 +157,7 @@ def delete(request, fdname, mail_id): def mark(request, name): if not request.GET.has_key("status") or not request.GET.has_key("ids"): return - mbc = IMAPconnector(request) + mbc = IMAPconnector(user=request.user.username) try: getattr(mbc, "msg_%s" % request.GET["status"])(name, request.GET["ids"]) except AttributeError: @@ -167,14 +168,14 @@ def mark(request, name): @is_not_localadmin() def empty(request, name): if name == "Trash": - mbc = IMAPconnector(request) + mbc = IMAPconnector(user=request.user.username) mbc.empty(name) return folder(request, name, False) @login_required @is_not_localadmin() def compact(request, name): - mbc = IMAPconnector(request) + mbc = IMAPconnector(user=request.user.username) mbc.compact(name) return folder(request, name, False) @@ -221,7 +222,7 @@ def send_mail(request, withctx=False, origmsg=None): s.login(request.user.username, request.session["password"]) s.sendmail(msg['From'], rcpts, msg.as_string()) s.quit() - IMAPconnector(request).push_mail("Sent", msg) + IMAPconnector(user=request.user.username).push_mail("Sent", msg) ctx = getctx("ok", url=__get_current_url(request)) else: ctx = getctx("ko", level=2, listing=render_to_string("webmail/compose.html", @@ -247,7 +248,7 @@ def reply(request, folder, mail_id): if request.method == "POST": ctx, r = send_mail(request, True, origmsg=msg) if ctx["status"] == "ok": - IMAPconnector(request).msg_answered(folder, mail_id) + IMAPconnector(user=request.user.usernam).msg_answered(folder, mail_id) return r email = ImapEmail(msg, True) lines = email.body.split('\n') @@ -289,7 +290,7 @@ def forward(request, folder, mail_id): if request.method == "POST": ctx, response = send_mail(request, True) if ctx["status"] == "ok": - IMAPconnector(request).msgforwarded(folder, mail_id) + IMAPconnector(user=request.user.username).msgforwarded(folder, mail_id) return response msg = fetchmail(request, folder, mail_id, True) diff --git a/lib/__init__.py b/lib/__init__.py index aec3a6e77..b5f2dbed2 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -19,7 +19,7 @@ def _render(request, tpl, user_context): return render_to_response(tpl, user_context, context_instance=RequestContext(request)) -def _render_error(request, errortpl, user_context): +def _render_error(request, errortpl="error", user_context={}): return render_to_response("common/%s.html" % errortpl, user_context, context_instance=RequestContext(request)) diff --git a/lib/events.py b/lib/events.py index bb9e1ce36..ffb0aaecd 100644 --- a/lib/events.py +++ b/lib/events.py @@ -15,7 +15,8 @@ events = ["CreateDomain", "UserMenuDisplay", "AdminMenuDisplay", - "UserLogin"] + "UserLogin", + "UserLogout"] callbacks = {} diff --git a/templates/nlayout.html b/templates/nlayout.html index 2274bba45..97e1f9c05 100644 --- a/templates/nlayout.html +++ b/templates/nlayout.html @@ -62,7 +62,7 @@
  • - {% url django.contrib.auth.views.logout_then_login as logout_url %} + {% url mailng.auth.views.dologout as logout_url %} {% trans "Logout" %}
  • diff --git a/urls.py b/urls.py index cf830bfdc..c585a472f 100644 --- a/urls.py +++ b/urls.py @@ -22,7 +22,7 @@ urlpatterns = patterns('', (r'^mailng/admin/', include('mailng.admin.urls')), (r'^mailng/userprefs/', include('mailng.userprefs.urls')), (r'^accounts/login/$', 'mailng.auth.views.dologin'), - (r'^accounts/logout/$', 'django.contrib.auth.views.logout_then_login'), + (r'^accounts/logout/$', 'mailng.auth.views.dologout'), (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', {'packages': ('mailng',),}),