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,11 +84,10 @@ | ||||||
|         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" | ||||||
|         /> |         /> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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, |  | ||||||
|         #                                 context=pau) |  | ||||||
|     for name, plugin in pau.getAuthenticatorPlugins(): |     for name, plugin in pau.getAuthenticatorPlugins(): | ||||||
|         if name == authPluginId: |         if name == authPluginId: | ||||||
|             return plugin |             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
	
	 helmutm
						helmutm