Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turnstile implementation and removal of captcha #2502

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ requests = "*"
Django = ">=4.2.14, <5.0"
bagit = "*"
django-registration = "*"
django-simple-captcha = "*"
django-tinymce = "*"
elasticsearch = "<7.14.0"
django-elasticsearch-dsl = "==7.3"
Expand Down
514 changes: 248 additions & 266 deletions Pipfile.lock

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions concordia/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,32 @@ def site_navigation(request):
def maintenance_mode_frontend_available(request):
value = cache.get("maintenance_mode_frontend_available", False)
return {"maintenance_mode_frontend_available": value}


def turnstile_default_settings(request):
"""
Expose turnstile default settings to the default template context
- Cloudflare Turnstile
"""

return {
"TURNSTILE_JS_API_URL": getattr(
settings,
"TURN_JS_API_URL",
"https://challenges.cloudflare.com/turnstile/v0/api.js",
),
"TURNSTILE_VERIFY_URL": getattr(
settings,
"TURNSTILE_VERIFY_URL",
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
),
"TURNSTILE_SITEKEY": getattr(
settings, "TURNSTILE_SITEKEY", "1x00000000000000000000BB"
),
"TURNSTILE_SECRET": getattr(
settings, "TURNSTILE_SECRET", "1x0000000000000000000000000000000AA"
),
"TURNSTILE_TIMEOUT": getattr(settings, "TURNSTILE_TIMEOUT", 5),
"TURNSTILE_DEFAULT_CONFIG": getattr(settings, "TURNSTILE_DEFAULT_CONFIG", {}),
"TURNSTILE_PROXIES": getattr(settings, "TURNSTILE_PROXIES", {}),
}
6 changes: 6 additions & 0 deletions concordia/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from django_registration.forms import RegistrationForm
from django_registration.signals import user_activated

from .turnstile.fields import TurnstileField

User = get_user_model()


Expand Down Expand Up @@ -119,6 +121,10 @@ def __init__(self, *, request, **kwargs):
super().__init__(**kwargs)


class TurnstileForm(forms.Form):
turnstile = TurnstileField()


class ContactUsForm(forms.Form):
referrer = forms.CharField(
label="Referring Page", widget=forms.HiddenInput(), required=False
Expand Down
5 changes: 5 additions & 0 deletions concordia/settings_ecs.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@

DATABASES["default"].update({"PASSWORD": postgres_secret["password"]})

cf_turnstile_secret_json = get_secret("crowd/%s/Turnstile" % ENV_NAME)
cf_turnstile_secret = json.loads(cf_turnstile_secret_json)
TURNSTILE_SITEKEY = cf_turnstile_secret["TurnstileSiteKey"]
TURNSTILE_SECRET = cf_turnstile_secret["TurnstileSecret"]

smtp_secret_json = get_secret("concordia/SMTP")
smtp_secret = json.loads(smtp_secret_json)
EMAIL_HOST = smtp_secret["Hostname"]
Expand Down
16 changes: 16 additions & 0 deletions concordia/settings_local_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

from .settings_template import * # NOQA ignore=F405
from .settings_template import DATABASES

Expand All @@ -21,3 +23,17 @@
"CONFIG": {"hosts": [("localhost", 63791)]},
}
}

# Turnstile settings
TURNSTILE_JS_API_URL = os.environ.get(
"TURNSTILE_JS_API_URL", "https://challenges.cloudflare.com/turnstile/v0/api.js"
)
TURNSTILE_VERIFY_URL = os.environ.get(
"TURNSTILE_VERIFY_URL", "https://challenges.cloudflare.com/turnstile/v0/siteverify"
)
TURNSTILE_SITEKEY = os.environ.get(
"TURNSTILE_SITEKEY", "1x00000000000000000000BB"
) # Always pass, invisible
TURNSTILE_SECRET = os.environ.get(
"TURNSTILE_SECRET", "1x0000000000000000000000000000000AA"
) # Always pass
16 changes: 9 additions & 7 deletions concordia/settings_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@
"concordia.apps.ConcordiaAppConfig",
"exporter",
"importer",
"captcha",
"prometheus_metrics.apps.PrometheusMetricsConfig",
"robots",
"django_celery_beat",
Expand Down Expand Up @@ -161,6 +160,7 @@
"concordia.context_processors.system_configuration",
"concordia.context_processors.site_navigation",
"concordia.context_processors.maintenance_mode_frontend_available",
"concordia.context_processors.turnstile_default_settings",
],
"libraries": {
"staticfiles": "django.templatetags.static",
Expand Down Expand Up @@ -317,12 +317,14 @@
"concordia.authentication_backends.EmailOrUsernameModelBackend"
]

