member registration basically usable
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1221 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
a70fe7d830
commit
00e27595ca
11 changed files with 353 additions and 57 deletions
|
@ -44,7 +44,7 @@ from loops import util
|
||||||
|
|
||||||
class EditForm(BaseEditForm):
|
class EditForm(BaseEditForm):
|
||||||
|
|
||||||
template = NamedTemplate('pageform')
|
template = NamedTemplate('loops.pageform')
|
||||||
|
|
||||||
def deleteObjectAction(self):
|
def deleteObjectAction(self):
|
||||||
return None # better not to show the edit button at the moment
|
return None # better not to show the edit button at the moment
|
||||||
|
|
|
@ -33,6 +33,7 @@ from zope.cachedescriptors.property import Lazy
|
||||||
from zope.dottedname.resolve import resolve
|
from zope.dottedname.resolve import resolve
|
||||||
from zope.event import notify
|
from zope.event import notify
|
||||||
from zope.formlib.form import EditForm, FormFields
|
from zope.formlib.form import EditForm, FormFields
|
||||||
|
from zope.formlib.namedtemplate import NamedTemplate
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
from zope.publisher.interfaces import BadRequest
|
from zope.publisher.interfaces import BadRequest
|
||||||
from zope.publisher.interfaces.browser import IBrowserRequest
|
from zope.publisher.interfaces.browser import IBrowserRequest
|
||||||
|
@ -63,8 +64,11 @@ class ConceptEditForm(EditForm):
|
||||||
|
|
||||||
class ConceptView(BaseView):
|
class ConceptView(BaseView):
|
||||||
|
|
||||||
template = ViewPageTemplateFile('concept_macros.pt')
|
template = NamedTemplate('loops.concept_macros')
|
||||||
macro = template.macros['conceptlisting']
|
|
||||||
|
@Lazy
|
||||||
|
def macro(self):
|
||||||
|
return self.template.macros['conceptlisting']
|
||||||
|
|
||||||
def children(self):
|
def children(self):
|
||||||
for r in self.context.getChildRelations():
|
for r in self.context.getChildRelations():
|
||||||
|
|
|
@ -61,12 +61,27 @@
|
||||||
permission="zope.View"
|
permission="zope.View"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- named template(s) -->
|
<!-- named templates - forms and macro templates -->
|
||||||
|
|
||||||
<zope:adapter
|
<zope:adapter
|
||||||
factory="loops.browser.util.pageform"
|
factory="loops.browser.util.pageform"
|
||||||
for="zope.interface.Interface"
|
for="zope.interface.Interface"
|
||||||
name="pageform" />
|
name="loops.pageform" />
|
||||||
|
|
||||||
|
<zope:adapter
|
||||||
|
factory="loops.browser.util.dataform"
|
||||||
|
for="zope.interface.Interface"
|
||||||
|
name="loops.dataform" />
|
||||||
|
|
||||||
|
<zope:adapter
|
||||||
|
factory="loops.browser.util.concept_macros"
|
||||||
|
for="loops.browser.common.BaseView"
|
||||||
|
name="loops.concept_macros" />
|
||||||
|
|
||||||
|
<zope:adapter
|
||||||
|
factory="loops.browser.util.node_macros"
|
||||||
|
for="loops.browser.common.BaseView"
|
||||||
|
name="loops.node_macros" />
|
||||||
|
|
||||||
<!-- loops top-level container -->
|
<!-- loops top-level container -->
|
||||||
|
|
||||||
|
|
169
browser/dataform.pt
Normal file
169
browser/dataform.pt
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
<html metal:extend-macro="context/@@standard_macros/view"
|
||||||
|
metal:define-macro="main">
|
||||||
|
<head></head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
<metal:settings fill-slot="settings"
|
||||||
|
tal:define="dummy python:
|
||||||
|
controller.macros.register('css', resourceName='node.css', media='all');" />
|
||||||
|
|
||||||
|
|
||||||
|
<div class="box" metal:fill-slot="navigators">
|
||||||
|
<h4>Navigation</h4>
|
||||||
|
<tal:menu define="item view/menu;
|
||||||
|
level level|python: 1"
|
||||||
|
condition="item">
|
||||||
|
<div class="body">
|
||||||
|
<metal:menu use-macro="views/node_macros/menu" />
|
||||||
|
</div>
|
||||||
|
</tal:menu>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div metal:fill-slot="body">
|
||||||
|
|
||||||
|
<div metal:define-macro="form">
|
||||||
|
|
||||||
|
<form action="." metal:define-macro="master"
|
||||||
|
tal:attributes="action request/URL" method="post"
|
||||||
|
class="edit-form" enctype="multipart/form-data"
|
||||||
|
id="zc.page.browser_form">
|
||||||
|
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
|
||||||
|
function toggleFormFieldHelp(ob,state) {
|
||||||
|
// ob is the label element
|
||||||
|
var field = ob.form[ob.htmlFor];
|
||||||
|
if (field) {
|
||||||
|
var viz = state && 'hidden' || 'visible';
|
||||||
|
if (field.length == null) {
|
||||||
|
field.style.visibility = viz;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (var i = 0; i < field.length; ++i) {
|
||||||
|
var e = field.item(i);
|
||||||
|
e.style.visibility = viz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var help = document.getElementById("field-help-for-" + field.name);
|
||||||
|
if (help) {
|
||||||
|
help.style.visibility = state && 'visible' || 'hidden';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-->
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="viewspace" metal:define-slot="viewspace">
|
||||||
|
|
||||||
|
<h1 tal:content="view/label">Edit ...</h1>
|
||||||
|
|
||||||
|
<metal:block define-macro="header">
|
||||||
|
|
||||||
|
<div class="form-status"
|
||||||
|
tal:define="status view/status"
|
||||||
|
tal:condition="status">
|
||||||
|
|
||||||
|
<div class="summary"
|
||||||
|
i18n:translate=""
|
||||||
|
tal:content="view/status">
|
||||||
|
Form status summary
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="errors" tal:condition="view/errors">
|
||||||
|
<li tal:repeat="error view/error_views">
|
||||||
|
<span tal:replace="structure error">Error Type</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
</metal:block>
|
||||||
|
|
||||||
|
<div metal:define-slot="extra_info" tal:replace="nothing">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="form-fields">
|
||||||
|
<tr class="row" metal:define-slot="extra_top" tal:replace="nothing">
|
||||||
|
<td class="label">Extra top</td>
|
||||||
|
<td class="label"><input type="text" /></td>
|
||||||
|
</tr>
|
||||||
|
<tbody metal:define-slot="formbody" tal:omit-tag="">
|
||||||
|
<tr tal:repeat="widget view/widgets">
|
||||||
|
<td class="label" tal:define="hint widget/hint"
|
||||||
|
metal:define-macro="labelcell">
|
||||||
|
<label tal:condition="python:hint"
|
||||||
|
tal:attributes="for widget/name"
|
||||||
|
onmousedown="toggleFormFieldHelp(this,1)"
|
||||||
|
onmouseup="toggleFormFieldHelp(this,0)"
|
||||||
|
onmouseout="toggleFormFieldHelp(this,0)"
|
||||||
|
style="cursor: help">
|
||||||
|
<span class="required" tal:condition="widget/required"
|
||||||
|
>*</span><span i18n:translate=""
|
||||||
|
tal:content="widget/label">label</span>
|
||||||
|
</label>
|
||||||
|
<label tal:condition="python:not hint"
|
||||||
|
tal:attributes="for widget/name">
|
||||||
|
<span class="required" tal:condition="widget/required"
|
||||||
|
>*</span><span i18n:translate=""
|
||||||
|
tal:content="widget/label">label</span>
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td class="field" tal:define="hint widget/hint"
|
||||||
|
metal:define-macro="widgetcell">
|
||||||
|
<div class="form-fields-help"
|
||||||
|
i18n:translate=""
|
||||||
|
tal:content="hint"
|
||||||
|
tal:condition="hint"
|
||||||
|
tal:attributes="id string:field-help-for-${widget/name}"
|
||||||
|
onclick="this.style.visibility='hidden';"
|
||||||
|
style="visibility: hidden; position: absolute;"
|
||||||
|
>Title of this content object.</div>
|
||||||
|
<div class="widget" tal:content="structure widget">
|
||||||
|
<input type="text" /></div>
|
||||||
|
<div class="error"
|
||||||
|
tal:condition="widget/error"
|
||||||
|
>
|
||||||
|
<!-- TODO Put this back, the Zope3 way.
|
||||||
|
<img src="alert.gif" alt="Error"
|
||||||
|
tal:replace="structure context/alert.gif" />
|
||||||
|
-->
|
||||||
|
<span tal:replace="structure widget/error">error</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tr class="row" metal:define-slot="extra_bottom" tal:replace="nothing">
|
||||||
|
<td class="label">Extra bottom</td>
|
||||||
|
<td class="label"><input type="text" /></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<metal:block define-slot="above_buttons" />
|
||||||
|
</div>
|
||||||
|
<div id="actionsView">
|
||||||
|
<br />
|
||||||
|
<span class="actionButtons"
|
||||||
|
tal:condition="view/availableActions"
|
||||||
|
metal:define-slot="bottom_buttons">
|
||||||
|
<input tal:repeat="action view/actions"
|
||||||
|
tal:replace="structure action/render"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form metal:use-macro="views/resource_macros/delete_object" />
|
||||||
|
|
||||||
|
<script type="text/javascript" metal:define-slot="trackChanges">
|
||||||
|
zc_trackChanges(document.getElementById('zc.page.browser_form'));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript"
|
||||||
|
tal:define="extra_script view/extra_script | nothing"
|
||||||
|
tal:condition="extra_script"
|
||||||
|
tal:content="structure extra_script" />
|
||||||
|
|
||||||
|
</div></div></body></html>
|
|
@ -34,6 +34,7 @@ from zope.app.pagetemplate import ViewPageTemplateFile
|
||||||
from zope.app.intid.interfaces import IIntIds
|
from zope.app.intid.interfaces import IIntIds
|
||||||
from zope.dottedname.resolve import resolve
|
from zope.dottedname.resolve import resolve
|
||||||
from zope.event import notify
|
from zope.event import notify
|
||||||
|
from zope.formlib.namedtemplate import NamedTemplate
|
||||||
from zope.proxy import removeAllProxies
|
from zope.proxy import removeAllProxies
|
||||||
from zope.security import canAccess, canWrite
|
from zope.security import canAccess, canWrite
|
||||||
from zope.security.proxy import removeSecurityProxy
|
from zope.security.proxy import removeSecurityProxy
|
||||||
|
@ -50,7 +51,7 @@ from loops.browser.concept import ConceptView
|
||||||
|
|
||||||
class NodeView(BaseView):
|
class NodeView(BaseView):
|
||||||
|
|
||||||
template = ViewPageTemplateFile('node_macros.pt')
|
template = NamedTemplate('loops.node_macros')
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def macro(self):
|
def macro(self):
|
||||||
|
|
|
@ -30,6 +30,10 @@ from zope.formlib.namedtemplate import NamedTemplateImplementation
|
||||||
|
|
||||||
|
|
||||||
pageform = NamedTemplateImplementation(ViewPageTemplateFile('pageform.pt'))
|
pageform = NamedTemplateImplementation(ViewPageTemplateFile('pageform.pt'))
|
||||||
|
dataform = NamedTemplateImplementation(ViewPageTemplateFile('dataform.pt'))
|
||||||
|
|
||||||
|
concept_macros = NamedTemplateImplementation(ViewPageTemplateFile('concept_macros.pt'))
|
||||||
|
node_macros = NamedTemplateImplementation(ViewPageTemplateFile('node_macros.pt'))
|
||||||
|
|
||||||
|
|
||||||
class LoopsMenu(BrowserMenu):
|
class LoopsMenu(BrowserMenu):
|
||||||
|
|
|
@ -208,19 +208,19 @@ sure that a principal object can be served by a corresponding factory):
|
||||||
>>> from zope.app.authentication.principalfolder import FoundPrincipalFactory
|
>>> from zope.app.authentication.principalfolder import FoundPrincipalFactory
|
||||||
>>> component.provideAdapter(FoundPrincipalFactory)
|
>>> component.provideAdapter(FoundPrincipalFactory)
|
||||||
|
|
||||||
>>> form = {'field.userId': u'newuser',
|
>>> data = {'loginName': u'newuser',
|
||||||
... 'field.passwd': u'quack',
|
... 'password': u'quack',
|
||||||
... 'field.passwdConfirm': u'quack',
|
... 'passwordConfirm': u'quack',
|
||||||
... 'field.lastName': u'Sawyer',
|
... 'lastName': u'Sawyer',
|
||||||
... 'field.firstName': u'Tom'}
|
... 'firstName': u'Tom'}
|
||||||
>>> from zope.publisher.browser import TestRequest
|
|
||||||
>>> request = TestRequest(form=form)
|
|
||||||
|
|
||||||
and register it
|
and register it
|
||||||
|
|
||||||
|
>>> from zope.publisher.browser import TestRequest
|
||||||
|
>>> request = TestRequest()
|
||||||
>>> from loops.organize.browser import MemberRegistration
|
>>> from loops.organize.browser import MemberRegistration
|
||||||
>>> regView = MemberRegistration(menu, request)
|
>>> regView = MemberRegistration(menu, request)
|
||||||
>>> personAdapter = regView.register()
|
>>> personAdapter = regView.register(data)
|
||||||
|
|
||||||
>>> personAdapter.context.__name__, personAdapter.lastName, personAdapter.userId
|
>>> personAdapter.context.__name__, personAdapter.lastName, personAdapter.userId
|
||||||
(u'newuser', u'Sawyer', u'loops.newuser')
|
(u'newuser', u'Sawyer', u'loops.newuser')
|
||||||
|
|
|
@ -25,23 +25,31 @@ $Id$
|
||||||
|
|
||||||
from zope import interface, component
|
from zope import interface, component
|
||||||
from zope.app import zapi
|
from zope.app import zapi
|
||||||
|
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.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.namedtemplate import NamedTemplate
|
||||||
from zope.i18nmessageid import MessageFactory
|
from zope.i18nmessageid import MessageFactory
|
||||||
|
|
||||||
from loops.browser.common import BaseView
|
from loops.browser.common import BaseView
|
||||||
|
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 raiseValidationError
|
from loops.organize.interfaces import IMemberRegistration, raiseValidationError
|
||||||
|
|
||||||
_ = MessageFactory('zope')
|
_ = MessageFactory('zope')
|
||||||
|
|
||||||
|
|
||||||
class MyConcepts(BaseView):
|
class MyConcepts(BaseView):
|
||||||
|
|
||||||
template = ViewPageTemplateFile('../browser/concept_macros.pt')
|
template = NamedTemplate('loops.concept_macros')
|
||||||
macro = template.macros['conceptlisting']
|
|
||||||
|
@Lazy
|
||||||
|
def macro(self):
|
||||||
|
return self.template.macros['conceptlisting']
|
||||||
|
|
||||||
def __init__(self, context, request):
|
def __init__(self, context, request):
|
||||||
self.context = context
|
self.context = context
|
||||||
|
@ -70,21 +78,42 @@ class MyConcepts(BaseView):
|
||||||
yield ConceptRelationView(r, self.request, contextIsSecond=True)
|
yield ConceptRelationView(r, self.request, contextIsSecond=True)
|
||||||
|
|
||||||
|
|
||||||
class MemberRegistration(object):
|
class PasswordWidget(BasePasswordWidget):
|
||||||
|
|
||||||
|
def getInputValue(self):
|
||||||
|
value = super(PasswordWidget, self).getInputValue()
|
||||||
|
confirm = self.request.get('form.passwordConfirm')
|
||||||
|
if confirm != value:
|
||||||
|
v = _(u'Password and password confirmation do not match.')
|
||||||
|
self._error = WidgetInputError(
|
||||||
|
self.context.__name__, self.label, v)
|
||||||
|
raise self._error
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class MemberRegistration(Form, NodeView):
|
||||||
|
|
||||||
|
form_fields = FormFields(IMemberRegistration)
|
||||||
|
template = NamedTemplate('loops.dataform')
|
||||||
|
label = _(u'Member Registration')
|
||||||
|
|
||||||
def __init__(self, context, request):
|
def __init__(self, context, request):
|
||||||
self.context = context
|
NodeView.__init__(self, context, request)
|
||||||
self.request = request
|
|
||||||
|
|
||||||
def register(self):
|
@action(_(u'Register'))
|
||||||
form = self.request.form
|
def handle_register_action(self, action, data):
|
||||||
pw = form.get('field.passwd')
|
self.register(data)
|
||||||
if form.get('field.passwdConfirm') != pw:
|
|
||||||
raiseValidationError(_(u'Password and password confirmation '
|
def register(self, data=None):
|
||||||
'do not match.'))
|
form = data or self.request.form
|
||||||
|
pw = form.get('password')
|
||||||
|
if form.get('passwordConfirm') != pw:
|
||||||
|
raise ValueError(u'Password and password confirmation do not match.')
|
||||||
regMan = IMemberRegistrationManager(self.context.getLoopsRoot())
|
regMan = IMemberRegistrationManager(self.context.getLoopsRoot())
|
||||||
person = regMan.register(form.get('field.userId'), pw,
|
person = regMan.register(form.get('loginName'), pw,
|
||||||
form.get('field.lastName'),
|
form.get('lastName'),
|
||||||
form.get('field.firstName'))
|
form.get('firstName'))
|
||||||
|
message = _(u'You have been registered and can now login.')
|
||||||
|
self.request.response.redirect('%s?message=%s' % (self.url, message))
|
||||||
return person
|
return person
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
i18n_domain="zope"
|
i18n_domain="zope"
|
||||||
>
|
>
|
||||||
|
|
||||||
<!-- adapters -->
|
<!-- party: person, ... -->
|
||||||
|
|
||||||
<zope:adapter factory="loops.organize.party.Person"
|
<zope:adapter factory="loops.organize.party.Person"
|
||||||
provides="loops.organize.interfaces.IPerson"
|
provides="loops.organize.interfaces.IPerson"
|
||||||
|
@ -19,19 +19,44 @@
|
||||||
set_schema="loops.organize.interfaces.IPerson" />
|
set_schema="loops.organize.interfaces.IPerson" />
|
||||||
</zope:class>
|
</zope:class>
|
||||||
|
|
||||||
<zope:adapter
|
|
||||||
name="myconcepts"
|
|
||||||
for="loops.interfaces.IConcept
|
|
||||||
zope.publisher.interfaces.browser.IBrowserRequest"
|
|
||||||
provides="zope.interface.Interface"
|
|
||||||
factory="loops.organize.browser.MyConcepts"
|
|
||||||
permission="zope.View"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<zope:subscriber
|
<zope:subscriber
|
||||||
for="loops.interfaces.IConcept
|
for="loops.interfaces.IConcept
|
||||||
zope.app.container.interfaces.IObjectRemovedEvent"
|
zope.app.container.interfaces.IObjectRemovedEvent"
|
||||||
handler="loops.organize.party.removePersonReferenceFromPrincipal"
|
handler="loops.organize.party.removePersonReferenceFromPrincipal"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- my stuff and other views -->
|
||||||
|
|
||||||
|
<zope:adapter
|
||||||
|
name="myconcepts"
|
||||||
|
for="loops.interfaces.IConcept
|
||||||
|
zope.publisher.interfaces.browser.IBrowserRequest"
|
||||||
|
provides="zope.interface.Interface"
|
||||||
|
factory="loops.organize.browser.MyConcepts"
|
||||||
|
permission="zope.View"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- member registration -->
|
||||||
|
|
||||||
|
<zope:adapter factory="loops.organize.member.MemberRegistrationManager"
|
||||||
|
trusted="True" />
|
||||||
|
|
||||||
|
<zope:class class="loops.organize.member.MemberRegistrationManager">
|
||||||
|
<require permission ="zope.Public"
|
||||||
|
interface="loops.organize.interfaces.IMemberRegistrationManager" />
|
||||||
|
</zope:class>
|
||||||
|
|
||||||
|
<browser:page name="registration.html"
|
||||||
|
for="loops.interfaces.IView"
|
||||||
|
class="loops.organize.browser.MemberRegistration"
|
||||||
|
permission="zope.Public" />
|
||||||
|
|
||||||
|
<zope:view
|
||||||
|
type="zope.publisher.interfaces.browser.IBrowserRequest"
|
||||||
|
for="loops.organize.interfaces.Password"
|
||||||
|
provides="zope.app.form.interfaces.IInputWidget"
|
||||||
|
factory="loops.organize.browser.PasswordWidget"
|
||||||
|
permission="zope.Public"
|
||||||
|
/>
|
||||||
|
|
||||||
</configure>
|
</configure>
|
||||||
|
|
|
@ -23,7 +23,7 @@ $Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope.interface import Interface, Attribute
|
from zope.interface import Interface, Attribute
|
||||||
from zope import component, schema
|
from zope import interface, component, schema
|
||||||
from zope.app import zapi
|
from zope.app import zapi
|
||||||
from zope.app.principalannotation import annotations
|
from zope.app.principalannotation import annotations
|
||||||
from zope.app.security.interfaces import IAuthentication, PrincipalLookupError
|
from zope.app.security.interfaces import IAuthentication, PrincipalLookupError
|
||||||
|
@ -65,22 +65,68 @@ class UserId(schema.TextLine):
|
||||||
userId=userId)))
|
userId=userId)))
|
||||||
|
|
||||||
|
|
||||||
|
class LoginName(schema.TextLine):
|
||||||
|
|
||||||
|
def _validate(self, userId):
|
||||||
|
super(LoginName, self)._validate(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
|
||||||
lists fields used in addidtion to those provided by the
|
lists fields used in addition to those provided by the
|
||||||
basic cybertools.organize package.
|
basic cybertools.organize package.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
userId = UserId(
|
userId = UserId(title=_(u'User ID'),
|
||||||
title=_(u'User ID'),
|
description=_(u'The principal id (including prinicipal '
|
||||||
description=_(u'The principal id of a user that should '
|
'folder prefix) of a user that should '
|
||||||
'be associated with this person.'),
|
'be associated with this person.'),
|
||||||
required=False,)
|
required=False,)
|
||||||
|
|
||||||
|
|
||||||
|
class IPasswordEntry(Interface):
|
||||||
|
|
||||||
|
password = Password(title=_(u'Password'),
|
||||||
|
description=_(u'Enter password.'),
|
||||||
|
required=True,)
|
||||||
|
passwordConfirm = schema.Password(title=_(u'Confirm password'),
|
||||||
|
description=_(u'Please repeat the password.'),
|
||||||
|
required=True,)
|
||||||
|
|
||||||
|
#@interface.invariant
|
||||||
|
#def passwordMatchConfirm(data):
|
||||||
|
# if data.password != data.passwordConfirm:
|
||||||
|
# raise interface.Invalid(_(u'Password and password confirmation '
|
||||||
|
# 'do not match.'))
|
||||||
|
|
||||||
|
|
||||||
|
class IPasswordChange(IPasswordEntry):
|
||||||
|
|
||||||
|
oldPassword = schema.Password(title=_(u'Old password'),
|
||||||
|
description=_(u'Enter old password.'),
|
||||||
|
required=True,)
|
||||||
|
|
||||||
|
|
||||||
|
class IMemberRegistration(IBasePerson, IPasswordEntry):
|
||||||
|
""" Schema for registering a new member (user + person).
|
||||||
|
"""
|
||||||
|
|
||||||
|
loginName = LoginName(
|
||||||
|
title=_(u'User ID'),
|
||||||
|
description=_(u'Enter a user id.'),
|
||||||
|
required=True,)
|
||||||
|
|
||||||
|
|
||||||
class IMemberRegistrationManager(Interface):
|
class IMemberRegistrationManager(Interface):
|
||||||
""" Knows what to do for registrating a new member (portal user).
|
""" Knows what to do for registrating a new member (portal user),
|
||||||
|
change password, etc.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
authPluginId = Attribute(u'The id of an authentication plugin to be '
|
authPluginId = Attribute(u'The id of an authentication plugin to be '
|
||||||
|
@ -89,11 +135,11 @@ class IMemberRegistrationManager(Interface):
|
||||||
def register(userId, password, lastName, firstName=u'', **kw):
|
def register(userId, password, lastName, firstName=u'', **kw):
|
||||||
""" Register a new member for this loops site.
|
""" Register a new member for this loops site.
|
||||||
Return the person adapter for the concept created.
|
Return the person adapter for the concept created.
|
||||||
Raise ValidationError if the user could not be created.
|
Raise Validation Error (?) if the user could not be created.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def changePassword(oldPw, newPw):
|
def changePassword(newPw):
|
||||||
""" Change the password of the user currently logged-in.
|
""" Change the password of the user currently logged-in.
|
||||||
Raise a ValidationError if the oldPw does not match the
|
Raise a Validation Error (?) if the oldPw does not match the
|
||||||
current password.
|
current password.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -23,13 +23,15 @@ $Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope.app import zapi
|
from zope.app import zapi
|
||||||
from zope import interface, component
|
from zope import interface, component, schema
|
||||||
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.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent
|
||||||
from zope.app.security.interfaces import IAuthentication
|
from zope.app.security.interfaces import IAuthentication
|
||||||
|
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
|
||||||
|
|
||||||
|
@ -37,7 +39,6 @@ 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.interfaces import raiseValidationError
|
|
||||||
|
|
||||||
_ = MessageFactory('zope')
|
_ = MessageFactory('zope')
|
||||||
|
|
||||||
|
@ -56,24 +57,24 @@ 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:
|
||||||
pau = zapi.getUtility(IAuthentication, context=self.context)
|
pau = zapi.getUtility(IAuthentication, context=self.context)
|
||||||
if not IPluggableAuthentication.providedBy(pau):
|
if not IPluggableAuthentication.providedBy(pau):
|
||||||
raiseValidationError(_(u'There is no pluggable authentication '
|
raise ValueError(u'There is no pluggable authentication '
|
||||||
'utility available.'))
|
'utility available.')
|
||||||
if not self.authPluginId in pau.authenticatorPlugins:
|
if not self.authPluginId in pau.authenticatorPlugins:
|
||||||
raiseValidationError(_(u'There is no loops authenticator '
|
raise ValueError(u'There is no loops authenticator '
|
||||||
'plugin available.'))
|
'plugin available.')
|
||||||
pFolder = component.queryUtility(IAuthenticatorPlugin, self.authPluginId,
|
pFolder = component.queryUtility(IAuthenticatorPlugin, self.authPluginId,
|
||||||
context=pau)
|
context=pau)
|
||||||
title = firstName and ' '.join((firstName, lastName)) or lastName
|
title = firstName and ' '.join((firstName, lastName)) or lastName
|
||||||
# TODO: encrypt password:
|
# TODO: care for password encryption:
|
||||||
principal = InternalPrincipal(userId, password, title)
|
principal = InternalPrincipal(userId, password, title)
|
||||||
pFolder[userId] = principal
|
pFolder[userId] = principal
|
||||||
# step 1: create a corresponding person concept:
|
# step 2: create a corresponding person concept:
|
||||||
cm = self.context.getConceptManager()
|
cm = self.context.getConceptManager()
|
||||||
id = userId
|
id = userId
|
||||||
num = 0
|
num = 0
|
||||||
while id in cm:
|
while id in cm:
|
||||||
num +=1
|
num +=1
|
||||||
id = userid + str(num)
|
id = userId + str(num)
|
||||||
person = cm[id] = Concept(title)
|
person = cm[id] = Concept(title)
|
||||||
# TODO: the name of the person type object must be kept flexible!
|
# TODO: the name of the person type object must be kept flexible!
|
||||||
person.conceptType = cm['person']
|
person.conceptType = cm['person']
|
||||||
|
@ -81,6 +82,8 @@ class MemberRegistrationManager(object):
|
||||||
personAdapter.firstName = firstName
|
personAdapter.firstName = firstName
|
||||||
personAdapter.lastName = lastName
|
personAdapter.lastName = lastName
|
||||||
personAdapter.userId = '.'.join((self.authPluginId, userId))
|
personAdapter.userId = '.'.join((self.authPluginId, userId))
|
||||||
|
notify(ObjectCreatedEvent(person))
|
||||||
|
notify(ObjectModifiedEvent(person))
|
||||||
return personAdapter
|
return personAdapter
|
||||||
|
|
||||||
def changePassword(self, oldPw, newPw):
|
def changePassword(self, oldPw, newPw):
|
||||||
|
|
Loading…
Add table
Reference in a new issue