captcha.py 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. from base64 import b64encode
  2. from captcha.audio import AudioCaptcha
  3. from captcha.image import ImageCaptcha
  4. from rest_framework import serializers
  5. from api import settings
  6. from desecapi.models import Captcha
  7. class CaptchaSerializer(serializers.ModelSerializer):
  8. challenge = serializers.SerializerMethodField()
  9. class Meta:
  10. model = Captcha
  11. fields = (
  12. ("id", "challenge", "kind")
  13. if not settings.DEBUG
  14. else ("id", "challenge", "kind", "content")
  15. )
  16. def get_challenge(self, obj: Captcha):
  17. # TODO Does this need to be stored in the object instance, in case this method gets called twice?
  18. if obj.kind == Captcha.Kind.IMAGE:
  19. challenge = ImageCaptcha().generate(obj.content).getvalue()
  20. elif obj.kind == Captcha.Kind.AUDIO:
  21. challenge = AudioCaptcha().generate(obj.content)
  22. else:
  23. raise ValueError(f"Unknown captcha type {obj.kind}")
  24. return b64encode(challenge)
  25. class CaptchaSolutionSerializer(serializers.Serializer):
  26. id = serializers.PrimaryKeyRelatedField(
  27. queryset=Captcha.objects.all(),
  28. error_messages={"does_not_exist": "CAPTCHA does not exist."},
  29. )
  30. solution = serializers.CharField(write_only=True, required=True)
  31. def validate(self, attrs):
  32. captcha = attrs["id"] # Note that this already is the Captcha object
  33. if not captcha.verify(attrs["solution"]):
  34. raise serializers.ValidationError(
  35. "CAPTCHA could not be validated. Please obtain a new one and try again."
  36. )
  37. return attrs