Skip to content
Snippets Groups Projects
Commit 66edb46e authored by Felix Chadwick-Smith's avatar Felix Chadwick-Smith
Browse files

Merge branch 'master' into 'main'

Master

See merge request !6
parents f46114b7 130a9582
No related branches found
No related tags found
1 merge request!6Master
File deleted
File deleted
File deleted
File deleted
from wtforms.fields import Field
from . import widgets
from .validators import Recaptcha
__all__ = ["RecaptchaField"]
class RecaptchaField(Field):
widget = widgets.RecaptchaWidget()
# error message if recaptcha validation fails
recaptcha_error = None
def __init__(self, label="", validators=None, **kwargs):
validators = validators or [Recaptcha()]
super().__init__(label, validators, **kwargs)
import json
from urllib import request as http
from urllib.parse import urlencode
from flask import current_app
from flask import request
from wtforms import ValidationError
RECAPTCHA_VERIFY_SERVER_DEFAULT = "https://www.google.com/recaptcha/api/siteverify"
RECAPTCHA_ERROR_CODES = {
"missing-input-secret": "The secret parameter is missing.",
"invalid-input-secret": "The secret parameter is invalid or malformed.",
"missing-input-response": "The response parameter is missing.",
"invalid-input-response": "The response parameter is invalid or malformed.",
}
__all__ = ["Recaptcha"]
class Recaptcha:
"""Validates a ReCaptcha."""
def __init__(self, message=None):
if message is None:
message = RECAPTCHA_ERROR_CODES["missing-input-response"]
self.message = message
def __call__(self, form, field):
if current_app.testing:
return True
if request.is_json:
response = request.json.get("g-recaptcha-response", "")
else:
response = request.form.get("g-recaptcha-response", "")
remote_ip = request.remote_addr
if not response:
raise ValidationError(field.gettext(self.message))
if not self._validate_recaptcha(response, remote_ip):
field.recaptcha_error = "incorrect-captcha-sol"
raise ValidationError(field.gettext(self.message))
def _validate_recaptcha(self, response, remote_addr):
"""Performs the actual validation."""
try:
private_key = current_app.config["RECAPTCHA_PRIVATE_KEY"]
except KeyError:
raise RuntimeError("No RECAPTCHA_PRIVATE_KEY config set") from None
verify_server = current_app.config.get("RECAPTCHA_VERIFY_SERVER")
if not verify_server:
verify_server = RECAPTCHA_VERIFY_SERVER_DEFAULT
data = urlencode(
{"secret": private_key, "remoteip": remote_addr, "response": response}
)
http_response = http.urlopen(verify_server, data.encode("utf-8"))
if http_response.code != 200:
return False
json_resp = json.loads(http_response.read())
if json_resp["success"]:
return True
for error in json_resp.get("error-codes", []):
if error in RECAPTCHA_ERROR_CODES:
raise ValidationError(RECAPTCHA_ERROR_CODES[error])
return False
from urllib.parse import urlencode
from flask import current_app
from markupsafe import Markup
RECAPTCHA_SCRIPT_DEFAULT = "https://www.google.com/recaptcha/api.js"
RECAPTCHA_DIV_CLASS_DEFAULT = "g-recaptcha"
RECAPTCHA_TEMPLATE = """
<script src='%s' async defer></script>
<div class="%s" %s></div>
"""
__all__ = ["RecaptchaWidget"]
class RecaptchaWidget:
def recaptcha_html(self, public_key):
html = current_app.config.get("RECAPTCHA_HTML")
if html:
return Markup(html)
params = current_app.config.get("RECAPTCHA_PARAMETERS")
script = current_app.config.get("RECAPTCHA_SCRIPT")
if not script:
script = RECAPTCHA_SCRIPT_DEFAULT
if params:
script += "?" + urlencode(params)
attrs = current_app.config.get("RECAPTCHA_DATA_ATTRS", {})
attrs["sitekey"] = public_key
snippet = " ".join(f'data-{k}="{attrs[k]}"' for k in attrs) # noqa: B028, B907
div_class = current_app.config.get("RECAPTCHA_DIV_CLASS")
if not div_class:
div_class = RECAPTCHA_DIV_CLASS_DEFAULT
return Markup(RECAPTCHA_TEMPLATE % (script, div_class, snippet))
def __call__(self, field, error=None, **kwargs):
"""Returns the recaptcha input HTML."""
try:
public_key = current_app.config["RECAPTCHA_PUBLIC_KEY"]
except KeyError:
raise RuntimeError("RECAPTCHA_PUBLIC_KEY config not set") from None
return self.recaptcha_html(public_key)
import sys import sys
import logging import logging
from app import app as application from app import app as application
from markupsafe import Markup
sys.modules['flask'].Markup = Markup
logging.basicConfig(stream=sys.stderr) logging.basicConfig(stream=sys.stderr)
if __name__ == '__main__': if __name__ == '__main__':
application.run(host='0.0.0.0', port=int(os.environ.get('PORT', 8080))) application.run(host='0.0.0.0', port=8080)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment