provide change_password.html
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1816 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
c8b3e250d7
commit
bdaffda265
5 changed files with 142 additions and 30 deletions
|
@ -224,6 +224,26 @@ Now we can also retrieve it from the authentication utility:
|
||||||
u'Tom Sawyer'
|
u'Tom Sawyer'
|
||||||
|
|
||||||
|
|
||||||
|
Change Password
|
||||||
|
---------------
|
||||||
|
|
||||||
|
>>> data = {'oldPassword': u'tiger',
|
||||||
|
... 'password': u'lion',
|
||||||
|
... 'passwordConfirm': u'lion'}
|
||||||
|
|
||||||
|
>>> request = TestRequest()
|
||||||
|
|
||||||
|
We need a principal for testing the login stuff:
|
||||||
|
|
||||||
|
>>> from zope.app.authentication.principalfolder import InternalPrincipal
|
||||||
|
>>> principal = InternalPrincipal('scott', 'tiger', 'Scotty')
|
||||||
|
>>> request.setPrincipal(principal)
|
||||||
|
|
||||||
|
>>> from loops.organize.browser import PasswordChange
|
||||||
|
>>> pwcView = PasswordChange(menu, request, testing=True)
|
||||||
|
>>> pwcView.changePassword(data)
|
||||||
|
|
||||||
|
|
||||||
Fin de partie
|
Fin de partie
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ $Id$
|
||||||
|
|
||||||
from zope import interface, component
|
from zope import interface, component
|
||||||
from zope.app import zapi
|
from zope.app import zapi
|
||||||
|
from zope.app.authentication.principalfolder import InternalPrincipal
|
||||||
from zope.app.form.browser.textwidgets import PasswordWidget as BasePasswordWidget
|
from zope.app.form.browser.textwidgets import PasswordWidget as BasePasswordWidget
|
||||||
from zope.app.form.interfaces import WidgetInputError
|
from zope.app.form.interfaces import WidgetInputError
|
||||||
from zope.app.pagetemplate import ViewPageTemplateFile
|
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||||
|
@ -39,8 +40,9 @@ from loops.browser.concept import ConceptView
|
||||||
from loops.browser.node import NodeView
|
from loops.browser.node import NodeView
|
||||||
from loops.browser.concept import ConceptRelationView
|
from loops.browser.concept import ConceptRelationView
|
||||||
from loops.organize.interfaces import ANNOTATION_KEY, IMemberRegistrationManager
|
from loops.organize.interfaces import ANNOTATION_KEY, IMemberRegistrationManager
|
||||||
from loops.organize.interfaces import IMemberRegistration
|
from loops.organize.interfaces import IMemberRegistration, IPasswordChange
|
||||||
from loops.organize.party import getPersonForUser
|
from loops.organize.party import getPersonForUser
|
||||||
|
from loops.organize.util import getInternalPrincipal
|
||||||
import loops.browser.util
|
import loops.browser.util
|
||||||
|
|
||||||
_ = MessageFactory('zope')
|
_ = MessageFactory('zope')
|
||||||
|
@ -73,9 +75,26 @@ class PasswordWidget(BasePasswordWidget):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class OldPasswordWidget(BasePasswordWidget):
|
||||||
|
|
||||||
|
def getInputValue(self):
|
||||||
|
value = super(OldPasswordWidget, self).getInputValue()
|
||||||
|
if value:
|
||||||
|
principal = self.request.principal
|
||||||
|
if not isinstance(principal, InternalPrincipal):
|
||||||
|
principal = getInternalPrincipal(principal.id)
|
||||||
|
if not principal.checkPassword(value):
|
||||||
|
v = _(u'Your old password was not entered correctly.')
|
||||||
|
self._error = WidgetInputError(
|
||||||
|
self.context.__name__, self.label, v)
|
||||||
|
raise self._error
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
class MemberRegistration(NodeView, Form):
|
class MemberRegistration(NodeView, Form):
|
||||||
|
|
||||||
form_fields = FormFields(IMemberRegistration).omit('age')
|
form_fields = FormFields(IMemberRegistration).omit('age')
|
||||||
|
form_fields['password'].custom_widget = PasswordWidget
|
||||||
template = loops.browser.util.dataform
|
template = loops.browser.util.dataform
|
||||||
label = _(u'Member Registration')
|
label = _(u'Member Registration')
|
||||||
|
|
||||||
|
@ -92,10 +111,11 @@ class MemberRegistration(NodeView, Form):
|
||||||
def item(self):
|
def item(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def xupdate(self):
|
def update(self):
|
||||||
# see cybertools.browser.view.GenericView.update()
|
# see cybertools.browser.view.GenericView.update()
|
||||||
NodeView.update(self)
|
NodeView.update(self)
|
||||||
Form.update(self)
|
Form.update(self)
|
||||||
|
return True
|
||||||
|
|
||||||
@action(_(u'Register'))
|
@action(_(u'Register'))
|
||||||
def handle_register_action(self, action, data):
|
def handle_register_action(self, action, data):
|
||||||
|
@ -117,3 +137,53 @@ class MemberRegistration(NodeView, Form):
|
||||||
% (self.url, login, message))
|
% (self.url, login, message))
|
||||||
return person
|
return person
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordChange(NodeView, Form):
|
||||||
|
|
||||||
|
form_fields = FormFields(IPasswordChange).select(
|
||||||
|
'oldPassword', 'password', 'passwordConfirm')
|
||||||
|
form_fields['oldPassword'].custom_widget = OldPasswordWidget
|
||||||
|
form_fields['password'].custom_widget = PasswordWidget
|
||||||
|
template = loops.browser.util.dataform
|
||||||
|
label = _(u'Change Password')
|
||||||
|
|
||||||
|
def __init__(self, context, request, testing=False):
|
||||||
|
super(PasswordChange, self).__init__(context, request)
|
||||||
|
if not testing:
|
||||||
|
self.setUpWidgets()
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def macro(self):
|
||||||
|
return self.template.macros['content']
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def item(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
# see cybertools.browser.view.GenericView.update()
|
||||||
|
NodeView.update(self)
|
||||||
|
Form.update(self)
|
||||||
|
return True
|
||||||
|
|
||||||
|
@action(_(u'Change Password'))
|
||||||
|
def handle_change_password_action(self, action, data):
|
||||||
|
self.changePassword(data)
|
||||||
|
|
||||||
|
def changePassword(self, data=None):
|
||||||
|
form = data or self.request.form
|
||||||
|
oldPw = form.get('oldPassword')
|
||||||
|
pw = form.get('password')
|
||||||
|
if form.get('passwordConfirm') != pw:
|
||||||
|
raise ValueError(u'Password and password confirmation do not match.')
|
||||||
|
regMan = IMemberRegistrationManager(self.context.getLoopsRoot())
|
||||||
|
principal = self.request.principal
|
||||||
|
result = regMan.changePassword(principal, oldPw, pw)
|
||||||
|
if not result:
|
||||||
|
raise ValueError(u'Your old password was not entered correctly.')
|
||||||
|
message = _(u'Your password has been changed')
|
||||||
|
self.request.response.redirect('%s?message=%s'
|
||||||
|
% (self.url, message))
|
||||||
|
#self.request.response.redirect('%s/logout.html?message=%s'
|
||||||
|
# % (self.url, message))
|
||||||
|
|
||||||
|
|
|
@ -84,13 +84,12 @@
|
||||||
permission="zope.Public"
|
permission="zope.Public"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<zope:view
|
<browser:page
|
||||||
type="zope.publisher.interfaces.browser.IBrowserRequest"
|
for="loops.interfaces.INode"
|
||||||
for="loops.organize.interfaces.Password"
|
name="change_password.html"
|
||||||
provides="zope.app.form.interfaces.IInputWidget"
|
class="loops.organize.browser.PasswordChange"
|
||||||
factory="loops.organize.browser.PasswordWidget"
|
permission="zope.Public"
|
||||||
permission="zope.Public"
|
/>
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- other adapters -->
|
<!-- other adapters -->
|
||||||
|
|
||||||
|
|
|
@ -22,15 +22,15 @@ Member registration adapter(s).
|
||||||
$Id$
|
$Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope.app import zapi
|
|
||||||
from zope import interface, component, schema
|
from zope import interface, component, schema
|
||||||
|
from zope.app.component import queryNextUtility
|
||||||
from zope.component import adapts
|
from zope.component import adapts
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
from zope.app.authentication.interfaces import IPluggableAuthentication
|
from zope.app.authentication.interfaces import IPluggableAuthentication
|
||||||
from zope.app.authentication.interfaces import IAuthenticatorPlugin
|
from zope.app.authentication.interfaces import IAuthenticatorPlugin
|
||||||
from zope.app.authentication.principalfolder import InternalPrincipal
|
from zope.app.authentication.principalfolder import InternalPrincipal
|
||||||
from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
|
from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
|
||||||
from zope.app.security.interfaces import IAuthentication
|
from zope.app.security.interfaces import IAuthentication, PrincipalLookupError
|
||||||
from zope.event import notify
|
from zope.event import notify
|
||||||
from zope.i18nmessageid import MessageFactory
|
from zope.i18nmessageid import MessageFactory
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
|
@ -39,9 +39,8 @@ from cybertools.typology.interfaces import IType
|
||||||
from loops.interfaces import ILoops
|
from loops.interfaces import ILoops
|
||||||
from loops.concept import Concept
|
from loops.concept import Concept
|
||||||
from loops.organize.interfaces import IMemberRegistrationManager
|
from loops.organize.interfaces import IMemberRegistrationManager
|
||||||
from loops.organize.util import getPrincipalFolder, authPluginId
|
from loops.organize.util import getPrincipalFolder, authPluginId, getInternalPrincipal
|
||||||
|
from loops.util import _
|
||||||
_ = MessageFactory('zope')
|
|
||||||
|
|
||||||
|
|
||||||
class MemberRegistrationManager(object):
|
class MemberRegistrationManager(object):
|
||||||
|
@ -56,7 +55,6 @@ class MemberRegistrationManager(object):
|
||||||
# step 1: create an internal principal in the loops principal folder:
|
# step 1: create an internal principal in the loops principal folder:
|
||||||
pFolder = getPrincipalFolder(self.context)
|
pFolder = getPrincipalFolder(self.context)
|
||||||
title = firstName and ' '.join((firstName, lastName)) or lastName
|
title = firstName and ' '.join((firstName, lastName)) or lastName
|
||||||
# TODO: care for password encryption:
|
|
||||||
principal = InternalPrincipal(userId, password, title)
|
principal = InternalPrincipal(userId, password, title)
|
||||||
pFolder[userId] = principal
|
pFolder[userId] = principal
|
||||||
# step 2: create a corresponding person concept:
|
# step 2: create a corresponding person concept:
|
||||||
|
@ -80,6 +78,11 @@ class MemberRegistrationManager(object):
|
||||||
notify(ObjectModifiedEvent(person))
|
notify(ObjectModifiedEvent(person))
|
||||||
return personAdapter
|
return personAdapter
|
||||||
|
|
||||||
def changePassword(self, oldPw, newPw):
|
def changePassword(self, principal, oldPw, newPw):
|
||||||
pass
|
if not isinstance(principal, InternalPrincipal):
|
||||||
|
principal = getInternalPrincipal(principal.id)
|
||||||
|
if not principal.checkPassword(oldPw):
|
||||||
|
return False
|
||||||
|
principal.setPassword(newPw)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ Utilities for the loops.organize package.
|
||||||
$Id$
|
$Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope.app import zapi
|
|
||||||
from zope import interface, component, schema
|
from zope import interface, component, schema
|
||||||
from zope.app.authentication.interfaces import IPluggableAuthentication
|
from zope.app.authentication.interfaces import IPluggableAuthentication
|
||||||
from zope.app.authentication.interfaces import IAuthenticatorPlugin
|
from zope.app.authentication.interfaces import IAuthenticatorPlugin
|
||||||
|
@ -32,16 +31,37 @@ authPluginId = 'loops'
|
||||||
|
|
||||||
|
|
||||||
def getPrincipalFolder(context=None):
|
def getPrincipalFolder(context=None):
|
||||||
pau = zapi.getUtility(IAuthentication, context=context)
|
pau = component.getUtility(IAuthentication, context=context)
|
||||||
if not IPluggableAuthentication.providedBy(pau):
|
if not IPluggableAuthentication.providedBy(pau):
|
||||||
raise ValueError(u'There is no pluggable authentication '
|
raise ValueError(u'There is no pluggable authentication '
|
||||||
'utility available.')
|
'utility available.')
|
||||||
if not authPluginId in pau.authenticatorPlugins:
|
if not authPluginId in pau.authenticatorPlugins:
|
||||||
raise ValueError(u'There is no loops authenticator '
|
raise ValueError(u'There is no loops authenticator '
|
||||||
'plugin available.')
|
'plugin available.')
|
||||||
#return component.queryUtility(IAuthenticatorPlugin, authPluginId,
|
for name, plugin in pau.getAuthenticatorPlugins():
|
||||||
# context=pau)
|
if name == authPluginId:
|
||||||
for name, plugin in pau.getAuthenticatorPlugins():
|
return plugin
|
||||||
if name == authPluginId:
|
|
||||||
return plugin
|
|
||||||
|
|
||||||
|
|
||||||
|
def getInternalPrincipal(id, context=None):
|
||||||
|
pau = component.getUtility(IAuthentication, context=context)
|
||||||
|
if not IPluggableAuthentication.providedBy(pau):
|
||||||
|
raise ValueError(u'There is no pluggable authentication '
|
||||||
|
'utility available.')
|
||||||
|
if not id.startswith(pau.prefix):
|
||||||
|
next = queryNextUtility(pau, IAuthentication)
|
||||||
|
if next is None:
|
||||||
|
raise PrincipalLookupError(id)
|
||||||
|
return next.getPrincipal(id)
|
||||||
|
id = id[len(pau.prefix):]
|
||||||
|
for name, authplugin in pau.getAuthenticatorPlugins():
|
||||||
|
if not id.startswith(authplugin.prefix):
|
||||||
|
continue
|
||||||
|
principal = authplugin.get(id[len(authplugin.prefix):])
|
||||||
|
if principal is None:
|
||||||
|
continue
|
||||||
|
return principal
|
||||||
|
next = queryNextUtility(pau, IAuthentication)
|
||||||
|
if next is not None:
|
||||||
|
return next.getPrincipal(pau.prefix + id)
|
||||||
|
raise PrincipalLookupError(id)
|
||||||
|
|
Loading…
Add table
Reference in a new issue