View | Details | Raw Unified | Return to bug 30991 | Differences between
and this patch

Collapse All | Expand All

(-)univention-management-console-module-udm/umc/python/udm/udm_ldap.py (-42 / +110 lines)
 Lines 407-413    Link Here 
407
			raise UDM_Error( get_exception_msg(e) )
407
			raise UDM_Error( get_exception_msg(e) )
408
408
409
	@LDAP_Connection
409
	@LDAP_Connection
410
	def search( self, container = None, attribute = None, value = None, superordinate = None, scope = 'sub', filter = '', ldap_connection = None, ldap_position = None ):
410
	def search( self, container = None, attribute = None, value = None, superordinate = None, scope = 'sub', filter = '', simple = False, simple_attrs = None, ldap_connection = None, ldap_position = None ):
411
		"""Searches for LDAP objects based on a search pattern"""
411
		"""Searches for LDAP objects based on a search pattern"""
412
		if container == 'all':
412
		if container == 'all':
413
			container = ldap_position.getBase()
413
			container = ldap_position.getBase()
 Lines 421-427    Link Here 
421
		result = None
421
		result = None
422
		try:
422
		try:
423
			sizelimit = int(ucr.get('directory/manager/web/sizelimit', '2000'))
423
			sizelimit = int(ucr.get('directory/manager/web/sizelimit', '2000'))
424
			result = self.module.lookup( None, ldap_connection, filter_s, base = container, superordinate = superordinate, scope = scope, sizelimit = sizelimit )
424
			if simple:
425
				object_type_filter = 'univentionObjectType=%s' % self.module.module
426
				if filter:
427
					if not filter.startswith('('):
428
						filter = '(%s)' % filter
429
					object_type_filter = '(&(%s)%s)' % (object_type_filter, filter)
430
				if simple_attrs is not None:
431
					result = ldap_connection.search( filter = object_type_filter, base = container, scope = scope, sizelimit = sizelimit, attr = simple_attrs )
432
				else:
433
					result = ldap_connection.searchDn( filter = object_type_filter, base = container, scope = scope, sizelimit = sizelimit )
434
			else:
435
				result = self.module.lookup( None, ldap_connection, filter_s, base = container, superordinate = superordinate, scope = scope, sizelimit = sizelimit )
425
		except udm_errors.insufficientInformation, e:
436
		except udm_errors.insufficientInformation, e:
426
			return []
437
			return []
427
		except udm_errors.ldapTimeout, e:
438
		except udm_errors.ldapTimeout, e:
 Lines 1004-1010    Link Here 
1004
		filter_s = '(&%s%s)' % (property_filter_s, filter_s)
1015
		filter_s = '(&%s%s)' % (property_filter_s, filter_s)
1005
	return filter_s
1016
	return filter_s
1006
1017
1007
LDAP_ATTR_RE = re.compile(r'^%\(([^(]*)\)s$') # '%(username)s' -> 'username'
1018
LDAP_ATTR_RE = re.compile(r'^%\(([^)]*)\)s$') # '%(username)s' -> 'username'
1008
def _get_syntax( syntax_name ):
1019
def _get_syntax( syntax_name ):
1009
	if syntax_name not in udm_syntax.__dict__:
1020
	if syntax_name not in udm_syntax.__dict__:
1010
		return None
1021
		return None
 Lines 1051-1057    Link Here 
1051
			filter_s = _create_ldap_filter( syn, options, module )
1062
			filter_s = _create_ldap_filter( syn, options, module )
1052
			if filter_s is not None:
1063
			if filter_s is not None:
1053
				try:
1064
				try:
1054
					size += len( module.search( filter = filter_s ) )
1065
					size += len( module.search( filter = filter_s, simple=True ) )
1055
				except udm_errors.ldapSizelimitExceeded:
1066
				except udm_errors.ldapSizelimitExceeded:
1056
					return {'performs_well' : True, 'size_limit_exceeded' : True}
1067
					return {'performs_well' : True, 'size_limit_exceeded' : True}
1057
		return {'size' : size, 'performs_well' : True }
1068
		return {'size' : size, 'performs_well' : True }
 Lines 1065-1110    Link Here 
1065
1076
1066
	if issubclass( syn.__class__, udm_syntax.UDM_Objects ):
1077
	if issubclass( syn.__class__, udm_syntax.UDM_Objects ):
