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,30 +25,22 @@ from plone.app.discussion.interfaces import IDiscussionSettings, ICaptcha
from plone.app.discussion.browser.validator import CaptchaValidator 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): class Captcha(Persistent):
"""Captcha input field.
"""
interface.implements(ICaptcha) interface.implements(ICaptcha)
adapts(Comment) adapts(Comment)
captcha = u"" captcha = u""
Captcha = factory(Captcha) 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):
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 adapts(Interface, IDefaultBrowserLayer, CommentForm) # context, request, form
fields = Fields(ICaptcha) fields = Fields(ICaptcha)
@ -66,28 +58,12 @@ if HAS_CAPTCHA or HAS_RECAPTCHA:
def update(self): def update(self):
if self.captcha != 'disabled' and self.isAnon: if self.captcha != 'disabled' and self.isAnon:
# Add captcha field if captcha is enabled in the registry # Add a captcha field if captcha is enabled in the registry
self.add(ICaptcha, prefix="") self.add(ICaptcha, prefix="")
if HAS_CAPTCHA and self.captcha == 'captcha': if self.captcha == 'captcha':
# If Captcha is installed and Captcha is enabled, from plone.formwidget.captcha import CaptchaFieldWidget
# use the CaptchaFieldWidget
self.form.fields['captcha'].widgetFactory = CaptchaFieldWidget self.form.fields['captcha'].widgetFactory = CaptchaFieldWidget
elif HAS_RECAPTCHA and self.captcha == 'recaptcha': elif self.captcha == 'recaptcha':
# If ReCaptcha is installed and ReCaptcha is enabled, from plone.formwidget.recaptcha import ReCaptchaFieldWidget
# use the ReCaptchaFieldWidget
self.form.fields['captcha'].widgetFactory = ReCaptchaFieldWidget self.form.fields['captcha'].widgetFactory = ReCaptchaFieldWidget
# Register Captcha validator for the Captcha field in the ICaptcha Form
validator.WidgetValidatorDiscriminators(CaptchaValidator, field=ICaptcha['captcha'])
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 <configure
xmlns="http://namespaces.zope.org/zope" xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser" xmlns:browser="http://namespaces.zope.org/browser"
xmlns:zcml="http://namespaces.zope.org/zcml"
i18n_domain="plone.app.discussion"> i18n_domain="plone.app.discussion">
<include package="plone.app.registry" /> <include package="plone.app.registry" />
@ -81,18 +82,23 @@
/> />
<!-- Comment form extender --> <!-- Comment form extender -->
<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 <adapter
factory=".captcha.Captcha" factory=".captcha.Captcha"
provides="plone.app.discussion.interfaces.ICaptcha" /> provides="plone.app.discussion.interfaces.ICaptcha" />
<adapter <adapter
factory=".captcha.CaptchaExtender" factory=".captcha.CaptchaExtender"
provides="plone.z3cform.fieldsets.interfaces.IFormExtender" /> provides="plone.z3cform.fieldsets.interfaces.IFormExtender" />
<!-- Captcha validator -->
<adapter <adapter
factory=".captcha.CaptchaValidator" factory=".captcha.CaptchaValidator"
/> />
</configure>
<!-- Comment view --> <!-- Comment view -->
<browser:view <browser:view

View File

@ -1,8 +1,4 @@
# Captcha/ReCaptcha validators. We override the standard validators from # -*- coding: utf-8 -*-
# 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.
from Acquisition import aq_inner from Acquisition import aq_inner
@ -14,25 +10,24 @@ from zope.component import getMultiAdapter, provideAdapter, queryUtility
from zope.schema import ValidationError 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.registry.interfaces import IRegistry
from plone.app.discussion.interfaces import IDiscussionSettings, IDiscussionLayer, MessageFactory as _ from plone.app.discussion.interfaces import ICaptcha
from plone.app.discussion.interfaces import IDiscussionSettings
from zope.interface import implements, Interface from plone.app.discussion.interfaces import IDiscussionLayer
from zope.schema.interfaces import IField from plone.app.discussion.interfaces import MessageFactory as _
from zope.component import adapts
try: try:
from plone.formwidget.captcha import CaptchaMessageFactory as _ from plone.formwidget.captcha.validator import WrongCaptchaCode
class WrongCaptchaCode(ValidationError):
__doc__ = _("""The code you entered was wrong, please enter the new one.""")
except: except:
pass pass
try: try:
from plone.formwidget.recaptcha import ReCaptchaMessageFactory as _ from plone.formwidget.recaptcha.validator import WrongCaptchaCode
class WrongReCaptchaCode(ValidationError):
__doc__ = _("""The code you entered was wrong, please enter the new one.""")
except: except:
pass pass
@ -40,6 +35,7 @@ from zope.interface import implements, Interface
from zope.schema.interfaces import IField from zope.schema.interfaces import IField
from zope.component import adapts from zope.component import adapts
class CaptchaValidator(validator.SimpleFieldValidator): class CaptchaValidator(validator.SimpleFieldValidator):
implements(IValidator) implements(IValidator)
adapts(Interface,IDiscussionLayer,Interface,IField,Interface) adapts(Interface,IDiscussionLayer,Interface,IField,Interface)
@ -53,7 +49,8 @@ class CaptchaValidator(validator.SimpleFieldValidator):
if settings.captcha == 'captcha': if settings.captcha == 'captcha':
# Fetch captcha view # 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 value:
if not captcha.verify(value): if not captcha.verify(value):
raise WrongCaptchaCode raise WrongCaptchaCode
@ -61,9 +58,14 @@ class CaptchaValidator(validator.SimpleFieldValidator):
return True return True
raise WrongCaptchaCode raise WrongCaptchaCode
elif settings.captcha == 'recaptcha': elif settings.captcha == 'recaptcha':
# Fetch recatpcha view # Fetch recaptcha view
captcha = getMultiAdapter((aq_inner(self.context), self.request), name='recaptcha') captcha = getMultiAdapter((aq_inner(self.context), self.request),
name='recaptcha')
if not captcha.verify(): if not captcha.verify():
raise WrongReCaptchaCode raise WrongCaptchaCode
else: else:
return True return True
# Register Captcha validator for the Captcha field in the ICaptcha Form
validator.WidgetValidatorDiscriminators(CaptchaValidator,
field=ICaptcha['captcha'])