|
@@ -20,7 +20,8 @@ class VPNSubscription(CoinLdapSyncMixin, models.Model):
|
|
|
related_name=backend_name,
|
|
|
validators=[ValidateBackendType(backend_name)])
|
|
|
activated = models.BooleanField(default=False)
|
|
|
- login = models.CharField(max_length=50, unique=True)
|
|
|
+ login = models.CharField(max_length=50, unique=True, blank=True,
|
|
|
+ help_text="leave empty for automatic generation")
|
|
|
password = models.CharField(max_length=256, blank=True, null=True)
|
|
|
ipv4_endpoint = InetAddressField(validators=[validation.validate_v4],
|
|
|
blank=True, null=True)
|
|
@@ -110,6 +111,20 @@ class VPNSubscription(CoinLdapSyncMixin, models.Model):
|
|
|
raise ValidationError("Endpoint {} is not in an attributed range".format(self.ipv6_endpoint))
|
|
|
|
|
|
def clean(self):
|
|
|
+ # Generate VPN login, of the form "user_vpnX"
|
|
|
+ if not self.login:
|
|
|
+ username = self.administrative_subscription.member.ldap_cn
|
|
|
+ vpns = VPNSubscription.objects.filter(administrative_subscription__member__ldap_cn=username)
|
|
|
+ # This is the list of existing VPN logins for this user.
|
|
|
+ logins = [vpn.login for vpn in vpns]
|
|
|
+ # 100 VPNs ought to be enough for anybody.
|
|
|
+ for login in ["{}-vpn{}".format(username, k) for k in range(1, 101)]:
|
|
|
+ if login not in logins:
|
|
|
+ self.login = login
|
|
|
+ break
|
|
|
+ # We may have failed.
|
|
|
+ if not self.login:
|
|
|
+ ValidationError("Unable to allocate a VPN login.")
|
|
|
# Hash password if needed
|
|
|
self.password = utils.ldap_hash(self.password)
|
|
|
# If saving for the first time and IP endpoints are not specified,
|