Annotation of loncom/html/adm/help/tex/Institutional_Integration_Identity_Management.tex, revision 1.5
1.2 raeburn 1: \label{Institutional_Integration_Identity_Management}
1.1 raeburn 2: Two subroutines exist in localenroll.pm to provide a connection between
3: institutional directory data (e.g., user information from LDAP) and
4: LON-CAPA. The first is \emph{get\_userinfo()} which can operate in
5: two modes.: (a) it can be used to provide first name, last name, e-mail
6: address, student/employee ID etc., for a specified username, e.g.,
7: for a new user being created in LON-CAPA, and (b) it can be used to
8: retrieve user information for multiple users from an institutional
9: directory searches when (for example) a course coordinator is adding
10: a new user directly to a course. At MSU the routine which actually
11: queries institutional data sources is itself called by \emph{get\_userinfo()}.
12: This was done so that the same underlying routine can also be used
13: by the second of the two subroutines: \emph{allusers\_info()} which
14: is called by Autoupdate.pl (a script which can be run periodically
15: to reconcile user information in LON-CAPA with institutional directory
16: data for all users).
17:
18:
19:
20: \textbf{\large get\_userinfo}{\large \par}
21:
22: Four required arguments and additional optional arguments
23:
24: Two modes of operation:
25:
26: \begin{enumerate}
27: \item Retrieves institutional data for a single user either by username,
28: if \$uname is included as second argument,
29:
30:
31: or by ID if \$id is included as a third argument. Either second or
32: third arguments must be provided; seventh, eighth and ninth args will
33: be undefined.
34:
35: \item Retrieves institutional user data from search of an institutional
36: directory based on a search. seventh and eighth args are required;
37: ninth is optional. second and third will be undefined.
38: \end{enumerate}
39: Arguments:
40:
41: \begin{enumerate}
42: \item \$dom - domain
43: \item \$uname - username of user
44: \item \$id - student/faculty ID of user
45: \item \$instusers - reference to hash which will contain info for user as
46: key = value; keys will be one or all of: lastname, firstname, middlename,
47: generation, id, inststatus - institutional status (e.g., faculty,staff,student).
48:
49:
50: Values are all scalars except inststatus, which is an array.
51:
52: \item \$instids - reference to hash which will contain ID numbers - keys
53: will be unique IDs (student or faculty/staff ID)
54:
55:
56: values will be either: scalar (username) or an array if a single ID
57: matches multiple usernames.
58:
59: \item \$types - optional reference to array which contains institutional
60: types to check.
61: \item \$srchby - optional if \$uname or \$id defined, otherwise required.
62:
63:
64: Allowed values include: 1. lastfirst, 2. last, 3. uname corresponding
65: to searches by 1. lastname,firstname; 2. lastname; 3. username
66:
67: \item \$srchterm - optional if \$uname or \$id defined, otherwise required
68: - String to search for.
69: \item \$srchtype - optional. Allowed values: contains, begins (defaults
70: to exact match otherwise).
71: \end{enumerate}
72: Returns 'ok' if no error occurred. Side effects - populates the \$instusers
73: and \$instids refs to hashes with information for specified username,
74: or specified id, if fifth argument provided, from all available, or
75: specified (e.g., faculty only) institutional datafeeds, if sixth argument
76: provided.
77:
78: At MSU six separate MS-SQL database tables are queried, with each
1.3 raeburn 79: table corresponding to a specific institutional type. A routine is
1.1 raeburn 80: called to connect to the database. and the actual queries are handled
81: by a separate routine - \emph{query\_user\_tables()}.
82:
83: \begin{quotation}
84: \texttt{sub get\_userinfo \{}
85: \begin{quotation}
86: \texttt{my (\$dom,\$uname,\$id,\$instusers,\$instids,\$types,}
87: \begin{quotation}
88: \texttt{\$srchby,\$srchterm,\$srchtype) = @\_;}
89: \end{quotation}
90: \texttt{my \$outcome;}
91: \begin{quotation}
92: \texttt{my @srchtables;}
93: \end{quotation}
94: \texttt{my \%tables = (}
95: \begin{quotation}
96: \texttt{Faculty => 'FACULTY\_VU',}
97:
98: \texttt{Staff => 'STAFF\_VU',}
99:
100: \texttt{Student => 'STUDENT',}
101:
102: \texttt{Assistant => 'ASSISTANT',}
103:
104: \texttt{StaffAff => 'AFFILIATE',}
105:
106: \texttt{StuAff => 'STUDENT\_AFFILIATE'}
107: \end{quotation}
108: \texttt{);}
109:
110: \texttt{my (\$dbh,\$dbflag) = \&connect\_DB('HR');}
111:
112: \texttt{foreach my \$type (@\{\$types\}) \{}
113: \begin{quotation}
114: \texttt{if (exists(\$tables\{\$type\})) \{}
115: \begin{quotation}
116: \texttt{push(@srchtables,\$tables\{\$type\});}
117: \end{quotation}
118: \texttt{\}}
119: \end{quotation}
120: \texttt{\}}
121:
122: \texttt{if (@srchtables == 0) \{}
123: \begin{quotation}
124: \texttt{foreach my \$type (keys(\%tables)) \{}
125: \begin{quotation}
126: \texttt{push(@srchtables,\$tables\{\$type\});}
127: \end{quotation}
128: \texttt{\}}
129: \end{quotation}
130: \texttt{\}}
131:
132: \texttt{if (\$srchby eq '' \&\& \$srchterm eq '') \{}
133: \begin{quotation}
134: \texttt{if (\$uname ne '') \{}
135: \begin{quotation}
136: \texttt{\$srchby = 'uname';}
137:
138: \texttt{\$srchterm = \$uname;}
139: \end{quotation}
140: \texttt{\} elsif (\$id ne '') \{}
141: \begin{quotation}
142: \texttt{\$srchby = 'id';}
143:
144: \texttt{\$srchterm = \$id;}
145: \end{quotation}
146: \texttt{\}}
147: \end{quotation}
148: \texttt{\}}
149:
150: \texttt{if (\$srchterm ne '') \{}
151: \begin{quotation}
1.5 ! raeburn 152: \texttt{\$outcome = \&query\_user\_tables(\$dbflag,\$dbh,\textbackslash{}@srchtables,}
1.1 raeburn 153: \begin{quotation}
1.5 ! raeburn 154: \texttt{~~~~~~~\$instusers,\$instids,\$srchby,\$srchterm,\$srchtype,\$types);}
1.1 raeburn 155: \end{quotation}
156: \end{quotation}
157: \texttt{\}}
158:
159: \texttt{if (\$dbflag) \{}
160: \begin{quotation}
161: \texttt{\&disconnect\_DB(\$dbh);}
162: \end{quotation}
163: \texttt{\}}
164:
165: \texttt{return \$outcome;}
166: \end{quotation}
167: \texttt{\}}
168:
169: Although query\_user\_tables() is not a subroutine included as a stub
170: in the standard localenroll.pm, it is included below to show how the
171: database queries are implemented at MSU.
172:
173: \texttt{sub query\_user\_tables \{}
174: \begin{quotation}
1.5 ! raeburn 175: \texttt{my (\$dbflag,\$dbh,\$srchtables,\$instusers,\$instids,\$srchby,\$srchterm,}
! 176: \texttt{~~~~\$srchtype,\$types) = @\_;}
1.1 raeburn 177:
178: \texttt{my (\$outcome,\$condition,\%multipids,\$ldapfilter);}
179:
180: \texttt{if (\$srchby eq 'uname') \{}
181: \begin{quotation}
1.4 raeburn 182: \texttt{if (\$srchterm =\~{} /\^{}\textbackslash{}w\{2,8\}\$/)
1.1 raeburn 183: \{}
184: \begin{quotation}
185: \texttt{if (\$srchtype eq 'contains') \{}
186:
1.4 raeburn 187: \texttt{~~\$condition = \char`\"{}WHERE MSUNetID LIKE '\%\$srchterm\%'\char`\"{};}
188:
189: \texttt{~~\$ldapfilter = '(uid={*}'.\$srchterm.'{*})';}
190:
1.1 raeburn 191: \texttt{\} elsif (\$srchtype eq 'begins') \{}
192:
1.4 raeburn 193: \texttt{~~\$condition = \char`\"{}WHERE MSUNetID LIKE '\$srchterm\%'\char`\"{};}
194:
195: \texttt{~~\$ldapfilter = '(uid='.\$srchterm.'{*})';}
196:
1.1 raeburn 197: \texttt{\} else \{}
198:
1.4 raeburn 199: \texttt{~~\$condition = \char`\"{}WHERE MSUNetID = '\$srchterm'\char`\"{};}
200:
201: \texttt{~~\$ldapfilter = '(uid='.\$srchterm.')';}
202:
1.1 raeburn 203: \texttt{\}}
204: \end{quotation}
205: \texttt{\}}
206: \end{quotation}
207: \texttt{\} elsif (\$srchby eq 'lastname') \{}
208: \begin{quotation}
209: \texttt{if (\$srchterm =\~{} /{[}A-Za-z\textbackslash{}-\textbackslash{}.'\textbackslash{}s]+/)
210: \{}
211: \begin{quotation}
212: \texttt{if (\$srchtype eq 'contains') \{}
213:
1.4 raeburn 214: \texttt{~~if (\$dbflag) \{}
215:
216: \texttt{~~~~my \$quoted\_last = \$dbh->quote('\%'.\$srchterm.'\%');}
217:
218: \texttt{~~~~\$condition = \char`\"{}WHERE LastName LIKE \$quoted\_last\char`\"{};}
219:
220: \texttt{~~\}}
221:
222: \texttt{~~\$ldapfilter = '(sn={*}'.\$srchterm.'{*})';}
1.1 raeburn 223:
224: \texttt{\} elsif (\$srchtype eq 'begins') \{}
225:
1.4 raeburn 226: \texttt{~~if (\$dbflag) \{}
227:
228: \texttt{~~~~my \$quoted\_last = \$dbh->quote(\$srchterm.'\%');}
229:
230: \texttt{~~~~\$condition = \char`\"{}WHERE LastName LIKE \$quoted\_last\char`\"{};}
231:
232: \texttt{~~\}}
233:
234: \texttt{~~\$ldapfilter = '(sn='.\$srchterm.'{*})';}
1.1 raeburn 235:
236: \texttt{\} else \{}
237:
1.4 raeburn 238: \texttt{~~if (\$dbflag) \{}
239:
240: \texttt{~~~my \$quoted\_last = \$dbh->quote(\$srchterm);}
241:
242: \texttt{~~~~\$condition = \char`\"{}WHERE LastName = \$quoted\_last\char`\"{};}
243:
244: \texttt{~~\}}
245:
246: \texttt{~~\$ldapfilter = '(sn='.\$srchterm.')';}
1.1 raeburn 247:
248: \texttt{\}}
249: \end{quotation}
250: \texttt{\}}
251: \end{quotation}
252: \texttt{\} elsif (\$srchby eq 'lastfirst') \{}
253: \begin{quotation}
254: \texttt{my (\$srchlast,\$srchfirst) = split(/,/,\$srchterm);}
255:
256: \texttt{\$srchlast =\~{} s/\textbackslash{}s+\$//;}
257:
1.4 raeburn 258: \texttt{\$srchfirst =\~{} s/\^{}\textbackslash{}s+//;}
1.1 raeburn 259:
260: \texttt{if ((\$srchlast =\~{} /{[}A-Za-z\textbackslash{}-\textbackslash{}.'\textbackslash{}s]+/)
261: \&\& (\$srchfirst =\~{} /{[}A-Za-z\textbackslash{}-\textbackslash{}.'\textbackslash{}s]+/))
262: \{}
263: \begin{quotation}
264: \texttt{my (\$quoted\_first,\$quoted\_last);}
265:
266: \texttt{if (\$srchtype eq 'contains') \{}
267:
1.4 raeburn 268: \texttt{~~if (\$dbflag) \{}
269:
270: \texttt{~~~~\$quoted\_last = \$dbh->quote('\%'.\$srchlast.'\%');}
271:
272: \texttt{~~~~\$quoted\_first = \$dbh->quote('\%'.\$srchfirst.'\%');}
1.1 raeburn 273:
1.4 raeburn 274: \texttt{~~~~\$condition = \char`\"{}WHERE ( LastName LIKE \$quoted\_last
1.1 raeburn 275: AND FirstName LIKE \$quoted\_first )\char`\"{};}
276:
1.4 raeburn 277: \texttt{~~\}}
278:
279: \texttt{~~\$ldapfilter = '(\&(sn='.\$srchlast.'{*})(givenName='.\$srchfirst.'{*}))';}
280:
1.1 raeburn 281: \texttt{\} else \{}
282: \begin{quotation}
1.4 raeburn 283: \texttt{foreach my \$table (@\{\$srchtables\}) \{}
1.1 raeburn 284: \begin{quotation}
1.4 raeburn 285: \texttt{next if (\$srchby \&\& \$condition eq '');}
286:
1.5 ! raeburn 287: \texttt{my \$statement = \char`\"{}SELECT MSUNetID,Pid,FirstName,LastName,}
! 288: \texttt{~~~~~~~~~~~~~~~~~Person\_Type FROM \$table \$condition\char`\"{};}
1.4 raeburn 289:
290: \texttt{my \$sth = \$dbh->prepare(\char`\"{}\$statement\char`\"{});}
291:
292: \texttt{\$sth->execute();}
293:
294: \texttt{while ( my(\$uname,\$pid,\$first,\$last,\$type) = \$sth->fetchrow\_array
295: ) \{}
1.1 raeburn 296:
1.4 raeburn 297: \texttt{~~\$pid=lc(\$pid);}
1.1 raeburn 298:
1.4 raeburn 299: \texttt{~~if (ref(\$instusers->\{\$uname\}) eq 'HASH') \{}
300:
301: \texttt{~~~~if (ref(\$instusers->\{\$uname\}\{'instst}
302: \end{quotation}
303: \end{quotation}
304: \texttt{~~if (\$dbflag) \{}
305:
306: \texttt{~~~~\$quoted\_last = \$dbh->quote(\$srchterm);}
307:
308: \texttt{~~~~\$quoted\_first = \$dbh->quote(\$srchterm);}
309:
310: \texttt{~~~~\$condition = \char`\"{}WHERE ( LastName = \$quoted\_last
1.1 raeburn 311: AND FirstName = \$quoted\_first )\char`\"{};}
312:
1.4 raeburn 313: \texttt{~~\}}
314:
315: \texttt{~~\$ldapfilter = '(\&(sn='.\$srchlast.')(givenName='.\$srchfirst.'))';}
316:
1.1 raeburn 317: \texttt{\}}
318: \end{quotation}
319: \texttt{\}}
320: \end{quotation}
321: \texttt{\} elsif (\$srchby eq 'id') \{}
322: \begin{quotation}
323: \texttt{if (\$dbflag) \{}
1.4 raeburn 324:
325: \texttt{~~if (\$srchterm =\~{} /\^{}{[}AZ]\textbackslash{}d\{8\}\$/)
1.1 raeburn 326: \{}
327: \begin{quotation}
1.4 raeburn 328: \texttt{~~\$condition = \char`\"{}WHERE Pid = '\$srchterm'\char`\"{};}
1.1 raeburn 329: \end{quotation}
1.4 raeburn 330: \texttt{~~\}}
331:
1.1 raeburn 332: \texttt{\}}
333: \end{quotation}
334: \texttt{\}}
335:
336: \texttt{if (\$dbflag) \{}
337: \begin{quotation}
338: \texttt{foreach my \$table (@\{\$srchtables\}) \{}
339: \begin{quotation}
340: \texttt{next if (\$srchby \&\& \$condition eq '');}
341:
342: \texttt{my \$statement = \char`\"{}SELECT MSUNetID,Pid,FirstName,LastName,Person\_Type
343: FROM \$table \$condition\char`\"{};}
344:
345: \texttt{my \$sth = \$dbh->prepare(\char`\"{}\$statement\char`\"{});}
346:
347: \texttt{\$sth->execute();}
348:
349: \texttt{while ( my(\$uname,\$pid,\$first,\$last,\$type) = \$sth->fetchrow\_array
350: ) \{}
351:
1.4 raeburn 352: \texttt{~~\$pid=lc(\$pid);}
353:
354: \texttt{~~if (ref(\$instusers->\{\$uname\}) eq 'HASH') \{}
355:
356: \texttt{~~~~if (ref(\$instusers->\{\$uname\}\{'inststatus'\})
357: eq 'ARRAY') \{}
358:
359: \texttt{~~~~~~if (!grep(/\^{}\$type\$/,@\{\$instusers->\{\$uname\}\{'inststatus'\}\}))
1.1 raeburn 360: \{}
1.4 raeburn 361:
362: \texttt{~~~~~~~~push(@\{\$instusers->\{\$uname\}\{'inststatus'\}\},\$type);}
363:
364: \texttt{~~~~~~\}}
365:
366: \texttt{~~~~\}}
367:
368: \texttt{~~~~if (\$pid ne \$instusers->\{\$uname\}\{'id'\}) \{}
369:
370: \texttt{~~~~~~if (\$instusers->\{\$uname\}\{'id'\} =\~{}
371: /\^{}A\textbackslash{}d\{8\}\$/) \{}
372:
373: \texttt{~~~~~~~~if (\$pid =\~{} /\^{}A\textbackslash{}d\{8\}\$/)
1.1 raeburn 374: \{}
375:
1.4 raeburn 376: \texttt{~~~~~~~~~~if (ref(\$multipids\{\$uname\}) eq 'ARRAY')
1.1 raeburn 377: \{}
1.4 raeburn 378:
379: \texttt{~~~~~~~~~~~~if (!grep(/\^{}\$pid\$/,@\{\$multipids\{\$uname\}\}))
1.1 raeburn 380: \{}
1.4 raeburn 381:
382: \texttt{~~~~~~~~~~~~~~push(@\{\$multipids\{\$uname\}\},\$pid);}
383:
384: \texttt{~~~~~~~~~~~~\}}
385:
386: \texttt{~~~~~~~~~~\} else \{}
387:
1.5 ! raeburn 388: \texttt{~~~~~~~~~~~~@\{\$multipids\{\$uname\}\}=(\$instusers->\{\$uname\}\{'id'\},\$pid);}
1.4 raeburn 389:
390: \texttt{~~~~~~~~~~\}}
391:
392: \texttt{~~~~~~~~~~\$instusers->\{\$uname\}\{'id'\} = \$pid;}
393:
394: \texttt{~~~~~~~~\}}
395:
396: \texttt{~~~~~~\} elsif (\$instusers->\{\$uname\}\{'id'\} =\~{}
397: /\^{}Z\textbackslash{}d\{8\}\$/) \{}
398:
399: \texttt{~~~~~~~~if (\$pid =\~{} /\^{}Z\textbackslash{}d\{8\}\$/)
1.1 raeburn 400: \{}
401:
1.4 raeburn 402: \texttt{~~~~~~~~~~if (ref(\$multipids\{\$uname\}) eq 'ARRAY')
1.1 raeburn 403: \{}
1.4 raeburn 404:
405: \texttt{~~~~~~~~~~~~if (!grep(/\^{}\$pid\$/,@\{\$multipids\{\$uname\}\}))
1.1 raeburn 406: \{}
1.4 raeburn 407:
408: \texttt{~~~~~~~~~~~~~~push(@\{\$multipids\{\$uname\}\},\$pid);}
409:
410: \texttt{~~~~~~~~~~~~\}}
411:
412: \texttt{~~~~~~~~~~\} else \{}
413:
1.5 ! raeburn 414: \texttt{~~~~~~~~~~~~@\{\$multipids\{\$uname\}\}=(\$instusers->\{\$uname\}\{'id'\},\$pid);}
1.4 raeburn 415:
416: \texttt{~~~~~~~~~~\}}
417:
418: \texttt{~~~~~~~~\} elsif (\$pid =\~{} /\^{}A\textbackslash{}d\{8\}\$/)
1.1 raeburn 419: \{}
420:
1.4 raeburn 421: \texttt{~~~~~~~~~~\$instusers->\{\$uname\}\{'id'\} = \$pid;}
422:
423: \texttt{~~~~~~~~\}}
424:
425: \texttt{~~~~~~\}}
426:
427: \texttt{~~~~\}}
428:
429: \texttt{~~\} else \{}
430:
431: \texttt{~~~~\$instusers->\{\$uname\} = \{}
432:
433: \texttt{~~~~~~firstname => \$first,}
434:
435: \texttt{~~~~~~lastname => \$last,}
436:
437: \texttt{~~~~~~id => \$pid,}
438:
439: \texttt{~~~~~~permanentemail => \$uname.'@msu.edu', }
440:
441: \texttt{~~~~~~inststatus => {[}\$type],}
442:
443: \texttt{~~~~\};}
1.1 raeburn 444:
1.4 raeburn 445: \texttt{~~\}}
1.1 raeburn 446:
1.4 raeburn 447: \texttt{~~if (defined(\$instids->\{\$pid\})) \{}
1.1 raeburn 448:
1.4 raeburn 449: \texttt{~~~~if (ref(\$instids->\{\$pid\}) eq 'ARRAY') \{}
1.1 raeburn 450:
1.4 raeburn 451: \texttt{~~~~~~if (!grep(/\^{}\$uname\$/,@\{\$instids->\{\$pid\}\}))
1.1 raeburn 452: \{}
1.4 raeburn 453:
454: \texttt{~~~~~~~~push(@\{\$instids->\{\$pid\}\},\$uname);}
455:
456: \texttt{~~~~~~\}}
457:
458: \texttt{~~~~\} elsif (\$instids->\{\$pid\} ne \$uname) \{}
459:
460: \texttt{~~~~~~@\{\$instids->\{\$pid\}\} = (\$instids->\{\$pid\},\$uname);}
461:
462: \texttt{~~~~\}}
463:
464: \texttt{~~\} else \{}
465:
466: \texttt{~~~~\$instids->\{\$pid\} = \$uname;}
467:
468: \texttt{~~\}}
469:
1.1 raeburn 470: \texttt{\}}
471:
472: \texttt{\$outcome = 'ok';}
473: \end{quotation}
474: \texttt{\}}
475: \end{quotation}
476: \texttt{\}}
477:
478: \texttt{if (\$ldapfilter ne '') \{}
479: \begin{quotation}
480: \texttt{my \$ldapres = \&ldap\_search(\$ldapfilter,\$instusers,\$types);}
481:
482: \texttt{if (!\$dbflag) \{}
483: \begin{quotation}
484: \texttt{\$outcome = \$ldapres;}
485: \end{quotation}
486: \texttt{\}}
487: \end{quotation}
488: \texttt{\}}
489:
490: \texttt{return \$outcome;}
491: \end{quotation}
492: \texttt{\}}
493: \end{quotation}
494: At MSU, a search of the LDAP directory is used to supplement SQL queries
495: of Faculty, Staff and Student database tables, because there are no
496: student/employee IDs available from MSU's LDAP service. The LDAP search
497: is used to retrieve information about users who have MSUNetIDs (i.e.,
1.3 raeburn 498: official usernames from MSU), but are not currently affiliated with
1.1 raeburn 499: any of the institutional user types, so are absent from the six SQL
500: database tables.
501:
502: \begin{quotation}
503: \texttt{sub ldap\_search \{}
504: \begin{quotation}
505: \texttt{my (\$ldapfilter,\$instusers,\$types) = @\_;}
506:
507: \texttt{my \$outcome;}
508:
509: \texttt{my \$ldap = Net::LDAP->new( 'ldap.msu.edu' );}
510:
511: \texttt{if (\$ldap) \{}
512: \begin{quotation}
513: \texttt{\$ldap->bind;}
514:
515: \texttt{my \$mesg = \$ldap->search(}
516: \begin{quotation}
517: \texttt{base => \char`\"{}dc=msu, dc=edu\char`\"{},}
518:
519: \texttt{filter => \$ldapfilter,}
520:
521: \texttt{attrs => {[}'sn','givenName','title','uid','mail','employeeType'],}
522: \end{quotation}
523: \texttt{);}
524:
525: \texttt{if (\$mesg->code) \{}
526: \begin{quotation}
527: \texttt{\$ldap->unbind;}
528:
529: \texttt{return;}
530: \end{quotation}
531: \texttt{\} else \{}
532: \begin{quotation}
533: \texttt{\$outcome = 'ok';}
534: \end{quotation}
535: \texttt{\}}
536:
537: \texttt{foreach my \$entry (\$mesg->entries) \{}
538: \begin{quotation}
539: \texttt{my \$uname = \$entry->get\_value('uid');}
540:
541: \texttt{next if (\$uname eq '');}
542:
543: \texttt{my \$first = \$entry->get\_value('givenName');}
544:
545: \texttt{my \$last = \$entry->get\_value('sn');}
546:
547: \texttt{my \$email = \$entry->get\_value('mail');}
548:
549: \texttt{my \$type;}
550:
551: \texttt{if ((\$entry->get\_value('employeeType') eq 'Faculty') ||
552: (\$entry->get\_value('employeeType') eq 'Staff')) \{}
553: \begin{quotation}
554: \texttt{\$type = \$entry->get\_value('employeeType');}
555: \end{quotation}
556: \texttt{\} elsif (\$entry->get\_value('title') eq 'Student') \{}
557: \begin{quotation}
558: \texttt{\$type = \$entry->get\_value('title');}
559: \end{quotation}
560: \texttt{\}}
561:
562: \texttt{if (ref(\$types) eq 'ARRAY') \{}
1.4 raeburn 563:
564: \texttt{~~if (@\{\$types\} > 0) \{}
1.1 raeburn 565: \begin{quotation}
1.4 raeburn 566: \texttt{~~if ((\$type ne '') \&\& !(grep(/\^{}\$type\$/,@\{\$types\}))) }
567:
568: \texttt{~~~~next if (!grep(/\^{}default\$/,@\{\$types\}));}
569:
570: \texttt{~~\}}
571:
572: \texttt{~~next if ((\$type eq '') \&\& (!grep(/\^{}default\$/,@\{\$types\})));}
1.1 raeburn 573:
574: \texttt{\}}
575: \end{quotation}
576: \texttt{\}}
577:
578: \texttt{if (ref(\$instusers->\{\$uname\}) eq 'HASH') \{}
1.4 raeburn 579:
580: \texttt{~~if (ref(\$instusers->\{\$uname\}\{'inststatus'\}) eq 'ARRAY')
1.1 raeburn 581: \{}
1.4 raeburn 582:
583: \texttt{~~~~if (!grep(/\^{}\$type\$/,@\{\$instusers->\{\$uname\}\{'inststatus'\}\}))
1.1 raeburn 584: \{}
1.4 raeburn 585:
586: \texttt{~~~~~~push(@\{\$instusers->\{\$uname\}\{'inststatus'\}\},\$type);}
587:
588: \texttt{~~~~\}}
589:
590: \texttt{~~\}}
591:
1.1 raeburn 592: \texttt{\} else \{}
593:
1.4 raeburn 594: \texttt{~~\$instusers->\{\$uname\} = \{}
595:
596: \texttt{~~firstname => \$first,}
597:
598: \texttt{~~lastname => \$last,}
599:
600: \texttt{~~id => '',}
1.1 raeburn 601:
1.4 raeburn 602: \texttt{~~permanentemail => \$email,}
1.1 raeburn 603:
1.4 raeburn 604: \texttt{~~inststatus => {[}\$type],}
1.1 raeburn 605:
606: \texttt{\};}
607: \end{quotation}
608: \texttt{\}}
609:
610: \texttt{\$ldap->unbind;}
611: \end{quotation}
612: \texttt{\}}
613:
614: \texttt{return \$outcome;}
615: \end{quotation}
616: \texttt{\}}
617: \end{quotation}
618: \textbf{\large allusers\_info}{\large \par}
619:
620: Three arguments are required:
621:
622: \begin{enumerate}
623: \item \$dom - domain
624: \item \$instusers - reference to hash which will contain hashes, where keys
625: will be usernames and value will be a hash of user information.
626:
627:
628: Keys in the inner hash will be some or all of: lastname, firstname,
629: middlename, generation, id, inststatus - institutional status (e.g.,
630: faculty,staff,student)
631:
632: Values are all scalars except inststatus, which is an array.
633:
634: \item \$instids - reference to hash which will contain ID numbers. keys
635: will be unique IDs (student or faculty/staff ID).
636:
637:
638: Values will be either: scalar (username) or an array if a single ID
639: matches multiple usernames.
640:
641: \end{enumerate}
642: Returns 'ok' if no error occurred.
643:
644: Side effects - populates the \$instusers and \$instids refs to hashes
645: with information for all users from all available institutional datafeeds.
646:
647: In the MSU case, six SQL database tables are queried via the \emph{query\_user\_tables()}
648: routine described above.
649:
650: \begin{quotation}
651: \texttt{sub allusers\_info \{}
652: \begin{quotation}
653: \texttt{my (\$dom,\$instusers,\$instids) = @\_;}
654:
655: \texttt{my \$outcome;}
656:
657: \texttt{my (\$dbh,\$dbflag) = \&connect\_DB('HR');}
658:
659: \texttt{if (\$dbflag) \{}
660: \begin{quotation}
1.5 ! raeburn 661: \texttt{my @srchtables = ('FACULTY\_VU','STAFF\_VU','STUDENT','AFFILIATE',}
! 662: \texttt{~~~~~~~~~~~~~~~~~~'ASSISTANT','STUDENT\_AFFILIATE');}
1.1 raeburn 663:
664: \texttt{\&query\_user\_tables(\$dbflag,\$dbh,\textbackslash{}@srchtables,\$instusers,\$instids);}
665:
666: \texttt{\$outcome = 'ok';}
667:
668: \texttt{\&disconnect\_DB(\$dbh);}
669: \end{quotation}
670: \texttt{\}}
671:
672: \texttt{return \$outcome;}
673: \end{quotation}
674: \texttt{\}}
675: \end{quotation}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>