1067
		syn.choices = []
1078
		syn.choices = []
1068
		def map_choices( obj_list ):
1079
		# try to avoid using the slow udm interface
1069
			result = []
1080
		simple = False
1070
			for obj in obj_list:
1081
		attr = []
1071
				obj.open()
1082
		if not syn.always_use_objects and not syn.udm_filter:
1083
			attr.extend(re.findall(r'%\(([^)]+)\)', syn.key))
1084
			if syn.label:
1085
				attr.extend(re.findall(r'%\(([^)]+)\)', syn.label))
1086
			attr = set(attr)
1087
			for udm_module in syn.udm_modules:
1088
				module = UDM_Module( udm_module )
1089
				if module is not None:
1090
					mapping = module.module.mapping
1091
					if not all([mapping.mapName(att) for att in attr]):
1092
						break
1093
			else:
1094
				simple = True
1095
		def extract_key_label(syn, dn, info):
1096
			key = label = None
1097
			if syn.key == 'dn':
1098
				key = dn
1099
			else:
1100
				try:
1101
					key = syn.key % info
1102
				except KeyError:
1103
					pass
1104
			if syn.label == 'dn':
1105
				label = dn
1106
			elif syn.label is None:
1107
				pass
1108
			else:
1109
				try:
1110
					label = syn.label % info
1111
				except KeyError:
1112
					pass
1113
			return key, label
1114
		if not simple:
1115
			def map_choices( obj_list ):
1116
				result = []
1117
				for obj in obj_list:
1118
					# first try it without obj.open() (expensive)
1119
					key, label = extract_key_label(syn, obj.dn, obj.info)
1120
					if key is None or label is None:
1121
						obj.open()
1122
						key, label = extract_key_label(syn, obj.dn, obj.info)
1123
						if key is None:
1124
							# ignore the entry as the key is important for a selection, there
1125
							# is no sensible fallback for the key (Bug #26994)
1126
							continue
1127
						if label is None:
1128
							# fallback to the default description as this is just what displayed
1129
							# to the user (Bug #26994)
1130
							label = udm_objects.description( obj )
1131
					result.append( (key, label) )
1132
				return result
1072
1133
1073
				if syn.key == 'dn':
1134
			for udm_module in syn.udm_modules:
1074
					key = obj.dn
1135
				module = UDM_Module( udm_module )
1136
				if module is None:
1137
					continue
1138
				filter_s = _create_ldap_filter( syn, options, module )
1139
				if filter_s is None:
1140
					syn.choices = []
1075
				else:
1141
				else:
1076
					try:
1142
					search_options = {'filter' : filter_s}
1077
						key = syn.key % obj.info
1143
					search_options.update(module_search_options)
1078
					except KeyError:
1144
					syn.choices.extend( map_choices( module.search( **search_options ) ) )
1079
						# ignore the entry as the key is important for a selection, there
1145
		else:
1080
						# is no sensible fallback for the key (Bug #26994)
1146
			for udm_module in syn.udm_modules:
1081
						continue
1147
				module = UDM_Module( udm_module )
1082
				if syn.label is None:
1148
				if module is None:
1083
					label = udm_objects.description( obj )
1149
					continue
1084
				elif syn.label == 'dn':
1150
				filter_s = _create_ldap_filter( syn, options, module )
1085
					label = obj.dn
1151
				if filter_s is not None:
1086
				else:
1152
					if filter_s and not filter_s.startswith('('):
1087
					try:
1153
						filter_s = '(%s)' % filter_s
1088
						label = syn.label % obj.info
1154
					mapping = module.module.mapping
1089
					except KeyError:
1155
					ldap_attr = [mapping.mapName(att) for att in attr]
1090
						# fallback to the default description as this is just what displayed
1156
					search_options = {'filter' : filter_s, 'simple' : True}
1091
						# to the user (Bug #26994)
1157
					search_options.update(module_search_options)
1092
						label = udm_objects.description( obj )
1158
					if ldap_attr:
1093
1159
						search_options['simple_attrs'] = ldap_attr
1094
				result.append( (key, label) )
1160
						result = module.search( **search_options )
1095
			return result
1161
						for dn, ldap_map in result:
1096
1162
							info = univention.admin.mapping.mapDict(mapping, ldap_map)
1097
		for udm_module in syn.udm_modules:
1163
							key, label = extract_key_label(syn, dn, info)
1098
			module = UDM_Module( udm_module )
1164
							if key is None:
1099
			if module is None:
1165
								continue
1100
				continue
1166
							if label is None:
1101
			filter_s = _create_ldap_filter( syn, options, module )
1167
								label = ldap_connection.explodeDn(dn, 1)[0]
1102
			if filter_s is None:
1168
							syn.choices.append((key, label))
1103
				syn.choices = []
1169
					else:
1104
			else:
1170
						keys = module.search( **search_options )
1105
				search_options = {'filter' : filter_s}
1171
						if syn.label == 'dn':
1106
				search_options.update(module_search_options)
1172
							labels = keys
1107
				syn.choices.extend( map_choices( module.search( **search_options ) ) )
1173
						else:
1174
							labels = [ldap_connection.explodeDn(dn, 1)[0] for dn in keys]
1175
						syn.choices.extend(zip(keys, labels))
1108
		if isinstance( syn.static_values, ( tuple, list ) ):
1176
		if isinstance( syn.static_values, ( tuple, list ) ):
1109
			for value in syn.static_values:
1177
			for value in syn.static_values:
1110
				syn.choices.insert( 0, value )
1178
				syn.choices.insert( 0, value )
(-)univention-directory-manager-modules/modules/univention/admin/syntax.py (-6 / +8 lines)
 Lines 274-279    Link Here 
274
	depends = None
274
	depends = None
275
	error_message = _( "Not a valid LDAP DN" )
275
	error_message = _( "Not a valid LDAP DN" )
276
	simple = False # by default a MultiObjectSelect widget is used; if simple == True a ComboBox is used
276
	simple = False # by default a MultiObjectSelect widget is used; if simple == True a ComboBox is used
277
	always_use_objects = False
277
278
278
	@classmethod
279
	@classmethod
279
	def parse( self, text ):
280
	def parse( self, text ):
 Lines 1210-1216    Link Here 
1210
1211
1211
class LDAP_Server( UDM_Objects ):
1212
class LDAP_Server( UDM_Objects ):
1212
	udm_modules = ( 'computers/domaincontroller_master', 'computers/domaincontroller_backup', 'computers/domaincontroller_slave' )
1213
	udm_modules = ( 'computers/domaincontroller_master', 'computers/domaincontroller_backup', 'computers/domaincontroller_slave' )
1213
	label = '%(fqdn)s'
1214
	label = '%(name)s.%(domain)s' # ldap-optimized '%(fqdn)s'
1214
	simple = True
1215
	simple = True
1215
1216
1216
class IMAP_POP3( select ):
1217
class IMAP_POP3( select ):
 Lines 1609-1614    Link Here 
1609
1610
1610
class HostDN( UDM_Objects ):
1611
class HostDN( UDM_Objects ):
1611
	udm_modules = ( 'computers/computer', )
1612
	udm_modules = ( 'computers/computer', )
1613
	always_use_objects = True
1612
1614
1613
class UserID( UDM_Objects ):
1615
class UserID( UDM_Objects ):
1614
	udm_modules = ( 'users/user', )
1616
	udm_modules = ( 'users/user', )
 Lines 1626-1633    Link Here 
1626
1628
1627
class IComputer_FQDN( UDM_Objects ):
1629
class IComputer_FQDN( UDM_Objects ):
1628
	udm_modules = ()
1630
	udm_modules = ()
1629
	key = '%(fqdn)s'
1631
	key = '%(name)s.%(domain)s' # ldap-optimized '%(fqdn)s'
1630
	label = '%(fqdn)s'
1632
	label = '%(name)s.%(domain)s' # ldap-optimized '%(fqdn)s'
1631
	regex = re.compile( '(?=^.{1,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z0-9]{2,})$)' ) #'(^[a-zA-Z])(([a-zA-Z0-9-_]*)([a-zA-Z0-9]$))?$' )
1633
	regex = re.compile( '(?=^.{1,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z0-9]{2,})$)' ) #'(^[a-zA-Z])(([a-zA-Z0-9-_]*)([a-zA-Z0-9]$))?$' )
1632
	error_message = _( 'Not a valid FQDN' )
1634
	error_message = _( 'Not a valid FQDN' )
1633
	simple = True
1635
	simple = True
 Lines 1693-1698    Link Here 
