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

Collapse All | Expand All

(-)a/ucs-school-umc-exam/umc/python/schoolexam-master/__init__.py (-23 / +50 lines)
 Lines 43-54    Link Here 
43
import subprocess
43
import subprocess
44
import tempfile
44
import tempfile
45
from ldap.filter import filter_format
45
from ldap.filter import filter_format
46
from ldap import explode_dn
47
from collections import defaultdict
46
48
47
from univention.management.console.config import ucr
49
from univention.management.console.config import ucr
48
from univention.management.console.log import MODULE
50
from univention.management.console.log import MODULE
49
from univention.management.console.modules import UMC_Error
51
from univention.management.console.modules import UMC_Error
50
from univention.management.console.modules.decorators import sanitize
52
from univention.management.console.modules.decorators import sanitize
51
from univention.management.console.modules.sanitizers import StringSanitizer
53
from univention.management.console.modules.sanitizers import StringSanitizer, DNSanitizer, ListSanitizer
52
from ucsschool.lib.schoolldap import LDAP_Connection, SchoolBaseModule, ADMIN_WRITE, USER_READ
54
from ucsschool.lib.schoolldap import LDAP_Connection, SchoolBaseModule, ADMIN_WRITE, USER_READ
53
from ucsschool.lib.models import School, ComputerRoom, Student, ExamStudent, MultipleObjectsError
55
from ucsschool.lib.models import School, ComputerRoom, Student, ExamStudent, MultipleObjectsError
54
56
 Lines 200-206   def create_exam_user(self, request, ldap_user_read=None, ldap_admin_write=None, Link Here 
200
			return
202
			return
201
203
202
		# Ok, we have a valid target uid, so start cloning the user
204
		# Ok, we have a valid target uid, so start cloning the user
203
		# deepcopy(user_orig) soes not help much, as we cannot use users.user.object.create()
205
		# deepcopy(user_orig) does not help much, as we cannot use users.user.object.create()
204
		# because it currently cannot be convinced to preserve the password. So we do it manually:
206
		# because it currently cannot be convinced to preserve the password. So we do it manually:
205
		try:
207
		try:
206
			# Allocate new uidNumber
208
			# Allocate new uidNumber
 Lines 328-353   def getBlacklistSet(ucrvar): Link Here 
328
			MODULE.error('Creation of exam user account failed: %s' % (traceback.format_exc(),))
330
			MODULE.error('Creation of exam user account failed: %s' % (traceback.format_exc(),))
329
			raise
331
			raise
330
332
331
		# Add exam_user to groups
332
		if 'groups/group' in self._udm_modules:
333
			module_groups_group = self._udm_modules['groups/group']
334
		else:
335
			module_groups_group = univention.admin.modules.get('groups/group')
336
			univention.admin.modules.init(ldap_admin_write, ldap_position, module_groups_group)
337
			self._udm_modules['groups/group'] = module_groups_group
338
339
		if 'posix' in user_orig.options:
340
			grpobj = module_groups_group.object(None, ldap_admin_write, ldap_position, user_orig['primaryGroup'])
341
			grpobj.fast_member_add([exam_user_dn], [exam_user_uid])
342
343
			for group in user_orig.info.get('groups', []):
344
				grpobj = module_groups_group.object(None, ldap_admin_write, ldap_position, group)
345
				grpobj.fast_member_add([exam_user_dn], [exam_user_uid])
346
347
		# Add exam_user to examGroup
348
		examGroup = self.examGroup(ldap_admin_write, ldap_position, user.school or school)
349
		examGroup.fast_member_add([exam_user_dn], [exam_user_uid])
350
351
		# finally confirm allocated IDs
333
		# finally confirm allocated IDs
352
		univention.admin.allocators.confirm(ldap_admin_write, ldap_position, 'uid', exam_user_uid)
334
		univention.admin.allocators.confirm(ldap_admin_write, ldap_position, 'uid', exam_user_uid)
353
		if 'samba' in user_orig.options:
335
		if 'samba' in user_orig.options:
 Lines 359-365   def getBlacklistSet(ucrvar): Link Here 
359
			success=True,
341
			success=True,
360
			userdn=userdn,
342
			userdn=userdn,
361
			examuserdn=exam_user_dn,
343
			examuserdn=exam_user_dn,
362
		), success=True)
344
			examuseruid=exam_user_uid,
345
		))
346
347
	@sanitize(
348
		users=ListSanitizer(DNSanitizer(required=True), required=True),
349
		school=StringSanitizer(required=True)
350
	)
351
	@LDAP_Connection(USER_READ, ADMIN_WRITE)
352
	def add_exam_users_to_groups(self, request, ldap_user_read=None, ldap_admin_write=None, ldap_position=None):
353
		"""
354
		Add previously created exam users to groups.
355
		"""
356
		groups = defaultdict(dict)
357
		exam_group = self.examGroup(ldap_admin_write, ldap_position, request.options['school'])
358
359
		for user_dn in request.options['users']:
360
			try:
361
				ori_student = Student.from_dn(user_dn, None, ldap_admin_write)
362
				exam_student = ExamStudent.from_student_dn(ldap_admin_write, ori_student.school, ori_student.dn)
363
			except univention.admin.uexceptions.noObject:
364
				raise UMC_Error(_('Student %r not found.') % (user_dn,))
365
			except univention.admin.uexceptions.ldapError:
366
				raise
367
368
			udm_ori_student = ori_student.get_udm_object(ldap_admin_write)
369
			if 'posix' in udm_ori_student.options:  # why only if posix?
