Browse Source

Add Base64Field field (base64-encoded binary data)

pull/456/head
Pēteris Caune 4 years ago
parent
commit
d0f327b213
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
2 changed files with 44 additions and 32 deletions
  1. +20
    -31
      hc/accounts/forms.py
  2. +24
    -1
      hc/accounts/tests/test_add_credential.py

+ 20
- 31
hc/accounts/forms.py View File

@ -1,7 +1,9 @@
import base64 import base64
import binascii
from datetime import timedelta as td from datetime import timedelta as td
from django import forms from django import forms
from django.core.exceptions import ValidationError
from django.contrib.auth import authenticate from django.contrib.auth import authenticate
from django.contrib.auth.models import User from django.contrib.auth.models import User
from hc.api.models import TokenBucket from hc.api.models import TokenBucket
@ -13,6 +15,17 @@ class LowercaseEmailField(forms.EmailField):
return value.lower() return value.lower()
class Base64Field(forms.CharField):
def to_python(self, value):
if value is None:
return None
try:
return base64.b64decode(value.encode())
except binascii.Error:
raise ValidationError(message="Cannot decode base64")
class AvailableEmailForm(forms.Form): class AvailableEmailForm(forms.Form):
# Call it "identity" instead of "email" # Call it "identity" instead of "email"
# to avoid some of the dumber bots # to avoid some of the dumber bots
@ -109,7 +122,7 @@ class RemoveTeamMemberForm(forms.Form):
class ProjectNameForm(forms.Form): class ProjectNameForm(forms.Form):
name = forms.CharField(max_length=60, required=True)
name = forms.CharField(max_length=60)
class TransferForm(forms.Form): class TransferForm(forms.Form):
@ -118,36 +131,12 @@ class TransferForm(forms.Form):
class AddCredentialForm(forms.Form): class AddCredentialForm(forms.Form):
name = forms.CharField(max_length=100) name = forms.CharField(max_length=100)
client_data_json = forms.CharField(required=True)
attestation_object = forms.CharField(required=True)
def clean_client_data_json(self):
v = self.cleaned_data["client_data_json"]
return base64.b64decode(v.encode())
def clean_attestation_object(self):
v = self.cleaned_data["attestation_object"]
return base64.b64decode(v.encode())
client_data_json = Base64Field()
attestation_object = Base64Field()
class LoginTfaForm(forms.Form): class LoginTfaForm(forms.Form):
credential_id = forms.CharField(required=True)
client_data_json = forms.CharField(required=True)
authenticator_data = forms.CharField(required=True)
signature = forms.CharField(required=True)
def clean_credential_id(self):
v = self.cleaned_data["credential_id"]
return base64.b64decode(v.encode())
def clean_client_data_json(self):
v = self.cleaned_data["client_data_json"]
return base64.b64decode(v.encode())
def clean_authenticator_data(self):
v = self.cleaned_data["authenticator_data"]
return base64.b64decode(v.encode())
def clean_signature(self):
v = self.cleaned_data["signature"]
return base64.b64decode(v.encode())
credential_id = Base64Field()
client_data_json = Base64Field()
authenticator_data = Base64Field()
signature = Base64Field()

+ 24
- 1
hc/accounts/tests/test_add_credential.py View File

@ -52,4 +52,27 @@ class AddCredentialTestCase(BaseTestCase):
c = Credential.objects.get() c = Credential.objects.get()
self.assertEqual(c.name, "My New Key") self.assertEqual(c.name, "My New Key")
# FIXME: test authentication failure
def test_it_rejects_bad_base64(self):
self.client.login(username="[email protected]", password="password")
self._set_sudo_flag()
payload = {
"name": "My New Key",
"client_data_json": "not valid base64",
"attestation_object": "not valid base64",
}
r = self.client.post(self.url, payload)
self.assertEqual(r.status_code, 400)
def test_it_requires_client_data_json(self):
self.client.login(username="[email protected]", password="password")
self._set_sudo_flag()
payload = {
"name": "My New Key",
"attestation_object": "e30=",
}
r = self.client.post(self.url, payload)
self.assertEqual(r.status_code, 400)

Loading…
Cancel
Save