captcha.py 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  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 = ('id', 'challenge', 'kind') if not settings.DEBUG else ('id', 'challenge', 'kind', 'content')
  12. def get_challenge(self, obj: Captcha):
  13. # TODO Does this need to be stored in the object instance, in case this method gets called twice?
  14. if obj.kind == Captcha.Kind.IMAGE:
  15. challenge = ImageCaptcha().generate(obj.content).getvalue()
  16. elif obj.kind == Captcha.Kind.AUDIO:
  17. challenge = AudioCaptcha().generate(obj.content)
  18. else:
  19. raise ValueError(f'Unknown captcha type {obj.kind}')
  20. return b64encode(challenge)
  21. class CaptchaSolutionSerializer(serializers.Serializer):
  22. id = serializers.PrimaryKeyRelatedField(
  23. queryset=Captcha.objects.all(),
  24. error_messages={'does_not_exist': 'CAPTCHA does not exist.'}
  25. )
  26. solution = serializers.CharField(write_only=True, required=True)
  27. def validate(self, attrs):
  28. captcha = attrs['id'] # Note that this already is the Captcha object
  29. if not captcha.verify(attrs['solution']):
  30. raise serializers.ValidationError('CAPTCHA could not be validated. Please obtain a new one and try again.')
  31. return attrs