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.interfaces import IInstance
|
||||||
from cybertools.composer.schema.interfaces import ISchemaFactory
|
from cybertools.composer.schema.interfaces import ISchemaFactory
|
||||||
from cybertools.composer.schema.browser.common import schema_macros, schema_edit_macros
|
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 cybertools.typology.interfaces import IType, ITypeManager
|
||||||
from loops.common import adapted
|
from loops.common import adapted
|
||||||
from loops.concept import Concept, ResourceRelation
|
from loops.concept import Concept, ResourceRelation
|
||||||
|
@ -61,12 +62,11 @@ from loops.versioning.interfaces import IVersionable
|
||||||
# forms
|
# forms
|
||||||
|
|
||||||
class ObjectForm(NodeView):
|
class ObjectForm(NodeView):
|
||||||
""" Abstract base class for forms.
|
""" Abstract base class for resource or concept forms using Dojo dialog.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
template = ViewPageTemplateFile('form_macros.pt')
|
template = ViewPageTemplateFile('form_macros.pt')
|
||||||
|
formState = FormState() # dummy, don't update!
|
||||||
_isSetUp = False
|
|
||||||
|
|
||||||
def __init__(self, context, request):
|
def __init__(self, context, request):
|
||||||
super(ObjectForm, self).__init__(context, request)
|
super(ObjectForm, self).__init__(context, request)
|
||||||
|
@ -79,12 +79,12 @@ class ObjectForm(NodeView):
|
||||||
def typeInterface(self):
|
def typeInterface(self):
|
||||||
return IType(self.context).typeInterface or ITextDocument
|
return IType(self.context).typeInterface or ITextDocument
|
||||||
|
|
||||||
@property
|
@Lazy
|
||||||
def schemaMacros(self):
|
def fieldRenderers(self):
|
||||||
return schema_macros.macros
|
return schema_macros.macros
|
||||||
|
|
||||||
@property
|
@Lazy
|
||||||
def schemaEditMacros(self):
|
def fieldEditRenderers(self):
|
||||||
return schema_edit_macros.macros
|
return schema_edit_macros.macros
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
|
@ -211,7 +211,7 @@ class CreateObjectForm(ObjectForm, Form):
|
||||||
class InnerForm(CreateObjectForm):
|
class InnerForm(CreateObjectForm):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def macro(self): return self.schemaMacros['fields']
|
def macro(self): return self.fieldRenderers['fields']
|
||||||
|
|
||||||
|
|
||||||
# processing form input
|
# processing form input
|
||||||
|
|
|
@ -16,8 +16,7 @@
|
||||||
|
|
||||||
<tbody><tr><td colspan="5" style="padding-right: 15px">
|
<tbody><tr><td colspan="5" style="padding-right: 15px">
|
||||||
<div id="form.fields">
|
<div id="form.fields">
|
||||||
<!--<metal:fields use-macro="view/template/macros/fields" />-->
|
<metal:fields use-macro="view/fieldRenderers/fields" />
|
||||||
<metal:fields use-macro="view/schemaMacros/fields" />
|
|
||||||
</div>
|
</div>
|
||||||
</td></tr></tbody>
|
</td></tr></tbody>
|
||||||
|
|
||||||
|
@ -65,7 +64,7 @@
|
||||||
<tbody><tr><td colspan="5">
|
<tbody><tr><td colspan="5">
|
||||||
<div id="form.fields">
|
<div id="form.fields">
|
||||||
<!--<metal:fields use-macro="view/template/macros/fields" />-->
|
<!--<metal:fields use-macro="view/template/macros/fields" />-->
|
||||||
<metal:fields use-macro="view/schemaMacros/fields" />
|
<metal:fields use-macro="view/fieldRenderers/fields" />
|
||||||
</div>
|
</div>
|
||||||
</td></tr></tbody>
|
</td></tr></tbody>
|
||||||
|
|
||||||
|
@ -83,37 +82,6 @@
|
||||||
</metal:block>
|
</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">
|
<metal:assignments define-macro="assignments">
|
||||||
<tbody id="form.assignments">
|
<tbody id="form.assignments">
|
||||||
<tr tal:repeat="type view/presetTypesForAssignment">
|
<tr tal:repeat="type view/presetTypesForAssignment">
|
||||||
|
|
|
@ -401,6 +401,7 @@
|
||||||
<adapter factory="cybertools.composer.schema.field.FileUploadFieldInstance"
|
<adapter factory="cybertools.composer.schema.field.FileUploadFieldInstance"
|
||||||
name="fileupload" />
|
name="fileupload" />
|
||||||
|
|
||||||
|
<adapter factory="cybertools.composer.schema.factory.SchemaFactory" />
|
||||||
<adapter factory="loops.schema.ResourceSchemaFactory" />
|
<adapter factory="loops.schema.ResourceSchemaFactory" />
|
||||||
<adapter factory="loops.schema.ResourceSchemaFactory"
|
<adapter factory="loops.schema.ResourceSchemaFactory"
|
||||||
for="loops.interfaces.IResource" />
|
for="loops.interfaces.IResource" />
|
||||||
|
|
|
@ -229,9 +229,10 @@ Change Password
|
||||||
|
|
||||||
>>> data = {'oldPassword': u'tiger',
|
>>> data = {'oldPassword': u'tiger',
|
||||||
... 'password': u'lion',
|
... '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:
|
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')
|
>>> principal = InternalPrincipal('scott', 'tiger', 'Scotty')
|
||||||
>>> request.setPrincipal(principal)
|
>>> request.setPrincipal(principal)
|
||||||
|
|
||||||
>>> from loops.organize.browser import PasswordChange
|
>>> from cybertools.composer.schema.factory import SchemaFactory
|
||||||
>>> pwcView = PasswordChange(menu, request, testing=True)
|
>>> from cybertools.composer.schema.field import FieldInstance
|
||||||
>>> pwcView.changePassword(data)
|
>>> component.provideAdapter(SchemaFactory)
|
||||||
|
>>> component.provideAdapter(FieldInstance)
|
||||||
|
|
||||||
|
>>> from loops.organize.browser import PasswordChange
|
||||||
|
>>> pwcView = PasswordChange(menu, request)
|
||||||
|
>>> pwcView.update()
|
||||||
|
False
|
||||||
|
|
||||||
Fin de partie
|
Fin de partie
|
||||||
=============
|
=============
|
||||||
|
|
|
@ -24,17 +24,18 @@ $Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope import interface, component
|
from zope import interface, component
|
||||||
from zope.app import zapi
|
|
||||||
from zope.app.authentication.principalfolder import InternalPrincipal
|
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.principalannotation import annotations
|
from zope.app.principalannotation import annotations
|
||||||
from zope.cachedescriptors.property import Lazy
|
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.formlib.namedtemplate import NamedTemplate
|
||||||
from zope.i18nmessageid import MessageFactory
|
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 cybertools.typology.interfaces import IType
|
||||||
from loops.browser.concept import ConceptView
|
from loops.browser.concept import ConceptView
|
||||||
from loops.browser.node import NodeView
|
from loops.browser.node import NodeView
|
||||||
|
@ -74,23 +75,7 @@ class PasswordWidget(BasePasswordWidget):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
class OldPasswordWidget(BasePasswordWidget):
|
class MemberRegistration(NodeView, FormlibForm):
|
||||||
|
|
||||||
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):
|
|
||||||
|
|
||||||
form_fields = FormFields(IMemberRegistration).omit('age')
|
form_fields = FormFields(IMemberRegistration).omit('age')
|
||||||
form_fields['password'].custom_widget = PasswordWidget
|
form_fields['password'].custom_widget = PasswordWidget
|
||||||
|
@ -139,50 +124,64 @@ class MemberRegistration(NodeView, Form):
|
||||||
|
|
||||||
class PasswordChange(NodeView, Form):
|
class PasswordChange(NodeView, Form):
|
||||||
|
|
||||||
form_fields = FormFields(IPasswordChange).select(
|
interface = IPasswordChange
|
||||||
'oldPassword', 'password', 'passwordConfirm')
|
message = u'Your password has been changed.'
|
||||||
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):
|
formErrors = dict(
|
||||||
super(PasswordChange, self).__init__(context, request)
|
confirm_nomatch=FormError(u'Password and password confirmation do not match.'),
|
||||||
if not testing:
|
wrong_oldpw=FormError(u'Your old password was not entered correctly.'),
|
||||||
self.setUpWidgets()
|
)
|
||||||
|
|
||||||
|
label = label_submit = u'Change Password'
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def macro(self):
|
def macro(self):
|
||||||
return self.template.macros['content']
|
return schema_macros.macros['form']
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def item(self):
|
def item(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def data(self):
|
||||||
|
data = dict(oldPassword=u'', password=u'', passwordConfirm=u'')
|
||||||
|
data = {}
|
||||||
|
return data
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
# see cybertools.browser.view.GenericView.update()
|
form = self.request.form
|
||||||
NodeView.update(self)
|
if not form.get('action'):
|
||||||
Form.update(self)
|
return True
|
||||||
|
formState = self.formState = self.validate(form)
|
||||||
|
if formState.severity > 0:
|
||||||
return True
|
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')
|
pw = form.get('password')
|
||||||
if form.get('passwordConfirm') != pw:
|
pwConfirm = form.get('passwordConfirm')
|
||||||
raise ValueError(u'Password and password confirmation do not match.')
|
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())
|
regMan = IMemberRegistrationManager(self.context.getLoopsRoot())
|
||||||
principal = self.request.principal
|
principal = self.request.principal
|
||||||
result = regMan.changePassword(principal, oldPw, pw)
|
result = regMan.changePassword(principal, oldPw, pw)
|
||||||
if not result:
|
if not result:
|
||||||
raise ValueError(u'Your old password was not entered correctly.')
|
fi = formState.fieldInstances['oldPassword']
|
||||||
message = _(u'Your password has been changed.')
|
fi.setError('wrong_oldpw', self.formErrors)
|
||||||
self.request.response.redirect('%s?message=%s'
|
formState.severity = max(formState.severity, fi.severity)
|
||||||
% (self.url, message))
|
return True
|
||||||
#self.request.response.redirect('%s/logout.html?message=%s'
|
url = '%s?messsage=%s' % (self.url, self.message)
|
||||||
# % (self.url, 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)))
|
mapping=dict(userId=userId)))
|
||||||
|
|
||||||
|
|
||||||
class Password(schema.Password):
|
|
||||||
|
|
||||||
def _validate(self, pw):
|
|
||||||
super(Password, self)._validate(pw)
|
|
||||||
|
|
||||||
|
|
||||||
class IPerson(IBasePerson):
|
class IPerson(IBasePerson):
|
||||||
""" Resembles a human being with a name (first and last name),
|
""" Resembles a human being with a name (first and last name),
|
||||||
a birth date, and a set of addresses. This interface only
|
a birth date, and a set of addresses. This interface only
|
||||||
|
@ -99,7 +93,7 @@ class IPerson(IBasePerson):
|
||||||
|
|
||||||
class IPasswordEntry(Interface):
|
class IPasswordEntry(Interface):
|
||||||
|
|
||||||
password = Password(title=_(u'Password'),
|
password = schema.Password(title=_(u'Password'),
|
||||||
description=_(u'Enter password.'),
|
description=_(u'Enter password.'),
|
||||||
required=True,)
|
required=True,)
|
||||||
passwordConfirm = schema.Password(title=_(u'Confirm password'),
|
passwordConfirm = schema.Password(title=_(u'Confirm password'),
|
||||||
|
|
Loading…
Add table
Reference in a new issue