1from urllib.parse import urlencode
2
3from flask import current_app
4from markupsafe import Markup
5
6RECAPTCHA_SCRIPT_DEFAULT = "https://www.google.com/recaptcha/api.js"
7RECAPTCHA_DIV_CLASS_DEFAULT = "g-recaptcha"
8RECAPTCHA_TEMPLATE = """
9<script src='%s' async defer></script>
10<div class="%s" %s></div>
11"""
12
13__all__ = ["RecaptchaWidget"]
14
15
16class RecaptchaWidget:
17 def recaptcha_html(self, public_key):
18 html = current_app.config.get("RECAPTCHA_HTML")
19 if html:
20 return Markup(html)
21 params = current_app.config.get("RECAPTCHA_PARAMETERS")
22 script = current_app.config.get("RECAPTCHA_SCRIPT")
23 if not script:
24 script = RECAPTCHA_SCRIPT_DEFAULT
25 if params:
26 script += "?" + urlencode(params)
27 attrs = current_app.config.get("RECAPTCHA_DATA_ATTRS", {})
28 attrs["sitekey"] = public_key
29 snippet = " ".join(f'data-{k}="{attrs[k]}"' for k in attrs) # noqa: B028, B907
30 div_class = current_app.config.get("RECAPTCHA_DIV_CLASS")
31 if not div_class:
32 div_class = RECAPTCHA_DIV_CLASS_DEFAULT
33 return Markup(RECAPTCHA_TEMPLATE % (script, div_class, snippet))
34
35 def __call__(self, field, error=None, **kwargs):
36 """Returns the recaptcha input HTML."""
37
38 try:
39 public_key = current_app.config["RECAPTCHA_PUBLIC_KEY"]
40 except KeyError:
41 raise RuntimeError("RECAPTCHA_PUBLIC_KEY config not set") from None
42
43 return self.recaptcha_html(public_key)