File:  [LON-CAPA] / loncom / html / adm / help / tex / Institutional_Integration_Identity_Management.tex
Revision 1.5: download - view: text, annotated - select for diffs
Thu May 26 16:01:16 2011 UTC (13 years, 1 month ago) by raeburn
Branches: MAIN
CVS tags: version_2_12_X, version_2_11_X, version_2_11_5, version_2_11_4_uiuc, version_2_11_4_msu, version_2_11_4, version_2_11_3_uiuc, version_2_11_3_msu, version_2_11_3, version_2_11_2_uiuc, version_2_11_2_msu, version_2_11_2_educog, version_2_11_2, version_2_11_1, version_2_11_0_RC3, version_2_11_0_RC2, version_2_11_0_RC1, version_2_11_0, version_2_10_X, version_2_10_1, version_2_10_0, loncapaMITrelate_1, language_hyphenation_merge, language_hyphenation, HEAD, BZ4492-merge, BZ4492-feature_horizontal_radioresponse
- Changes to keep text within right margin in PDF version of manual.

    1: \label{Institutional_Integration_Identity_Management}
    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
   79: table corresponding to a specific institutional type. A routine is
   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,}
  153: \begin{quotation}
  154: \texttt{~~~~~~~\$instusers,\$instids,\$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,}
  176: \texttt{~~~~\$srchtype,\$types) = @\_;}
  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: 
  187: \texttt{~~\$condition = \char`\"{}WHERE MSUNetID LIKE '\%\$srchterm\%'\char`\"{};}
  188: 
  189: \texttt{~~\$ldapfilter = '(uid={*}'.\$srchterm.'{*})';}
  190: 
  191: \texttt{\} elsif (\$srchtype eq 'begins') \{}
  192: 
  193: \texttt{~~\$condition = \char`\"{}WHERE MSUNetID LIKE '\$srchterm\%'\char`\"{};}
  194: 
  195: \texttt{~~\$ldapfilter = '(uid='.\$srchterm.'{*})';}
  196: 
  197: \texttt{\} else \{}
  198: 
  199: \texttt{~~\$condition = \char`\"{}WHERE MSUNetID = '\$srchterm'\char`\"{};}
  200: 
  201: \texttt{~~\$ldapfilter = '(uid='.\$srchterm.')';}
  202: 
  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: 
  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.'{*})';}
  223: 
  224: \texttt{\} elsif (\$srchtype eq 'begins') \{}
  225: 
  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.'{*})';}
  235: 
  236: \texttt{\} else \{}
  237: 
  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.')';}
  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: 
  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: 
  268: \texttt{~~if (\$dbflag) \{}
  269: 
  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: 
  277: \texttt{~~\}}
  278: 
  279: \texttt{~~\$ldapfilter = '(\&(sn='.\$srchlast.'{*})(givenName='.\$srchfirst.'{*}))';}
  280: 
  281: \texttt{\} else \{}
  282: \begin{quotation}
  283: \texttt{foreach my \$table (@\{\$srchtables\}) \{}
  284: \begin{quotation}
  285: \texttt{next if (\$srchby \&\& \$condition eq '');}
  286: 
  287: \texttt{my \$statement = \char`\"{}SELECT MSUNetID,Pid,FirstName,LastName,}
  288: \texttt{~~~~~~~~~~~~~~~~~Person\_Type 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: ) \{}
  296: 
  297: \texttt{~~\$pid=lc(\$pid);}
  298: 
  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
  311: AND FirstName = \$quoted\_first )\char`\"{};}
  312: 
  313: \texttt{~~\}}
  314: 
  315: \texttt{~~\$ldapfilter = '(\&(sn='.\$srchlast.')(givenName='.\$srchfirst.'))';}
  316: 
  317: \texttt{\}}
  318: \end{quotation}
  319: \texttt{\}}
  320: \end{quotation}
  321: \texttt{\} elsif (\$srchby eq 'id') \{}
  322: \begin{quotation}
  323: \texttt{if (\$dbflag) \{}
  324: 
  325: \texttt{~~if (\$srchterm =\~{} /\^{}{[}AZ]\textbackslash{}d\{8\}\$/)
  326: \{}
  327: \begin{quotation}
  328: \texttt{~~\$condition = \char`\"{}WHERE Pid = '\$srchterm'\char`\"{};}
  329: \end{quotation}
  330: \texttt{~~\}}
  331: 
  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: 
  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'\}\}))
  360: \{}
  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\}\$/)
  374: \{}
  375: 
  376: \texttt{~~~~~~~~~~if (ref(\$multipids\{\$uname\}) eq 'ARRAY')
  377: \{}
  378: 
  379: \texttt{~~~~~~~~~~~~if (!grep(/\^{}\$pid\$/,@\{\$multipids\{\$uname\}\}))
  380: \{}
  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\}\$/)
  400: \{}
  401: 
  402: \texttt{~~~~~~~~~~if (ref(\$multipids\{\$uname\}) eq 'ARRAY')
  403: \{}
  404: 
  405: \texttt{~~~~~~~~~~~~if (!grep(/\^{}\$pid\$/,@\{\$multipids\{\$uname\}\}))
  406: \{}
  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\}\$/)
  419: \{}
  420: 
  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{~~~~\};}
  444: 
  445: \texttt{~~\}}
  446: 
  447: \texttt{~~if (defined(\$instids->\{\$pid\})) \{}
  448: 
  449: \texttt{~~~~if (ref(\$instids->\{\$pid\}) eq 'ARRAY') \{}
  450: 
  451: \texttt{~~~~~~if (!grep(/\^{}\$uname\$/,@\{\$instids->\{\$pid\}\}))
  452: \{}
  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: 
  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.,
  498: official usernames from MSU), but are not currently affiliated with
  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') \{}
  563: 
  564: \texttt{~~if (@\{\$types\} > 0) \{}
  565: \begin{quotation}
  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\})));}
  573: 
  574: \texttt{\}}
  575: \end{quotation}
  576: \texttt{\}}
  577: 
  578: \texttt{if (ref(\$instusers->\{\$uname\}) eq 'HASH') \{}
  579: 
  580: \texttt{~~if (ref(\$instusers->\{\$uname\}\{'inststatus'\}) eq 'ARRAY')
  581: \{}
  582: 
  583: \texttt{~~~~if (!grep(/\^{}\$type\$/,@\{\$instusers->\{\$uname\}\{'inststatus'\}\}))
  584: \{}
  585: 
  586: \texttt{~~~~~~push(@\{\$instusers->\{\$uname\}\{'inststatus'\}\},\$type);}
  587: 
  588: \texttt{~~~~\}}
  589: 
  590: \texttt{~~\}}
  591: 
  592: \texttt{\} else \{}
  593: 
  594: \texttt{~~\$instusers->\{\$uname\} = \{}
  595: 
  596: \texttt{~~firstname => \$first,}
  597: 
  598: \texttt{~~lastname => \$last,}
  599: 
  600: \texttt{~~id => '',}
  601: 
  602: \texttt{~~permanentemail => \$email,}
  603: 
  604: \texttt{~~inststatus => {[}\$type],}
  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',}
  662: \texttt{~~~~~~~~~~~~~~~~~~'ASSISTANT','STUDENT\_AFFILIATE');}
  663: 
  664: \texttt{\&query\_user\_tables(\$dbflag,\$dbh,\textbackslash{}@srchtables,\$instusers,\$instids);}
  665: 
  666: \texttt{\$outcome = 'ok';}
  667: 
  668: \texttt{\&disconnect\_DB(\$dbh);}
  669: \end{quotation}
  670: \texttt{\}}
  671: 
  672: \texttt{return \$outcome;}
  673: \end{quotation}
  674: \texttt{\}}
  675: \end{quotation}

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