1
0
Parcourir la source

Factor sanity checking for configuration backends

Baptiste Jonglez il y a 11 ans
Parent
commit
5e8abe8376
2 fichiers modifiés avec 30 ajouts et 28 suppressions
  1. 25 0
      coin/offers/backends.py
  2. 5 28
      coin/vpn/models.py

+ 25 - 0
coin/offers/backends.py

@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+from django.core.exceptions import ValidationError
+
+
+def ValidateBackendType(object):
+    """Helper validator for configuration backends.
+
+    It ensures that the related subscription has the right backend
+    type. This is a bit ugly, as validators are not meant for
+    database-level sanity checks, but this is the cost of doing genericity
+    the way we do.
+
+    Note that this validator should not be needed for most cases, as the
+    "limit_choices_to" parameter of the "administrative_subscription"
+    OneToOneField should automatically limit the available choices on
+    forms.  But it does not protect us if we fiddle manually with the
+    database: better safe than sorry.
+    """
+    def __init__(self, backend_name):
+        self.backend = backend_name
+
+    def __call__(self, subscription):
+        if OfferSubscription.objects.get(pk=subscription).offer.backend != self.backend:
+            raise ValidationError('Administrative subscription must have a "{}" backend.'.format(self.backend))

+ 5 - 28
coin/vpn/models.py

@@ -7,41 +7,18 @@ from ldapdb.models.fields import CharField, ListField
 
 
 from coin.models import CoinLdapSyncModel
 from coin.models import CoinLdapSyncModel
 from coin.offers.models import OfferSubscription
 from coin.offers.models import OfferSubscription
+from coin.offers.backends import ValidateBackendType
 from coin import utils
 from coin import utils
 from coin import validation
 from coin import validation
 
 
 
 
-def validate_backend_type(subscription):
-    """Ensures that the subscription we link to has the right backend
-    type. This is a bit ugly, as validators are not meant for
-    database-level sanity checks, but this is the cost of doing genericity
-    the way we do.
-
-    Note that this validator should not be needed for most cases, as the
-    "limit_choices_to" parameter of the "administrative_subscription"
-    OneToOneField automatically limits the available choices on forms.
-    But it does not protect us if we fiddle manually with the database:
-    better safe than sorry.
-
-    """
-    if OfferSubscription.objects.get(pk=subscription).offer.backend != 'openvpn_ldap':
-        raise ValidationError('Administrative subscription must have a "openvpn_ldap" backend.')
-
-
 class VPNSubscription(CoinLdapSyncModel):
 class VPNSubscription(CoinLdapSyncModel):
+    backend_name = "openvpn_ldap"
     administrative_subscription = models.OneToOneField(
     administrative_subscription = models.OneToOneField(
         'offers.OfferSubscription',
         'offers.OfferSubscription',
-        related_name='openvpn_ldap',
-        # Only consider VPN subscriptions.
-        # TODO: also filter out subscriptions that already have a OneToOne
-        # relation.  Simply adding "'openvpn_ldap': None" to the
-        # dictionary does not work well, as it will also remove ourselves
-        # from the list when editing the object in the admin.  Using a Q()
-        # query does not solve the problem, as there is no way to
-        # reference ourselves.  The proper solution would be to create a
-        # custom form.
-        limit_choices_to={'offer__backend': 'openvpn_ldap'},
-        validators=[validate_backend_type])
+        related_name=backend_name,
+        limit_choices_to={'offer__backend': backend_name},
+        validators=[ValidateBackendType(backend_name)])
     activated = models.BooleanField(default=False)
     activated = models.BooleanField(default=False)
     login = models.CharField(max_length=50, unique=True)
     login = models.CharField(max_length=50, unique=True)
     password = models.CharField(max_length=256)
     password = models.CharField(max_length=256)