forms.py 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import json
  2. from django import forms
  3. from django.core import signing
  4. from django.core.exceptions import ValidationError
  5. from django.utils.encoding import force_str
  6. class SignedDataForm(forms.Form):
  7. """Helper form that wraps a form to validate its contents on post.
  8. class PanelForm(forms.Form):
  9. # fields
  10. On render:
  11. form = SignedDataForm(initial=PanelForm(initial=data).initial)
  12. On POST:
  13. signed_form = SignedDataForm(request.POST)
  14. if signed_form.is_valid():
  15. panel_form = PanelForm(signed_form.verified_data)
  16. if panel_form.is_valid():
  17. # Success
  18. """
  19. salt = "django_debug_toolbar"
  20. signed = forms.CharField(required=True, widget=forms.HiddenInput)
  21. def __init__(self, *args, **kwargs):
  22. initial = kwargs.pop("initial", None)
  23. if initial:
  24. initial = {"signed": self.sign(initial)}
  25. super().__init__(*args, initial=initial, **kwargs)
  26. def clean_signed(self):
  27. try:
  28. verified = json.loads(
  29. signing.Signer(salt=self.salt).unsign(self.cleaned_data["signed"])
  30. )
  31. return verified
  32. except signing.BadSignature:
  33. raise ValidationError("Bad signature")
  34. def verified_data(self):
  35. return self.is_valid() and self.cleaned_data["signed"]
  36. @classmethod
  37. def sign(cls, data):
  38. return signing.Signer(salt=cls.salt).sign(
  39. json.dumps({key: force_str(value) for key, value in data.items()})
  40. )