CAPTCHA_CHALLENGE_FUNCT = "captcha.helpers.random_char_challenge"
#: Anonymous sessions require captcha validation every day by default:
ANONYMOUS_CAPTCHA_VALIDATION_INTERVAL = 86400

CAPTCHA_IMAGE_SIZE = [150, 100]
CAPTCHA_FONT_SIZE = 40
# Turnstile settings
TURNSTILE_JS_API_URL = os.environ.get("TURNSTILE_JS_API_URL", "")
TURNSTILE_VERIFY_URL = os.environ.get("TURNSTILE_VERIFY_URL", "")
TURNSTILE_SITEKEY = os.environ.get("TURNSTILE_SITEKEY", "")
TURNSTILE_SECRET = os.environ.get("TURNSTILE_SECRET", "")
TURNSTILE_TIMEOUT = os.environ.get("TURNSTILE_TIMEOUT", 5)
TURNSTILE_DEFAULT_CONFIG = os.environ.get("TURNSTILE_DEFAULT_CONFIG", {})
TURNSTILE_PROXIES = os.environ.get("TURNSTILE_PROXIES", {})

STORAGES = {
"default": {
Expand Down
16 changes: 16 additions & 0 deletions concordia/settings_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

from .settings_template import * # NOQA ignore=F405
from .settings_template import DATABASES

Expand All @@ -21,3 +23,17 @@
"CONFIG": {"hosts": [("localhost", 6379)]},
}
}

# Turnstile settings
TURNSTILE_JS_API_URL = os.environ.get(
"TURNSTILE_JS_API_URL", "https://challenges.cloudflare.com/turnstile/v0/api.js"
)
TURNSTILE_VERIFY_URL = os.environ.get(
"TURNSTILE_VERIFY_URL", "https://challenges.cloudflare.com/turnstile/v0/siteverify"
)
TURNSTILE_SITEKEY = os.environ.get(
"TURNSTILE_SITEKEY", "1x00000000000000000000BB"
) # Always pass, invisible
TURNSTILE_SECRET = os.environ.get(
"TURNSTILE_SECRET", "1x0000000000000000000000000000000AA"
) # Always pass
70 changes: 15 additions & 55 deletions concordia/static/js/src/contribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,40 +60,6 @@ $(document).on('keydown', function (event) {
});

