Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/flask_wtf/recaptcha/validators.py: 29%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

45 statements  

1import json 

2from urllib import request as http 

3from urllib.parse import urlencode 

4 

5from flask import current_app 

6from flask import request 

7from wtforms import ValidationError 

8 

9RECAPTCHA_VERIFY_SERVER_DEFAULT = "https://www.google.com/recaptcha/api/siteverify" 

10RECAPTCHA_ERROR_CODES = { 

11 "missing-input-secret": "The secret parameter is missing.", 

12 "invalid-input-secret": "The secret parameter is invalid or malformed.", 

13 "missing-input-response": "The response parameter is missing.", 

14 "invalid-input-response": "The response parameter is invalid or malformed.", 

15} 

16 

17 

18__all__ = ["Recaptcha"] 

19 

20 

21class Recaptcha: 

22 """Validates a ReCaptcha.""" 

23 

24 def __init__(self, message=None): 

25 if message is None: 

26 message = RECAPTCHA_ERROR_CODES["missing-input-response"] 

27 self.message = message 

28 

29 def __call__(self, form, field): 

30 if current_app.testing: 

31 return True 

32 

33 if request.is_json: 

34 response = request.json.get("g-recaptcha-response", "") 

35 else: 

36 response = request.form.get("g-recaptcha-response", "") 

37 remote_ip = request.remote_addr 

38 

39 if not response: 

40 raise ValidationError(field.gettext(self.message)) 

41 

42 if not self._validate_recaptcha(response, remote_ip): 

43 field.recaptcha_error = "incorrect-captcha-sol" 

44 raise ValidationError(field.gettext(self.message)) 

45 

46 def _validate_recaptcha(self, response, remote_addr): 

47 """Performs the actual validation.""" 

48 try: 

49 private_key = current_app.config["RECAPTCHA_PRIVATE_KEY"] 

50 except KeyError: 

51 raise RuntimeError("No RECAPTCHA_PRIVATE_KEY config set") from None 

52 

53 verify_server = current_app.config.get("RECAPTCHA_VERIFY_SERVER") 

54 if not verify_server: 

55 verify_server = RECAPTCHA_VERIFY_SERVER_DEFAULT 

56 

57 data = urlencode( 

58 {"secret": private_key, "remoteip": remote_addr, "response": response} 

59 ) 

60 

61 http_response = http.urlopen(verify_server, data.encode("utf-8")) 

62 

63 if http_response.code != 200: 

64 return False 

65 

66 json_resp = json.loads(http_response.read()) 

67 

68 if json_resp["success"]: 

69 return True 

70 

71 for error in json_resp.get("error-codes", []): 

72 if error in RECAPTCHA_ERROR_CODES: 

73 raise ValidationError(RECAPTCHA_ERROR_CODES[error]) 

74 

75 return False