backport fixes (member creation) from bbmaster2 branch
This commit is contained in:
parent
14242e77c7
commit
d445239beb
2 changed files with 105 additions and 7 deletions
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2013 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2014 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -25,6 +25,7 @@ from datetime import datetime
|
||||||
from email.MIMEText import MIMEText
|
from email.MIMEText import MIMEText
|
||||||
from zope import interface, component
|
from zope import interface, component
|
||||||
from zope.app.authentication.principalfolder import InternalPrincipal
|
from zope.app.authentication.principalfolder import InternalPrincipal
|
||||||
|
from zope.app.authentication.principalfolder import PrincipalInfo
|
||||||
from zope.app.form.browser.textwidgets import PasswordWidget as BasePasswordWidget
|
from zope.app.form.browser.textwidgets import PasswordWidget as BasePasswordWidget
|
||||||
from zope.app.pagetemplate import ViewPageTemplateFile
|
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||||
from zope.app.principalannotation import annotations
|
from zope.app.principalannotation import annotations
|
||||||
|
@ -47,9 +48,11 @@ from loops.browser.node import NodeView
|
||||||
from loops.common import adapted
|
from loops.common import adapted
|
||||||
from loops.concept import Concept
|
from loops.concept import Concept
|
||||||
from loops.organize.interfaces import ANNOTATION_KEY, IMemberRegistrationManager
|
from loops.organize.interfaces import ANNOTATION_KEY, IMemberRegistrationManager
|
||||||
from loops.organize.interfaces import IMemberRegistration, IPasswordChange
|
from loops.organize.interfaces import IMemberRegistration, IPasswordEntry
|
||||||
|
from loops.organize.interfaces import IPasswordChange, IPasswordReset
|
||||||
from loops.organize.party import getPersonForUser, Person
|
from loops.organize.party import getPersonForUser, Person
|
||||||
from loops.organize.util import getInternalPrincipal, getPrincipalForUserId
|
from loops.organize.util import getInternalPrincipal, getPrincipalForUserId
|
||||||
|
from loops.organize.util import getPrincipalFolder
|
||||||
import loops.browser.util
|
import loops.browser.util
|
||||||
from loops.util import _
|
from loops.util import _
|
||||||
|
|
||||||
|
@ -86,7 +89,8 @@ class BaseMemberRegistration(NodeView):
|
||||||
template = form_macros
|
template = form_macros
|
||||||
|
|
||||||
formErrors = dict(
|
formErrors = dict(
|
||||||
confirm_nomatch=FormError(_(u'Password and password confirmation do not match.')),
|
confirm_nomatch=FormError(_(u'Password and password confirmation '
|
||||||
|
u'do not match.')),
|
||||||
duplicate_loginname=FormError(_('Login name already taken.')),
|
duplicate_loginname=FormError(_('Login name already taken.')),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -187,7 +191,9 @@ class MemberRegistration(BaseMemberRegistration, CreateForm):
|
||||||
result = regMan.register(login, pw,
|
result = regMan.register(login, pw,
|
||||||
form.get('lastName'), form.get('firstName'),
|
form.get('lastName'), form.get('firstName'),
|
||||||
email=form.get('email'),
|
email=form.get('email'),
|
||||||
phoneNumbers=[x for x in phoneNumbers if x])
|
phoneNumbers=[x for x in phoneNumbers if x],
|
||||||
|
salutation=form.get('salutation'),
|
||||||
|
academicTitle=form.get('academicTitle'))
|
||||||
if isinstance(result, dict):
|
if isinstance(result, dict):
|
||||||
fi = formState.fieldInstances[result['fieldName']]
|
fi = formState.fieldInstances[result['fieldName']]
|
||||||
fi.setError(result['error'], self.formErrors)
|
fi.setError(result['error'], self.formErrors)
|
||||||
|
@ -210,6 +216,8 @@ class SecureMemberRegistration(BaseMemberRegistration, CreateForm):
|
||||||
@Lazy
|
@Lazy
|
||||||
def schema(self):
|
def schema(self):
|
||||||
schema = super(SecureMemberRegistration, self).schema
|
schema = super(SecureMemberRegistration, self).schema
|
||||||
|
schema.fields.remove('salutation')
|
||||||
|
schema.fields.remove('academicTitle')
|
||||||
schema.fields.remove('birthDate')
|
schema.fields.remove('birthDate')
|
||||||
schema.fields.remove('password')
|
schema.fields.remove('password')
|
||||||
schema.fields.remove('passwordConfirm')
|
schema.fields.remove('passwordConfirm')
|
||||||
|
@ -366,7 +374,8 @@ class PasswordChange(NodeView, Form):
|
||||||
message = _(u'Your password has been changed.')
|
message = _(u'Your password has been changed.')
|
||||||
|
|
||||||
formErrors = dict(
|
formErrors = dict(
|
||||||
confirm_nomatch=FormError(_(u'Password and password confirmation do not match.')),
|
confirm_nomatch=FormError(_(u'Password and password confirmation '
|
||||||
|
u'do not match.')),
|
||||||
wrong_oldpw=FormError(_(u'Your old password was not entered correctly.')),
|
wrong_oldpw=FormError(_(u'Your old password was not entered correctly.')),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -422,3 +431,84 @@ class PasswordChange(NodeView, Form):
|
||||||
formState.severity = max(formState.severity, fi.severity)
|
formState.severity = max(formState.severity, fi.severity)
|
||||||
return formState
|
return formState
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordReset(PasswordChange):
|
||||||
|
|
||||||
|
interface = IPasswordReset
|
||||||
|
message = _(u'Password Reset: You will receive an email with '
|
||||||
|
u'a link to change your password.')
|
||||||
|
|
||||||
|
formErrors = dict(
|
||||||
|
confirm_notfound=FormError(_(u'Invalid user account.')),
|
||||||
|
)
|
||||||
|
|
||||||
|
label = label_submit = _(u'Reset Password')
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def data(self):
|
||||||
|
data = dict(loginName=u'')
|
||||||
|
return data
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
form = self.request.form
|
||||||
|
if not form.get('action'):
|
||||||
|
return True
|
||||||
|
formState = self.formState = self.validate(form)
|
||||||
|
if formState.severity > 0:
|
||||||
|
return True
|
||||||
|
loginName = form.get('loginName')
|
||||||
|
person = principal = None
|
||||||
|
regMan = IMemberRegistrationManager(self.context.getLoopsRoot())
|
||||||
|
authenticator = regMan.getPrincipalFolderFromOption()
|
||||||
|
if authenticator is not None:
|
||||||
|
userId = authenticator.prefix + loginName
|
||||||
|
principal = getPrincipalForUserId(userId)
|
||||||
|
if principal is not None:
|
||||||
|
person = getPersonForUser(self.context, principal=principal)
|
||||||
|
if person is None:
|
||||||
|
fi = formState.fieldInstances['loginName']
|
||||||
|
fi.setError('confirm_notfound', self.formErrors)
|
||||||
|
formState.severity = max(formState.severity, fi.severity)
|
||||||
|
return True
|
||||||
|
person = adapted(person)
|
||||||
|
pa = self.getPrincipalAnnotation(principal)
|
||||||
|
pa['id'] = generateName()
|
||||||
|
pa['timestamp'] = datetime.utcnow()
|
||||||
|
self.notifyEmail(loginName, person.email, pa['id'])
|
||||||
|
url = '%s?messsage=%s' % (self.url, self.message)
|
||||||
|
self.request.response.redirect(url)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getPrincipalAnnotation(self, principal):
|
||||||
|
return annotations(principal).get(ANNOTATION_KEY, None)
|
||||||
|
|
||||||
|
def notifyEmail(self, userid, recipient, id):
|
||||||
|
baseUrl = absoluteURL(self.context.getMenu(), self.request)
|
||||||
|
url = u'%s/selfservice_confirmation.html?login=%s&id=%s' % (
|
||||||
|
baseUrl, userid, id,)
|
||||||
|
recipients = [recipient]
|
||||||
|
subject = _(u'password_reset_mail_subject')
|
||||||
|
message = _(u'password_reset_mail_text') + u':\n\n'
|
||||||
|
message = (message + url).encode('UTF-8')
|
||||||
|
senderInfo = self.globalOptions('email.sender')
|
||||||
|
sender = senderInfo and senderInfo[0] or 'info@loops.cy55.de'
|
||||||
|
sender = sender.encode('UTF-8')
|
||||||
|
msg = MIMEText(message, 'plain', 'utf-8')
|
||||||
|
msg['Subject'] = subject.encode('UTF-8')
|
||||||
|
msg['From'] = sender
|
||||||
|
msg['To'] = ', '.join(recipients)
|
||||||
|
mailhost = component.getUtility(IMailDelivery, 'Mail')
|
||||||
|
mailhost.send(sender, recipients, msg.as_string())
|
||||||
|
|
||||||
|
|
||||||
|
class FixPersonRoles(object):
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
concepts = self.context['concepts']
|
||||||
|
for p in concepts['person'].getChildren([concepts['hasType']]):
|
||||||
|
person = adapted(p)
|
||||||
|
userId = person.userId
|
||||||
|
print '***', userId
|
||||||
|
person.userId = userId
|
||||||
|
return 'blubb'
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2013 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2015 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -82,7 +82,7 @@ class LoginName(schema.TextLine):
|
||||||
super(LoginName, self)._validate(userId)
|
super(LoginName, self)._validate(userId)
|
||||||
if userId in getPrincipalFolder(self.context):
|
if userId in getPrincipalFolder(self.context):
|
||||||
raiseValidationError(
|
raiseValidationError(
|
||||||
_(u'There is alread a user with ID $userId.',
|
_(u'There is already a user with ID $userId.',
|
||||||
mapping=dict(userId=userId)))
|
mapping=dict(userId=userId)))
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,6 +124,14 @@ class IPasswordChange(IPasswordEntry):
|
||||||
required=True,)
|
required=True,)
|
||||||
|
|
||||||
|
|
||||||
|
class IPasswordReset(Interface):
|
||||||
|
|
||||||
|
loginName = schema.TextLine(title=_(u'User ID'),
|
||||||
|
description=_(u'Your login name.'),
|
||||||
|
required=True,)
|
||||||
|
loginName.nostore = True
|
||||||
|
|
||||||
|
|
||||||
class IMemberRegistration(IBasePerson, IPasswordEntry):
|
class IMemberRegistration(IBasePerson, IPasswordEntry):
|
||||||
""" Schema for registering a new member (user + person).
|
""" Schema for registering a new member (user + person).
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Add table
Reference in a new issue