If you're getting "ImportError: No module named recaptcha", this is
a known issue ticketed at http://code.google.com/p/recaptcha/issues/detail?id=10
. The workaround for now is to svn checkout http://recaptcha.googlecode.com/svn/trunk/recaptcha-plugins/python
&& python setup.py develop. Apologies for not catching this sooner.
Stay tuned for further updates on this issue.
Josh
On Mon, Jul 14, 2008 at 5:29 PM, Joshua Bronson <[EMAIL PROTECTED]>
wrote:
I added recaptcha captchas to the email_link form for non-logged-in
users in r1043. This adds a new dependency on recaptcha-client
(google code project here). This also adds two new configuration
settings, melkjug.recaptcha.public_key (checked in below) and
melkjug.recaptcha.private_key (not checked in for security reasons),
which identifies melkjug.com, the domain I registered, to the
recaptcha servers. I have emailed the private key to a new closed
mailing list I set up, [EMAIL PROTECTED]
According to http://recaptcha.net/apidocs/captcha/client.html,
If one of your servers is "localhost" or "127.0.0.1", reCAPTCHA will
not enforce the same-domain rule. Just use the same key as for the
production server.
so once you add the private key to your development.ini, your
anonymous email_link forms will work locally again.
Josh
---------- Forwarded message ----------
From: <[EMAIL PROTECTED]>
Date: Mon, Jul 14, 2008 at 5:06 PM
Subject: [Melkjug SVN Commits] melkjug r1043 - in melkjug/trunk: .
melkjug/controllers melkjug/lib melkjug/public/javascripts melkjug/
templates/reader
To: [EMAIL PROTECTED]
Author: jab
Date: 2008-07-14 17:06:50 -0400 (Mon, 14 Jul 2008)
New Revision: 1043
Modified:
melkjug/trunk/development.ini
melkjug/trunk/melkjug/controllers/reader.py
melkjug/trunk/melkjug/lib/helpers.py
melkjug/trunk/melkjug/lib/validation.py
melkjug/trunk/melkjug/public/javascripts/melk_widgets.js
melkjug/trunk/melkjug/templates/reader/email_link.mako
melkjug/trunk/setup.py
Log:
add recaptcha captcha to email_link form for non-logged-in users.
the captcha widget could stand to be customized as it's a little
big, but at least it's nicely rigged into the formencode validation.
Modified: melkjug/trunk/development.ini
===================================================================
--- melkjug/trunk/development.ini 2008-07-14 20:48:35 UTC (rev
1042)
+++ melkjug/trunk/development.ini 2008-07-14 21:06:50 UTC (rev
1043)
@@ -47,6 +47,10 @@
melkjug.http_cache = %(here)s/data/http_cache
+## recaptcha keys
+# registered to melkjug.com domain:
+melkjug.recaptcha.public_key =
6LfbdAIAAAAAAKx_MLzSqmCV_5O83p9GUScukAQD
+melkjug.recaptcha.private_key =
## melkjug will send various emails from this name & address:
melkjug.email.from_name = Melkjug
Modified: melkjug/trunk/melkjug/controllers/reader.py
===================================================================
--- melkjug/trunk/melkjug/controllers/reader.py 2008-07-14 20:48:35
UTC (rev 1042)
+++ melkjug/trunk/melkjug/controllers/reader.py 2008-07-14 21:06:50
UTC (rev 1043)
@@ -23,10 +23,11 @@
from melkjug.lib.base import *
from melkjug.lib import backend
from melkjug.lib.itemchoice import choose_items, compute_rating,
get_starred_items, get_read_items
-from melkjug.lib.validation import EmailList
+from melkjug.lib.validation import EmailList, LoggedIn,
RecaptchaResponse
from pylons import session
import formencode
from formencode import Schema, Invalid, htmlfill
+from formencode.compound import Any
from formencode.validators import *
from melkjug.lib import filterui
import traceback
@@ -51,6 +52,7 @@
note = String()
link = String()
title = String()
+ chained_validators = [Any(RecaptchaResponse(), LoggedIn())]
class ReaderController(BaseController):
Modified: melkjug/trunk/melkjug/lib/helpers.py
===================================================================
--- melkjug/trunk/melkjug/lib/helpers.py 2008-07-14 20:48:35
UTC (rev 1042)
+++ melkjug/trunk/melkjug/lib/helpers.py 2008-07-14 21:06:50
UTC (rev 1043)
@@ -34,6 +34,16 @@
from dateutil.tz import tzlocal, tzutc
+def display_captcha():
+ return """
+ <script type="text/javascript" src="http://api.recaptcha.net/js/recaptcha_ajax.js
">
+ </script>
+ <script type="text/javascript">
+ Recaptcha.create('%s', 'recaptcha_div', {theme: 'white'});
+ </script>
+ """ % pylons.config['melkjug.recaptcha.public_key']
+
+
def javascript_include_tag(file, **kw):
if 'melkjug.deploy_timestamp' in config:
kw['dts'] = config['melkjug.deploy_timestamp']
Modified: melkjug/trunk/melkjug/lib/validation.py
===================================================================
--- melkjug/trunk/melkjug/lib/validation.py 2008-07-14 20:48:35
UTC (rev 1042)
+++ melkjug/trunk/melkjug/lib/validation.py 2008-07-14 21:06:50
UTC (rev 1043)
@@ -36,6 +36,8 @@
import pylons
from pylons.decorators import determine_response_charset,
encode_formencode_errors
+from recaptcha.client.captcha import submit as submit_captcha
+
log = logging.getLogger(__name__)
BAD_FILE_CHARS = re.compile(r'[^a-zA-Z0-9\-\_]')
@@ -84,9 +86,42 @@
if re.search(self._pat, value) is not None:
raise Invalid(self.message('invalid', state), value,
state)
+class LoggedIn(FancyValidator):
+ messages = {
+ 'invalid': 'must be logged in'
+ }
+ def __init__(self, *args, **kwargs):
+ FancyValidator.__init__(self, *args, **kwargs)
+
+ def validate_python(self, value, state):
+ if pylons.c.security.is_anonymous():
+ raise Invalid(self.message('invalid', state), value,
state)
+
+class RecaptchaResponse(FormValidator):
+ messages = {
+ 'invalid': 'Please type the words below (case matters!)'
+ }
+ def __init__(self, *args, **kwargs):
+ FancyValidator.__init__(self, *args, **kwargs)
+
+ def validate_python(self, field_dict, state):
+ forwarded_for =
pylons.request.environ.get('HTTP_X_FORWARDED_FOR')
+ if forwarded_for: # we're behind a proxy
+ remote_ip = forwarded_for
+ else:
+ remote_ip = pylons.request.environ['REMOTE_ADDR']
+ private_key = pylons.config['melkjug.recaptcha.private_key']
+ recaptcha_response = submit_captcha(
+ field_dict['recaptcha_challenge_field'],
+ field_dict['recaptcha_response_field'], private_key,
remote_ip)
+ if not recaptcha_response.is_valid:
+ errormsg = self.message('invalid', state)
+ errors = {'recaptcha_marker_field': errormsg}
+ raise Invalid(errormsg, field_dict, state,
error_dict=errors)
+
class EmailList(FancyValidator):
messages = {
- 'invalid': 'must contain a comma-separated list of email
addresses'
+ 'invalid': 'Please enter a comma-separated list of email
addresses.'
}
def __init__(self, sep=',', *args, **kwargs):
FancyValidator.__init__(self, *args, **kwargs)
Modified: melkjug/trunk/melkjug/public/javascripts/melk_widgets.js
===================================================================
--- melkjug/trunk/melkjug/public/javascripts/melk_widgets.js
2008-07-14 20:48:35 UTC (rev 1042)
+++ melkjug/trunk/melkjug/public/javascripts/melk_widgets.js
2008-07-14 21:06:50 UTC (rev 1043)
@@ -224,7 +224,7 @@
var options = {setup_callback: Melk.with_scope(this,
this._setup_dialog),
width: 450,
- height: 400,
+ height: 450,
top: 50};
var cb = {
success: function(response) {
@@ -258,7 +258,7 @@
var options = {setup_callback: Melk.with_scope(this,
this._setup_dialog),
width: 450,
- height: 400,
+ height: 450,
top: 50};
var cb = {
success: function(response) {
Modified: melkjug/trunk/melkjug/templates/reader/email_link.mako
===================================================================
--- melkjug/trunk/melkjug/templates/reader/email_link.mako
2008-07-14 20:48:35 UTC (rev 1042)
+++ melkjug/trunk/melkjug/templates/reader/email_link.mako
2008-07-14 21:06:50 UTC (rev 1043)
@@ -21,7 +21,12 @@
<label for="note">Note (optional)</label>
<textarea name="note" id="note"></textarea>
- ## XXX spam protection???
+ ## display a captcha if the user is not logged in
+ % if c.security.is_anonymous():
+ <input type="hidden" name="recaptcha_marker_field" />
+ ${h.display_captcha()}
+ <div id="recaptcha_div"></div>
+ % endif
<ul class="form-buttons">
<li><a href="#" class="ok-button">Send</a></li>
<li><a href="#" class="cancel-button">Cancel</a></li>
Modified: melkjug/trunk/setup.py
===================================================================
--- melkjug/trunk/setup.py 2008-07-14 20:48:35 UTC (rev 1042)
+++ melkjug/trunk/setup.py 2008-07-14 21:06:50 UTC (rev 1043)
@@ -44,6 +44,7 @@
'minibrain',
'melk.selection',
'BeautifulSoup',
+ 'recaptcha-client',
],
dependency_links=[
"https://svn.openplans.org/melk/eggs/links.html",
--
To unsubscribe send an email with subject "unsubscribe" to [EMAIL PROTECTED]
. Please contact [EMAIL PROTECTED]
for questions.
!DSPAM:4013,487ce43945493668746562!