Annotation of loncom/html/adm/help/tex/Institutional_Integration_Identity_Management.tex, revision 1.3
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}
152: \texttt{\$outcome = \&query\_user\_tables(\$dbflag,\$dbh,\textbackslash{}@srchtables,\$instusers,\$instids,}
153: \begin{quotation}
154: \texttt{\$srchby,\$srchterm,\$srchtype,\$types);}
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}
175: \texttt{my (\$dbflag,\$dbh,\$srchtables,\$instusers,\$instids,\$srchby,\$srchterm,\$srchtype,\$types)
176: = @\_;}
177:
178: \texttt{my (\$outcome,\$condition,\%multipids,\$ldapfilter);}
179:
180: \texttt{if (\$srchby eq 'uname') \{}
181: \begin{quotation}
182: \texttt{if (\$srchterm =\~{} /^\textbackslash{}w\{2,8\}\$/)
183: \{}
184: \begin{quotation}
185: \texttt{if (\$srchtype eq 'contains') \{}
186: \begin{quotation}
187: \texttt{\$condition = \char`\"{}WHERE MSUNetID LIKE '\%\$srchterm\%'\char`\"{};}
188:
189: \texttt{\$ldapfilter = '(uid={*}'.\$srchterm.'{*})';}
190: \end{quotation}
191: \texttt{\} elsif (\$srchtype eq 'begins') \{}
192: \begin{quotation}
193: \texttt{\$condition = \char`\"{}WHERE MSUNetID LIKE '\$srchterm\%'\char`\"{};}
194:
195: \texttt{\$ldapfilter = '(uid='.\$srchterm.'{*})';}
196: \end{quotation}
197: \texttt{\} else \{}
198: \begin{quotation}
199: \texttt{\$condition = \char`\"{}WHERE MSUNetID = '\$srchterm'\char`\"{};}
200:
201: \texttt{\$ldapfilter = '(uid='.\$srchterm.')';}
202: \end{quotation}
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: \begin{quotation}
214: \texttt{if (\$dbflag) \{}
215: \begin{quotation}
216: \texttt{my \$quoted\_last = \$dbh->quote('\%'.\$srchterm.'\%');}
217:
218: \texttt{\$condition = \char`\"{}WHERE LastName LIKE \$quoted\_last\char`\"{};}
219: \end{quotation}
220: \texttt{\}}
221:
222: \texttt{\$ldapfilter = '(sn={*}'.\$srchterm.'{*})';}
223: \end{quotation}
224: \texttt{\} elsif (\$srchtype eq 'begins') \{}
225: \begin{quotation}
226: \texttt{if (\$dbflag) \{}
227: \begin{quotation}
228: \texttt{my \$quoted\_last = \$dbh->quote(\$srchterm.'\%');}
229:
230: \texttt{\$condition = \char`\"{}WHERE LastName LIKE \$quoted\_last\char`\"{};}
231: \end{quotation}
232: \texttt{\}}
233:
234: \texttt{\$ldapfilter = '(sn='.\$srchterm.'{*})';}
235: \end{quotation}
236: \texttt{\} else \{}
237: \begin{quotation}
238: \texttt{if (\$dbflag) \{}
239: \begin{quotation}
240: \texttt{my \$quoted\_last = \$dbh->quote(\$srchterm);}
241:
242: \texttt{\$condition = \char`\"{}WHERE LastName = \$quoted\_last\char`\"{};}
243: \end{quotation}
244: \texttt{\}}
245:
246: \texttt{\$ldapfilter = '(sn='.\$srchterm.')';}
247: \end{quotation}
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:
258: \texttt{\$srchfirst =\~{} s/^\textbackslash{}s+//;}
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: \begin{quotation}
268: \texttt{if (\$dbflag) \{}
269: \begin{quotation}
270: \texttt{\$quoted\_last = \$dbh->quote('\%'.\$srchlast.'\%');}
271:
272: \texttt{\$quoted\_first = \$dbh->quote('\%'.\$srchfirst.'\%');}
273:
274: \texttt{\$condition = \char`\"{}WHERE ( LastName LIKE \$quoted\_last
275: AND FirstName LIKE \$quoted\_first )\char`\"{};}
276: \end{quotation}
277: \texttt{\}}
278:
279: \texttt{\$ldapfilter = '(\&(sn='.\$srchlast.'{*})(givenName='.\$srchfirst.'{*}))';}
280: \end{quotation}
281: \texttt{\} else \{}
282: \begin{quotation}
283: \texttt{if (\$dbflag) \{}
284: \begin{quotation}
285: \texttt{\$quoted\_last = \$dbh->quote(\$srchterm);}
286:
287: \texttt{\$quoted\_first = \$dbh->quote(\$srchterm);}
288:
289: \texttt{\$condition = \char`\"{}WHERE ( LastName = \$quoted\_last
290: AND FirstName = \$quoted\_first )\char`\"{};}
291: \end{quotation}
292: \texttt{\}}
293:
294: \texttt{\$ldapfilter = '(\&(sn='.\$srchlast.')(givenName='.\$srchfirst.'))';}
295: \end{quotation}
296: \texttt{\}}
297: \end{quotation}
298: \texttt{\}}
299: \end{quotation}
300: \texttt{\} elsif (\$srchby eq 'id') \{}
301: \begin{quotation}
302: \texttt{if (\$dbflag) \{}
303: \begin{quotation}
304: \texttt{if (\$srchterm =\~{} /^{[}AZ]\textbackslash{}d\{8\}\$/)
305: \{}
306: \begin{quotation}
307: \texttt{\$condition = \char`\"{}WHERE Pid = '\$srchterm'\char`\"{};}
308: \end{quotation}
309: \texttt{\}}
310: \end{quotation}
311: \texttt{\}}
312: \end{quotation}
313: \texttt{\}}
314:
315: \texttt{if (\$dbflag) \{}
316: \begin{quotation}
317: \texttt{foreach my \$table (@\{\$srchtables\}) \{}
318: \begin{quotation}
319: \texttt{next if (\$srchby \&\& \$condition eq '');}
320:
321: \texttt{my \$statement = \char`\"{}SELECT MSUNetID,Pid,FirstName,LastName,Person\_Type
322: FROM \$table \$condition\char`\"{};}
323:
324: \texttt{my \$sth = \$dbh->prepare(\char`\"{}\$statement\char`\"{});}
325:
326: \texttt{\$sth->execute();}
327:
328: \texttt{while ( my(\$uname,\$pid,\$first,\$last,\$type) = \$sth->fetchrow\_array
329: ) \{}
330: \begin{quotation}
331: \texttt{\$pid=lc(\$pid);}
332:
333: \texttt{if (ref(\$instusers->\{\$uname\}) eq 'HASH') \{}
334: \begin{quotation}
335: \texttt{if (ref(\$instusers->\{\$uname\}\{'inststatus'\}) eq 'ARRAY')
336: \{}
337: \begin{quotation}
338: \texttt{if (!grep(/^\$type\$/,@\{\$instusers->\{\$uname\}\{'inststatus'\}\}))
339: \{}
340: \begin{quotation}
341: \texttt{push(@\{\$instusers->\{\$uname\}\{'inststatus'\}\},\$type);}
342: \end{quotation}
343: \texttt{\}}
344: \end{quotation}
345: \texttt{\}}
346:
347: \texttt{if (\$pid ne \$instusers->\{\$uname\}\{'id'\}) \{}
348: \begin{quotation}
349: \texttt{if (\$instusers->\{\$uname\}\{'id'\} =\~{} /^A\textbackslash{}d\{8\}\$/)
350: \{}
351: \begin{quotation}
352: \texttt{if (\$pid =\~{} /^A\textbackslash{}d\{8\}\$/)
353: \{}
354: \begin{quotation}
355: \texttt{if (ref(\$multipids\{\$uname\}) eq 'ARRAY') \{}
356: \begin{quotation}
357: \texttt{if (!grep(/^\$pid\$/,@\{\$multipids\{\$uname\}\}))
358: \{}
359: \begin{quotation}
360: \texttt{push(@\{\$multipids\{\$uname\}\},\$pid);}
361: \end{quotation}
362: \texttt{\}}
363: \end{quotation}
364: \texttt{\} else \{}
365: \begin{quotation}
366: \texttt{@\{\$multipids\{\$uname\}\} = (\$instusers->\{\$uname\}\{'id'\},\$pid);}
367: \end{quotation}
368: \texttt{\}}
369:
370: \texttt{\$instusers->\{\$uname\}\{'id'\} = \$pid;}
371: \end{quotation}
372: \texttt{\}}
373: \end{quotation}
374: \texttt{\} elsif (\$instusers->\{\$uname\}\{'id'\} =\~{}
375: /^Z\textbackslash{}d\{8\}\$/) \{}
376: \begin{quotation}
377: \texttt{if (\$pid =\~{} /^Z\textbackslash{}d\{8\}\$/)
378: \{}
379: \begin{quotation}
380: \texttt{if (ref(\$multipids\{\$uname\}) eq 'ARRAY') \{}
381: \begin{quotation}
382: \texttt{if (!grep(/^\$pid\$/,@\{\$multipids\{\$uname\}\}))
383: \{}
384: \begin{quotation}
385: \texttt{push(@\{\$multipids\{\$uname\}\},\$pid);}
386: \end{quotation}
387: \texttt{\}}
388: \end{quotation}
389: \texttt{\} else \{}
390: \begin{quotation}
391: \texttt{@\{\$multipids\{\$uname\}\} = (\$instusers->\{\$uname\}\{'id'\},\$pid);}
392: \end{quotation}
393: \texttt{\}}
394: \end{quotation}
395: \texttt{\} elsif (\$pid =\~{} /^A\textbackslash{}d\{8\}\$/)
396: \{}
397: \begin{quotation}
398: \texttt{\$instusers->\{\$uname\}\{'id'\} = \$pid;}
399: \end{quotation}
400: \texttt{\}}
401: \end{quotation}
402: \texttt{\}}
403: \end{quotation}
404: \texttt{\}}
405: \end{quotation}
406: \texttt{\} else \{}
407: \begin{quotation}
408: \texttt{\$instusers->\{\$uname\} = \{}
409: \begin{quotation}
410: \texttt{firstname => \$first,}
411:
412: \texttt{lastname => \$last,}
413:
414: \texttt{id => \$pid,}
415:
416: \texttt{permanentemail => \$uname.'@msu.edu', }
417:
418: \texttt{inststatus => {[}\$type],}
419: \end{quotation}
420: \texttt{\};}
421: \end{quotation}
422: \texttt{\}}
423:
424: \texttt{if (defined(\$instids->\{\$pid\})) \{}
425: \begin{quotation}
426: \texttt{if (ref(\$instids->\{\$pid\}) eq 'ARRAY') \{}
427: \begin{quotation}
428: \texttt{if (!grep(/^\$uname\$/,@\{\$instids->\{\$pid\}\}))
429: \{}
430: \begin{quotation}
431: \texttt{push(@\{\$instids->\{\$pid\}\},\$uname);}
432: \end{quotation}
433: \texttt{\}}
434: \end{quotation}
435: \texttt{\} elsif (\$instids->\{\$pid\} ne \$uname) \{}
436: \begin{quotation}
437: \texttt{@\{\$instids->\{\$pid\}\} = (\$instids->\{\$pid\},\$uname);}
438: \end{quotation}
439: \texttt{\}}
440: \end{quotation}
441: \end{quotation}
442: \end{quotation}
443: \texttt{\} else \{}
444: \begin{quotation}
445: \texttt{\$instids->\{\$pid\} = \$uname;}
446: \begin{quotation}
447: \texttt{\}}
448: \end{quotation}
449: \texttt{\}}
450:
451: \texttt{\$outcome = 'ok';}
452: \end{quotation}
453: \texttt{\}}
454: \end{quotation}
455: \texttt{\}}
456:
457: \texttt{if (\$ldapfilter ne '') \{}
458: \begin{quotation}
459: \texttt{my \$ldapres = \&ldap\_search(\$ldapfilter,\$instusers,\$types);}
460:
461: \texttt{if (!\$dbflag) \{}
462: \begin{quotation}
463: \texttt{\$outcome = \$ldapres;}
464: \end{quotation}
465: \texttt{\}}
466: \end{quotation}
467: \texttt{\}}
468:
469: \texttt{return \$outcome;}
470: \end{quotation}
471: \texttt{\}}
472: \end{quotation}
473: At MSU, a search of the LDAP directory is used to supplement SQL queries
474: of Faculty, Staff and Student database tables, because there are no
475: student/employee IDs available from MSU's LDAP service. The LDAP search
476: is used to retrieve information about users who have MSUNetIDs (i.e.,
1.3 ! raeburn 477: official usernames from MSU), but are not currently affiliated with
1.1 raeburn 478: any of the institutional user types, so are absent from the six SQL
479: database tables.
480:
481: \begin{quotation}
482: \texttt{sub ldap\_search \{}
483: \begin{quotation}
484: \texttt{my (\$ldapfilter,\$instusers,\$types) = @\_;}
485:
486: \texttt{my \$outcome;}
487:
488: \texttt{my \$ldap = Net::LDAP->new( 'ldap.msu.edu' );}
489:
490: \texttt{if (\$ldap) \{}
491: \begin{quotation}
492: \texttt{\$ldap->bind;}
493:
494: \texttt{my \$mesg = \$ldap->search(}
495: \begin{quotation}
496: \texttt{base => \char`\"{}dc=msu, dc=edu\char`\"{},}
497:
498: \texttt{filter => \$ldapfilter,}
499:
500: \texttt{attrs => {[}'sn','givenName','title','uid','mail','employeeType'],}
501: \end{quotation}
502: \texttt{);}
503:
504: \texttt{if (\$mesg->code) \{}
505: \begin{quotation}
506: \texttt{\$ldap->unbind;}
507:
508: \texttt{return;}
509: \end{quotation}
510: \texttt{\} else \{}
511: \begin{quotation}
512: \texttt{\$outcome = 'ok';}
513: \end{quotation}
514: \texttt{\}}
515:
516: \texttt{foreach my \$entry (\$mesg->entries) \{}
517: \begin{quotation}
518: \texttt{my \$uname = \$entry->get\_value('uid');}
519:
520: \texttt{next if (\$uname eq '');}
521:
522: \texttt{my \$first = \$entry->get\_value('givenName');}
523:
524: \texttt{my \$last = \$entry->get\_value('sn');}
525:
526: \texttt{my \$email = \$entry->get\_value('mail');}
527:
528: \texttt{my \$type;}
529:
530: \texttt{if ((\$entry->get\_value('employeeType') eq 'Faculty') ||
531: (\$entry->get\_value('employeeType') eq 'Staff')) \{}
532: \begin{quotation}
533: \texttt{\$type = \$entry->get\_value('employeeType');}
534: \end{quotation}
535: \texttt{\} elsif (\$entry->get\_value('title') eq 'Student') \{}
536: \begin{quotation}
537: \texttt{\$type = \$entry->get\_value('title');}
538: \end{quotation}
539: \texttt{\}}
540:
541: \texttt{if (ref(\$types) eq 'ARRAY') \{}
542: \begin{quotation}
543: \texttt{if (@\{\$types\} > 0) \{}
544: \begin{quotation}
545: \texttt{if ((\$type ne '') \&\& !(grep(/^\$type\$/,@\{\$types\})))
546: \{}
547: \begin{quotation}
548: \texttt{next if (!grep(/^default\$/,@\{\$types\}));}
549: \end{quotation}
550: \texttt{\}}
551:
552: \texttt{next if ((\$type eq '') \&\& (!grep(/^default\$/,@\{\$types\})));}
553: \end{quotation}
554: \texttt{\}}
555: \end{quotation}
556: \texttt{\}}
557:
558: \texttt{if (ref(\$instusers->\{\$uname\}) eq 'HASH') \{}
559: \begin{quotation}
560: \texttt{if (ref(\$instusers->\{\$uname\}\{'inststatus'\}) eq 'ARRAY')
561: \{}
562: \begin{quotation}
563: \texttt{if (!grep(/^\$type\$/,@\{\$instusers->\{\$uname\}\{'inststatus'\}\}))
564: \{}
565: \begin{quotation}
566: \texttt{push(@\{\$instusers->\{\$uname\}\{'inststatus'\}\},\$type);}
567: \end{quotation}
568: \texttt{\}}
569: \end{quotation}
570: \texttt{\}}
571: \end{quotation}
572: \texttt{\} else \{}
573: \begin{quotation}
574: \texttt{\$instusers->\{\$uname\} = \{}
575: \begin{quotation}
576: \texttt{firstname => \$first,}
577:
578: \texttt{lastname => \$last,}
579:
580: \texttt{id => '',}
581:
582: \texttt{permanentemail => \$email,}
583:
584: \texttt{inststatus => {[}\$type],}
585: \end{quotation}
586: \texttt{\};}
587: \end{quotation}
588: \texttt{\}}
589: \end{quotation}
590: \texttt{\}}
591:
592: \texttt{\$ldap->unbind;}
593: \end{quotation}
594: \texttt{\}}
595:
596: \texttt{return \$outcome;}
597: \end{quotation}
598: \texttt{\}}
599: \end{quotation}
600: \textbf{\large allusers\_info}{\large \par}
601:
602: Three arguments are required:
603:
604: \begin{enumerate}
605: \item \$dom - domain
606: \item \$instusers - reference to hash which will contain hashes, where keys
607: will be usernames and value will be a hash of user information.
608:
609:
610: Keys in the inner hash will be some or all of: lastname, firstname,
611: middlename, generation, id, inststatus - institutional status (e.g.,
612: faculty,staff,student)
613:
614: Values are all scalars except inststatus, which is an array.
615:
616: \item \$instids - reference to hash which will contain ID numbers. keys
617: will be unique IDs (student or faculty/staff ID).
618:
619:
620: Values will be either: scalar (username) or an array if a single ID
621: matches multiple usernames.
622:
623: \end{enumerate}
624: Returns 'ok' if no error occurred.
625:
626: Side effects - populates the \$instusers and \$instids refs to hashes
627: with information for all users from all available institutional datafeeds.
628:
629: In the MSU case, six SQL database tables are queried via the \emph{query\_user\_tables()}
630: routine described above.
631:
632: \begin{quotation}
633: \texttt{sub allusers\_info \{}
634: \begin{quotation}
635: \texttt{my (\$dom,\$instusers,\$instids) = @\_;}
636:
637: \texttt{my \$outcome;}
638:
639: \texttt{my (\$dbh,\$dbflag) = \&connect\_DB('HR');}
640:
641: \texttt{if (\$dbflag) \{}
642: \begin{quotation}
643: \texttt{my @srchtables = ('FACULTY\_VU','STAFF\_VU','STUDENT','AFFILIATE','ASSISTANT','STUDENT\_AFFILIATE');}
644:
645: \texttt{\&query\_user\_tables(\$dbflag,\$dbh,\textbackslash{}@srchtables,\$instusers,\$instids);}
646:
647: \texttt{\$outcome = 'ok';}
648:
649: \texttt{\&disconnect\_DB(\$dbh);}
650: \end{quotation}
651: \texttt{\}}
652:
653: \texttt{return \$outcome;}
654: \end{quotation}
655: \texttt{\}}
656: \end{quotation}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>