File:
[LON-CAPA] /
loncom /
interface /
lonuserutils.pm
Revision
1.1:
download - view:
text,
annotated -
select for diffs
Mon Oct 22 22:16:38 2007 UTC (16 years, 8 months ago) by
raeburn
Branches:
MAIN
CVS tags:
HEAD
Bug 2593 csv file upload by DC to change passwords
- DCs can change authentication, add a domain or course role for uploaded users, and/or change user information (names, ID, e-mail address etc.)
- Authors can add co-authors
- Course Coordinators can add course roles.
- Some subroutines in londropdd.pm moved to lonuserutils.pm. Some routines in loncreateuser.pm moved to lonuserutils.pm
- &process_pick() moved from lonroles.pm to lonpickcourse.pm
- Work in progress. Ultimate goal is to provide user listing functionality in different contexts and eliminate separate ENRL button.
1: # The LearningOnline Network with CAPA
2: # Utility functions for managing LON-CAPA user accounts
3: #
4: # $Id: lonuserutils.pm,v 1.1 2007/10/22 22:16:38 raeburn Exp $
5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA#
23: # /home/httpd/html/adm/gpl.txt
24: #
25: # http://www.lon-capa.org/
26: #
27: #
28: ###############################################################
29: ###############################################################
30:
31: package Apache::lonuserutils;
32:
33: use strict;
34: use Apache::lonnet;
35: use Apache::loncommon();
36: use Apache::lonhtmlcommon;
37: use Apache::lonlocal;
38: use LONCAPA();
39:
40: ###############################################################
41: ###############################################################
42: # Drop student from all sections of a course, except optional $csec
43: sub modifystudent {
44: my ($udom,$unam,$courseid,$csec,$desiredhost)=@_;
45: # if $csec is undefined, drop the student from all the courses matching
46: # this one. If $csec is defined, drop them from all other sections of
47: # this course and add them to section $csec
48: my $cdom = $env{'course.'.$courseid.'.domain'};
49: my $cnum = $env{'course.'.$courseid.'.num'};
50: my %roles = &Apache::lonnet::dump('roles',$udom,$unam);
51: my ($tmp) = keys(%roles);
52: # Bail out if we were unable to get the students roles
53: return "$1" if ($tmp =~ /^(con_lost|error|no_such_host)/i);
54: # Go through the roles looking for enrollment in this course
55: my $result = '';
56: foreach my $course (keys(%roles)) {
57: if ($course=~m{^/\Q$cdom\E/\Q$cnum\E(?:\/)*(?:\s+)*(\w+)*\_st$}) {
58: # We are in this course
59: my $section=$1;
60: $section='' if ($course eq "/$cdom/$cnum".'_st');
61: if (defined($csec) && $section eq $csec) {
62: $result .= 'ok:';
63: } elsif ( ((!$section) && (!$csec)) || ($section ne $csec) ) {
64: my (undef,$end,$start)=split(/\_/,$roles{$course});
65: my $now=time;
66: # if this is an active role
67: if (!($start && ($now<$start)) || !($end && ($now>$end))) {
68: my $reply=&Apache::lonnet::modifystudent
69: # dom name id mode pass f m l g
70: ($udom,$unam,'', '', '',undef,undef,undef,undef,
71: $section,time,undef,undef,$desiredhost);
72: $result .= $reply.':';
73: }
74: }
75: }
76: }
77: if ($result eq '') {
78: $result = 'Unable to find section for this student';
79: } else {
80: $result =~ s/(ok:)+/ok/g;
81: }
82: return $result;
83: }
84:
85: sub modifyuserrole {
86: my ($context,$setting,$changeauth,$cid,$udom,$uname,$uid,$umode,$upass,
87: $first,$middle,$last,$gene,$sec,$forceid,$desiredhome,$email,$role,
88: $end,$start) = @_;
89: my ($scope,$userresult,$authresult,$roleresult);
90: if ($setting eq 'course' || $context eq 'course') {
91: $scope = '/'.$cid;
92: $scope =~ s/\_/\//g;
93: if ($role ne 'cc' && $sec ne '') {
94: $scope .='/'.$sec;
95: }
96: } elsif ($setting eq 'domain') {
97: $scope = '/'.$env{'request.role.domain'}.'/';
98: } elsif ($setting eq 'construction_space') {
99: $scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'};
100: }
101: if ($context eq 'domain') {
102: my $uhome = &Apache::lonnet::homeserver($uname,$udom);
103: if ($uhome ne 'no_host') {
104: if (($changeauth) && (&Apache::lonnet::allowed('mau',$udom))) {
105: if ((($umode =~ /^krb4|krb5|internal$/) && $upass ne '') ||
106: ($umode eq 'localauth')) {
107: $authresult = &Apache::lonnet::modifyuserauth($udom,$uname,$umode,$upass);
108: }
109: }
110: }
111: }
112: $userresult =
113: &Apache::lonnet::modifyuser($udom,$uname,$uid,$umode,$upass,$first,
114: $middle,$last,$gene,$forceid,$desiredhome,
115: $email,$role,$start,$end);
116: if ($userresult eq 'ok') {
117: if ($role ne '') {
118: $roleresult = &Apache::lonnet::assignrole($udom,$uname,$scope,
119: $role,$end,$start);
120: }
121: }
122: return ($userresult,$authresult,$roleresult);
123: }
124:
125: ###############################################################
126: ###############################################################
127: # build a domain and server selection form
128: sub domain_form {
129: my ($defdom) = @_;
130: # Set up domain and server selection forms
131: #
132: # Get the domains
133: my @domains = &Apache::lonnet::all_domains();
134: # build up the menu information to be passed to
135: # &Apache::loncommon::linked_select_forms
136: my %select_menus;
137: foreach my $dom (@domains) {
138: # set up the text for this domain
139: $select_menus{$dom}->{'text'}= $dom;
140: # we want a choice of 'default' as the default in the second menu
141: $select_menus{$dom}->{'default'}= 'default';
142: $select_menus{$dom}->{'select2'}->{'default'} = 'default';
143: # Now build up the other items in the second menu
144: my %servers = &Apache::lonnet::get_servers($dom,'library');
145: foreach my $server (keys(%servers)) {
146: $select_menus{$dom}->{'select2'}->{$server}
147: = "$server $servers{$server}";
148: }
149: }
150: my $result = &Apache::loncommon::linked_select_forms
151: ('studentform',' with home server ',$defdom,
152: 'lcdomain','lcserver',\%select_menus);
153: return $result;
154: }
155:
156: ###############################################################
157: ###############################################################
158: sub hidden_input {
159: my ($name,$value) = @_;
160: return '<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n";
161: }
162:
163: sub print_upload_manager_header {
164: my ($r,$datatoken,$distotal,$krbdefdom,$context)=@_;
165: my $javascript;
166: #
167: if (! exists($env{'form.upfile_associate'})) {
168: $env{'form.upfile_associate'} = 'forward';
169: }
170: if ($env{'form.associate'} eq 'Reverse Association') {
171: if ( $env{'form.upfile_associate'} ne 'reverse' ) {
172: $env{'form.upfile_associate'} = 'reverse';
173: } else {
174: $env{'form.upfile_associate'} = 'forward';
175: }
176: }
177: if ($env{'form.upfile_associate'} eq 'reverse') {
178: $javascript=&upload_manager_javascript_reverse_associate();
179: } else {
180: $javascript=&upload_manager_javascript_forward_associate();
181: }
182: #
183: # Deal with restored settings
184: my $password_choice = '';
185: if (exists($env{'form.ipwd_choice'}) &&
186: $env{'form.ipwd_choice'} ne '') {
187: # If a column was specified for password, assume it is for an
188: # internal password. This is a bug waiting to be filed (could be
189: # local or krb auth instead of internal) but I do not have the
190: # time to mess around with this now.
191: $password_choice = 'int';
192: }
193: #
194: my $javascript_validations =
195: &javascript_validations('auth',$krbdefdom,$password_choice,undef,
196: $env{'request.role.domain'});
197: my $checked=(($env{'form.noFirstLine'})?' checked="checked" ':'');
198: $r->print(&mt('Total number of records found in file: <b>[_1]</b>.',$distotal).
199: "<br />\n");
200: $r->print('<div class="LC_left_float"><h3>'.
201: &mt('Identify fields in uploaded list')."</h3>\n");
202: $r->print(&mt('Enter as many fields as you can.<br /> The system will inform you and bring you back to this page, <br /> if the data selected are insufficient to add users.')."<br />\n");
203: $r->print(&hidden_input('action','upload').
204: &hidden_input('state','got_file').
205: &hidden_input('associate','').
206: &hidden_input('datatoken',$datatoken).
207: &hidden_input('fileupload',$env{'form.fileupload'}).
208: &hidden_input('upfiletype',$env{'form.upfiletype'}).
209: &hidden_input('upfile_associate',$env{'form.upfile_associate'}));
210: $r->print('<br /><input type="button" value="Reverse Association" '.
211: 'name="'.&mt('Reverse Association').'" '.
212: 'onClick="javascript:this.form.associate.value=\'Reverse Association\';submit(this.form);" />');
213: $r->print('<label><input type="checkbox" name="noFirstLine"'.$checked.'/>'.
214: &mt('Ignore First Line').'</label>');
215: $r->print("<br /><br />\n".
216: '<script type="text/javascript" language="Javascript">'."\n".
217: $javascript."\n".$javascript_validations.'</script>');
218: }
219:
220: ###############################################################
221: ###############################################################
222: sub javascript_validations {
223: my ($mode,$krbdefdom,$curr_authtype,$curr_authfield,$domain)=@_;
224: my $authheader;
225: if ($mode eq 'auth') {
226: my %param = ( formname => 'studentform',
227: kerb_def_dom => $krbdefdom,
228: curr_authtype => $curr_authtype);
229: $authheader = &Apache::loncommon::authform_header(%param);
230: } elsif ($mode eq 'createcourse') {
231: my %param = ( formname => 'ccrs',
232: kerb_def_dom => $krbdefdom,
233: curr_authtype => $curr_authtype );
234: $authheader = &Apache::loncommon::authform_header(%param);
235: } elsif ($mode eq 'modifycourse') {
236: my %param = ( formname => 'cmod',
237: kerb_def_dom => $krbdefdom,
238: mode => 'modifycourse',
239: curr_authtype => $curr_authtype,
240: curr_autharg => $curr_authfield );
241: $authheader = &Apache::loncommon::authform_header(%param);
242: }
243:
244: my %alert = &Apache::lonlocal::texthash
245: (username => 'You need to specify the username field.',
246: authen => 'You must choose an authentication type.',
247: krb => 'You need to specify the Kerberos domain.',
248: ipass => 'You need to specify the initial password.',
249: name => 'The optional name field was not specified.',
250: snum => 'The optional ID number field was not specified.',
251: section => 'The optional section field was not specified.',
252: email => 'The optional email address field was not specified.',
253: role => 'The optional role field was not specified.',
254: continue => 'Continue adding users?',
255: );
256:
257: # my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
258: my $function_name =(<<END);
259: function verify_message (vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail) {
260: END
261: my ($authnum,%can_assign) = &Apache::loncommon::get_assignable_auth($domain);
262: my $auth_checks;
263: if ($mode eq 'createcourse') {
264: $auth_checks .= (<<END);
265: if (vf.autoadds[0].checked == true) {
266: if (current.radiovalue == null || current.radiovalue == 'nochange') {
267: alert('$alert{'authen'}');
268: return;
269: }
270: }
271: END
272: } else {
273: $auth_checks .= (<<END);
274: var foundatype=0;
275: if (founduname==0) {
276: alert('$alert{'username'}');
277: return;
278: }
279:
280: END
281: if ($authnum > 1) {
282: $auth_checks .= (<<END);
283: if (current.radiovalue == null || current.radiovalue == '' || current.radiovalue == 'nochange') {
284: // They did not check any of the login radiobuttons.
285: alert('$alert{'authen'}');
286: return;
287: }
288: END
289: }
290: }
291: if ($mode eq 'createcourse') {
292: $auth_checks .= "
293: if ( (vf.autoadds[0].checked == true) &&
294: (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') ) {
295: ";
296: } elsif ($mode eq 'modifycourse') {
297: $auth_checks .= "
298: if (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') {
299: ";
300: }
301: if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
302: $auth_checks .= (<<END);
303: var alertmsg = '';
304: switch (current.radiovalue) {
305: case 'krb':
306: alertmsg = '$alert{'krb'}';
307: break;
308: default:
309: alertmsg = '';
310: }
311: if (alertmsg != '') {
312: alert(alertmsg);
313: return;
314: }
315: }
316: END
317: } else {
318: $auth_checks .= (<<END);
319: foundatype=1;
320: if (current.argfield == null || current.argfield == '') {
321: var alertmsg = '';
322: switch (current.value) {
323: case 'krb':
324: alertmsg = '$alert{'krb'}';
325: break;
326: case 'loc':
327: case 'fsys':
328: alertmsg = '$alert{'ipass'}';
329: break;
330: case 'fsys':
331: alertmsg = '';
332: break;
333: default:
334: alertmsg = '';
335: }
336: if (alertmsg != '') {
337: alert(alertmsg);
338: return;
339: }
340: }
341: END
342: }
343: my $section_checks;
344: my $optional_checks = '';
345: if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
346: $optional_checks = (<<END);
347: vf.submit();
348: }
349: END
350: } else {
351: $section_checks = §ion_check_js();
352: $optional_checks = (<<END);
353: var message='';
354: if (foundname==0) {
355: message='$alert{'name'}';
356: }
357: if (foundid==0) {
358: if (message!='') {
359: message+='\\n';
360: }
361: message+='$alert{'snum'}';
362: }
363: if (foundsec==0) {
364: if (message!='') {
365: message+='\\n';
366: }
367: }
368: if (foundemail==0) {
369: if (message!='') {
370: message+='\\n';
371: }
372: message+='$alert{'email'}';
373: }
374: if (message!='') {
375: message+= '\\n$alert{'continue'}';
376: if (confirm(message)) {
377: vf.state.value='enrolling';
378: vf.submit();
379: }
380: } else {
381: vf.state.value='enrolling';
382: vf.submit();
383: }
384: }
385: END
386: }
387: my $result = $function_name;
388: if ( ($mode eq 'auth') || ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
389: $result .= $auth_checks;
390: }
391: $result .= $optional_checks."\n".$section_checks;
392: if ( ($mode eq 'auth') || ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
393: $result .= $authheader;
394: }
395: return $result;
396: }
397: ###############################################################
398: ###############################################################
399: sub upload_manager_javascript_forward_associate {
400: return(<<ENDPICK);
401: function verify(vf,sec_caller) {
402: var founduname=0;
403: var foundpwd=0;
404: var foundname=0;
405: var foundid=0;
406: var foundsec=0;
407: var foundemail=0;
408: var foundrole=0;
409: var tw;
410: for (i=0;i<=vf.nfields.value;i++) {
411: tw=eval('vf.f'+i+'.selectedIndex');
412: if (tw==1) { founduname=1; }
413: if ((tw>=2) && (tw<=6)) { foundname=1; }
414: if (tw==7) { foundid=1; }
415: if (tw==8) { foundsec=1; }
416: if (tw==9) { foundpwd=1; }
417: if (tw==10) { foundemail=1; }
418: if (tw==11) { foundrole=1; }
419: }
420: verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole);
421: }
422:
423: //
424: // vf = this.form
425: // tf = column number
426: //
427: // values of nw
428: //
429: // 0 = none
430: // 1 = username
431: // 2 = names (lastname, firstnames)
432: // 3 = fname (firstname)
433: // 4 = mname (middlename)
434: // 5 = lname (lastname)
435: // 6 = gen (generation)
436: // 7 = id
437: // 8 = section
438: // 9 = ipwd (password)
439: // 10 = email address
440: // 11 = role
441:
442: function flip(vf,tf) {
443: var nw=eval('vf.f'+tf+'.selectedIndex');
444: var i;
445: // make sure no other columns are labeled the same as this one
446: for (i=0;i<=vf.nfields.value;i++) {
447: if ((i!=tf) && (eval('vf.f'+i+'.selectedIndex')==nw)) {
448: eval('vf.f'+i+'.selectedIndex=0;')
449: }
450: }
451: // If we set this to 'lastname, firstnames', clear out all the ones
452: // set to 'fname','mname','lname','gen' (3,4,5,6) currently.
453: if (nw==2) {
454: for (i=0;i<=vf.nfields.value;i++) {
455: if ((eval('vf.f'+i+'.selectedIndex')>=3) &&
456: (eval('vf.f'+i+'.selectedIndex')<=6)) {
457: eval('vf.f'+i+'.selectedIndex=0;')
458: }
459: }
460: }
461: // If we set this to one of 'fname','mname','lname','gen' (3,4,5,6),
462: // clear out any that are set to 'lastname, firstnames' (2)
463: if ((nw>=3) && (nw<=6)) {
464: for (i=0;i<=vf.nfields.value;i++) {
465: if (eval('vf.f'+i+'.selectedIndex')==2) {
466: eval('vf.f'+i+'.selectedIndex=0;')
467: }
468: }
469: }
470: // If we set the password, make the password form below correspond to
471: // the new value.
472: if (nw==9) {
473: changed_radio('int',document.studentform);
474: set_auth_radio_buttons('int',document.studentform);
475: vf.intarg.value='';
476: vf.krbarg.value='';
477: vf.locarg.value='';
478: }
479: }
480:
481: function clearpwd(vf) {
482: var i;
483: for (i=0;i<=vf.nfields.value;i++) {
484: if (eval('vf.f'+i+'.selectedIndex')==9) {
485: eval('vf.f'+i+'.selectedIndex=0;')
486: }
487: }
488: }
489:
490: ENDPICK
491: }
492:
493: ###############################################################
494: ###############################################################
495: sub upload_manager_javascript_reverse_associate {
496: return(<<ENDPICK);
497: function verify(vf,sec_caller) {
498: var founduname=0;
499: var foundpwd=0;
500: var foundname=0;
501: var foundid=0;
502: var foundsec=0;
503: var foundrole=0;
504: var tw;
505: for (i=0;i<=vf.nfields.value;i++) {
506: tw=eval('vf.f'+i+'.selectedIndex');
507: if (i==0 && tw!=0) { founduname=1; }
508: if (((i>=1) && (i<=5)) && tw!=0 ) { foundname=1; }
509: if (i==6 && tw!=0) { foundid=1; }
510: if (i==7 && tw!=0) { foundsec=1; }
511: if (i==8 && tw!=0) { foundpwd=1; }
512: if (i==9 && tw!=0) { foundrole=1; }
513: }
514: verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundrole);
515: }
516:
517: function flip(vf,tf) {
518: var nw=eval('vf.f'+tf+'.selectedIndex');
519: var i;
520: // picked the all one name field, reset the other name ones to blank
521: if (tf==1 && nw!=0) {
522: for (i=2;i<=5;i++) {
523: eval('vf.f'+i+'.selectedIndex=0;')
524: }
525: }
526: //picked one of the piecewise name fields, reset the all in
527: //one field to blank
528: if ((tf>=2) && (tf<=5) && (nw!=0)) {
529: eval('vf.f1.selectedIndex=0;')
530: }
531: // intial password specified, pick internal authentication
532: if (tf==8 && nw!=0) {
533: changed_radio('int',document.studentform);
534: set_auth_radio_buttons('int',document.studentform);
535: vf.krbarg.value='';
536: vf.intarg.value='';
537: vf.locarg.value='';
538: }
539: }
540:
541: function clearpwd(vf) {
542: var i;
543: if (eval('vf.f8.selectedIndex')!=0) {
544: eval('vf.f8.selectedIndex=0;')
545: }
546: }
547: ENDPICK
548: }
549:
550: ###############################################################
551: ###############################################################
552: sub print_upload_manager_footer {
553: my ($r,$i,$keyfields,$defdom,$today,$halfyear,$context)=@_;
554: my $formname;
555: if ($context eq 'course') {
556: $formname = 'document.studentform';
557: } elsif ($context eq 'construction_space') {
558: $formname = 'document.studentform';
559: } elsif ($context eq 'domain') {
560: $formname = 'document.studentform';
561: }
562: my ($krbdef,$krbdefdom) =
563: &Apache::loncommon::get_kerberos_defaults($defdom);
564: my %param = ( formname => $formname,
565: kerb_def_dom => $krbdefdom,
566: kerb_def_auth => $krbdef
567: );
568: if (exists($env{'form.ipwd_choice'}) &&
569: defined($env{'form.ipwd_choice'}) &&
570: $env{'form.ipwd_choice'} ne '') {
571: $param{'curr_authtype'} = 'int';
572: }
573: my $krbform = &Apache::loncommon::authform_kerberos(%param);
574: my $intform = &Apache::loncommon::authform_internal(%param);
575: my $locform = &Apache::loncommon::authform_local(%param);
576: my $date_table = &date_setting_table(undef,undef,$context);
577:
578: my $Str = "\n".'<div class="LC_left_float">';
579: $Str .= &hidden_input('nfields',$i);
580: $Str .= &hidden_input('keyfields',$keyfields);
581: $Str .= "<h3>".&mt('Login Type')."</h3>\n";
582: if ($context eq 'domain') {
583: $Str .= '<p>'.&mt('Change authentication for existing users to these settings?').' <span class="LC_nobreak"><label><input type="radio" name="changeauth" value="No" checked="checked" />'.&mt('No').'</label> <label><input type="radio" name="changeauth" value="Yes" />'.&mt('Yes').'</label></span></p>';
584: } else {
585: $Str .= "<p>\n".
586: &mt('Note: this will not take effect if the user already exists').
587: &Apache::loncommon::help_open_topic('Auth_Options').
588: "</p>\n";
589: }
590: $Str .= &set_login($defdom,$krbform,$intform,$locform);
591: my ($home_server_pick,$numlib) =
592: &Apache::loncommon::home_server_form_item($defdom,'lcserver',
593: 'default','hide');
594: if ($numlib > 1) {
595: $Str .= '<h3>'.&mt('LON-CAPA Home Server for New Users')."</h3>\n".
596: &mt('LON-CAPA domain: [_1] with home server: [_2]',$defdom,
597: $home_server_pick).'<br />';
598: } else {
599: $Str .= $home_server_pick;
600: }
601: $Str .= '<h3>'.&mt('Starting and Ending Dates').
602: "</h3>\n";
603: $Str .= "<p>\n".$date_table."</p>\n";
604: if ($context eq 'domain') {
605: $Str .= '<h3>'.&mt('Settings for assigning roles:').'</h3>'."\n".
606: &mt('Pick the action to take on roles for these users:').'<br /><span class="LC_nobreak"><label><input type="radio" name="roleaction" value="norole" checked="checked" /> '.&mt('No role changes').'</label> <label><input type="radio" name="roleaction" value="domain" /> '.&mt('Add a domain role').'</label> <label><input type="radio" name="roleaction" value="course" /> '.&mt('Add a course role').'</label></span>';
607: }
608: if ($context eq 'construction_space') {
609: $Str .= '<h3>'.&mt('Default role')."</h3>\n".
610: &mt('Choose the role to assign to users without one specified in the uploaded file');
611: } elsif ($context eq 'course') {
612: $Str .= '<h3>'.&mt('Default role and section')."</h3>\n".
613: &mt('Choose the role and/or section to assign to users without one specified in the uploaded file');
614: } else {
615: $Str .= '<br /><br /><b>'.&mt('Default role and/or section')."</b><br />\n".
616: &mt('Role and/or section for users without one in the uploaded file.');
617: }
618: $Str .= '<br /><br />';
619: my ($options,$cb_script,$coursepick) = &default_role_selector($context);
620: if ($context eq 'domain') {
621: $Str .= '<span class="LC_role_level">'.&mt('Domain Level').'</span><br />'.$options.'<br /><br /><span class="LC_role_level">'.&mt('Course Level').'</span><br />'.$cb_script.$coursepick;
622: } else {
623: $Str .= $options;
624: }
625: if ($context eq 'course') {
626: $Str .= "<h3>".&mt('Full Update')."</h3>\n".
627: '<label><input type="checkbox" name="fullup" value="yes">'.
628: ' '.&mt('Full update (also print list of users not enrolled anymore)').
629: "</label></p>\n";
630: }
631: $Str .= "<h3>".&mt('ID/Student Number')."</h3>\n";
632: $Str .= "<p>\n".'<label><input type="checkbox" name="forceid" value="yes">';
633: $Str .= &mt('Disable ID/Student Number Safeguard and Force Change '.
634: 'of Conflicting IDs').
635: '</label><br />'."\n".
636: &mt('(only do if you know what you are doing.)')."</p><p>\n";
637: $Str .= '</div><div class="LC_clear_float_footer"><br /><input type="button"'.
638: 'onClick="javascript:verify(this.form,this.form.csec)" '.
639: 'value="Update Users" />'."<br />\n";
640: if ($context eq 'course') {
641: $Str .= &mt('Note: for large courses, this operation may be time '.
642: 'consuming');
643: }
644: $Str .= '</div>';
645: $r->print($Str);
646: return;
647: }
648:
649: ###############################################################
650: ###############################################################
651: sub print_upload_manager_form {
652: my ($r,$context) = @_;
653: my $firstLine;
654: my $datatoken;
655: if (!$env{'form.datatoken'}) {
656: $datatoken=&Apache::loncommon::upfile_store($r);
657: } else {
658: $datatoken=$env{'form.datatoken'};
659: &Apache::loncommon::load_tmp_file($r);
660: }
661: my @records=&Apache::loncommon::upfile_record_sep();
662: if($env{'form.noFirstLine'}){
663: $firstLine=shift(@records);
664: }
665: my $total=$#records;
666: my $distotal=$total+1;
667: my $today=time;
668: my $halfyear=$today+15552000;
669: #
670: # Restore memorized settings
671: my $col_setting_names = { 'username_choice' => 'scalar', # column settings
672: 'names_choice' => 'scalar',
673: 'fname_choice' => 'scalar',
674: 'mname_choice' => 'scalar',
675: 'lname_choice' => 'scalar',
676: 'gen_choice' => 'scalar',
677: 'id_choice' => 'scalar',
678: 'sec_choice' => 'scalar',
679: 'ipwd_choice' => 'scalar',
680: 'email_choice' => 'scalar',
681: 'role_choice' => 'scalar',
682: };
683: my $defdom = $env{'request.role.domain'};
684: if ($context eq 'course') {
685: &Apache::loncommon::restore_course_settings('enrollment_upload',
686: $col_setting_names);
687: } else {
688: &Apache::loncommon::restore_settings($context,'user_upload',
689: $col_setting_names);
690: }
691: #
692: # Determine kerberos parameters as appropriate
693: my ($krbdef,$krbdefdom) =
694: &Apache::loncommon::get_kerberos_defaults($defdom);
695: #
696: &print_upload_manager_header($r,$datatoken,$distotal,$krbdefdom,$context);
697: my $i;
698: my $keyfields;
699: if ($total>=0) {
700: my @field=
701: (['username',&mt('Username'), $env{'form.username_choice'}],
702: ['names',&mt('Last Name, First Names'),$env{'form.names_choice'}],
703: ['fname',&mt('First Name'), $env{'form.fname_choice'}],
704: ['mname',&mt('Middle Names/Initials'),$env{'form.mname_choice'}],
705: ['lname',&mt('Last Name'), $env{'form.lname_choice'}],
706: ['gen', &mt('Generation'), $env{'form.gen_choice'}],
707: ['id', &mt('ID/Student Number'),$env{'form.id_choice'}],
708: ['sec', &mt('Section'), $env{'form.sec_choice'}],
709: ['ipwd', &mt('Initial Password'),$env{'form.ipwd_choice'}],
710: ['email',&mt('E-mail Address'), $env{'form.email_choice'}],
711: ['role',&mt('Role'), $env{'form.role_choice'}]);
712: if ($env{'form.upfile_associate'} eq 'reverse') {
713: &Apache::loncommon::csv_print_samples($r,\@records);
714: $i=&Apache::loncommon::csv_print_select_table($r,\@records,
715: \@field);
716: foreach (@field) {
717: $keyfields.=$_->[0].',';
718: }
719: chop($keyfields);
720: } else {
721: unshift(@field,['none','']);
722: $i=&Apache::loncommon::csv_samples_select_table($r,\@records,
723: \@field);
724: my %sone=&Apache::loncommon::record_sep($records[0]);
725: $keyfields=join(',',sort(keys(%sone)));
726: }
727: }
728: $r->print('</div>');
729: &print_upload_manager_footer($r,$i,$keyfields,$defdom,$today,$halfyear,
730: $context);
731: }
732:
733: sub setup_date_selectors {
734: my ($starttime,$endtime,$mode) = @_;
735: if (! defined($starttime)) {
736: $starttime = time;
737: unless ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') {
738: if (exists($env{'course.'.$env{'request.course.id'}.
739: '.default_enrollment_start_date'})) {
740: $starttime = $env{'course.'.$env{'request.course.id'}.
741: '.default_enrollment_start_date'};
742: }
743: }
744: }
745: if (! defined($endtime)) {
746: $endtime = time+(6*30*24*60*60); # 6 months from now, approx
747: unless ($mode eq 'createcourse') {
748: if (exists($env{'course.'.$env{'request.course.id'}.
749: '.default_enrollment_end_date'})) {
750: $endtime = $env{'course.'.$env{'request.course.id'}.
751: '.default_enrollment_end_date'};
752: }
753: }
754: }
755: my $startdateform = &Apache::lonhtmlcommon::date_setter('studentform',
756: 'startdate',
757: $starttime);
758: my $enddateform = &Apache::lonhtmlcommon::date_setter('studentform',
759: 'enddate',
760: $endtime);
761: if ($mode eq 'create_enrolldates') {
762: $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs',
763: 'startenroll',
764: $starttime);
765: $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs',
766: 'endenroll',
767: $endtime);
768: }
769: if ($mode eq 'create_defaultdates') {
770: $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs',
771: 'startaccess',
772: $starttime);
773: $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs',
774: 'endaccess',
775: $endtime);
776: }
777: return ($startdateform,$enddateform);
778: }
779:
780:
781: sub get_dates_from_form {
782: my $startdate = &Apache::lonhtmlcommon::get_date_from_form('startdate');
783: my $enddate = &Apache::lonhtmlcommon::get_date_from_form('enddate');
784: if ($env{'form.no_end_date'}) {
785: $enddate = 0;
786: }
787: return ($startdate,$enddate);
788: }
789:
790: sub date_setting_table {
791: my ($starttime,$endtime,$mode) = @_;
792: my ($startform,$endform)=&setup_date_selectors($starttime,$endtime,$mode);
793: my $dateDefault;
794: if ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') {
795: $dateDefault = ' ';
796: } elsif ($mode ne 'construction_space' && $mode ne 'domain') {
797: $dateDefault = '<nobr>'.
798: '<label><input type="checkbox" name="makedatesdefault" /> '.
799: &mt('make these dates the default for future enrollment').
800: '</label></nobr>';
801: }
802: my $perpetual = '<nobr><label><input type="checkbox" name="no_end_date"';
803: if (defined($endtime) && $endtime == 0) {
804: $perpetual .= ' checked';
805: }
806: $perpetual.= ' /> '.&mt('no ending date').'</label></nobr>';
807: if ($mode eq 'create_enrolldates') {
808: $perpetual = ' ';
809: }
810: my $result = &Apache::lonhtmlcommon::start_pick_box()."\n".
811: &Apache::lonhtmlcommon::row_title(&mt('Starting Date'),
812: 'LC_oddrow_value')."\n".
813: $startform."\n".
814: &Apache::lonhtmlcommon::row_closure(1).
815: &Apache::lonhtmlcommon::row_title(&mt('Ending Date'),
816: 'LC_oddrow_value')."\n".
817: $endform.' '.$perpetual.
818: &Apache::lonhtmlcommon::row_closure(1).
819: &Apache::lonhtmlcommon::end_pick_box().'<br />';
820: if ($dateDefault) {
821: $result .= $dateDefault.'<br />'."\n";
822: }
823: return $result;
824: }
825:
826: sub make_dates_default {
827: my ($startdate,$enddate,$context) = @_;
828: my $result = '';
829: if ($context eq 'course') {
830: my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
831: my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
832: my $put_result = &Apache::lonnet::put('environment',
833: {'default_enrollment_start_date'=>$startdate,
834: 'default_enrollment_end_date' =>$enddate},$dom,$crs);
835: if ($put_result eq 'ok') {
836: $result .= "Set default start and end dates for course<br />";
837: #
838: # Refresh the course environment
839: &Apache::lonnet::coursedescription($env{'request.course.id'},
840: {'freshen_cache' => 1});
841: } else {
842: $result .= &mt('Unable to set default dates for course').":".$put_result.
843: '<br />';
844: }
845: }
846: return $result;
847: }
848:
849: sub default_role_selector {
850: my ($context) = @_;
851: my %customroles;
852: my ($options,$coursepick,$cb_jscript);
853: if ($context ne 'construction_space') {
854: %customroles = &my_custom_roles();
855: }
856:
857: my %lt=&Apache::lonlocal::texthash(
858: 'rol' => "Role",
859: 'grs' => "Section",
860: 'exs' => "Existing sections",
861: 'new' => "New section",
862: );
863: $options = '<select name="defaultrole">'."\n".
864: ' <option value="">'.&mt('Please select').'</option>'."\n";
865: if ($context eq 'course') {
866: $options .= &default_course_roles($context,%customroles);
867: } elsif ($context eq 'construction_space') {
868: my @roles = &construction_space_roles();
869: foreach my $role (@roles) {
870: my $plrole=&Apache::lonnet::plaintext($role);
871: $options .= ' <option value="'.$role.'">'.$plrole.'</option>'."\n";
872: }
873: } elsif ($context eq 'domain') {
874: my @roles = &domain_roles();
875: foreach my $role (@roles) {
876: my $plrole=&Apache::lonnet::plaintext($role);
877: $options .= ' <option value="'.$role.'">'.$plrole.'</option>';
878: }
879: my $courseform = &Apache::loncommon::selectcourse_link
880: ('studentform','defaultcourse','defaultdomain','defaultdesc',"$env{'request.role.domain'}",undef,'Course');
881: $cb_jscript =
882: &Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'},'defaultsec','studentform');
883: $coursepick = &Apache::loncommon::start_data_table().
884: &Apache::loncommon::start_data_table_header_row().
885: '<th>'.$courseform.'</th><th>'.$lt{'rol'}.'</th>'.
886: '<th>'.$lt{'grs'}.'</th>'.
887: &Apache::loncommon::end_data_table_header_row().
888: &Apache::loncommon::start_data_table_row()."\n".
889: '<td><input type="text" name="defaultdesc" value="" onFocus="this.blur();opencrsbrowser('."'studentform','defcourse','defdomain','coursedesc',''".')" /></td>'."\n".
890: '<td><select name="courserole">'."\n".
891: &default_course_roles($context,%customroles)."\n".
892: '</select></td><td>'.
893: '<table class="LC_createuser">'.
894: '<tr class="LC_section_row"><td valign"top">'.
895: $lt{'exs'}.'<br /><select name="defaultsec">'.
896: ' <option value=""><--'.&mt('Pick course first').
897: '</select></td>'.
898: '<td> </td>'.
899: '<td valign="top">'.$lt{'new'}.'<br />'.
900: '<input type="text" name="newsec" value="" size="5" />'.
901: '<input type="hidden" name="groups" value="" /></td>'.
902: '</tr></table></td>'.
903: &Apache::loncommon::end_data_table_row().
904: &Apache::loncommon::end_data_table()."\n".
905: '<input type="hidden" name="defaultcourse" value="" />'.
906: '<input type="hidden" name="defaultdomain" value="" />';
907: }
908: $options .= '</select>';
909: return ($options,$cb_jscript,$coursepick);
910: }
911:
912: sub default_course_roles {
913: my ($context,%customroles) = @_;
914: my $output;
915: my @roles = &course_roles($context);
916: foreach my $role (@roles) {
917: my $plrole=&Apache::lonnet::plaintext($role);
918: $output .= ' <option value="'.$role.'">'.$plrole.'</option>';
919: }
920: if (keys(%customroles) > 0) {
921: foreach my $cust (sort(keys(%customroles))) {
922: my $custrole='cr_cr_'.$env{'user.domain'}.
923: '_'.$env{'user.name'}.'_'.$cust;
924: $output .= ' <option value="'.$custrole.'">'.$cust.'</option>';
925: }
926: }
927: return $output;
928: }
929:
930: sub construction_space_roles {
931: my @allroles = ('ca','aa');
932: my @roles;
933: foreach my $role (@allroles) {
934: if (&Apache::lonnet::allowed('c'.$role,$env{'user.domain'}.'/'.$env{'user.name'})) {
935: push(@roles,$role);
936: }
937: }
938: return @roles;
939: }
940:
941: sub domain_roles {
942: my @allroles = ('dc','li','dg','au','sc');
943: my @roles;
944: foreach my $role (@allroles) {
945: if (&Apache::lonnet::allowed('c'.$role,$env{'request.role.domain'})) {
946: push(@roles,$role);
947: }
948: }
949: return @roles;
950: }
951:
952: sub course_roles {
953: my ($context) = @_;
954: my @allroles = ('st','ta','ep','in','cc');
955: my @roles;
956: if ($context eq 'domain') {
957: @roles = @allroles;
958: } elsif ($context eq 'course') {
959: if ($env{'request.course.id'}) {
960: foreach my $role (@allroles) {
961: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
962: push(@roles,$role);
963: } else {
964: if ($role ne 'cc' && $env{'request.course.section'} ne '') {
965: if (!&Apache::lonnet::allowed('c'.$role,
966: $env{'request.course.id'}.'/'.
967: $env{'request.course.section'})) {
968: push(@roles,$role);
969: }
970: }
971: }
972: }
973: }
974: }
975: return @roles;
976: }
977:
978: sub curr_role_permissions {
979: my ($context,$setting) = @_;
980: my @roles;
981: if ($context eq 'construction_space') {
982: @roles = &construction_space_roles();
983: } elsif ($context eq 'domain') {
984: if ($setting eq 'course') {
985: @roles = &course_roles($context);
986: } else {
987: @roles = &domain_roles();
988: }
989: } elsif ($context eq 'course') {
990: @roles = &course_roles($context);
991: }
992: return @roles;
993: }
994:
995: # ======================================================= Existing Custom Roles
996:
997: sub my_custom_roles {
998: my %returnhash=();
999: my %rolehash=&Apache::lonnet::dump('roles');
1000: foreach my $key (keys %rolehash) {
1001: if ($key=~/^rolesdef\_(\w+)$/) {
1002: $returnhash{$1}=$1;
1003: }
1004: }
1005: return %returnhash;
1006: }
1007:
1008: sub print_html_classlist {
1009: my ($r,$mode,$permission,$context) = @_;
1010: if (! exists($env{'form.sortby'})) {
1011: $env{'form.sortby'} = 'username';
1012: }
1013: if ($env{'form.status'} !~ /^(Any|Expired|Active|Future)$/) {
1014: $env{'form.status'} = 'Active';
1015: }
1016: my $status_select = &Apache::lonhtmlcommon::StatusOptions
1017: ($env{'form.status'});
1018:
1019: if (! defined($env{'form.output'}) ||
1020: $env{'form.output'} !~ /^(csv|excel|html)$/ ) {
1021: $env{'form.output'} = 'html';
1022: }
1023:
1024: if ($context eq 'course') {
1025: my $cid =$env{'request.course.id'};
1026: my $cdom=$env{'course.'.$cid.'.domain'};
1027: my $cnum=$env{'course.'.$cid.'.num'};
1028: #
1029: # List course personnel
1030: my %coursepersonnel=&Apache::lonnet::get_course_adv_roles($cdom.'/'.$cnum);
1031: #
1032:
1033: $r->print('<br />'.&Apache::loncommon::start_data_table());
1034: foreach my $role (sort keys %coursepersonnel) {
1035: next if ($role =~ /^\s*$/);
1036: $r->print(&Apache::loncommon::start_data_table_row().
1037: '<td>'.$role.'</td><td>');
1038: foreach my $user (split(',',$coursepersonnel{$role})) {
1039: my ($puname,$pudom)=split(':',$user);
1040: $r->print(' '.&Apache::loncommon::aboutmewrapper(
1041: &Apache::loncommon::plainname($puname,$pudom),
1042: $puname,$pudom));
1043: }
1044: $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1045: }
1046: $r->print(&Apache::loncommon::end_data_table());
1047: }
1048: #
1049: # Interface output
1050: $r->print('<input type="hidden" name="action" value="'.
1051: $env{'form.action'}.'" />');
1052: $r->print("<p>\n");
1053: if ($env{'form.action'} ne 'modifystudent') {
1054: my %lt=&Apache::lonlocal::texthash('csv' => "CSV",
1055: 'excel' => "Excel",
1056: 'html' => 'HTML');
1057: my $output_selector = '<select size="1" name="output" >';
1058: foreach my $outputformat ('html','csv','excel') {
1059: my $option = '<option value="'.$outputformat.'" ';
1060: if ($outputformat eq $env{'form.output'}) {
1061: $option .= 'selected ';
1062: }
1063: $option .='>'.$lt{$outputformat}.'</option>';
1064: $output_selector .= "\n".$option;
1065: }
1066: $output_selector .= '</select>';
1067: $r->print('<label>'.&mt('Output Format: [_1]',$output_selector).'</label>'.(' 'x3));
1068: }
1069: $r->print('<label>'.&mt('Student Status: [_1]',$status_select)."</label>\n");
1070: $r->print('<input type="submit" value="'.&mt('Update Display').'" />'.
1071: "\n</p>\n");
1072:
1073: if ($context eq 'course') {
1074: #
1075: # Print the classlist
1076: $r->print('<h2>'.&mt('Current Class List').'</h2>');
1077: my ($classlist,$keylist)=&Apache::loncoursedata::get_classlist();
1078:
1079: if (exists($permission->{'view_section'})) {
1080: my $sec = &Apache::loncoursedata::CL_SECTION();
1081: foreach my $student (keys(%{$classlist})) {
1082: if ($classlist->{$student}[$sec] ne $permission->{'view_section'}) {
1083: delete($classlist->{$student});
1084: }
1085: }
1086: }
1087:
1088: if (! defined($classlist)) {
1089: $r->print(&mt('There are no students currently enrolled.')."\n");
1090: } else {
1091: # Print out the available choices
1092: if ($env{'form.action'} eq 'modifystudent') {
1093: &show_users_list($r,$context,'view','modify',
1094: $env{'form.Status'},$classlist,$keylist);
1095: } else {
1096: &show_users_list($r,$context,$env{'form.output'},'aboutme',
1097: $env{'form.Status'},$classlist,$keylist);
1098: }
1099: }
1100: } elsif ($context eq 'construction_space') {
1101: # List co-authors and assistant co-authors
1102: my @statuses;
1103: if ($env{'form.status'} eq 'Any') {
1104: @statuses = ('previous','active','future');
1105: } elsif ($env{'form.status'} eq 'Expired') {
1106: @statuses = ('previous');
1107: } elsif ($env{'form.status'} eq 'Active') {
1108: @statuses = ('active');
1109: } elsif ($env{'form.status'} eq 'Future') {
1110: @statuses = ('future');
1111: }
1112: my @possroles = ('ca','aa');
1113: my %cstr_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
1114: \@statuses,\@possroles);
1115: if (keys(%cstr_roles) == 0) {
1116: $r->print(&mt('There are no authors or co-authors.')."\n");
1117: } else {
1118: # Print out the available choices
1119: if ($env{'form.action'} eq 'modifystudent') {
1120: &show_users_list($r,$context,'view','modify',
1121: $env{'form.Status'},\%cstr_roles);
1122: } else {
1123: &show_users_list($r,$context,$env{'form.output'},'aboutme',
1124: $env{'form.Status'},\%cstr_roles);
1125: }
1126: }
1127: } else {
1128:
1129: }
1130: }
1131:
1132: sub show_users_list {
1133: my ($r,$context,$mode,$linkto,$statusmode,$classlist,$keylist)=@_;
1134: #
1135: # Variables for excel output
1136: my ($excel_workbook, $excel_sheet, $excel_filename,$row,$format);
1137: #
1138: # Variables for csv output
1139: my ($CSVfile,$CSVfilename);
1140: #
1141: my $sortby = $env{'form.sortby'};
1142: if ($sortby !~ /^(username|domain|section|groups|fullname|id|start|end|type)$/) {
1143: $sortby = 'username';
1144: }
1145: my ($cid,$cdom,$cnum,$classgroups,$displayphotos,$displayclickers)=@_;
1146: if ($context eq 'course') {
1147: $cid=$env{'request.course.id'};
1148: $cdom = $env{'course.'.$cid.'.domain'};
1149: $cnum = $env{'course.'.$cid.'.num'};
1150: $classgroups = &Apache::loncoursedata::get_group_memberships(
1151: $classlist,$keylist,$cdom,$cnum);
1152: if (! exists($env{'form.displayphotos'})) {
1153: $env{'form.displayphotos'} = 'off';
1154: }
1155: $displayphotos = $env{'form.displayphotos'};
1156: if (! exists($env{'form.displayclickers'})) {
1157: $env{'form.displayclickers'} = 'off';
1158: }
1159: $displayclickers = $env{'form.displayclickers'};
1160: if ($env{'course.'.$cid.'.internal.showphoto'}) {
1161: $r->print('
1162: <script type="text/javascript">
1163: function photowindow(photolink) {
1164: var title = "Photo_Viewer";
1165: var options = "scrollbars=1,resizable=1,menubar=0";
1166: options += ",width=240,height=240";
1167: stdeditbrowser = open(photolink,title,options,"1");
1168: stdeditbrowser.focus();
1169: }
1170: </script>
1171: ');
1172: }
1173: $r->print(<<END);
1174: <input type="hidden" name="displayphotos" value="$displayphotos" />
1175: <input type="hidden" name="displayclickers" value="$displayclickers" />
1176: END
1177: }
1178: unless ($mode eq 'autoenroll') {
1179: $r->print(<<END);
1180: <input type="hidden" name="state" value="$env{'form.state'}" />
1181: END
1182: }
1183: $r->print(<<END);
1184: <input type="hidden" name="sortby" value="$sortby" />
1185: END
1186:
1187: my %lt=&Apache::lonlocal::texthash(
1188: 'username' => "username",
1189: 'domain' => "domain",
1190: 'id' => 'ID',
1191: 'fullname' => "name",
1192: 'section' => "section",
1193: 'groups' => "active groups",
1194: 'start' => "start date",
1195: 'end' => "end date",
1196: 'status' => "status",
1197: 'type' => "enroll type/action",
1198: 'email' => "email address",
1199: 'clicker' => "clicker id",
1200: 'photo' => "photo",
1201: );
1202: my @cols = ('username','domain','id','fullname');
1203: if ($context eq 'course') {
1204: push(@cols,'section');
1205: }
1206: push(@cols,('start','end'));
1207: if ($statusmode eq 'Any') {
1208: push(@cols,'status');
1209: }
1210: if ($context eq 'course') {
1211: push(@cols,'groups');
1212: }
1213: push(@cols,'email');
1214:
1215: if ($mode eq 'html' || $mode eq 'view') {
1216: if ($linkto eq 'aboutme') {
1217: $r->print(&mt("Select a user name to view the user's personal page."));
1218: } elsif ($linkto eq 'modify') {
1219: $r->print(&mt("Select a user name to modify the user's information"));
1220: }
1221: $r->print(<<END);
1222: <input type="hidden" name="sname" value="" />
1223: <input type="hidden" name="sdom" value="" />
1224: END
1225:
1226: $r->print("\n<p>\n".
1227: &Apache::loncommon::start_data_table().
1228: &Apache::loncommon::start_data_table_header_row());
1229: if ($mode eq 'autoenroll') {
1230: $r->print("
1231: <th><a href=\"javascript:document.studentform.sortby.value='type';document.studentform.submit();\">$lt{'type'}</a></th>
1232: ");
1233: } else {
1234: $r->print("
1235: <th>Count</th>
1236: ");
1237: }
1238: foreach my $item (@cols) {
1239: $r->print('<th><a href="javascript:document.studentform.sortby.value='.$item.';document.studentform.submit();">'.$lt{$item}.'</a></th>'."\n");
1240: }
1241: if ($context eq 'course') {
1242: # Clicker display on or off?
1243: my %clicker_options = &Apache::lonlocal::texthash(
1244: 'on' => 'Show',
1245: 'off' => 'Hide',
1246: );
1247: my $clickerchg = 'on';
1248: if ($displayclickers eq 'on') {
1249: $clickerchg = 'off';
1250: }
1251: $r->print(' <th>'."\n".' '.
1252: '<a href="javascript:document.studentform.displayclickers.value='.
1253: "'".$clickerchg."'".';document.studentform.submit();">'.
1254: $clicker_options{$clickerchg}.'</a> '.$lt{'clicker'}."\n".
1255: ' </th>'."\n");
1256:
1257: # Photo display on or off?
1258: if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
1259: my %photo_options = &Apache::lonlocal::texthash(
1260: 'on' => 'Show',
1261: 'off' => 'Hide',
1262: );
1263: my $photochg = 'on';
1264: if ($displayphotos eq 'on') {
1265: $photochg = 'off';
1266: }
1267: $r->print(' <th>'."\n".' '.
1268: '<a href="javascript:document.studentform.displayphotos.value='.
1269: "'".$photochg."'".';document.studentform.submit();">'.
1270: $photo_options{$photochg}.'</a> '.$lt{'photo'}."\n".
1271: ' </th>'."\n");
1272: }
1273: $r->print(&Apache::end_data_table_header_row());
1274: }
1275: # Done with the HTML header line
1276:
1277: } elsif ($mode eq 'csv') {
1278: #
1279: # Open a file
1280: $CSVfilename = '/prtspool/'.
1281: $env{'user.name'}.'_'.$env{'user.domain'}.'_'.
1282: time.'_'.rand(1000000000).'.csv';
1283: unless ($CSVfile = Apache::File->new('>/home/httpd'.$CSVfilename)) {
1284: $r->log_error("Couldn't open $CSVfilename for output $!");
1285: $r->print("Problems occured in writing the csv file. ".
1286: "This error has been logged. ".
1287: "Please alert your LON-CAPA administrator.");
1288: $CSVfile = undef;
1289: }
1290: #
1291: # Write headers and data to file
1292: if($statusmode eq 'Expired') {
1293: print $CSVfile '"'.&mt('Users with expired roles').'"'."\n"; }
1294: if($statusmode eq 'Future') {
1295: print $CSVfile '"'.&mt('Users with future roles').'"'."\n";
1296: }
1297: print $CSVfile '"'.join('","',map {
1298: &Apache::loncommon::csv_translate($lt{$_})
1299: } (@cols)).'"'."\n";
1300: } elsif ($mode eq 'excel') {
1301: # Create the excel spreadsheet
1302: ($excel_workbook,$excel_filename,$format) =
1303: &Apache::loncommon::create_workbook($r);
1304: return if (! defined($excel_workbook));
1305: $excel_sheet = $excel_workbook->addworksheet('userlist');
1306: #
1307: my $description;
1308: if ($context eq 'course') {
1309: $description = &mt('Class List for ').
1310: $env{'course.'.$env{'request.course.id'}.'.description'};
1311: } elsif ($context eq 'construction_space') {
1312: $description = &mt('List of co-authors for construction space for [_1]',
1313: &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'}));
1314: } else {
1315: $description = &mt('List of users for domain: [_1]',&Apache::lonnet::domain($env{'request.role.domain'},'description'));
1316: }
1317: $excel_sheet->write($row++,0,$description,$format->{'h1'});
1318: #
1319: my @colnames = map {$lt{$_}} (@cols);
1320: $excel_sheet->write($row++,0,\@colnames,$format->{'bold'});
1321: }
1322:
1323: # Done with header lines in all formats
1324:
1325: #
1326: # Sort the users
1327: my %index;
1328: my $i;
1329: foreach (@$keylist) {
1330: $index{$_} = $i++;
1331: }
1332: $index{'groups'} = scalar(@$keylist);
1333: my $index = $index{$sortby};
1334: my $second = $index{'username'};
1335: my $third = $index{'domain'};
1336: my @Sorted_Students = sort {
1337: lc($classlist->{$a}->[$index]) cmp lc($classlist->{$b}->[$index])
1338: ||
1339: lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second]) ||
1340: lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third])
1341: } (keys(%$classlist));
1342: my $studentcount = 0;
1343: my $autocount = 0;
1344: my $manualcount = 0;
1345: my $unlockcount = 0;
1346: my $lockcount = 0;
1347: foreach my $student (@Sorted_Students) {
1348: my $sdata = $classlist->{$student};
1349: my $groups = $classgroups->{$student};
1350: my $username = $sdata->[$index{'username'}];
1351: my $domain = $sdata->[$index{'domain'}];
1352: my $section = $sdata->[$index{'section'}];
1353: my $active_groups;
1354: if (ref($groups->{active}) eq 'HASH') {
1355: $active_groups = join(', ',keys(%{$groups->{'active'}}));
1356: }
1357: my $name = $sdata->[$index{'fullname'}];
1358: my $id = $sdata->[$index{'id'}];
1359: my $status = $sdata->[$index{'status'}];
1360: next if (($statusmode ne 'Any') && ($status ne $statusmode));
1361: my $start = $sdata->[$index{'start'}];
1362: my $end = $sdata->[$index{'end'}];
1363: if (! defined($start) || $start == 0) {
1364: $start = &mt('none');
1365: } else {
1366: $start = &Apache::lonlocal::locallocaltime($start);
1367: }
1368: if (! defined($end) || $end == 0) {
1369: $end = &mt('none');
1370: } else {
1371: $end = &Apache::lonlocal::locallocaltime($end);
1372: }
1373: my $status = $sdata->[$index{'status'}];
1374: next if ($status ne 'Active');
1375: #
1376: $r->print(&Apache::loncommon::start_data_table_row());
1377: $r->print(<<"END");
1378: <td><input type="checkbox" name="droplist" value="$student"></td>
1379: <td>$username</td>
1380: <td>$domain</td>
1381: <td>$id</td>
1382: <td>$name</td>
1383: <td>$start</td>
1384: <td>$end</td>
1385: END
1386: $r->print(&Apache::loncommon::end_data_table_row());
1387: }
1388: $r->print(&Apache::loncommon::end_data_table().'<br />');
1389: %lt=&Apache::lonlocal::texthash(
1390: 'dp' => "Expire User Roles",
1391: 'ca' => "check all",
1392: 'ua' => "uncheck all",
1393: );
1394: $r->print(<<"END");
1395: </p><p>
1396: <input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.studentform.droplist)">
1397: <input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.studentform.droplist)">
1398: <p><input type=submit value="$lt{'dp'}"></p>
1399: END
1400: return;
1401: }
1402:
1403: #################################################
1404: #################################################
1405: sub show_drop_list {
1406: my ($r,$classlist,$keylist,$nosort)=@_;
1407: my $cid=$env{'request.course.id'};
1408: if (! exists($env{'form.sortby'})) {
1409: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1410: ['sortby']);
1411: }
1412: my $sortby = $env{'form.sortby'};
1413: if ($sortby !~ /^(username|domain|section|groups|fullname|id|start|end)$/) {
1414: $sortby = 'username';
1415: }
1416: my $cdom = $env{'course.'.$cid.'.domain'};
1417: my $cnum = $env{'course.'.$cid,'.num'};
1418: my ($classgroups) = &Apache::loncoursedata::get_group_memberships(
1419: $classlist,$keylist,$cdom,$cnum);
1420: #
1421: my $action = "drop";
1422: $r->print(<<END);
1423: <input type="hidden" name="sortby" value="$sortby" />
1424: <input type="hidden" name="action" value="$action" />
1425: <input type="hidden" name="state" value="done" />
1426: <script>
1427: function checkAll(field) {
1428: for (i = 0; i < field.length; i++)
1429: field[i].checked = true ;
1430: }
1431:
1432: function uncheckAll(field) {
1433: for (i = 0; i < field.length; i++)
1434: field[i].checked = false ;
1435: }
1436: </script>
1437: <p>
1438: <input type="hidden" name="phase" value="four">
1439: END
1440:
1441: my %lt=&Apache::lonlocal::texthash('usrn' => "username",
1442: 'dom' => "domain",
1443: 'sn' => "student name",
1444: 'sec' => "section",
1445: 'start' => "start date",
1446: 'end' => "end date",
1447: 'groups' => "active groups",
1448: );
1449: if ($nosort) {
1450: $r->print(&Apache::loncommon::start_data_table());
1451: $r->print(<<END);
1452: <tr>
1453: <th> </th>
1454: <th>$lt{'usrn'}</th>
1455: <th>$lt{'dom'}</th>
1456: <th>ID</th>
1457: <th>$lt{'sn'}</th>
1458: <th>$lt{'sec'}</th>
1459: <th>$lt{'start'}</th>
1460: <th>$lt{'end'}</th>
1461: <th>$lt{'groups'}</th>
1462: </tr>
1463: END
1464:
1465: } else {
1466: $r->print(&Apache::loncommon::start_data_table());
1467: $r->print(<<END);
1468: <tr><th> </th>
1469: <th>
1470: <a href="/adm/dropadd?action=$action&sortby=username">$lt{'usrn'}</a>
1471: </th><th>
1472: <a href="/adm/dropadd?action=$action&sortby=domain">$lt{'dom'}</a>
1473: </th><th>
1474: <a href="/adm/dropadd?action=$action&sortby=id">ID</a>
1475: </th><th>
1476: <a href="/adm/dropadd?action=$action&sortby=fullname">$lt{'sn'}</a>
1477: </th><th>
1478: <a href="/adm/dropadd?action=$action&sortby=section">$lt{'sec'}</a>
1479: </th><th>
1480: <a href="/adm/dropadd?action=$action&sortby=start">$lt{'start'}</a>
1481: </th><th>
1482: <a href="/adm/dropadd?action=$action&sortby=end">$lt{'end'}</a>
1483: </th><th>
1484: <a href="/adm/dropadd?action=$action&sortby=groups">$lt{'groups'}</a>
1485: </th>
1486: </tr>
1487: END
1488: }
1489: #
1490: # Sort the students
1491: my %index;
1492: my $i;
1493: foreach (@$keylist) {
1494: $index{$_} = $i++;
1495: }
1496: $index{'groups'} = scalar(@$keylist);
1497: my $index = $index{$sortby};
1498: my $second = $index{'username'};
1499: my $third = $index{'domain'};
1500: my @Sorted_Students = sort {
1501: lc($classlist->{$a}->[$index]) cmp lc($classlist->{$b}->[$index])
1502: ||
1503: lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second])
1504: ||
1505: lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third])
1506: } (keys(%$classlist));
1507: foreach my $student (@Sorted_Students) {
1508: my $error;
1509: my $sdata = $classlist->{$student};
1510: my $username = $sdata->[$index{'username'}];
1511: my $domain = $sdata->[$index{'domain'}];
1512: my $section = $sdata->[$index{'section'}];
1513: my $name = $sdata->[$index{'fullname'}];
1514: my $id = $sdata->[$index{'id'}];
1515: my $start = $sdata->[$index{'start'}];
1516: my $end = $sdata->[$index{'end'}];
1517: my $groups = $classgroups->{$student};
1518: my $active_groups;
1519: if (ref($groups->{active}) eq 'HASH') {
1520: $active_groups = join(', ',keys(%{$groups->{'active'}}));
1521: }
1522: if (! defined($start) || $start == 0) {
1523: $start = &mt('none');
1524: } else {
1525: $start = &Apache::lonlocal::locallocaltime($start);
1526: }
1527: if (! defined($end) || $end == 0) {
1528: $end = &mt('none');
1529: } else {
1530: $end = &Apache::lonlocal::locallocaltime($end);
1531: }
1532: my $status = $sdata->[$index{'status'}];
1533: next if ($status ne 'Active');
1534: #
1535: $r->print(&Apache::loncommon::start_data_table_row());
1536: $r->print(<<"END");
1537: <td><input type="checkbox" name="droplist" value="$student"></td>
1538: <td>$username</td>
1539: <td>$domain</td>
1540: <td>$id</td>
1541: <td>$name</td>
1542: <td>$section</td>
1543: <td>$start</td>
1544: <td>$end</td>
1545: <td>$active_groups</td>
1546: END
1547: $r->print(&Apache::loncommon::end_data_table_row());
1548: }
1549: $r->print(&Apache::loncommon::end_data_table().'<br />');
1550: %lt=&Apache::lonlocal::texthash(
1551: 'dp' => "Expire Users' Roles",
1552: 'ca' => "check all",
1553: 'ua' => "uncheck all",
1554: );
1555: $r->print(<<"END");
1556: </p><p>
1557: <input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.studentform.droplist)">
1558: <input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.studentform.droplist)">
1559: <p><input type=submit value="$lt{'dp'}"></p>
1560: END
1561: return;
1562: }
1563:
1564:
1565:
1566: #
1567: # Print out the initial form to get the file containing a list of users
1568: #
1569: sub print_first_users_upload_form {
1570: my ($r,$context) = @_;
1571: my $str;
1572: $str = '<input type="hidden" name="phase" value="two">';
1573: $str .= '<input type="hidden" name="action" value="upload" />';
1574: $str .= '<input type="hidden" name="state" value="got_file" />';
1575: $str .= "<h3>".&mt('Upload a list of users')."</h3>\n";
1576: $str .= &Apache::loncommon::upfile_select_html();
1577: $str .= "<p>\n";
1578: $str .= '<input type="submit" name="fileupload" value="'.
1579: &mt('Upload users list').'">'."\n";
1580: $str .= '<label><input type="checkbox" name="noFirstLine" /> '.
1581: &mt('Ignore First Line')."</label></p>\n";
1582: $str .= &Apache::loncommon::help_open_topic("Course_Create_Class_List",
1583: &mt("How do I create a users list from a spreadsheet")).
1584: "<br />\n";
1585: $str .= &Apache::loncommon::help_open_topic("Course_Convert_To_CSV",
1586: &mt("How do I create a CSV file from a spreadsheet")).
1587: "<br />\n";
1588: $str .= &Apache::loncommon::end_page();
1589: $r->print($str);
1590: return;
1591: }
1592:
1593: # ================================================= Drop/Add from uploaded file
1594: sub upfile_drop_add {
1595: my ($r,$context) = @_;
1596: &Apache::loncommon::load_tmp_file($r);
1597: my @userdata=&Apache::loncommon::upfile_record_sep();
1598: if($env{'form.noFirstLine'}){shift(@userdata);}
1599: my @keyfields = split(/\,/,$env{'form.keyfields'});
1600: my %fields=();
1601: for (my $i=0; $i<=$env{'form.nfields'}; $i++) {
1602: if ($env{'form.upfile_associate'} eq 'reverse') {
1603: if ($env{'form.f'.$i} ne 'none') {
1604: $fields{$keyfields[$i]}=$env{'form.f'.$i};
1605: }
1606: } else {
1607: $fields{$env{'form.f'.$i}}=$keyfields[$i];
1608: }
1609: }
1610: #
1611: # Store the field choices away
1612: foreach my $field (qw/username names
1613: fname mname lname gen id sec ipwd email role/) {
1614: $env{'form.'.$field.'_choice'}=$fields{$field};
1615: }
1616: &Apache::loncommon::store_course_settings('enrollment_upload',
1617: { 'username_choice' => 'scalar',
1618: 'names_choice' => 'scalar',
1619: 'fname_choice' => 'scalar',
1620: 'mname_choice' => 'scalar',
1621: 'lname_choice' => 'scalar',
1622: 'gen_choice' => 'scalar',
1623: 'id_choice' => 'scalar',
1624: 'sec_choice' => 'scalar',
1625: 'ipwd_choice' => 'scalar',
1626: 'email_choice' => 'scalar',
1627: 'role_choice' => 'scalar' });
1628: #
1629: my ($startdate,$enddate) = &get_dates_from_form();
1630: if ($env{'form.makedatesdefault'}) {
1631: $r->print(&make_dates_default($startdate,$enddate));
1632: }
1633: # Determine domain and desired host (home server)
1634: my $domain=$env{'request.role.domain'};
1635: my $desiredhost = $env{'form.lcserver'};
1636: if (lc($desiredhost) eq 'default') {
1637: $desiredhost = undef;
1638: } else {
1639: my %home_servers = &Apache::lonnet::get_servers($domain,'library');
1640: if (! exists($home_servers{$desiredhost})) {
1641: $r->print('<span class="LC_error">'.&mt('Error').
1642: &mt('Invalid home server specified').'</span>');
1643: $r->print(&Apache::loncommon::end_page());
1644: return;
1645: }
1646: }
1647: # Determine authentication mechanism
1648: my $changeauth;
1649: if ($context eq 'domain') {
1650: $changeauth = $env{'form.changeauth'};
1651: }
1652: my $amode = '';
1653: my $genpwd = '';
1654: if ($env{'form.login'} eq 'krb') {
1655: $amode='krb';
1656: $amode.=$env{'form.krbver'};
1657: $genpwd=$env{'form.krbarg'};
1658: } elsif ($env{'form.login'} eq 'int') {
1659: $amode='internal';
1660: if ((defined($env{'form.intarg'})) && ($env{'form.intarg'})) {
1661: $genpwd=$env{'form.intarg'};
1662: }
1663: } elsif ($env{'form.login'} eq 'loc') {
1664: $amode='localauth';
1665: if ((defined($env{'form.locarg'})) && ($env{'form.locarg'})) {
1666: $genpwd=$env{'form.locarg'};
1667: }
1668: }
1669: if ($amode =~ /^krb/) {
1670: if (! defined($genpwd) || $genpwd eq '') {
1671: $r->print('<span class="Error">'.
1672: &mt('Unable to enroll users').' '.
1673: &mt('No Kerberos domain was specified.').'</span></p>');
1674: $amode = ''; # This causes the loop below to be skipped
1675: }
1676: }
1677: my ($cid,$defaultsec,$defaultrole,$setting);
1678: if ($context eq 'domain') {
1679: $setting = $env{'form.roleaction'};
1680: if ($setting eq 'domain') {
1681: $defaultrole = $env{'form.defaultrole'};
1682: } elsif ($setting eq 'course') {
1683: $defaultrole = $env{'form.courserole'};
1684: }
1685: } elsif ($context eq 'construction_space') {
1686: $defaultrole = $env{'form.defaultrole'};
1687: }
1688: if ($context eq 'domain' && $setting eq 'course') {
1689: if ($env{'form.newsec'} ne '') {
1690: $defaultsec = $env{'form.newsec'};
1691: } elsif ($env{'form.defaultsec'} ne '') {
1692: $defaultsec = $env{'form.defaultsec'}
1693: }
1694: }
1695: if ($env{'request.course.id'} ne '') {
1696: $cid = $env{'request.course.id'};
1697: } elsif ($env{'form.defaultdomain'} ne '' && $env{'form.defaultcourse'} ne '') {
1698: $cid = $env{'form.defaultdomain'}.'_'.
1699: $env{'form.defaultcourse'};
1700: }
1701: if ( $domain eq &LONCAPA::clean_domain($domain)
1702: && ($amode ne '')) {
1703: #######################################
1704: ## Add/Modify Users ##
1705: #######################################
1706: if ($context eq 'course') {
1707: $r->print('<h3>'.&mt('Enrolling Users')."</h3>\n<p>\n");
1708: } elsif ($context eq 'construction_space') {
1709: $r->print('<h3>'.&mt('Updating Co-authors')."</h3>\n<p>\n");
1710: } else {
1711: $r->print('<h3>'.&mt('Adding/Modifying Users')."</h3>\n<p>\n");
1712: }
1713: my %counts = (
1714: user => 0,
1715: auth => 0,
1716: role => 0,
1717: );
1718: my $flushc=0;
1719: my %student=();
1720: my %curr_groups;
1721: my %userchg;
1722: if ($context eq 'course') {
1723: # Get information about course groups
1724: %curr_groups = &Apache::longroup::coursegroups();
1725: }
1726: # Get new users list
1727: foreach (@userdata) {
1728: my %entries=&Apache::loncommon::record_sep($_);
1729: # Determine user name
1730: unless (($entries{$fields{'username'}} eq '') ||
1731: (!defined($entries{$fields{'username'}}))) {
1732: my ($fname, $mname, $lname,$gen) = ('','','','');
1733: if (defined($fields{'names'})) {
1734: ($lname,$fname,$mname)=($entries{$fields{'names'}}=~
1735: /([^\,]+)\,\s*(\w+)\s*(.*)$/);
1736: } else {
1737: if (defined($fields{'fname'})) {
1738: $fname=$entries{$fields{'fname'}};
1739: }
1740: if (defined($fields{'mname'})) {
1741: $mname=$entries{$fields{'mname'}};
1742: }
1743: if (defined($fields{'lname'})) {
1744: $lname=$entries{$fields{'lname'}};
1745: }
1746: if (defined($fields{'gen'})) {
1747: $gen=$entries{$fields{'gen'}};
1748: }
1749: }
1750: if ($entries{$fields{'username'}}
1751: ne &LONCAPA::clean_username($entries{$fields{'username'}})) {
1752: $r->print('<br />'.
1753: &mt('<b>[_1]</b>: Unacceptable username for user [_2] [_3] [_4] [_5]',
1754: $entries{$fields{'username'}},$fname,$mname,$lname,$gen).
1755: '</b>');
1756: } else {
1757: my $username = $entries{$fields{'username'}};
1758: my $sec;
1759: if ($context eq 'course' || $setting eq 'course') {
1760: # determine section number
1761: if (defined($fields{'sec'})) {
1762: if (defined($entries{$fields{'sec'}})) {
1763: $sec=$entries{$fields{'sec'}};
1764: }
1765: } else {
1766: $sec = $defaultsec;
1767: }
1768: # remove non alphanumeric values from section
1769: $sec =~ s/\W//g;
1770: if ($sec eq "none" || $sec eq 'all') {
1771: $r->print('<br />'.
1772: &mt('<b>[_1]</b>: Unable to enroll: section name "[_2]" for user [_3] [_4] [_5] [_6] is a reserved word.',
1773: $username,$sec,$fname,$mname,$lname,$gen));
1774: next;
1775: } elsif (($sec ne '') && (exists($curr_groups{$sec}))) {
1776: $r->print('<br />'.
1777: &mt('<b>[_1]</b>: Unable to enroll: section name "[_2]" for user [_3] [_4] [_5] [_6] is a course group. Section names and group names must be distinct.',
1778: $username,$sec,$fname,$mname,$lname,$gen));
1779: next;
1780: }
1781: }
1782: # determine id number
1783: my $id='';
1784: if (defined($fields{'id'})) {
1785: if (defined($entries{$fields{'id'}})) {
1786: $id=$entries{$fields{'id'}};
1787: }
1788: $id=~tr/A-Z/a-z/;
1789: }
1790: # determine email address
1791: my $email='';
1792: if (defined($fields{'email'})) {
1793: if (defined($entries{$fields{'email'}})) {
1794: $email=$entries{$fields{'email'}};
1795: unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; } }
1796: }
1797: # determine user password
1798: my $password = $genpwd;
1799: if (defined($fields{'ipwd'})) {
1800: if ($entries{$fields{'ipwd'}}) {
1801: $password=$entries{$fields{'ipwd'}};
1802: }
1803: }
1804: # determine user role
1805: my $role = '';
1806: if (defined($fields{'role'})) {
1807: if ($entries{$fields{'role'}}) {
1808: my @poss_roles =
1809: &curr_role_permissions($context,$setting);
1810: if (grep(/^\Q$entries{$fields{'role'}}\E/,@poss_roles)) {
1811: $role=$entries{$fields{'role'}};
1812: } else {
1813: my $rolestr = join(', ',@poss_roles);
1814: $r->print('<br />'.
1815: &mt('<b>[_1]</b>: You do not have permission to add the requested role [_2] for the user.',$entries{$fields{'username'}},$entries{$fields{'role'}}).'<br />'.&mt('Allowable role(s) is/are: [_1].',$rolestr)."\n");
1816: next;
1817: }
1818: }
1819: }
1820: if ($role eq '') {
1821: $role = $defaultrole;
1822: }
1823: # Clean up whitespace
1824: foreach (\$domain,\$username,\$id,\$fname,\$mname,
1825: \$lname,\$gen,\$sec,\$role) {
1826: $$_ =~ s/(\s+$|^\s+)//g;
1827: }
1828: if ($password || $env{'form.login'} eq 'loc') {
1829: my ($userresult,$authresult,$roleresult);
1830: if ($role eq 'st') {
1831: &modifystudent($domain,$username,$cid,$sec,
1832: $desiredhost);
1833: $roleresult =
1834: &Apache::lonnet::modifystudent
1835: ($domain,$username,$id,$amode,$password,
1836: $fname,$mname,$lname,$gen,$sec,$enddate,
1837: $startdate,$env{'form.forceid'},
1838: $desiredhost,$email);
1839: } else {
1840: ($userresult,$authresult,$roleresult) =
1841: &modifyuserrole($context,$setting,
1842: $changeauth,$cid,$domain,$username,
1843: $id,$amode,$password,$fname,
1844: $mname,$lname,$gen,$sec,
1845: $env{'form.forceid'},$desiredhost,
1846: $email,$role,$enddate,$startdate);
1847: }
1848: $flushc =
1849: &user_change_result($r,$userresult,$authresult,
1850: $roleresult,\%counts,$flushc,
1851: $username,%userchg);
1852: } else {
1853: if ($context eq 'course') {
1854: $r->print('<br />'.
1855: &mt('<b>[_1]</b>: Unable to enroll. No password specified.',$username)
1856: );
1857: } elsif ($context eq 'construction_space') {
1858: $r->print('<br />'.
1859: &mt('<b>[_1]</b>: Unable to add co-author. No password specified.',$username)
1860: );
1861: } else {
1862: $r->print('<br />'.
1863: &mt('<b>[_1]</b>: Unable to add user. No password specified.',$username)
1864: );
1865: }
1866: }
1867: }
1868: }
1869: } # end of foreach (@userdata)
1870: # Flush the course logs so reverse user roles immediately updated
1871: if ($context eq 'course' || ($context eq 'domain' && $setting eq 'course')) {
1872: &Apache::lonnet::flushcourselogs();
1873: }
1874: $r->print("</p>\n<p>\n".&mt('Processed [_1] user(s).',$counts{'user'}).
1875: "</p>\n");
1876: if ($counts{'role'} > 0) {
1877: $r->print("<p>\n".
1878: &mt('Roles added for [_1] users. If user is active, the new role will be available when the user next logs in to LON-CAPA.',$counts{'role'})."</p>\n");
1879: }
1880: if ($counts{'auth'} > 0) {
1881: $r->print("<p>\n".
1882: &mt('Authentication changed for [_1] existing users.',
1883: $counts{'auth'})."</p>\n");
1884: }
1885: $r->print('<form name="uploadresult" action="/adm/createuser">');
1886: $r->print(&Apache::lonhtmlcommon::echo_form_input(['phase','prevphase','currstate']));
1887: $r->print('</form>');
1888: #####################################
1889: # Drop students #
1890: #####################################
1891: if ($env{'form.fullup'} eq 'yes') {
1892: $r->print('<h3>'.&mt('Dropping Students')."</h3>\n");
1893: # Get current classlist
1894: my ($classlist,$keylist)=&Apache::loncoursedata::get_classlist();
1895: if (! defined($classlist)) {
1896: $r->print(&mt('There are no students currently enrolled.').
1897: "\n");
1898: } else {
1899: # Remove the students we just added from the list of students.
1900: foreach (@userdata) {
1901: my %entries=&Apache::loncommon::record_sep($_);
1902: unless (($entries{$fields{'username'}} eq '') ||
1903: (!defined($entries{$fields{'username'}}))) {
1904: delete($classlist->{$entries{$fields{'username'}}.
1905: ':'.$domain});
1906: }
1907: }
1908: # Print out list of dropped students.
1909: &show_drop_list($r,$classlist,$keylist,'nosort');
1910: }
1911: }
1912: } # end of unless
1913: }
1914:
1915: sub user_change_result {
1916: my ($r,$userresult,$authresult,$roleresult,$counts,$flushc,$username,
1917: $userchg) = @_;
1918: my $okresult = 0;
1919: if ($userresult ne 'ok') {
1920: if ($userresult =~ /^error:(.+)$/) {
1921: my $error = $1;
1922: $r->print('<br />'.
1923: &mt('<b>[_1]</b>: Unable to add/modify: [_2]',$username,$error));
1924: }
1925: } else {
1926: $counts->{'user'} ++;
1927: $okresult = 1;
1928: }
1929: if ($authresult ne 'ok') {
1930: if ($authresult =~ /^error:(.+)$/) {
1931: my $error = $1;
1932: $r->print('<br />'.
1933: &mt('<b>[_1]</b>: Unable to modify authentication: [_2]',$username,$error));
1934: }
1935: } else {
1936: $counts->{'auth'} ++;
1937: $okresult = 1;
1938: }
1939: if ($roleresult ne 'ok') {
1940: if ($roleresult =~ /^error:(.+)$/) {
1941: my $error = $1;
1942: $r->print('<br />'.
1943: &mt('<b>[_1]</b>: Unable to add role: [_2]',$username,$error));
1944: }
1945: } else {
1946: $counts->{'role'} ++;
1947: $okresult = 1;
1948: }
1949: if ($okresult) {
1950: $flushc++;
1951: $userchg->{$username}=1;
1952: $r->print('. ');
1953: if ($flushc>15) {
1954: $r->rflush;
1955: $flushc=0;
1956: }
1957: }
1958: return $flushc;
1959: }
1960:
1961: # ========================================================= Menu Phase Two Drop
1962: sub print_expire_menu {
1963: my ($r,$context) = @_;
1964: $r->print("<h3>".&mt("Expire Users' Roles")."</h3>");
1965: my $cid=$env{'request.course.id'};
1966: my ($classlist,$keylist) = &Apache::loncoursedata::get_classlist();
1967: if (! defined($classlist)) {
1968: $r->print(&mt('There are no students currently enrolled.')."\n");
1969: return;
1970: }
1971: # Print out the available choices
1972: &show_drop_list($r,$classlist,$keylist);
1973: return;
1974: }
1975:
1976:
1977: # ================================================================== Phase four
1978:
1979: sub expire_user_list {
1980: my ($r,$context) = @_;
1981: my $count=0;
1982: my @droplist = &Apache::loncommon::get_env_multiple('form.droplist');
1983: foreach (@droplist) {
1984: my ($uname,$udom)=split(/\:/,$_);
1985: # drop student
1986: my $result = &modifystudent($udom,$uname,$env{'request.course.id'});
1987: if ($result eq 'ok' || $result eq 'ok:') {
1988: $r->print(&mt('Dropped [_1]',$uname.'@'.$udom).'<br>');
1989: $count++;
1990: } else {
1991: $r->print(
1992: &mt('Error dropping [_1]:[_2]',$uname.'@'.$udom,$result).
1993: '<br />');
1994: }
1995: }
1996: $r->print('<p><b>'.&mt('Dropped [_1] user(s).',$count).'</b></p>');
1997: $r->print('<p>'.&mt('Re-enrollment will re-activate data.')) if ($count);
1998: }
1999:
2000: sub section_check_js {
2001: my $groupslist;
2002: my %curr_groups = &Apache::longroup::coursegroups();
2003: if (%curr_groups) {
2004: $groupslist = join('","',sort(keys(%curr_groups)));
2005: }
2006: return <<"END";
2007: function validate(caller) {
2008: var groups = new Array("$groupslist");
2009: var secname = caller.value;
2010: if ((secname == 'all') || (secname == 'none')) {
2011: alert("'"+secname+"' may not be used as the name for a section, as it is a reserved word.\\nPlease choose a different section name.");
2012: return 'error';
2013: }
2014: if (secname != '') {
2015: for (var k=0; k<groups.length; k++) {
2016: if (secname == groups[k]) {
2017: alert("'"+secname+"' may not be used as the name for a section, as it is the name of a course group.\\nSection names and group names must be distinct. Please choose a different section name.");
2018: return 'error';
2019: }
2020: }
2021: }
2022: return 'ok';
2023: }
2024: END
2025: }
2026:
2027: sub set_login {
2028: my ($dom,$authformkrb,$authformint,$authformloc) = @_;
2029: my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
2030: my $response;
2031: my ($authnum,%can_assign) =
2032: &Apache::loncommon::get_assignable_auth($dom);
2033: if ($authnum) {
2034: $response = &Apache::loncommon::start_data_table();
2035: if (($can_assign{'krb4'}) || ($can_assign{'krb5'})) {
2036: $response .= &Apache::loncommon::start_data_table_row().
2037: '<td>'.$authformkrb.'</td>'.
2038: &Apache::loncommon::end_data_table_row()."\n";
2039: }
2040: if ($can_assign{'int'}) {
2041: $response .= &Apache::loncommon::start_data_table_row().
2042: '<td>'.$authformint.'</td>'.
2043: &Apache::loncommon::end_data_table_row()."\n"
2044: }
2045: if ($can_assign{'loc'}) {
2046: $response .= &Apache::loncommon::start_data_table_row().
2047: '<td>'.$authformloc.'</td>'.
2048: &Apache::loncommon::end_data_table_row()."\n";
2049: }
2050: $response .= &Apache::loncommon::end_data_table();
2051: }
2052: return $response;
2053: }
2054:
2055: 1;
2056:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>