370
				groups[udm_ori_student['primaryGroup']].setdefault('dns', set()).add(exam_student.dn)
371
				groups[udm_ori_student['primaryGroup']].setdefault('uids', set()).add(exam_student.name)
372
				for grp in udm_ori_student.info.get('groups', []):
373
					groups[grp].setdefault('dns', set()).add(exam_student.dn)
374
					groups[grp].setdefault('uids', set()).add(exam_student.name)
375
376
			groups[exam_group.dn].setdefault('dns', set()).add(exam_student.dn)
377
			groups[exam_group.dn].setdefault('uids', set()).add(exam_student.name)
378
379
			if 'groups/group' not in self._udm_modules:
380
				self._udm_modules['groups/group'] = univention.admin.modules.get('groups/group')
381
				univention.admin.modules.init(ldap_admin_write, ldap_position, self._udm_modules['groups/group'])
382
			module_groups_group = self._udm_modules['groups/group']
383
384
			for group_dn, users in groups.items():
385
				grpobj = module_groups_group.object(None, ldap_admin_write, ldap_position, group_dn)
386
				MODULE.info('Adding users %r to group %r...' % (users['uids'], group_dn))
387
				grpobj.fast_member_add(users['dns'], users['uids'])
388
389
		self.finished(request.id, None)
363
390
364
	@sanitize(
391
	@sanitize(
365
		userdn=StringSanitizer(required=True),
392
		userdn=StringSanitizer(required=True),
(-)a/ucs-school-umc-exam/umc/python/schoolexam/__init__.py (-3 / +11 lines)
 Lines 253-274   def _thread(): Link Here 
253
			progress.component(_('Preparing exam accounts'))
253
			progress.component(_('Preparing exam accounts'))
254
			percentPerUser = 25.0 / (1 + len(users))
254
			percentPerUser = 25.0 / (1 + len(users))
255
			examUsers = set()
255
			examUsers = set()
256
			student_dns = set()
256
			usersReplicated = set()
257
			usersReplicated = set()
257
			for iuser in users:
258
			for iuser in users:
258
				progress.info('%s, %s (%s)' % (iuser.lastname, iuser.firstname, iuser.username))
259
				progress.info('%s, %s (%s)' % (iuser.lastname, iuser.firstname, iuser.username))
259
				try:
260
				try:
260
					ires = client.umc_command('schoolexam-master/create-exam-user', dict(
261
					ires = client.umc_command('schoolexam-master/create-exam-user', dict(
261
						school=request.options['school'],
262
						school=request.options['school'],
262
						userdn=iuser.dn
263
						userdn=iuser.dn,
263
					)).result
264
					)).result
264
					examUsers.add(ires.get('examuserdn'))
265
					examuser_dn = ires.get('examuserdn')
265
					MODULE.info('Exam user has been created: %s' % ires.get('examuserdn'))
266
					examUsers.add(examuser_dn)
267
					student_dns.add(iuser.dn)
268
					MODULE.info('Exam user has been created: %r' % examuser_dn)
266
				except (ConnectionError, HTTPError) as exc:
269
				except (ConnectionError, HTTPError) as exc:
267
					MODULE.warn('Could not create exam user account for %r: %s' % (iuser.dn, exc))
270
					MODULE.warn('Could not create exam user account for %r: %s' % (iuser.dn, exc))
268
271
269
				# indicate the the user has been processed
272
				# indicate the the user has been processed
270
				progress.add_steps(percentPerUser)
273
				progress.add_steps(percentPerUser)
271
274
275
			client.umc_command('schoolexam-master/add-exam-users-to-groups', dict(
276
				users=list(student_dns),
277
				school=request.options['school'],
278
			))
279
272
			progress.add_steps(percentPerUser)
280
			progress.add_steps(percentPerUser)
273
281
274
			# wait for the replication of all users to be finished
282
			# wait for the replication of all users to be finished
(-)a/ucs-school-umc-exam/umc/schoolexam-master.xml (-13 / +5 lines)
 Lines 4-21    Link Here 
4
	<name>Start exam</name>
4
	<name>Start exam</name>
5
	<description>Starts a new exam for a specified computer room</description>
5
	<description>Starts a new exam for a specified computer room</description>
6
6
7
	<command name="schoolexam-master/create-exam-user" function="create_exam_user">
7
	<command name="schoolexam-master/create-exam-user" function="create_exam_user"/>
8
		<attribute name="userdn" syntax="String"/>
8
	<command name="schoolexam-master/add-exam-users-to-groups" function="add_exam_users_to_groups"/>
9
		<attribute name="description" syntax="String"/>
9
	<command name="schoolexam-master/remove-exam-user" function="remove_exam_user"/>
10
	</command>
10
	<command name="schoolexam-master/set-computerroom-exammode" function="set_computerroom_exammode"/>
11
	<command name="schoolexam-master/remove-exam-user" function="remove_exam_user">
11
	<command name="schoolexam-master/unset-computerroom-exammode" function="unset_computerroom_exammode"/>
12
		<attribute name="userdn" syntax="String"/>
13
	</command>
14
	<command name="schoolexam-master/set-computerroom-exammode" function="set_computerroom_exammode">
15
		<attribute name="roomdn" syntax="String"/>
16
	</command>
17
	<command name="schoolexam-master/unset-computerroom-exammode" function="unset_computerroom_exammode">
18
		<attribute name="roomdn" syntax="String"/>
19
	</command>
20
  </module>
12
  </module>
21
</umc>
13
</umc>

Return to bug 43019