1693
class DNS_ReverseZone( UDM_Objects ):
1695
class DNS_ReverseZone( UDM_Objects ):
1694
 	description=_('DNS reverse zone')
1696
 	description=_('DNS reverse zone')
1695
	udm_modules = ( 'dns/reverse_zone', )
1697
	udm_modules = ( 'dns/reverse_zone', )
1698
	label = '%(subnet)s'
1696
	empty_value = True
1699
	empty_value = True
1697
	size = 'TwoThirds'
1700
	size = 'TwoThirds'
1698
1701
 Lines 1717-1723    Link Here 
1717
class dhcpService( UDM_Objects ):
1720
class dhcpService( UDM_Objects ):
1718
	udm_modules = ( 'dhcp/service', )
1721
	udm_modules = ( 'dhcp/service', )
1719
	description=_('DHCP service')
1722
	description=_('DHCP service')
1720
	label = '%(name)s'
1721
	empty_value = True
1723
	empty_value = True
1722
	size = 'TwoThirds'
1724
	size = 'TwoThirds'
1723
1725
 Lines 2435-2440    Link Here 
2435
class nagiosHostsEnabledDn( UDM_Objects ):
2437
class nagiosHostsEnabledDn( UDM_Objects ):
2436
	udm_modules = ( 'computers/computer', )
2438
	udm_modules = ( 'computers/computer', )
2437
	udm_filter = '(&(objectClass=univentionNagiosHostClass)(univentionNagiosEnabled=1)(aRecord=*))'
2439
	udm_filter = '(&(objectClass=univentionNagiosHostClass)(univentionNagiosEnabled=1)(aRecord=*))'
2440
	always_use_objects = True
2438
2441
2439
class nagiosServiceDn( UDM_Objects ):
2442
class nagiosServiceDn( UDM_Objects ):
2440
	udm_modules = ( 'nagios/service', )
2443
	udm_modules = ( 'nagios/service', )
 Lines 2550-2557    Link Here 
2550
2553
2551
class nfsShare(UDM_Objects):
2554
class nfsShare(UDM_Objects):
2552
	udm_modules = ( 'shares/share', )
2555
	udm_modules = ( 'shares/share', )
2553
	key = 'dn'
2556
	label = '%(name)s (%(host)s)' # '%(printablename)s' optimized for performance...
2554
	label = '%(printablename)s'
2555
	udm_filter = 'objectClass=univentionShareNFS'
2557
	udm_filter = 'objectClass=univentionShareNFS'
2556
2558
2557
class nfsMounts(complex):
2559
class nfsMounts(complex):
(-)univention-directory-manager-modules/modules/univention/admin/handlers/groups/group.py (-2 / +1 lines)
 Lines 260-265    Link Here 
260
260
261
mapping=univention.admin.mapping.mapping()
261
mapping=univention.admin.mapping.mapping()
262
mapping.register('name', 'cn', None, univention.admin.mapping.ListToString)
262
mapping.register('name', 'cn', None, univention.admin.mapping.ListToString)
263
mapping.register('gidNumber', 'gidNumber', None, univention.admin.mapping.ListToString)
263
mapping.register('description', 'description', None, univention.admin.mapping.ListToString)
264
mapping.register('description', 'description', None, univention.admin.mapping.ListToString)
264
mapping.register('sambaGroupType', 'sambaGroupType', None, univention.admin.mapping.ListToString)
265
mapping.register('sambaGroupType', 'sambaGroupType', None, univention.admin.mapping.ListToString)
265
mapping.register('mailAddress', 'mailPrimaryAddress', None, univention.admin.mapping.ListToString)
266
mapping.register('mailAddress', 'mailPrimaryAddress', None, univention.admin.mapping.ListToString)
 Lines 373-380    Link Here 
373
		else:
374
		else:
374
			self._define_options( options )
375
			self._define_options( options )
375
376
376
		self.info['gidNumber'] = self.oldattr.get('gidNumber', [''])[0]
377
378
		if 'samba' in self.options:
377
		if 'samba' in self.options:
379
			sid = self.oldattr.get('sambaSID', [''])[0]
378
			sid = self.oldattr.get('sambaSID', [''])[0]
380
			pos = sid.rfind('-')
379
			pos = sid.rfind('-')
