Annotation of loncom/cgi/createpending.pl, revision 1.2
1.1 raeburn 1: #!/usr/bin/perl
2: $|=1;
3: # Script to complete processing of course/community requests
1.2 ! raeburn 4: # for unofficial courses, textbook courses, communities and
! 5: # placement tests queued pending validation, once validated.
1.1 raeburn 6: #
1.2 ! raeburn 7: # $Id: createpending.pl,v 1.1 2014/04/16 15:36:38 raeburn Exp $
1.1 raeburn 8: #
9: # Copyright Michigan State University Board of Trustees
10: #
11: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
12: #
13: # LON-CAPA is free software; you can redistribute it and/or modify
14: # it under the terms of the GNU General Public License as published by
15: # the Free Software Foundation; either version 2 of the License, or
16: # (at your option) any later version.
17: #
18: # LON-CAPA is distributed in the hope that it will be useful,
19: # but WITHOUT ANY WARRANTY; without even the implied warranty of
20: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21: # GNU General Public License for more details.
22: #
23: # You should have received a copy of the GNU General Public License
24: # along with LON-CAPA; if not, write to the Free Software
25: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26: #
27: # /home/httpd/html/adm/gpl.txt
28: #
29: # http://www.lon-capa.org/
30: #
31: #############################################
32: #############################################
33:
34: =pod
35:
36: =head1 NAME
37:
38: createpending.pl
39:
40: =head1 SYNOPSIS
41:
42: CGI script to process pending course/community requests
43: and output URL which user will return to if course
44: creation successful.
45:
46: Data expected by createpending.pl are the same fields
47: as included for a POST to the external validation site,
48: as specified in the domain configuration for
49: course request validation, which can be some or all of:
50:
51: 1. courseID (domain_coursenum)
52: 2. requester's username:domain
53: 3. course type
54: 4. course description
55:
56: Both 1 and 2 are required, whereas 3 and 4 are optional.
57:
58: The data can be passed either in a query string or as
59: POSTed form variables.
60:
61: =head1 Subroutines
62:
63: =over 4
64:
65: =cut
66:
67: #############################################
68: #############################################
69:
70: use strict;
71:
72: use lib '/home/httpd/lib/perl/';
73: use LONCAPA::loncgi;
74: use Apache::lonnet;
75: use Apache::loncommon();
76: use Apache::lonuserutils();
77: use Apache::loncoursequeueadmin();
78: use Apache::lonlocal;
79: use LONCAPA;
80: use IO::Socket;
81:
82: &main();
83: exit 0;
84:
85: #############################################
86: #############################################
87:
88: =pod
89:
90: =item main()
91:
92: Inputs: None
93:
94: Returns: Nothing
95:
96: Description: Main program. Determines if requesting IP is the IP
97: of the validation server. Side effect is to
98: print content (with text/plain HTTP header).
99: Content is URL course requester should use
100: to access the course, when course creation
101: is successful.
102:
103: =cut
104:
105: #############################################
106: #############################################
107:
108: sub main {
109: my $query = CGI->new();
110:
111: my @okdoms = &Apache::lonnet::current_machine_domains();
112:
113: my $perlvar = &LONCAPA::Configuration::read_conf();
114: my $lonidsdir;
115: if (ref($perlvar) eq 'HASH') {
116: $lonidsdir = $perlvar->{'lonIDsDir'};
117: }
118: undef($perlvar);
119:
120: my ($cdom,$cnum);
121: if ($query->param('course')) {
122: my $course = $query->param('course');
123: $course =~ s/^\s+|\s+$//g;
124: if ($course =~ /^($LONCAPA::match_domain)_($LONCAPA::match_courseid)$/) {
125: my $possdom = $1;
126: my $domdesc = &Apache::lonnet::domain($possdom);
127: unless ($domdesc eq '') {
128: $cdom = $possdom;
129: }
130: } else {
131: print &LONCAPA::loncgi::cgi_header('text/plain',1);
132: return;
133: }
134: }
135:
136: if ($cdom eq '') {
137: print &LONCAPA::loncgi::cgi_header('text/plain',1);
138: return;
139: }
140:
141: if (!grep(/^\Q$cdom\E$/,@okdoms)) {
142: print &LONCAPA::loncgi::cgi_header('text/plain',1);
143: return;
144: }
145:
146: my %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$cdom);
147: my $remote_ip = $ENV{'REMOTE_ADDR'};
148: my $allowed;
149:
150: if (ref($domconfig{'requestcourses'}) eq 'HASH') {
151: if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
152: if ($domconfig{'requestcourses'}{'validation'}{'url'} =~ m{^https?://([^/]+)/}) {
153: my $ip = gethostbyname($1);
154: if ($ip ne '') {
155: my $validator_ip = inet_ntoa($ip);
156: if (($validator_ip ne '') && ($remote_ip eq $validator_ip)) {
157: $allowed = 1;
158: }
159: }
160: } elsif ($domconfig{'requestcourses'}{'validation'}{'url'} =~ m{^/}) {
161: if ($remote_ip ne '') {
162: if (($remote_ip eq '127.0.0.1') || ($remote_ip eq $ENV{'SERVER_ADDR'})) {
163: $allowed = 1;
164: }
165: }
166: }
167: }
168: }
169:
170: my (%params,@fields,$numrequired);
171: if ($allowed) {
172: &Apache::lonlocal::get_language_handle();
173: my ($validreq,@fields);
174: if (ref($domconfig{'requestcourses'}) eq 'HASH') {
175: if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
176: if (ref($domconfig{'requestcourses'}{'validation'}{'fields'}) eq 'ARRAY') {
177: $numrequired = scalar(@{$domconfig{'requestcourses'}{'validation'}{'fields'}});
178: foreach my $field (@{$domconfig{'requestcourses'}{'validation'}{'fields'}}) {
179: $params{$field} = $query->param($field);
180: if ($field eq 'owner') {
181: if ($query->param($field) =~ /^(LONCAPA::match_username):($LONCAPA::match_domain)$$/) {
182: $params{$field} = $query->param($field);
183: }
184: }
185: if ($field eq 'course') {
186: if ($query->param($field) =~ /^(?:LONCAPA::match_domain)_(?:LONCAPA::match_courseid)$/) {
187: $params{$field} = $query->param($field);
188: }
189: }
190: if ($field eq 'coursetype') {
1.2 ! raeburn 191: if ($query->param($field) =~ /^(unofficial|community|textbook|placement)$/) {
1.1 raeburn 192: $params{$field} = $query->param($field);
193: }
194: }
195: if ($field eq 'description') {
196: $params{$field} = $query->param($field);
197: }
198: }
199: if ($numrequired == scalar(keys(%params))) {
200: $validreq = 1;
201: }
202: }
203: }
204: }
205: print &LONCAPA::loncgi::cgi_header('text/plain',1);
206: if ($validreq) {
207: $params{'token'} = $query->param('token');
208: my ($url,$code) = &process_courserequest($cdom,$lonidsdir,\%params);
209: if ($url) {
210: print("$url\n$code");
211: }
212: }
213: } else {
214: print &LONCAPA::loncgi::cgi_header('text/plain',1);
215: }
216: return;
217: }
218:
219: #############################################
220: #############################################
221:
222: =pod
223:
224: =item process_courserequest()
225:
226: Inputs: $dom - domain of course to be created
227: $lonidsdir - Path to directory containing session files for users.
228: Perl var lonIDsDir is read from loncapa_apache.conf
229: in &main() and passed as third arg to process_courserequest().
230: $params - references to hash of key=value pairs from input
231: (either query string or POSTed). Keys which will be
232: used are fields specified in domain configuration
233: for validation of pending unofficial courses, textbook courses,
1.2 ! raeburn 234: communities and placement tests.
1.1 raeburn 235:
236: Returns: $url,$code - If processing of the pending course request succeeds,
237: a URL is returned which may be used by the requester to access
238: the new course. If a six character code was also set, that is
239: returned as a second item.
240:
241: Description: Processes a pending course creation request, given the username
242: and domain of the requester and the courseID of the new course.
243:
244: =cut
245:
246: #############################################
247: #############################################
248:
249: sub process_courserequest {
250: my ($dom,$lonidsdir,$params) = @_;
251: return () unless (ref($params) eq 'HASH');
252:
253: my $cid = $params->{'course'};
254: my $owner = $params->{'owner'};
255: my $token = $params->{'token'};
256: my ($ownername,$ownerdom) = split(/:/,$owner);
257: my $ownerhome = &Apache::lonnet::homeserver($ownername,$ownerdom);
258: return () if ($ownerhome eq 'no_host');
259: return () if ($cid eq '');
260: my ($cdom,$cnum) = split(/_/,$cid);
261: my $chome = &Apache::lonnet::homeserver($cnum,$cdom);
262: return () unless ($chome eq 'no_host');
263: my ($url,$code);
264: my $confname = &Apache::lonnet::get_domainconfiguser($cdom);
265: my %queuehash = &Apache::lonnet::get('courserequestqueue',
266: [$cnum.'_pending'],$cdom,$confname);
267: return () unless (ref($queuehash{$cnum.'_pending'}) eq 'HASH');
268: my ($crstype,$lonhost,$hostname,$handle);
269: $crstype = $queuehash{$cnum.'_pending'}{'crstype'};
270: $lonhost = $queuehash{$cnum.'_pending'}{'lonhost'};
271: if ($lonhost ne '') {
272: $hostname = &Apache::lonnet::hostname($lonhost);
273: }
274: my $savedtoken = $queuehash{$cnum.'_pending'}{'token'};
275: my $process;
276: if ($token ne '') {
277: if ($token eq $savedtoken) {
278: $process = 1;
279: }
280: }
281: return () unless ($process);
282:
283: my %domdefs = &Apache::lonnet::get_domain_defaults($cdom);
284: my ($logmsg,$newusermsg,$addresult,$enrollcount,$response,$keysmsg,%longroles,$code,
285: $dcname,$dcdom);
286: my $type = 'Course';
287: my $now = time;
288: if ($crstype eq 'community') {
289: $type = 'Community';
290: }
291: my @roles = &Apache::lonuserutils::roles_by_context('course','',$type);
292: foreach my $role (@roles) {
293: $longroles{$role}=&Apache::lonnet::plaintext($role,$type);
294: }
295: my @permissions = ('mau','ccc','cin','cta','cep','ccr','cst');
296: my %permissionflags = ();
297: &set_permissions(\%permissionflags,\@permissions);
298: my %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$cdom);
299: if (ref($domconfig{'requestcourses'}) eq 'HASH') {
300: if (ref($domconfig{'requestcourses'}{'validation'}) eq 'HASH') {
301: if ($domconfig{'requestcourses'}{'validation'}{'dc'}) {
302: ($dcname,$dcdom) = split(/:/,$domconfig{'requestcourses'}{'validation'}{'dc'});
303: }
304: }
305: }
306: my %history = &Apache::lonnet::restore($cid,'courserequests',$ownerdom,$ownername);
307: if (ref($history{'details'}) eq 'HASH') {
308: my %reqhash = (
309: reqtime => $now,
310: crstype => $crstype,
311: details => $history{'details'},
312: );
313: my %customitems;
314: my $fullname = &Apache::loncommon::plainname($ownername,$ownerdom);
315: my $inprocess = &Apache::lonnet::auto_crsreq_update($cdom,$cnum,$crstype,'process',
316: $ownername,$ownerdom,$fullname,
317: $history{'details'}{'cdescr'});
318: if (ref($inprocess) eq 'HASH') {
319: foreach my $key (keys(%{$inprocess})) {
320: if (exists($history{'details'}{$key})) {
321: $customitems{$key} = $history{'details'}{$key};
322: }
323: }
324: }
325: &set_dc_env($dcname,$dcdom,$dcdom,$ownername,$ownerdom,$crstype);
326: my ($result,$postprocess) = &Apache::loncoursequeueadmin::course_creation($cdom,$cnum,
327: 'domain',$history{'details'},\$logmsg,\$newusermsg,
328: \$addresult,\$enrollcount,\$response,\$keysmsg,\%domdefs,
329: \%longroles,\$code,\%customitems);
330: &unset_dc_env($dcname,$dcdom,$ownername,$ownerdom,$crstype);
331: if ($result eq 'created') {
332: my $disposition = 'created';
333: my $reqstatus = 'created';
334: if (($code) || ((ref($postprocess) eq 'HASH') &&
335: (($postprocess->{'createdweb'}) || ($postprocess->{'createdmsg'})))) {
336: my $addmsg = [];
337: my $recipient = $ownername.':'.$ownerdom;
338: my $sender = $recipient;
339: if ($code) {
340: push(@{$addmsg},{
341: mt => 'Students can automatically select your course: "[_1]" by entering this code: [_2]',
342: args => [$history{'details'}{'cdescr'},$code],
343: });
344: }
345: if (ref($postprocess) eq 'HASH') {
346: if (ref($postprocess->{'createdmsg'}) eq 'ARRAY') {
347: foreach my $item (@{$postprocess->{'createdmsg'}}) {
348: if (ref($item) eq 'HASH') {
349: if ($item->{'mt'} ne '') {
350: push(@{$addmsg},$item);
351: }
352: }
353: }
354: }
355: }
356: if (scalar(@{$addmsg}) > 0) {
357: my $type = 'createdcrsreq';
358: if ($code) {
359: $type = 'uniquecode';
360: }
361: &Apache::loncoursequeueadmin::send_selfserve_notification($recipient,$addmsg,$cdom.'_'.$cnum,
362: $history{'details'}{'cdescr'},
363: $now,$type,$sender);
364: }
365: }
366: if ($code) {
367: $reqhash{'code'} = $code;
368: }
369: my $creationresult = 'created';
370: my ($storeresult,$updateresult) =
371: &Apache::loncoursequeueadmin::update_coursereq_status(\%reqhash,$cdom,
372: $cnum,$reqstatus,'request',$ownerdom,$ownername);
373: #
374: # check for session for this user
375: # if session, construct URL point at check for new roles.
376: #
377: if ($lonhost) {
378: my @hosts = &Apache::lonnet::current_machine_ids();
379: if (grep(/^\Q$lonhost\E$/,@hosts) && ($handle) && ($hostname)) {
380: if ($lonidsdir ne '') {
381: if (-e "$lonidsdir/$handle.id") {
382: my $protocol = $Apache::lonnet::protocol{$lonhost};
383: $protocol = 'http' if ($protocol ne 'https');
384: $url = $protocol.'://'.$hostname.'/adm/roles?state=doupdate';
385: }
386: }
387: }
388: #
389: # otherwise point at default portal, or if non specified, at /adm/login?querystring where
390: # querystring contains role=st./$cdom/$cnum
391: #
392: if ($url eq '') {
393: my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom);
394: if ($domdefaults{'portal_def'}) {
395: $url = $domdefaults{'portal_def'};
396: } else {
397: my $chome = &Apache::lonnet::homeserver($cnum,$cdom);
398: my $hostname = &Apache::lonnet::hostname($chome);
399: my $protocol = $Apache::lonnet::protocol{$chome};
400: $protocol = 'http' if ($protocol ne 'https');
401: my $role = 'cc';
402: if ($crstype eq 'community') {
403: $role = 'co';
404: }
405: $url = $protocol.'://'.$hostname.'/adm/login?role='.$role.'./'.$cdom.'/'.$cnum;
406: }
407: }
408: }
409: }
410: }
411: &unset_permissions(\%permissionflags);
412: return ($url,$code);
413: }
414:
415: sub set_permissions {
416: my ($permissionflags,$permissions) = @_;
417: foreach my $allowtype (@{$permissions}) {
418: unless($env{"allowed.$allowtype"}) {
419: $env{"allowed.$allowtype"} = 'F';
420: $permissionflags->{$allowtype} = 1;
421: }
422: }
423: }
424:
425: sub unset_permissions {
426: my ($permissionflags) = @_;
427: foreach my $allowtype (keys(%{$permissionflags})) {
428: delete($env{"allowed.$allowtype"});
429: }
430: }
431:
432: sub set_dc_env {
433: my ($dcname,$dcdom,$defdom,$ownername,$ownerdom,$crstype) = @_;
434: $env{'user.name'} = $dcname;
435: $env{'user.domain'} = $dcdom;
436: $env{'user.home'} = &Apache::lonnet::homeserver($dcname,$dcdom);
437: if ($defdom ne '') {
438: $env{'request.role.domain'} = $defdom;
439: }
440: if (($dcname eq $ownername) && ($dcdom eq $ownerdom)) {
441: $env{'environment.canrequest.'.$crstype} = 1;
442: }
443: return;
444: }
445:
446: sub unset_dc_env {
447: my ($dcname,$dcdom,$ownername,$ownerdom,$crstype) = @_;
448: delete($env{'user.name'});
449: delete($env{'user.domain'});
450: delete($env{'user.home'});
451: if ($env{'request.role.domain'}) {
452: delete($env{'request.role.domain'});
453: }
454: if (($dcname eq $ownername) && ($dcdom eq $ownerdom)) {
455: delete($env{'environment.canrequest.'.$crstype});
456: }
457: return;
458: }
459:
460: =pod
461:
462: =back
463:
464: =cut
465:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>