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>