Clean up (Re)Captcha code. Register Captcha field/validator only if a package is installed that provides the "plone.app.discussion-captcha" feature (currently plone.formwidget.captcha and plone.formwidget.recaptcha trunk only).

svn path=/plone.app.discussion/trunk/; revision=36877
This commit is contained in:
Timo Stollenwerk 2010-06-01 16:38:29 +00:00
parent e16b15708b
commit 2e0b52889d
3 changed files with 70 additions and 86 deletions

View File

@ -25,69 +25,45 @@ from plone.app.discussion.interfaces import IDiscussionSettings, ICaptcha
from plone.app.discussion.browser.validator import CaptchaValidator
HAS_CAPTCHA = False
try:
from plone.formwidget.captcha import CaptchaFieldWidget
HAS_CAPTCHA = True
except ImportError:
pass
HAS_RECAPTCHA = False
try:
from plone.formwidget.recaptcha import ReCaptchaFieldWidget
HAS_RECAPTCHA = True
except ImportError:
pass
class Captcha(Persistent):
"""Captcha input field.
"""
interface.implements(ICaptcha)
adapts(Comment)
captcha = u""
Captcha = factory(Captcha)
if HAS_CAPTCHA or HAS_RECAPTCHA:
# Extend the comment form with captcha, if a captcha solution is installed.
class CaptchaExtender(extensible.FormExtender):
adapts(Interface, IDefaultBrowserLayer, CommentForm) # context, request, form
fields = Fields(ICaptcha)
class CaptchaExtender(extensible.FormExtender):
"""Extends the comment form with a Captcha. This Captcha extender is only
registered when a plugin is installed that provides the
"plone.app.discussion-captcha" feature.
"""
adapts(Interface, IDefaultBrowserLayer, CommentForm) # context, request, form
def __init__(self, context, request, form):
self.context = context
self.request = request
self.form = form
fields = Fields(ICaptcha)
registry = queryUtility(IRegistry)
settings = registry.forInterface(IDiscussionSettings)
self.captcha = settings.captcha
portal_membership = getToolByName(self.context, 'portal_membership')
self.isAnon = portal_membership.isAnonymousUser()
def __init__(self, context, request, form):
self.context = context
self.request = request
self.form = form
def update(self):
if self.captcha != 'disabled' and self.isAnon:
# Add captcha field if captcha is enabled in the registry
self.add(ICaptcha, prefix="")
if HAS_CAPTCHA and self.captcha == 'captcha':
# If Captcha is installed and Captcha is enabled,
# use the CaptchaFieldWidget
self.form.fields['captcha'].widgetFactory = CaptchaFieldWidget
elif HAS_RECAPTCHA and self.captcha == 'recaptcha':
# If ReCaptcha is installed and ReCaptcha is enabled,
# use the ReCaptchaFieldWidget
self.form.fields['captcha'].widgetFactory = ReCaptchaFieldWidget
registry = queryUtility(IRegistry)
settings = registry.forInterface(IDiscussionSettings)
self.captcha = settings.captcha
portal_membership = getToolByName(self.context, 'portal_membership')
self.isAnon = portal_membership.isAnonymousUser()
# Register Captcha validator for the Captcha field in the ICaptcha Form
validator.WidgetValidatorDiscriminators(CaptchaValidator, field=ICaptcha['captcha'])
def update(self):
if self.captcha != 'disabled' and self.isAnon:
# Add a captcha field if captcha is enabled in the registry
self.add(ICaptcha, prefix="")
if self.captcha == 'captcha':
from plone.formwidget.captcha import CaptchaFieldWidget
self.form.fields['captcha'].widgetFactory = CaptchaFieldWidget
elif self.captcha == 'recaptcha':
from plone.formwidget.recaptcha import ReCaptchaFieldWidget
self.form.fields['captcha'].widgetFactory = ReCaptchaFieldWidget
else:
# This is necessary, otherwise the zcml registration of the CaptchaExtender
# would fail if no captcha solution is installed.
class CaptchaExtender(extensible.FormExtender):
adapts(Interface, IDefaultBrowserLayer, CommentForm)
def __init__(self, context, request, form):
pass
def update(self):
pass

View File

