diff --git a/browser/form.py b/browser/form.py
index 39d864a..007d2c3 100644
--- a/browser/form.py
+++ b/browser/form.py
@@ -43,6 +43,7 @@ from cybertools.browser.form import FormController
from cybertools.composer.interfaces import IInstance
from cybertools.composer.schema.interfaces import ISchemaFactory
from cybertools.composer.schema.browser.common import schema_macros, schema_edit_macros
+from cybertools.composer.schema.schema import FormState
from cybertools.typology.interfaces import IType, ITypeManager
from loops.common import adapted
from loops.concept import Concept, ResourceRelation
@@ -61,12 +62,11 @@ from loops.versioning.interfaces import IVersionable
# forms
class ObjectForm(NodeView):
- """ Abstract base class for forms.
+ """ Abstract base class for resource or concept forms using Dojo dialog.
"""
template = ViewPageTemplateFile('form_macros.pt')
-
- _isSetUp = False
+ formState = FormState() # dummy, don't update!
def __init__(self, context, request):
super(ObjectForm, self).__init__(context, request)
@@ -79,12 +79,12 @@ class ObjectForm(NodeView):
def typeInterface(self):
return IType(self.context).typeInterface or ITextDocument
- @property
- def schemaMacros(self):
+ @Lazy
+ def fieldRenderers(self):
return schema_macros.macros
- @property
- def schemaEditMacros(self):
+ @Lazy
+ def fieldEditRenderers(self):
return schema_edit_macros.macros
@Lazy
@@ -211,7 +211,7 @@ class CreateObjectForm(ObjectForm, Form):
class InnerForm(CreateObjectForm):
@property
- def macro(self): return self.schemaMacros['fields']
+ def macro(self): return self.fieldRenderers['fields']
# processing form input
diff --git a/browser/form_macros.pt b/browser/form_macros.pt
index 6165583..23fa8d6 100644
--- a/browser/form_macros.pt
+++ b/browser/form_macros.pt
@@ -16,8 +16,7 @@
-
-
+
|
@@ -65,7 +64,7 @@
-
+
|
@@ -83,37 +82,6 @@
-
-
-
-
-
-
-
diff --git a/configure.zcml b/configure.zcml
index 6ffa57d..948ebfb 100644
--- a/configure.zcml
+++ b/configure.zcml
@@ -401,6 +401,7 @@
+
diff --git a/organize/README.txt b/organize/README.txt
index dc71710..afae88b 100644
--- a/organize/README.txt
+++ b/organize/README.txt
@@ -229,9 +229,10 @@ Change Password
>>> data = {'oldPassword': u'tiger',
... 'password': u'lion',
- ... 'passwordConfirm': u'lion'}
+ ... 'passwordConfirm': u'lion',
+ ... 'action': 'update'}
- >>> request = TestRequest()
+ >>> request = TestRequest(form=data)
We need a principal for testing the login stuff:
@@ -239,10 +240,15 @@ We need a principal for testing the login stuff:
>>> principal = InternalPrincipal('scott', 'tiger', 'Scotty')
>>> request.setPrincipal(principal)
- >>> from loops.organize.browser import PasswordChange
- >>> pwcView = PasswordChange(menu, request, testing=True)
- >>> pwcView.changePassword(data)
+ >>> from cybertools.composer.schema.factory import SchemaFactory
+ >>> from cybertools.composer.schema.field import FieldInstance
+ >>> component.provideAdapter(SchemaFactory)
+ >>> component.provideAdapter(FieldInstance)
+ >>> from loops.organize.browser import PasswordChange
+ >>> pwcView = PasswordChange(menu, request)
+ >>> pwcView.update()
+ False
Fin de partie
=============
diff --git a/organize/browser.py b/organize/browser.py
index ac97af6..87f5020 100644
--- a/organize/browser.py
+++ b/organize/browser.py
@@ -24,17 +24,18 @@ $Id$
"""
from zope import interface, component
-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.interfaces import WidgetInputError
-from zope.app.pagetemplate import ViewPageTemplateFile
from zope.app.principalannotation import annotations
from zope.cachedescriptors.property import Lazy
-from zope.formlib.form import Form, FormFields, action
+from zope.formlib.form import Form as FormlibForm, FormFields, action
from zope.formlib.namedtemplate import NamedTemplate
from zope.i18nmessageid import MessageFactory
+from cybertools.composer.schema.browser.common import schema_macros
+from cybertools.composer.schema.browser.form import Form
+from cybertools.composer.schema.schema import FormState, FormError
from cybertools.typology.interfaces import IType
from loops.browser.concept import ConceptView
from loops.browser.node import NodeView
@@ -74,23 +75,7 @@ class PasswordWidget(BasePasswordWidget):
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, FormlibForm):
form_fields = FormFields(IMemberRegistration).omit('age')
form_fields['password'].custom_widget = PasswordWidget
@@ -139,50 +124,64 @@ class MemberRegistration(NodeView, Form):
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')
+ interface = IPasswordChange
+ message = u'Your password has been changed.'
- def __init__(self, context, request, testing=False):
- super(PasswordChange, self).__init__(context, request)
- if not testing:
- self.setUpWidgets()
+ formErrors = dict(
+ confirm_nomatch=FormError(u'Password and password confirmation do not match.'),
+ wrong_oldpw=FormError(u'Your old password was not entered correctly.'),
+ )
+
+ label = label_submit = u'Change Password'
@Lazy
def macro(self):
- return self.template.macros['content']
+ return schema_macros.macros['form']
@Lazy
def item(self):
return self
+ @Lazy
+ def data(self):
+ data = dict(oldPassword=u'', password=u'', passwordConfirm=u'')
+ data = {}
+ return data
+
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')
+ form = self.request.form
+ if not form.get('action'):
+ return True
+ formState = self.formState = self.validate(form)
+ if formState.severity > 0:
+ return True
pw = form.get('password')
- if form.get('passwordConfirm') != pw:
- raise ValueError(u'Password and password confirmation do not match.')
+ pwConfirm = form.get('passwordConfirm')
+ if pw != pwConfirm:
+ fi = formState.fieldInstances['password']
+ fi.setError('confirm_nomatch', self.formErrors)
+ formState.severity = max(formState.severity, fi.severity)
+ return True
+ oldPw = form.get('oldPassword')
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))
+ fi = formState.fieldInstances['oldPassword']
+ fi.setError('wrong_oldpw', self.formErrors)
+ formState.severity = max(formState.severity, fi.severity)
+ return True
+ url = '%s?messsage=%s' % (self.url, self.message)
+ self.request.response.redirect(url)
+ return False
+
+ def validate(self, data):
+ formState = FormState()
+ for f in self.schema.fields:
+ fi = f.getFieldInstance()
+ value = data.get(f.name)
+ fi.validate(value, data)
+ formState.fieldInstances.append(fi)
+ formState.severity = max(formState.severity, fi.severity)
+ return formState
diff --git a/organize/interfaces.py b/organize/interfaces.py
index e7cd780..891b000 100644
--- a/organize/interfaces.py
+++ b/organize/interfaces.py
@@ -77,12 +77,6 @@ class LoginName(schema.TextLine):
mapping=dict(userId=userId)))
-class Password(schema.Password):
-
- def _validate(self, pw):
- super(Password, self)._validate(pw)
-
-
class IPerson(IBasePerson):
""" Resembles a human being with a name (first and last name),
a birth date, and a set of addresses. This interface only
@@ -99,7 +93,7 @@ class IPerson(IBasePerson):
class IPasswordEntry(Interface):
- password = Password(title=_(u'Password'),
+ password = schema.Password(title=_(u'Password'),
description=_(u'Enter password.'),
required=True,)
passwordConfirm = schema.Password(title=_(u'Confirm password'),