(-)univention-directory-manager-modules/modules/univention/admin/handlers/shares/share.py (-1 / +5 lines)
 Lines 827-832    Link Here 
827
			if 'univentionShareNFS' in self.oldattr['objectClass']:
827
			if 'univentionShareNFS' in self.oldattr['objectClass']:
828
				self.options.append( 'nfs' )
828
				self.options.append( 'nfs' )
829
			try:
829
			try:
830
				# Attention: Because of performance reasons, the syntax
831
				#   class nfsShare uses '%(name)s (%(host)s)' as label, not
832
				#   '%(printablename)s' (may be looked up in ldap directly).
833
				#   If you change printablename here you probably want to change
834
				#   nfsShare.label, too.
830
				self['printablename'] = "%s (%s)" % (self['name'], self['host'])
835
				self['printablename'] = "%s (%s)" % (self['name'], self['host'])
831
			except:
836
			except:
832
				pass
837
				pass
 Lines 900-906    Link Here 
900
		if not hasattr(self,"options"):
905
		if not hasattr(self,"options"):
901
			self.open()
906
			self.open()
902
		if 'nfs' in self.options:
907
		if 'nfs' in self.options:
903
			ulist=[]
904
			searchstring="*"+self['host']+":"+self['path']+"*"
908
			searchstring="*"+self['host']+":"+self['path']+"*"
905
			searchResult=self.lo.searchDn(base=self.position.getDomain(), filter='(&(objectClass=person)(automountInformation=%s))'%searchstring, scope='domain')
909
			searchResult=self.lo.searchDn(base=self.position.getDomain(), filter='(&(objectClass=person)(automountInformation=%s))'%searchstring, scope='domain')
906
			if searchResult:
910
			if searchResult:
(-)univention-directory-manager-modules/modules/univention/admin/handlers/users/user.py (-4 / +3 lines)
 Lines 1205-1210    Link Here 
1205
	return new
1205
	return new
1206
1206
1207
mapping=univention.admin.mapping.mapping()
1207
mapping=univention.admin.mapping.mapping()
1208
mapping.register('username', 'uid', None, univention.admin.mapping.ListToString)
1209
mapping.register('uidNumber', 'uidNumber', None, univention.admin.mapping.ListToString)
1210
mapping.register('gidNumber', 'gidNumber', None, univention.admin.mapping.ListToString)
1208
mapping.register('title', 'title', None, univention.admin.mapping.ListToString)
1211
mapping.register('title', 'title', None, univention.admin.mapping.ListToString)
1209
mapping.register('description', 'description', None, univention.admin.mapping.ListToString)
1212
mapping.register('description', 'description', None, univention.admin.mapping.ListToString)
1210
mapping.register('organisation', 'o', None, univention.admin.mapping.ListToString)
1213
mapping.register('organisation', 'o', None, univention.admin.mapping.ListToString)
 Lines 1412-1418    Link Here 
1412
					username_match=s.parse(uid)
1415
					username_match=s.parse(uid)
1413
				except univention.admin.uexceptions.valueError,e: # uid contains already mixed case umlauts, so we switch
1416
				except univention.admin.uexceptions.valueError,e: # uid contains already mixed case umlauts, so we switch
1414
					self.set_uid_umlauts()
1417
					self.set_uid_umlauts()
1415
				self['username']=uid
1416
			# FIXME: we should NEVER catch all exceptions
1418
			# FIXME: we should NEVER catch all exceptions
1417
			except Exception, e:
1419
			except Exception, e:
1418
				# at least write some debuging output..
1420
				# at least write some debuging output..
 Lines 1500-1508    Link Here 
1500
						self.save()
1502
						self.save()
1501
						raise univention.admin.uexceptions.primaryGroup
1503
						raise univention.admin.uexceptions.primaryGroup
1502
1504
1503
					self.info['uidNumber'] = self.oldattr.get('uidNumber', [''])[0]
1504
					self.info['gidNumber'] = self.oldattr.get('gidNumber', [''])[0]
1505
1506
			if self['passwordexpiry']:
1505
			if self['passwordexpiry']:
1507
				today=time.strftime('%Y-%m-%d').split('-')
1506
				today=time.strftime('%Y-%m-%d').split('-')
1508
				expiry=self['passwordexpiry'].split('-')
1507
				expiry=self['passwordexpiry'].split('-')

Return to bug 30991