use composer.schema for password change form
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@2090 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
55ed5b433d
commit
7496a39bbb
6 changed files with 73 additions and 105 deletions
|
@ -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
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
|
||||
<tbody><tr><td colspan="5" style="padding-right: 15px">
|
||||
<div id="form.fields">
|
||||
<!--<metal:fields use-macro="view/template/macros/fields" />-->
|
||||
<metal:fields use-macro="view/schemaMacros/fields" />
|
||||
<metal:fields use-macro="view/fieldRenderers/fields" />
|
||||
</div>
|
||||
</td></tr></tbody>
|
||||
|
||||
|
@ -65,7 +64,7 @@
|
|||
<tbody><tr><td colspan="5">
|
||||
<div id="form.fields">
|
||||
<!--<metal:fields use-macro="view/template/macros/fields" />-->
|
||||
<metal:fields use-macro="view/schemaMacros/fields" />
|
||||
<metal:fields use-macro="view/fieldRenderers/fields" />
|
||||
</div>
|
||||
</td></tr></tbody>
|
||||
|
||||
|
@ -83,37 +82,6 @@
|
|||
</metal:block>
|
||||
|
||||
|
||||
<metal:fields define-macro="fields"
|
||||
tal:define="show view/update">
|
||||
<tal:show condition="show">
|
||||
<div id="form_fields"
|
||||
tal:define="dummy view/setUp">
|
||||
<table width="100%">
|
||||
<tr tal:repeat="widget view/widgets">
|
||||
<td class="label" width="10%"
|
||||
tal:define="hint widget/hint">
|
||||
<label tal:attributes="for widget/name">
|
||||
<span class="required" tal:condition="widget/required"
|
||||
>*</span><span tal:content="widget/label">label</span>
|
||||
</label>
|
||||
</td>
|
||||
<td class="field" colspan="4" width="90%"
|
||||
tal:define="hint widget/hint">
|
||||
<div class="widget" tal:content="structure widget">
|
||||
<input type="text" />
|
||||
</div>
|
||||
<div class="error"
|
||||
tal:condition="widget/error">
|
||||
<span tal:replace="structure widget/error">error</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</tal:show>
|
||||
</metal:fields>
|
||||
|
||||
|
||||
<metal:assignments define-macro="assignments">
|
||||
<tbody id="form.assignments">
|
||||
<tr tal:repeat="type view/presetTypesForAssignment">
|
||||
|
|
|
@ -401,6 +401,7 @@
|
|||
<adapter factory="cybertools.composer.schema.field.FileUploadFieldInstance"
|
||||
name="fileupload" />
|
||||
|
||||
<adapter factory="cybertools.composer.schema.factory.SchemaFactory" />
|
||||
<adapter factory="loops.schema.ResourceSchemaFactory" />
|
||||
<adapter factory="loops.schema.ResourceSchemaFactory"
|
||||
for="loops.interfaces.IResource" />
|
||||
|
|
|
@ -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
|
||||
=============
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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'),
|
||||
|
|
Loading…
Add table
Reference in a new issue