From 9908093ba536183d4594c87d07f49a471a2c4462 Mon Sep 17 00:00:00 2001
From: Jean-Paul Calderone <exarkun@twistedmatrix.com>
Date: Mon, 2 Mar 2020 14:36:50 -0500
Subject: [PATCH] Some attrs validation helpers for defining the model

---
 src/_zkapauthorizer/model.py | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/_zkapauthorizer/model.py b/src/_zkapauthorizer/model.py
index 52bd98e..50c84cd 100644
--- a/src/_zkapauthorizer/model.py
+++ b/src/_zkapauthorizer/model.py
@@ -27,7 +27,9 @@ from json import (
 from datetime import (
     datetime,
 )
-
+from base64 import (
+    b64decode,
+)
 from zope.interface import (
     Interface,
     implementer,
@@ -606,6 +608,31 @@ class LeaseMaintenanceActivity(object):
 # x = store.get_latest_lease_maintenance_activity()
 # xs.started, xs.passes_required, xs.finished
 
+def is_base64_encoded(b64decode=b64decode):
+    def validate_is_base64_encoded(inst, attr, value):
+        try:
+            b64decode(value.encode("ascii"))
+        except (TypeError, Error):
+            raise TypeError(
+                "{name!r} must be base64 encoded unicode, (got {value!r})".format(
+                    name=attr.name,
+                    value=value,
+                ),
+            )
+    return validate_is_base64_encoded
+
+def has_length(expected):
+    def validate_has_length(inst, attr, value):
+        if len(value) != expected:
+            raise ValueError(
+                "{name!r} must have length {expected}, instead has length {actual}".format(
+                    name=attr.name,
+                    expected=expected,
+                    actual=len(value),
+                ),
+            )
+    return validate_has_length
+
 
 @attr.s(frozen=True)
 class UnblindedToken(object):
-- 
GitLab