52 lines
1.5 KiB
Python
52 lines
1.5 KiB
Python
import json
|
|
|
|
from django import forms
|
|
from django.core import signing
|
|
from django.core.exceptions import ValidationError
|
|
from django.utils.encoding import force_str
|
|
|
|
|
|
class SignedDataForm(forms.Form):
|
|
"""Helper form that wraps a form to validate its contents on post.
|
|
|
|
class PanelForm(forms.Form):
|
|
# fields
|
|
|
|
On render:
|
|
form = SignedDataForm(initial=PanelForm(initial=data).initial)
|
|
|
|
On POST:
|
|
signed_form = SignedDataForm(request.POST)
|
|
if signed_form.is_valid():
|
|
panel_form = PanelForm(signed_form.verified_data)
|
|
if panel_form.is_valid():
|
|
# Success
|
|
"""
|
|
|
|
salt = "django_debug_toolbar"
|
|
signed = forms.CharField(required=True, widget=forms.HiddenInput)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
initial = kwargs.pop("initial", None)
|
|
if initial:
|
|
initial = {"signed": self.sign(initial)}
|
|
super().__init__(*args, initial=initial, **kwargs)
|
|
|
|
def clean_signed(self):
|
|
try:
|
|
verified = json.loads(
|
|
signing.Signer(salt=self.salt).unsign(self.cleaned_data["signed"])
|
|
)
|
|
return verified
|
|
except signing.BadSignature:
|
|
raise ValidationError("Bad signature")
|
|
|
|
def verified_data(self):
|
|
return self.is_valid() and self.cleaned_data["signed"]
|
|
|
|
@classmethod
|
|
def sign(cls, data):
|
|
return signing.Signer(salt=cls.salt).sign(
|
|
json.dumps({key: force_str(value) for key, value in data.items()})
|
|
)
|