"""Explicit, administrator-controlled service grants for each effective level.""" import re from django.core.exceptions import ImproperlyConfigured from ldap3.core.exceptions import LDAPInvalidDnError from ldap3.utils.dn import parse_dn def validate_service_groups(value, paid_levels): if not isinstance(value, dict): raise ImproperlyConfigured("Membership service groups must be an object mapping levels to lists of LDAP group DNs.") valid_levels = {0, *paid_levels} for level, groups in value.items(): if not isinstance(level, str) or not re.fullmatch(r"0|[1-9][0-9]*", level) or int(level) not in valid_levels: raise ImproperlyConfigured("Service group levels must be 0 or a configured paid membership level.") if not isinstance(groups, list): raise ImproperlyConfigured("Each service group level must contain a list of LDAP group DNs.") seen = set() for dn in groups: if not isinstance(dn, str) or not dn or dn != dn.strip() or len(dn) > 1024 or any(ord(char) < 32 for char in dn): raise ImproperlyConfigured("Service group DNs must be nonempty valid LDAP DNs of at most 1024 characters.") try: parts = parse_dn(dn) except LDAPInvalidDnError: raise ImproperlyConfigured("Invalid LDAP service group DN.") from None if not parts or dn.casefold() in seen: raise ImproperlyConfigured("Service group DNs must be valid and unique within each level.") seen.add(dn.casefold()) return value def configured_groups(tiers, service_groups): """All managed targets, not only the groups this account currently earns.""" return {tier["group_dn"] for tier in tiers.values()} | { dn for groups in service_groups.values() for dn in groups }