plugin misc_accout: update relative to the introduction of profile password:

- check for the profile password instead of the xmpp password before a modification can be done
- "Change your password" action changes both passwords (a confirmation is asked)
This commit is contained in:
souliane 2014-05-21 12:07:13 +02:00
commit cf7c18e56b

View file

@ -21,13 +21,17 @@ from sat.core.i18n import _, D_
from sat.core.log import getLogger
log = getLogger(__name__)
from sat.core import exceptions
from sat.tools import xml_tools
from sat.memory.memory import Sessions
from sat.memory.crypto import PasswordHasher
from sat.core.constants import Const as C
from twisted.internet import reactor, defer, protocol
from os.path import join, dirname
from twisted.python.procutils import which
from twisted.python.failure import Failure
from email.mime.text import MIMEText
from twisted.mail.smtp import sendmail
from sat.tools import xml_tools
from os.path import join, dirname
from email.mime.text import MIMEText
PLUGIN_INFO = {
"name": "Account Plugin",
@ -132,15 +136,19 @@ class MiscAccount(object):
self._prosody_path = dirname(paths[0])
log.info(_('Prosody path found: %s') % (self._prosody_path, ))
self._sessions = Sessions()
self.__account_cb_id = host.registerCallback(self._accountDialogCb, with_data=True)
self.__delete_account_id = host.registerCallback(self.__deleteAccountCb, with_data=True)
self.__change_password_id = host.registerCallback(self.__changePasswordCb, with_data=True)
def deleteBlogCallback(posts, comments):
return lambda data, profile: self.__deleteBlogPostsCb(posts, comments, data, profile)
self.__delete_posts_comments_id = host.registerCallback(deleteBlogCallback(True, True), with_data=True)
self.__delete_posts_id = host.registerCallback(deleteBlogCallback(True, False), with_data=True)
self.__delete_comments_id = host.registerCallback(deleteBlogCallback(False, True), with_data=True)
self.__delete_posts_comments_id = host.registerCallback(deleteBlogCallback(True, True), with_data=True)
self.__delete_account_id = host.registerCallback(self.__deleteAccountCb, with_data=True)
def getConfig(self, name):
return self.host.memory.getConfig(CONFIG_SECTION, name) or default_conf[name]
@ -252,11 +260,11 @@ SàT team""" % {'login': login, 'jid': "%s@%s" % (login, self.getConfig('new_acc
@param profile: %(doc_profile)s
@return: XML of the dialog
"""
form_ui = xml_tools.XMLUI("form", "tabs", title=D_("Manage your XMPP account"), submit_id=self.__account_cb_id)
form_ui = xml_tools.XMLUI("form", "tabs", title=D_("Manage your account"), submit_id=self.__account_cb_id)
tab_container = form_ui.current_container
tab_container.addTab("update", D_("Change your password"), container=xml_tools.PairsContainer)
form_ui.addLabel(D_("Current password"))
form_ui.addLabel(D_("Current profile password"))
form_ui.addPassword("current_passwd", value="")
form_ui.addLabel(D_("New password"))
form_ui.addPassword("new_passwd1", value="")
@ -265,7 +273,7 @@ SàT team""" % {'login': login, 'jid': "%s@%s" % (login, self.getConfig('new_acc
if 'GROUPBLOG' in self.host.plugins:
tab_container.addTab("delete_posts", D_("Delete your posts"), container=xml_tools.PairsContainer)
form_ui.addLabel(D_("Current password"))
form_ui.addLabel(D_("Current profile password"))
form_ui.addPassword("delete_posts_passwd", value="")
form_ui.addLabel(D_("Delete all your posts and their comments"))
form_ui.addBool("delete_posts_checkbox", "false")
@ -273,7 +281,7 @@ SàT team""" % {'login': login, 'jid': "%s@%s" % (login, self.getConfig('new_acc
form_ui.addBool("delete_comments_checkbox", "false")
tab_container.addTab("delete", D_("Delete your account"), container=xml_tools.PairsContainer)
form_ui.addLabel(D_("Current password"))
form_ui.addLabel(D_("Current profile password"))
form_ui.addPassword("delete_passwd", value="")
form_ui.addLabel(D_("Delete your account"))
form_ui.addBool("delete_checkbox", "false")
@ -285,18 +293,25 @@ SàT team""" % {'login': login, 'jid': "%s@%s" % (login, self.getConfig('new_acc
@param data
@param profile
"""
password = yield self.host.memory.asyncGetParamA("Password", "Connection", profile_key=profile)
sat_cipher = yield self.host.memory.asyncGetParamA(C.PROFILE_PASS_PATH[1], C.PROFILE_PASS_PATH[0], profile_key=profile)
def error_ui():
error_ui = xml_tools.XMLUI("popup", title=D_("Error"))
error_ui.addText(D_("Passwords don't match!"))
@defer.inlineCallbacks
def verify(attempt):
auth = yield PasswordHasher.verify(attempt, sat_cipher)
defer.returnValue(auth)
def error_ui(message=None):
if not message:
D_("The provided profile password doesn't match.")
error_ui = xml_tools.XMLUI("popup", title=D_("Attempt failure"))
error_ui.addText(message)
return {'xmlui': error_ui.toXml()}
# check for account deletion
delete_passwd = data[xml_tools.SAT_FORM_PREFIX + 'delete_passwd']
delete_checkbox = data[xml_tools.SAT_FORM_PREFIX + 'delete_checkbox']
if delete_checkbox == 'true':
if password == delete_passwd:
if verify(delete_passwd):
defer.returnValue(self.__deleteAccount(profile))
defer.returnValue(error_ui())
@ -308,7 +323,7 @@ SàT team""" % {'login': login, 'jid': "%s@%s" % (login, self.getConfig('new_acc
posts = delete_posts_checkbox == 'true'
comments = delete_comments_checkbox == 'true'
if posts or comments:
if password == delete_posts_passwd:
if verify(delete_posts_passwd):
defer.returnValue(self.__deleteBlogPosts(posts, comments, profile))
defer.returnValue(error_ui())
@ -317,20 +332,38 @@ SàT team""" % {'login': login, 'jid': "%s@%s" % (login, self.getConfig('new_acc
new_passwd1 = data[xml_tools.SAT_FORM_PREFIX + 'new_passwd1']
new_passwd2 = data[xml_tools.SAT_FORM_PREFIX + 'new_passwd2']
if new_passwd1 or new_passwd2:
if password == current_passwd and new_passwd1 == new_passwd2:
data = yield self.__changePassword(new_passwd1, profile=profile)
defer.returnValue(data)
if verify(current_passwd):
if new_passwd1 == new_passwd2:
data = yield self.__changePassword(new_passwd1, profile=profile)
defer.returnValue(data)
else:
defer.returnValue(error_ui(D_("The values entered for the new password are not equal.")))
defer.returnValue(error_ui())
defer.returnValue({})
def __changePassword(self, password, profile):
"""Actually change the user XMPP account and SàT profile password
@param password: new password
@profile
"""Ask for a confirmation before changing the XMPP account and SàT profile passwords.
@param password (str): the new password
@param profile (str): %(doc_profile)s
"""
session_id, dummy = self._sessions.newSession({'new_password': password}, profile)
form_ui = xml_tools.XMLUI("form", title=D_("Change your password?"), submit_id=self.__change_password_id, session_id=session_id)
form_ui.addText(D_("Note for advanced users: this will actually change both your SàT profile password AND your XMPP account password."))
form_ui.addText(D_("Continue with changing the password?"))
return {'xmlui': form_ui.toXml()}
def __changePasswordCb(self, data, profile):
"""Actually change the user XMPP account and SàT profile password
@param data (dict)
@profile (str): %(doc_profile)s
"""
password = self._sessions.profileGet(data['session_id'], profile)['new_password']
def passwordChanged(result):
self.host.memory.setParam("Password", password, "Connection", profile_key=profile)
d = self.host.memory.setParam(C.PROFILE_PASS_PATH[1], password, C.PROFILE_PASS_PATH[0], profile_key=profile)
d.addCallback(lambda dummy: self.host.memory.setParam("Password", password, "Connection", profile_key=profile))
confirm_ui = xml_tools.XMLUI("popup", title=D_("Confirmation"))
confirm_ui.addText(D_("Your password has been changed."))
return defer.succeed({'xmlui': confirm_ui.toXml()})