Skip to content
This repository has been archived by the owner on Jul 14, 2023. It is now read-only.

Commit

Permalink
removing ajax creation for non gold accounts (#173)
Browse files Browse the repository at this point in the history
* removing ajax creation for non gold accounts
* updating docs and features
* fixing tests
  • Loading branch information
colevscode committed Feb 10, 2018
1 parent 9d394a9 commit d91088e
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 62 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -58,11 +58,11 @@ Add this "honeypot" field to avoid spam by fooling scrapers. If a value is provi

### Using AJAX

You can use Formspree via AJAX. This even works cross-origin. The trick is to set the Accept header to application/json. If you're using jQuery this can be done like so:
Formspree Gold users can submit forms via AJAX. This even works cross-origin. The trick is to set the Accept header to application/json. If you're using jQuery this can be done like so:

```javascript
$.ajax({
url: "https://formspree.io/you@email.com",
url: "https://formspree.io/FORM_ID",
method: "POST",
data: {message: "hello!"},
dataType: "json"
Expand Down
26 changes: 13 additions & 13 deletions formspree/forms/views.py
Expand Up @@ -157,21 +157,21 @@ def send(email_or_string):

# or create it if it doesn't exist
if not form:
if not url_domain(settings.SERVICE_URL) in host:
form = Form(email, host)
else:
if request_wants_json():
# Can't create a new ajax form unless from the dashboard
return jsonerror(400, {'error': "Only Gold accounts may create AJAX forms."})
elif url_domain(settings.SERVICE_URL) in host:
# Bad user is trying to submit a form spoofing formspree.io
# Error out silently
if request_wants_json():
return jsonerror(400, {'error': "Unable to submit form"})
else:
return render_template(
'error.html',
title='Unable to submit form',
text='Sorry'), 400

g.log.info('User attempting to create new form spoofing SERVICE_URL. Ignoring.')
return render_template(
'error.html',
title='Unable to submit form',
text='Sorry'), 400
else:
# all good, create form
form = Form(email, host)

# Check if it has been assigned about using AJAX or not
# Check if it has been assigned using AJAX or not
assign_ajax(form, request_wants_json())

if form.disabled:
Expand Down
48 changes: 24 additions & 24 deletions formspree/templates/static_pages/index.html
Expand Up @@ -81,7 +81,7 @@ <h3>4. All set, receive emails</h3>
<div class="container block">
<div class="col-1-2">
<div class="card">
<h4>Who are you guys?</h4>
<h4>Who are you people?</h4>
<p>We're a community of developers that work together to create products. You can contribute on <a href="https://github.com/formspree/formspree">GitHub</a>. {{config.SERVICE_NAME}} is a project that solves a problem many of us have faced: easily adding forms to otherwise static HTML pages.</p>
</div>
</div>
Expand Down Expand Up @@ -204,21 +204,6 @@ <h4><span class="code">_gotcha</span></h4>
</div>
</div>

<div class="container narrow block">
<div class="col-1-1">
<h4>Using AJAX</h4>
<p>You can use {{config.SERVICE_NAME}} via AJAX. This even works cross-origin. The trick is to set the <span class="code">Accept</span> header to <span class="code">application/json</span>. If you're using jQuery this can be done like so:
<p class="card code">
$.ajax({<br/>
&nbsp;&nbsp;&nbsp;&nbsp;url: "{{config.API_ROOT}}/you@email.com", <br/>
&nbsp;&nbsp;&nbsp;&nbsp;method: "POST",<br />
&nbsp;&nbsp;&nbsp;&nbsp;data: {message: "hello!"},<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="tooltip hint--top" data-hint="Required to set the Accept header">dataType: "json"</span><br />
});
</p>
</div>
</div>

<!--
<div class="container narrow block">
<div class="col-1-1">
Expand Down Expand Up @@ -265,6 +250,29 @@ <h3>Unlimited form submissions</h3>
</div>
</div>

<div class="container narrow block">
<div class="col-1-1">
<h3>Access to submissions archive</h3>
<p>If you ever missed a submission email, for any reason, you can just login and read your last 1000 submissions, all listed and timestamped with full data. Also, the submissions can be exported to CSV or JSON!</p>
<p>It even works for submissions made while you were not a {{ config.UPGRADED_PLAN_NAME }} user (the last 100, in this case).</p>
</div>
</div>

<div class="container narrow block">
<div class="col-1-1">
<h3>AJAX Forms</h3>
<p>{{config.SERVICE_NAME}} {{ config.UPGRADED_PLAN_NAME }} users can use AJAX to submit forms. This even works cross-origin. First create a new form in your account dashboard. Then set the <span class="code">Accept</span> header on your form to <span class="code">application/json</span>. If you're using jQuery this can be done like so:
<p class="card code">
$.ajax({<br/>
&nbsp;&nbsp;&nbsp;&nbsp;url: "{{config.API_ROOT}}/FORM_ID", <br/>
&nbsp;&nbsp;&nbsp;&nbsp;method: "POST",<br />
&nbsp;&nbsp;&nbsp;&nbsp;data: {message: "hello!"},<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class="tooltip hint--top" data-hint="Required to set the Accept header">dataType: "json"</span><br />
});
</p>
</div>
</div>

<div class="container narrow block">
<div class="col-1-1">
<h3>Same form on multiple pages</h3>
Expand All @@ -286,14 +294,6 @@ <h3>Disable reCAPTCHA</h3>
</div>
</div>

<div class="container narrow block">
<div class="col-1-1">
<h3>Access to submissions archive</h3>
<p>If you ever missed a submission email, for any reason, you can just login and read your last 1000 submissions, all listed and timestamped with full data. Also, the submissions can be exported to CSV or JSON!</p>
<p>It even works for submissions made while you were not a {{ config.UPGRADED_PLAN_NAME }} user (the last 100, in this case).</p>
</div>
</div>

</div>

<div class="row section">
Expand Down
1 change: 1 addition & 0 deletions formspree/templates/users/account.html
Expand Up @@ -62,6 +62,7 @@ <h3>Plan</h3>
<li>Unlimited submissions</li>
<li>Access to submission archives</li>
<li>Ability to hide your email from your page's HTML and replace it with a random-like URL</li>
<li>Ability to submit AJAX forms</li>
<li>Ability to create forms linked to other email accounts</li>
</ol>

Expand Down
58 changes: 35 additions & 23 deletions tests/test_form_posts.py
Expand Up @@ -7,12 +7,10 @@

from formspree_test_case import FormspreeTestCase

ajax_headers = {
'Referer': 'testwebsite.com',
'X_REQUESTED_WITH': 'xmlhttprequest'
http_headers = {
'Referer': 'testwebsite.com'
}


class FormPostsTestCase(FormspreeTestCase):

def test_index_page(self):
Expand All @@ -23,7 +21,7 @@ def test_index_page(self):
def test_submit_form(self):
httpretty.register_uri(httpretty.POST, 'https://api.sendgrid.com/api/mail.send.json')
self.client.post('/alice@testwebsite.com',
headers=ajax_headers,
headers=http_headers,
data={'name': 'alice', '_subject': 'my-nice-subject'}
)
self.assertEqual(1, Form.query.count())
Expand All @@ -32,7 +30,7 @@ def test_submit_form(self):

httpretty.register_uri(httpretty.POST, 'https://api.sendgrid.com/api/mail.send.json')
self.client.post('/alice@testwebsite.com',
headers=ajax_headers,
headers=http_headers,
data={'name': 'alice',
'_subject': 'my-nice-subject',
'_format': 'plain'}
Expand All @@ -47,7 +45,7 @@ def test_fail_form_without_header(self):
httpretty.register_uri(httpretty.POST, 'https://api.sendgrid.com/api/mail.send.json')
httpretty.reset()

no_referer = ajax_headers.copy()
no_referer = http_headers.copy()
del no_referer['Referer']
r = self.client.post('/bob@testwebsite.com',
headers = no_referer,
Expand Down Expand Up @@ -93,7 +91,7 @@ def test_fail_but_appears_to_have_succeeded_with_gotcha(self):
self.assertEqual(302, r.status_code)
self.assertEqual(0, Form.query.first().counter)

@httpretty.activate
@httpretty.activate
def test_fail_with_invalid_reply_to(self):
httpretty.register_uri(httpretty.POST, 'https://api.sendgrid.com/api/mail.send.json')

Expand Down Expand Up @@ -128,11 +126,25 @@ def test_fail_with_invalid_reply_to(self):
self.assertEqual(400, r.status_code)
self.assertEqual(0, Form.query.first().counter)

@httpretty.activate
@httpretty.activate
def test_fail_ajax_form(self):
httpretty.register_uri(httpretty.POST, 'https://api.sendgrid.com/api/mail.send.json')
httpretty.reset()

ajax_headers = http_headers.copy()
ajax_headers['X_REQUESTED_WITH'] = 'xmlhttprequest'
r = self.client.post('/bob@example.com',
headers = ajax_headers,
data={'name': 'bob'}
)
self.assertEqual(False, httpretty.has_request())
self.assertNotEqual(200, r.status_code)

@httpretty.activate
def test_activation_workflow(self):
httpretty.register_uri(httpretty.POST, 'https://api.sendgrid.com/api/mail.send.json')
r = self.client.post('/bob@testwebsite.com',
headers=ajax_headers,
headers=http_headers,
data={'name': 'bob'}
)
f = Form.query.first()
Expand All @@ -145,7 +157,7 @@ def test_activation_workflow(self):

# form has another submission, number of forms in the table should increase?
r = self.client.post('/bob@testwebsite.com',
headers=ajax_headers,
headers=http_headers,
data={'name': 'bob'}
)
number_of_forms = Form.query.count()
Expand All @@ -169,7 +181,7 @@ def test_activation_workflow(self):

# a third submission should now increase the counter
r = self.client.post('/bob@testwebsite.com',
headers=ajax_headers,
headers=http_headers,
data={'name': 'bob'}
)
number_of_forms = Form.query.count()
Expand All @@ -190,9 +202,9 @@ def test_monthly_limits(self):
# monthly limit is set to 2 during tests
self.assertEqual(settings.MONTHLY_SUBMISSIONS_LIMIT, 2)

# manually verify luke@testwebsite.com
# manually verify luke@example.com
r = self.client.post('/luke@testwebsite.com',
headers=ajax_headers,
headers=http_headers,
data={'name': 'luke'}
)
f = Form.query.first()
Expand All @@ -204,28 +216,28 @@ def test_monthly_limits(self):
# first submission
httpretty.register_uri(httpretty.POST, 'https://api.sendgrid.com/api/mail.send.json')
r = self.client.post('/luke@testwebsite.com',
headers=ajax_headers,
headers=http_headers,
data={'name': 'peter'}
)
self.assertEqual(r.status_code, 200)
self.assertEqual(r.status_code, 302)
self.assertIn('peter', httpretty.last_request().body)

# second submission
httpretty.register_uri(httpretty.POST, 'https://api.sendgrid.com/api/mail.send.json')
r = self.client.post('/luke@testwebsite.com',
headers=ajax_headers,
headers=http_headers,
data={'name': 'ana'}
)
self.assertEqual(r.status_code, 200)
self.assertEqual(r.status_code, 302)
self.assertIn('ana', httpretty.last_request().body)

# third submission, now we're over the limit
httpretty.register_uri(httpretty.POST, 'https://api.sendgrid.com/api/mail.send.json')
r = self.client.post('/luke@testwebsite.com',
headers=ajax_headers,
headers=http_headers,
data={'name': 'maria'}
)
self.assertEqual(r.status_code, 200) # the response to the user is the same
self.assertEqual(r.status_code, 302) # the response to the user is the same
# being the form over the limits or not

# but the mocked sendgrid should never receive this last form
Expand All @@ -252,17 +264,17 @@ def test_monthly_limits(self):
# the user should receive form posts again
httpretty.register_uri(httpretty.POST, 'https://api.sendgrid.com/api/mail.send.json')
r = self.client.post('/luke@testwebsite.com',
headers=ajax_headers,
headers=http_headers,
data={'name': 'noah'}
)
self.assertEqual(r.status_code, 200)
self.assertEqual(r.status_code, 302)
self.assertIn('noah', httpretty.last_request().body)

@httpretty.activate
def test_first_submission_is_stored(self):
httpretty.register_uri(httpretty.POST, 'https://api.sendgrid.com/api/mail.send.json')
r = self.client.post('/what@firstsubmissed.com',
headers=ajax_headers,
headers=http_headers,
data={'missed': 'this was important'}
)
f = Form.query.first()
Expand Down

0 comments on commit d91088e

Please sign in to comment.