mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
DNSNameParam parameter
New param type for domain names Part of ticket: IPA should allow internationalized domain names https://fedorahosted.org/freeipa/ticket/3169 Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
committed by
Martin Kosek
parent
9c7b0ad156
commit
64d8da21c6
@@ -886,7 +886,8 @@ from frontend import Command, LocalOrRemote, Updater, Advice
|
|||||||
from frontend import Object, Method
|
from frontend import Object, Method
|
||||||
from crud import Create, Retrieve, Update, Delete, Search
|
from crud import Create, Retrieve, Update, Delete, Search
|
||||||
from parameters import DefaultFrom, Bool, Flag, Int, Decimal, Bytes, Str, IA5Str, Password, DNParam, DeprecatedParam
|
from parameters import DefaultFrom, Bool, Flag, Int, Decimal, Bytes, Str, IA5Str, Password, DNParam, DeprecatedParam
|
||||||
from parameters import BytesEnum, StrEnum, IntEnum, AccessTime, File, DateTime
|
from parameters import (BytesEnum, StrEnum, IntEnum, AccessTime, File,
|
||||||
|
DateTime, DNSNameParam)
|
||||||
from errors import SkipPluginModule
|
from errors import SkipPluginModule
|
||||||
from text import _, ngettext, GettextFactory, NGettextFactory
|
from text import _, ngettext, GettextFactory, NGettextFactory
|
||||||
|
|
||||||
|
|||||||
@@ -114,6 +114,9 @@ from constants import TYPE_ERROR, CALLABLE_ERROR, LDAP_GENERALIZED_TIME_FORMAT
|
|||||||
from text import Gettext, FixMe
|
from text import Gettext, FixMe
|
||||||
from util import json_serialize
|
from util import json_serialize
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
|
from ipapython.dnsutil import DNSName
|
||||||
|
import dns.name
|
||||||
|
import encodings.idna
|
||||||
|
|
||||||
def _is_null(value):
|
def _is_null(value):
|
||||||
return not value and value != 0 # NOTE: False == 0
|
return not value and value != 0 # NOTE: False == 0
|
||||||
@@ -1919,3 +1922,69 @@ def create_param(spec):
|
|||||||
TYPE_ERROR % ('spec', (str, Param), spec, type(spec))
|
TYPE_ERROR % ('spec', (str, Param), spec, type(spec))
|
||||||
)
|
)
|
||||||
return Str(spec)
|
return Str(spec)
|
||||||
|
|
||||||
|
|
||||||
|
class DNSNameParam(Param):
|
||||||
|
"""
|
||||||
|
Domain name parameter type.
|
||||||
|
|
||||||
|
:only_absolute a domain name has to be absolute
|
||||||
|
(makes it absolute from unicode input)
|
||||||
|
:only_relative a domain name has to be relative
|
||||||
|
"""
|
||||||
|
type = DNSName
|
||||||
|
type_error = _('must be DNS name')
|
||||||
|
kwargs = Param.kwargs + (
|
||||||
|
('only_absolute', bool, False),
|
||||||
|
('only_relative', bool, False),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, name, *rules, **kw):
|
||||||
|
super(DNSNameParam, self).__init__(name, *rules, **kw)
|
||||||
|
if self.only_absolute and self.only_relative:
|
||||||
|
raise ValueError('%s: cannot be both absolute and relative' %
|
||||||
|
self.nice)
|
||||||
|
|
||||||
|
def _convert_scalar(self, value, index=None):
|
||||||
|
if isinstance(value, unicode):
|
||||||
|
error = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
domain_name = DNSName(value)
|
||||||
|
except dns.name.BadEscape:
|
||||||
|
error = _('invalid escape code in domain name')
|
||||||
|
except dns.name.EmptyLabel:
|
||||||
|
error = _('empty DNS label')
|
||||||
|
except dns.name.NameTooLong:
|
||||||
|
error = _('domain name cannot be longer than 255 characters')
|
||||||
|
except dns.name.LabelTooLong:
|
||||||
|
error = _('DNS label cannot be longer than 63 characters')
|
||||||
|
except dns.exception.SyntaxError:
|
||||||
|
error = _('invalid domain name')
|
||||||
|
|
||||||
|
#compare if IDN normalized and original domain match
|
||||||
|
#there is N:1 mapping between unicode and IDNA names
|
||||||
|
#user should use normalized names to avoid mistakes
|
||||||
|
normalized_domain_name = encodings.idna.nameprep(value)
|
||||||
|
if value != normalized_domain_name:
|
||||||
|
error = _("domain name '%(domain)s' and normalized domain name"
|
||||||
|
" '%(normalized)s' do not match. Please use only"
|
||||||
|
" normalized domains") % {'domain': value,
|
||||||
|
'normalized': normalized_domain_name}
|
||||||
|
if error:
|
||||||
|
raise ConversionError(name=self.get_param_name(), index=index,
|
||||||
|
error=error)
|
||||||
|
value = domain_name
|
||||||
|
|
||||||
|
if self.only_absolute and not value.is_absolute():
|
||||||
|
value = value.make_absolute()
|
||||||
|
|
||||||
|
return super(DNSNameParam, self)._convert_scalar(value, index)
|
||||||
|
|
||||||
|
def _rule_only_absolute(self, _, value):
|
||||||
|
if self.only_absolute and not value.is_absolute():
|
||||||
|
return _('must be absolute')
|
||||||
|
|
||||||
|
def _rule_only_relative(self, _, value):
|
||||||
|
if self.only_relative and value.is_absolute():
|
||||||
|
return _('must be relative')
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ class IPATypeChecker(TypeChecker):
|
|||||||
'ipalib.parameters.Number': ['minvalue', 'maxvalue'],
|
'ipalib.parameters.Number': ['minvalue', 'maxvalue'],
|
||||||
'ipalib.parameters.Decimal': ['precision', 'exponential',
|
'ipalib.parameters.Decimal': ['precision', 'exponential',
|
||||||
'numberclass'],
|
'numberclass'],
|
||||||
|
'ipalib.parameters.DNSNameParam': ['only_absolute', 'only_relative'],
|
||||||
'ipalib.plugable.API': NAMESPACE_ATTRS + LOGGING_ATTRS,
|
'ipalib.plugable.API': NAMESPACE_ATTRS + LOGGING_ATTRS,
|
||||||
'ipalib.plugable.Plugin': ['api', 'env'] + NAMESPACE_ATTRS +
|
'ipalib.plugable.Plugin': ['api', 'env'] + NAMESPACE_ATTRS +
|
||||||
LOGGING_ATTRS,
|
LOGGING_ATTRS,
|
||||||
|
|||||||
Reference in New Issue
Block a user