Annotation of loncom/html/adm/help/tex/Institutional_Integration_Identity_Management.tex, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>