[silva.infrae.contact][Emiliano D'Alterio] Added session managem...
[email protected] Tue, 15 Oct 2013 15:26:10 +0200
| Newsgroups | gmane.comp.web.zope.silva.cvs |
|---|---|
| Message-ID | <[email protected]> |
author: Emiliano D'Alterio
date: Tue Oct 15 15:25:57 2013 +0200
revision: 6:fa0679abc51d in silva.infrae.contact
branch:
details: https://hg.infrae.com/silva.infrae.contact?cmd=changeset;node=fa0679abc51d
modified: src/silva/infrae/contact/contactform.py src/silva/infrae/contact/contactform_templates/contactformtemplate.cpt src/silva/infrae/contact/static/contactform.css
added:
removed:
log: Added session management to fight spam-bots. Changed field names to
be less identifiable. Small changes to CSS and template.
diffstat:
src/silva/infrae/contact/contactform.py | 111 +++++++--
src/silva/infrae/contact/contactform_templates/contactformtemplate.cpt | 10 +-
src/silva/infrae/contact/static/contactform.css | 5 +-
3 files changed, 98 insertions(+), 28 deletions(-)
diffs (230 lines):
diff -r 6749166da5be -r fa0679abc51d src/silva/infrae/contact/contactform.py
--- a/src/silva/infrae/contact/contactform.py Fri Oct 11 19:12:22 2013 +0200
+++ b/src/silva/infrae/contact/contactform.py Tue Oct 15 15:25:57 2013 +0200
@@ -2,9 +2,14 @@
# Copyright (c) 2013 Infrae. All rights reserved.
# $Id$
+
+import uuid
+
from five import grok
from zope import interface, schema
from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
+from zope.traversing.browser import absoluteURL
+from silva.core.cache import store
from zope.publisher.interfaces.browser import IDefaultBrowserLayer
from z3c.schema.email import RFC822MailAddress
from zeam.form import silva as silvaforms
@@ -28,42 +33,56 @@
## Choices available for the subject in the contact form
subjects = SimpleVocabulary([
- SimpleTerm(value='Support Request', token='support',
+ SimpleTerm(value=u'Support Request',
+ token=u'support',
title=u'Professional Support'),
- SimpleTerm(value='Training Request', token='training',
+ SimpleTerm(value=u'Training Request',
+ token=u'training',
title=u'Technical Training'),
- SimpleTerm(value='Question', token='question',
+ SimpleTerm(value=u'Question',
+ token=u'question',
title=u'Ask us a question'),
- SimpleTerm(value='Feedback', token='feedback',
+ SimpleTerm(value=u'Feedback',
+ token=u'feedback',
title=u'Give us your feedback'), ])
class IContactFormFields(interface.Interface):
"""Fields present in the contact form.
"""
+ sid = schema.TextLine(
+ title=u'Sid',
+ required=True)
name = schema.TextLine(
- title=u'Full Name', required=True)
+ title=u'Full Name',
+ required=True)
company = schema.TextLine(
- title=u'Company', required=False)
+ title=u'Company',
+ required=False)
email = RFC822MailAddress(
- title=u'Email', required=True)
+ title=u'Email',
+ required=True)
phone = schema.TextLine(
- title=u'Phone', required=False)
+ title=u'Phone',
+ required=False)
subject = schema.Choice(
- title=u'Message subject', source=subjects, required=False)
+ title=u'Message subject',
+ source=subjects,
+ required=False)
message = schema.Text(
- title=u'Message', required=True)
+ title=u'Message',
+ required=True)
EMAIL_TEMPLATE = u"""
-{subject} from {name}
+{st} from {ne}
-{message}
+{me}
-From: {name}
-Company: {company}
-Email: {email}
-Telephone: {phone}
+From: {ne}
+Company: {cy}
+Email: {el}
+Telephone: {pe}
"""
@@ -85,34 +104,74 @@
grok.context(IViewableObject)
grok.implements(IPublicContactForm)
- label = u'Contact us'
+ label = _(u'Contact us')
+
sent = False
+ expired = False
+ refresh_url = None
+ sstore = None
fields = silvaforms.Fields(IContactFormFields)
+ fields['sid'].htmlAttributes['style'] = 'display: none;'
+ fields['sid'].mode = silvaforms.HIDDEN
+ fields['sid'].ignoreRequest = True
+
fields['name'].htmlAttributes['placeholder'] = _(u'Your full name*')
fields['company'].htmlAttributes['placeholder'] = _(u'Your company name')
fields['email'].htmlAttributes['placeholder'] = _(u'Your email address*')
fields['phone'].htmlAttributes['placeholder'] = _(u'Your phone number')
fields['message'].htmlAttributes['placeholder'] = _(u'Your message to us*')
- @silvaforms.action(u"Send", identifier='contact', accesskey='c')
+ ## Changing "name" attribute to something less understandable by spam-bots.
+ fields['name'].identifier = 'ne' # Name.
+ fields['company'].identifier = 'cy' # Company.
+ fields['email'].identifier = 'el' # Email.
+ fields['phone'].identifier = 'pe' # Phone.
+ fields['subject'].identifier = 'st' # Subject.
+ fields['message'].identifier = 'me' # Message.
+
+ def update(self):
+ need(IContactFormResources)
+ if self.sstore is None:
+ self.sstore = store.SessionStore(self.request)
+
+ return super(ContactForm, self).update()
+
+ def updateWidgets(self):
+ sid = uuid.uuid4()
+ self.sstore.set('sid', sid)
+ self.fields['sid'].defaultValue = sid
+
+ super(ContactForm, self).updateWidgets()
+
+ @silvaforms.action(_(u'Send'), identifier='contact', accesskey='c')
def contact(self):
data, errors = self.extractData()
if errors:
- self.status = u'There are errors, please check again.'
+ self.status = _(u'There are errors, please check again.')
return silvaforms.FAILURE
- msg = EMAIL_TEMPLATE.format(**data.getDictWithDefault())
+ data_dict = data.getDictWithDefault()
+ for key in data_dict:
+ if isinstance(data_dict[key], str):
+ data_dict[key] = unicode(data_dict[key], errors='replace')
- sub = '%s from %s' % (data['subject'], data['name'])
+ sid_sent = data_dict['sid']
+ sid_expected = str(self.sstore.get('sid'))
+
+ if sid_sent != sid_expected:
+ self.status = _(u'Session expired.')
+ self.sent = True
+ self.expired = True
+ self.refresh_url = absoluteURL(self.context, self.request)
+ return silvaforms.FAILURE
+
+ msg = EMAIL_TEMPLATE.format(**data_dict)
+ sub = u'%s from %s' % (data['st'], data['ne'])
sendmail(self.context, msg, mto='[email protected]',
mfrom='[email protected]', subject=sub)
+ self.status = _(u'Thank you for your message.')
self.sent = True
- self.status = _(u'Thank you for your message.')
return silvaforms.SUCCESS
-
- def update(self):
- need(IContactFormResources)
- return super(ContactForm, self).update()
diff -r 6749166da5be -r fa0679abc51d src/silva/infrae/contact/contactform_templates/contactformtemplate.cpt
--- a/src/silva/infrae/contact/contactform_templates/contactformtemplate.cpt Fri Oct 11 19:12:22 2013 +0200
+++ b/src/silva/infrae/contact/contactform_templates/contactformtemplate.cpt Tue Oct 15 15:25:57 2013 +0200
@@ -15,6 +15,12 @@
<p class="form-status"
tal:condition="form.status"
tal:content="form.status">Status</p>
+
+ <p class="form-status">
+ <a tal:condition="form.expired"
+ tal:attributes="href python:'%s#contactus-wrapper' % (form.refresh_url)">Refresh page.
+ </a>
+ </p>
<div class="form-error"
tal:condition="form.errors">
@@ -27,7 +33,7 @@
<div class="fields"
tal:condition="form.fieldWidgets">
<div class="field" tal:repeat="widget form.fieldWidgets">
- <br />
+
<tal:error tal:define="error widget.error"
tal:condition="error">
<span class="field-error"
@@ -36,7 +42,9 @@
</span>
<br />
</tal:error>
+
<tal:widget tal:content="structure widget.render()" />
+
</div>
</div>
diff -r 6749166da5be -r fa0679abc51d src/silva/infrae/contact/static/contactform.css
--- a/src/silva/infrae/contact/static/contactform.css Fri Oct 11 19:12:22 2013 +0200
+++ b/src/silva/infrae/contact/static/contactform.css Tue Oct 15 15:25:57 2013 +0200
@@ -17,7 +17,7 @@
#contactus-wrapper .field {
width: 95%;
- margin: 0 5px;
+ margin: 5px;
}
#contactus-wrapper textarea {
@@ -45,3 +45,6 @@
margin: 0 0.65em;
}
+.form-status a:hover {
+ color: #fff;
+}