Skip to content

Commit

Permalink
Merge pull request #566 from CityOfNewYork/johnyu95-recaptcha
Browse files Browse the repository at this point in the history
Updated recaptcha implementation
  • Loading branch information
johnyu95 authored Sep 20, 2023
2 parents faf17ff + 05828c1 commit 6256f55
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 180 deletions.
6 changes: 4 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,10 @@ LDAP_BASE_DN=<LDAP SEARCH BASE>
USE_LOCAL_AUTH=<USE LOCAL AUTHENTICATION>

# ReCaptcha
RECAPTCHA_SITE_KEY_V3=<SITE KEY>
RECAPTCHA_SECRET_KEY_V3=<SECRET KEY>
RECAPTCHA_ENABLED=
RECAPTCHA_PUBLIC_KEY=
RECAPTCHA_PRIVATE_KEY=
RECAPTCHA_THRESHOLD=

# Sentry
SENTRY_DSN=<SENTRY DSN>
Expand Down
152 changes: 0 additions & 152 deletions app/lib/recaptcha_utils.py

This file was deleted.

24 changes: 19 additions & 5 deletions app/main/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"""
from flask import (
current_app,
render_template,
flash,
render_template,
request,
Expand All @@ -18,8 +17,8 @@
from app.lib.db_utils import create_object, update_object
from app.lib.email_utils import send_contact_email
from app.models import Emails, Users
from app.request.forms import TechnicalSupportForm
from . import main
import requests


@main.route('/', methods=['GET', 'POST'])
Expand Down Expand Up @@ -47,9 +46,24 @@ def status():
@main.route('/contact', methods=['GET', 'POST'])
@main.route('/technical-support', methods=['GET', 'POST'])
def technical_support():
form = TechnicalSupportForm()

if request.method == 'POST':
if current_app.config['RECAPTCHA_ENABLED']:
try:
# Verify recaptcha token and return error if failed
recaptcha_response = requests.post(
url='https://www.google.com/recaptcha/api/siteverify?secret={}&response={}'
.format(current_app.config["RECAPTCHA_PRIVATE_KEY"],
request.form["g-recaptcha-response"])).json()

if recaptcha_response['success'] is False or recaptcha_response['score'] < current_app.config[
"RECAPTCHA_THRESHOLD"]:
flash('Recaptcha failed, please try again.', category='danger')
render_template('main/contact.html')
except:
current_app.logger.exception("Recaptcha failed to get a response.")
flash('Recaptcha failed, please try again.', category='danger')
render_template('main/contact.html')

name = request.form.get('name')
email = request.form.get('email')
subject = request.form.get('subject')
Expand Down Expand Up @@ -77,7 +91,7 @@ def technical_support():
else:
flash('Cannot send email.', category='danger')
error_id = request.args.get('error_id', '')
return render_template('main/contact.html', error_id=error_id, form=form)
return render_template('main/contact.html', error_id=error_id)


@main.route('/faq', methods=['GET'])
Expand Down
10 changes: 0 additions & 10 deletions app/request/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
)
from app.lib.db_utils import get_agency_choices
from app.models import Reasons, LetterTemplates, EnvelopeTemplates, CustomRequestForms
from app.lib.recaptcha_utils import Recaptcha3Field


class PublicUserRequestForm(Form):
Expand All @@ -54,8 +53,6 @@ class PublicUserRequestForm(Form):
# File Upload
request_file = FileField("Upload File (optional, must be less than 20 Mb)")

recaptcha = Recaptcha3Field(action="TestAction", execute_on_load=True)

# Submit Button
submit = SubmitField("Submit Request")

Expand Down Expand Up @@ -122,8 +119,6 @@ class AgencyUserRequestForm(Form):
# File Upload
request_file = FileField("Upload File (optional, must be less than 20 Mb)")

recaptcha = Recaptcha3Field(action="TestAction", execute_on_load=True)

# Submit Button
submit = SubmitField("Submit Request")

Expand Down Expand Up @@ -180,7 +175,6 @@ class AnonymousRequestForm(Form):
# File Upload
request_file = FileField("Upload File (optional, must be less than 20 Mb)")

recaptcha = Recaptcha3Field(action="TestAction", execute_on_load=True)
submit = SubmitField("Submit Request")

def __init__(self):
Expand Down Expand Up @@ -529,7 +523,3 @@ def __init__(self, request):
request.requester.notification_email or request.requester.email
)
self.subject.data = "Inquiry about {}".format(request.id)


class TechnicalSupportForm(Form):
recaptcha = Recaptcha3Field(action="TestAction", execute_on_load=True)
32 changes: 32 additions & 0 deletions app/request/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
from app.user_request.utils import get_current_point_of_contact
from app import sentry
import json
import requests


@request.route("/new", methods=["GET", "POST"])
Expand Down Expand Up @@ -97,6 +98,37 @@ def new():
new_request_template = "request/new_request_" + template_suffix

if flask_request.method == "POST":
if current_app.config['RECAPTCHA_ENABLED']:
try:
# Verify recaptcha token and return error if failed
recaptcha_response = requests.post(
url='https://www.google.com/recaptcha/api/siteverify?secret={}&response={}'
.format(current_app.config["RECAPTCHA_PRIVATE_KEY"],
flask_request.form["g-recaptcha-response"])).json()

if recaptcha_response['success'] is False or recaptcha_response['score'] < current_app.config[
"RECAPTCHA_THRESHOLD"]:
flash('Recaptcha failed, please try again.', category='danger')
return render_template(
new_request_template,
form=form,
kiosk_mode=kiosk_mode,
category=category,
agency=agency,
title=title,
)
except:
current_app.logger.exception("Recaptcha failed to get a response.")
flash('Recaptcha failed, please try again.', category='danger')
return render_template(
new_request_template,
form=form,
kiosk_mode=kiosk_mode,
category=category,
agency=agency,
title=title,
)

# validate upload with no request id available
upload_path = None
if form.request_file.data:
Expand Down
14 changes: 14 additions & 0 deletions app/static/js/request/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -842,4 +842,18 @@ function handlePIIModalReview(){
$(window).scrollTop($('#request-title').offset().top - 50);
showPIIWarning = true;
return;
}

/**
* Handles data-callback for submitting new requests when using recaptcha.
*/
function onSubmitRequest(token) {
$("#request-form").submit();
}

/**
* Handles data-callback for submitting technical support emails when using recaptcha.
*/
function onSubmitTechnicalSupport(token) {
$("#contact-info").submit();
}
1 change: 1 addition & 0 deletions app/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
</div>
<script type="text/javascript"
src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
<script type="text/javascript" src="https://www.google.com/recaptcha/api.js"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/plugins/jquery.js') }}"></script>
{{ moment.include_moment(local_js=url_for('static', filename='js/plugins/moment.min.js')) }}
<script type="text/javascript" src="{{ url_for('static', filename='js/plugins/bootstrap.min.js') }}"></script>
Expand Down
15 changes: 13 additions & 2 deletions app/templates/main/contact.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,19 @@ <h1 class="text-center">Technical Support</h1>
<p id="message-character-count" class="character-counter">5000 characters remaining</p>

<br>
{{ form.recaptcha }}
<input id="submit" name="submit" type="submit" value="Send" aria-label="Submit button">
{% if config['RECAPTCHA_ENABLED'] %}
<input id="send"
name="send"
type="submit"
value="Send"
aria-label="Send button"
class="g-recaptcha"
data-sitekey='{{ config['RECAPTCHA_PUBLIC_KEY'] }}'
data-callback='onSubmitTechnicalSupport'
data-action='technicalSupport'>
{% else %}
<input id="send" name="send" type="submit" value="Send" aria-label="Send button">
{% endif %}
</form>
</div>
</div>
Expand Down
14 changes: 12 additions & 2 deletions app/templates/request/new_request_agency.html
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,18 @@ <h3>Address</h3>
placeholder="12345") }}<br>
</div>
<input type="hidden" name="tz-name">
{{ form.recaptcha }}
{{ form.submit(id="submit", class="btn-primary") }}
{% if config['RECAPTCHA_ENABLED'] %}
<input id="submit"
class="g-recaptcha btn-primary"
value="Submit Request"
aria-label="Submit request button"
type="submit"
data-sitekey='{{ config['RECAPTCHA_PUBLIC_KEY'] }}'
data-callback='onSubmitRequest'
data-action='newRequestAgency'>
{% else %}
{{ form.submit(id="submit", class="btn-primary") }}
{% endif %}
{% include "request/_pii_warning_modal.html" %}
<span id="processing-submission" hidden>
<img src="{{ url_for("static", filename="img/loading.gif") }}"
Expand Down
Loading

0 comments on commit 6256f55

Please sign in to comment.