@ -1,6 +1,7 @@
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:zcml="http://namespaces.zope.org/zcml"
i18n_domain="plone.app.discussion">
<include package="plone.app.registry" />
@ -81,18 +82,23 @@
/>
<!-- Comment form extender -->
<adapter
factory=".captcha.Captcha"
provides="plone.app.discussion.interfaces.ICaptcha" />
<adapter
factory=".captcha.CaptchaExtender"
provides="plone.z3cform.fieldsets.interfaces.IFormExtender" />
<!-- Captcha validator -->
<adapter
factory=".captcha.CaptchaValidator"
/>
<configure zcml:condition="have plone.app.discussion-captcha">
<!--
Register the Captcha form extender and validator only if there are
plugins installed that declare to implement a Captcha solution for
plone.app.discussion (e.g. plone.formwidget.captcha and
plone.formwidget.recaptcha).
-->
<adapter
factory=".captcha.Captcha"
provides="plone.app.discussion.interfaces.ICaptcha" />
<adapter
factory=".captcha.CaptchaExtender"
provides="plone.z3cform.fieldsets.interfaces.IFormExtender" />
<adapter
factory=".captcha.CaptchaValidator"
/>
</configure>
<!-- Comment view -->
<browser:view
@ -125,4 +131,4 @@
permission="cmf.ManagePortal"
/>
</configure>
</configure>

View File

@ -1,8 +1,4 @@
# Captcha/ReCaptcha validators. We override the standard validators from
# plone.formwidget.captcha and plone.formwidget.recaptcha, in order to
# switch between the two. This is necessary, because the zcml registration
# of the CaptchaValidator has to be there, no matter which captcha solution
# is installed, or even when no captcha solution is installed.
# -*- coding: utf-8 -*-
from Acquisition import aq_inner
@ -14,25 +10,24 @@ from zope.component import getMultiAdapter, provideAdapter, queryUtility
from zope.schema import ValidationError
from zope.interface import implements, Interface
from zope.schema.interfaces import IField
from zope.component import adapts
from plone.registry.interfaces import IRegistry
from plone.app.discussion.interfaces import IDiscussionSettings, IDiscussionLayer, MessageFactory as _
from zope.interface import implements, Interface
from zope.schema.interfaces import IField
from zope.component import adapts
from plone.app.discussion.interfaces import ICaptcha
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.app.discussion.interfaces import IDiscussionLayer
from plone.app.discussion.interfaces import MessageFactory as _
try:
from plone.formwidget.captcha import CaptchaMessageFactory as _
class WrongCaptchaCode(ValidationError):
__doc__ = _("""The code you entered was wrong, please enter the new one.""")
from plone.formwidget.captcha.validator import WrongCaptchaCode
except:
pass
try:
from plone.formwidget.recaptcha import ReCaptchaMessageFactory as _
class WrongReCaptchaCode(ValidationError):
__doc__ = _("""The code you entered was wrong, please enter the new one.""")
from plone.formwidget.recaptcha.validator import WrongCaptchaCode
except:
pass
@ -40,6 +35,7 @@ from zope.interface import implements, Interface
from zope.schema.interfaces import IField
from zope.component import adapts
class CaptchaValidator(validator.SimpleFieldValidator):
implements(IValidator)
adapts(Interface,IDiscussionLayer,Interface,IField,Interface)
@ -53,7 +49,8 @@ class CaptchaValidator(validator.SimpleFieldValidator):
if settings.captcha == 'captcha':
# Fetch captcha view
captcha = getMultiAdapter((aq_inner(self.context), self.request), name='captcha')
captcha = getMultiAdapter((aq_inner(self.context), self.request),
name='captcha')
if value:
if not captcha.verify(value):
raise WrongCaptchaCode
@ -61,9 +58,14 @@ class CaptchaValidator(validator.SimpleFieldValidator):
return True
raise WrongCaptchaCode
elif settings.captcha == 'recaptcha':
# Fetch recatpcha view
captcha = getMultiAdapter((aq_inner(self.context), self.request), name='recaptcha')
# Fetch recaptcha view
captcha = getMultiAdapter((aq_inner(self.context), self.request),
name='recaptcha')
if not captcha.verify():
raise WrongReCaptchaCode
raise WrongCaptchaCode
else:
return True
return True
# Register Captcha validator for the Captcha field in the ICaptcha Form
validator.WidgetValidatorDiscriminators(CaptchaValidator,
field=ICaptcha['captcha'])