Annotation of loncom/html/adm/help/tex/Institutional_Integration_Identity_Management.tex, revision 1.4
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}
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:
! 287: \texttt{my \$statement = \char`\"{}SELECT MSUNetID,Pid,FirstName,LastName,Person\_Type
! 288: FROM \$table \$condition\char`\"{};}
! 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:
! 388: \texttt{~~~~~~~~~~~~@\{\$multipids\{\$uname\}\} = (\$instusers->\{\$uname\}\{'id'\},\$pid);}
! 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:
! 414: \texttt{~~~~~~~~~~~~@\{\$multipids\{\$uname\}\} = (\$instusers->\{\$uname\}\{'id'\},\$pid);}
! 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}
661: \texttt{my @srchtables = ('FACULTY\_VU','STAFF\_VU','STUDENT','AFFILIATE','ASSISTANT','STUDENT\_AFFILIATE');}
662:
663: \texttt{\&query\_user\_tables(\$dbflag,\$dbh,\textbackslash{}@srchtables,\$instusers,\$instids);}
664:
665: \texttt{\$outcome = 'ok';}
666:
667: \texttt{\&disconnect\_DB(\$dbh);}
668: \end{quotation}
669: \texttt{\}}
670:
671: \texttt{return \$outcome;}
672: \end{quotation}
673: \texttt{\}}
674: \end{quotation}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>