function setupPage() {
var $captchaModal = $('#captcha-modal');
var $triggeringCaptchaForm = false;
var $captchaForm = $captchaModal
.find('form')
.on('submit', function (event) {
event.preventDefault();

var formData = $captchaForm.serializeArray();

$.ajax({
url: $captchaForm.attr('action'),
method: 'POST',
dataType: 'json',
data: $.param(formData),
})
.done(function () {
$captchaModal.modal('hide');
if ($triggeringCaptchaForm) {
$triggeringCaptchaForm.submit();
}
$triggeringCaptchaForm = false;
})
.fail(function (jqXHR) {
if (jqXHR.status == 401) {
$captchaModal
.find('[name=key]')
.val(jqXHR.responseJSON.key);
$captchaModal
.find('#captcha-image')
.attr('src', jqXHR.responseJSON.image);
}
});
});

$('form.ajax-submission').each(function (index, formElement) {
/*
Generic AJAX submission logic which takes a form and POSTs its data to the
Expand Down Expand Up @@ -147,27 +113,16 @@ function setupPage() {
}
})
.fail(function (jqXHR, textStatus, errorThrown) {
if (jqXHR.status == 401) {
$captchaModal
.find('[name=key]')
.val(jqXHR.responseJSON.key);
$captchaModal
.find('#captcha-image')
.attr('src', jqXHR.responseJSON.image);
$triggeringCaptchaForm = $form;
$captchaModal.modal();
} else {
$form.trigger('form-submit-failure', {
textStatus: textStatus,
errorThrown: errorThrown,
requestData: formData,
$form: $form,
jqXHR: jqXHR,
});
unlockControls($form);
if (eventData.lockElement) {
unlockControls($(eventData.lockElement));
}
$form.trigger('form-submit-failure', {
textStatus: textStatus,
errorThrown: errorThrown,
requestData: formData,
$form: $form,
jqXHR: jqXHR,
});
unlockControls($form);
if (eventData.lockElement) {
unlockControls($(eventData.lockElement));
}
});

Expand Down Expand Up @@ -515,6 +470,11 @@ function setupPage() {
url: url,
method: 'POST',
dataType: 'json',
data: {
'cf-turnstile-response': $transcriptionEditor
.find('input[name="cf-turnstile-response"]')
.val(),
},
})
.done(function (responseData) {
displayMessage(
Expand Down
1 change: 1 addition & 0 deletions concordia/templates/forms/widgets/turnstile_widget.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div class="cf-turnstile" {% include "django/forms/widgets/attrs.html" %}></div>
2 changes: 2 additions & 0 deletions concordia/templates/registration/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
{% block head_content %}
<meta name="robots" content="noindex">
{{ block.super }}
<script module src="{{ TURNSTILE_JS_API_URL }}"></script>
{% endblock head_content %}

{% block title %}Login{% endblock title %}
Expand All @@ -23,6 +24,7 @@ <h2 id="dialog-title" class="text-center">Welcome back!</h2>
{% endif %}

{% bootstrap_form form %}
<div class="w-100 text-center mt-0 mb-3">{{ turnstile_form.turnstile }}</div>
<p>
By using this system, you agree to comply with
<a href="https://www.loc.gov/legal/" target="_blank">the Library's
Expand Down
4 changes: 1 addition & 3 deletions concordia/templates/transcriptions/asset_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
</script>
<script module src="{% static 'openseadragon/build/openseadragon/openseadragon.min.js' %}"></script>
<script module src="{% static 'openseadragon-filtering/openseadragon-filtering.js' %}"></script>
<script module src="{{ TURNSTILE_JS_API_URL }}"></script>

<script type="module" src="{% static 'js/contribute.js' %}"></script>
<script type="module" src="{% static 'js/viewer-split.js' %}"></script>
Expand Down Expand Up @@ -115,9 +116,6 @@
<div id="review-accepted-modal" class="modal" tabindex="-1" role="dialog">
{% include "transcriptions/asset_detail/review_accepted_modal.html" %}
</div>
<div id="captcha-modal" class="modal" tabindex="-1" role="alertdialog" aria-labeledby="captcha-modal-title" aria-describedby="captcha-modal-description">
{% include "transcriptions/asset_detail/captcha_modal.html" %}
</div>
<div id="ocr-transcription-modal" class="modal" tabindex="-1" role="dialog">
{% include "transcriptions/asset_detail/ocr_transcription_modal.html" %}
</div>
Expand Down
38 changes: 0 additions & 38 deletions concordia/templates/transcriptions/asset_detail/captcha_modal.html

This file was deleted.

2 changes: 2 additions & 0 deletions concordia/templates/transcriptions/asset_detail/editor.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ <h2 id="message-contributors" {% if transcription_status == 'not_started' %}hidd
</a>
</div>

<div class="w-100 text-center mt-0 mb-3">{{ turnstile_form.turnstile }}</div>

<button id="save-transcription-button" disabled type="submit" class="btn btn-primary mx-1" title="Save the text you entered above">
Save
</button>
Expand Down
Loading
Loading