Bdb packages | Design docs | Source docs | Guidelines | Recent releases

Search | Site Map .

Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

/BdbAccess/BdbAuthFederation.cc

Go to the documentation of this file.
00001 //--------------------------------------------------------------------------
00002 // File and Version Information:
00003 //      $Id: BdbAuthFederation.cc,v 1.3 2002/06/21 18:30:19 ryd Exp $
00004 //
00005 // Description:
00006 //      This class provides an access to and management of the BaBar
00007 //      Database athorization records for a federation.
00008 //
00009 // Environment:
00010 //      Software developed for the BaBar Detector at the SLAC B-Factory.
00011 //
00012 // Author List:
00013 //      Igor A. Gaponenko       Original Author
00014 //
00015 // History:
00016 //      Copyright (C) 2001      Lawrence Berkeley Laboratory
00017 //
00018 //------------------------------------------------------------------------
00019         /////////////////////////
00020         // This Class's Header //
00021         /////////////////////////
00022 
00023 #include "BdbAccess/BdbAuthFederation.hh"
00024 
00025         ///////////////
00026         // C Headers //
00027         ///////////////
00028 
00029 extern "C" {
00030 #include <assert.h>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <sys/types.h>
00035 #include <time.h>
00036 }
00037 
00038         /////////////////
00039         // C++ Headers //
00040         /////////////////
00041 
00042 #include <iostream.h>
00043 #include <string>
00044 using std::string;
00045 
00046         /////////////////////////////////
00047         // Collaborating Class Headers //
00048         /////////////////////////////////
00049 
00050 #include "BdbApplication/BdbDomain.hh"
00051 #include "BdbAccess/BdbAuthRegistry.hh"
00052 #include "BdbAccess/BdbAuthUser.hh"
00053 #include "BdbAccess/BdbAuthGroup.hh"
00054 #include "BdbAccess/BdbDbAccessMgr.hh"
00055 #include "BdbAccess/BdbAuthCache.hh"
00056 #include "BdbAccess/BdbAuthStatisticsMonitor.hh"
00057 
00058 
00059         /////////////////////////////////////////////////////////////////////////
00060         // Local Macros, Typedefs, Structures, Unions and Forward Declarations //
00061         /////////////////////////////////////////////////////////////////////////
00062 
00063 static const char rcsid[] = "$Id: BdbAuthFederation.cc,v 1.3 2002/06/21 18:30:19 ryd Exp $";
00064 
00065 
00066         ////////////////////////////////////
00067         // Static Data Member Definitions //
00068         ////////////////////////////////////
00069 
00070 const char* 
00071 BdbAuthFederation::RegistryNames[] = { "Registry_of_Conditions",
00072                                        "Registry_of_Events",
00073                                        "Registry_of_Online",
00074                                        "Registry_of_Spatial",
00075                                        "Registry_of_Temporal",
00076                                        "Registry_of_Configuration",
00077                                        "Registry_of_Ambient" };
00078 
00079         ////////////////
00080         // Destructor //
00081         ////////////////
00082 
00083 BdbAuthFederation::~BdbAuthFederation( )
00084 {
00085     delete _statMon;
00086     delete _cache;
00087 }
00088 
00089         /////////////////
00090         // Constructor //
00091         /////////////////
00092 
00093 BdbAuthFederation::BdbAuthFederation( const char* theName ) :
00094     _shortTransactionIsDisabled(false),
00095     _shortTransactionIsActive(false),
00096     _cachingIsDisabled(false),
00097     _statMon(0),
00098     _cache(0),
00099     _myName("")
00100 {
00101     if( 0 != theName ) _myName = theName;
00102 
00103     _statMon = new BdbAuthStatisticsMonitor( theName );
00104 
00105   // The actual database operations are deffered in order to allow someone else
00106   // to establish the proper context. 
00107 
00108     _isInitialized = false;
00109 }
00110 
00111 bool
00112 BdbAuthFederation::initialize( )
00113 {
00114     if( _isInitialized ) return _isInitialized;
00115     
00116   // Check for availability of short transaction, which is enabled by default.
00117   // This can be changed if the corresponding environment variable is found.
00118 
00119     if( 0 != getenv( "BDBAUTH_DISABLE_NESTED_TRANSACTIONS" )) {
00120         _shortTransactionIsDisabled = true;
00121     }
00122     
00123   // Check for availability of caching some frequently used information.
00124   // By default it's enabled.
00125   // The default behavior could be changed by defining
00126   // the following environment variable:
00127   //
00128   //    "BDBAUTH_DISABLE_CACHING"
00129   //
00130 
00131     if( 0 != getenv( "BDBAUTH_DISABLE_CACHING" )) {
00132         _cachingIsDisabled = true;
00133     }
00134 
00135   // Invalidate ::isAuthorized( ) cache.
00136 
00137     invalidateCache( );
00138 
00139   // Execute the rest of the method withing a short transaction in order to avoid
00140   // leaving the locked persistent objects.
00141 
00142     if( ! startShortReadTransaction( )) return _isInitialized;
00143 
00144     while( true ) {
00145 
00146       // Check if the database is properly configured.
00147       // Then lookup the registries in the authorization container.
00148 
00149         BdbHandle(BdbDBObj) theDbH;
00150         BdbDbAccessMgr      theAccessMgr;
00151 
00152         theAccessMgr.openManagementDb( theDbH, BdbcRead );
00153         if( BdbIsNull( theDbH )) {
00154             error( BdbDomain::IllegalDomain, "Unable to open/create Management DB." );
00155             break;
00156         }
00157 
00158       // Collect the information about registries for all known domains.
00159       //
00160       // NOTE: We are assuming that there is no holes in the enumeration of
00161       //       the domains.
00162 
00163         BdbHandle(BdbAuthRegistry) theRegH;
00164 
00165         for( int domain = BdbDomain::FirstDomain; domain < BdbDomain::IllegalDomain; domain++ ) {
00166             if( _registry[ domain - BdbDomain::FirstDomain ].isNull( )) {
00167                 theRegH.lookupObj( theDbH, RegistryNames[ domain - BdbDomain::FirstDomain ], BdbcRead );
00168                 _registry[ domain - BdbDomain::FirstDomain ] = theRegH;
00169             }
00170         }
00171 
00172       // And finally...
00173 
00174         bool transactionIsAvailable = true;
00175         if( ! populateCache( transactionIsAvailable )) {
00176             error( BdbDomain::IllegalDomain, "Failed to populate transient cache from the database." );
00177             break;
00178         }
00179 
00180       // Now, its all done.
00181 
00182         _isInitialized = true;
00183 
00184         break;
00185     }
00186     commitShortTransaction( );
00187 
00188     return _isInitialized;
00189 }
00190 
00191         ///////////////
00192         // Utilities //
00193         ///////////////
00194 
00195 char*
00196 BdbAuthFederation::current_time( )
00197 {
00198     time_t tt;
00199     char* buf;
00200     char* str;
00201     int i;
00202 
00203   // Obtain current time in ASCII in the following format:
00204   //   "Thu Sep  4 22:25:44 1997"
00205 
00206     tt  = time ( &tt );
00207     buf = ctime( &tt );
00208 
00209   // Compress the interesting information into:
00210   //   "Sep  4 22:25 1997"
00211 
00212     str = new char[18];
00213 
00214     // This does not work for unknown reason.
00215     // replaced by a stupid loop.
00216     //
00217     //    strncpy( &(str[0]), &(buf[4]), 12 );
00218 
00219     for( i = 0; i < 12; i++ )
00220         str[0+i] = buf[4+i];
00221 
00222     str[12] = ' ';
00223 
00224     // This does not work for unknown reason.
00225     // replaced by a stupid loop.
00226     //
00227     //    strncat( &(str[13]), &(buf[20]), 4  );
00228 
00229     for( i = 0; i < 4; i++ )
00230         str[13+i] = buf[20+i];
00231 
00232     str[17] = '\0';
00233 
00234     //    delete [] buf; We didn't do the new so I don't think we should delete it
00235 
00236     return str;
00237 }
00238 
00239         ///////////////////////
00240         // Selectors (const) //
00241         ///////////////////////
00242 
00243 string
00244 BdbAuthFederation::getName( )
00245 {
00246     return _myName;
00247 }
00248 
00249         ///////////////
00250         // Selectors //
00251         ///////////////
00252 
00253 d_Boolean
00254 BdbAuthFederation::isInitialized( BdbDomain::Domains theDomain )
00255 {
00256     assert( BdbDomain::isDomainValid( theDomain ));
00257 
00258     if( ! initialize( )) return false;
00259 
00260   // The domain is initialized if the corresponding Registry exists.
00261 
00262     return ( ! BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] ));
00263 }
00264 
00265 d_Boolean
00266 BdbAuthFederation::isAuthorized( BdbDomain::Domains    theDomain,
00267                                  BdbDomain::AuthLevels theAuthLevel,
00268                                  const char*           theAuthName )
00269 {
00270     d_Boolean result = false;
00271 
00272     assert( BdbDomain::isDomainValid   ( theDomain    ));
00273     assert( BdbDomain::isAuthLevelValid( theAuthLevel ));
00274 
00275     const char* theUserName  = BdbDomain::userName( );
00276     const char* theGroupName = theAuthName;
00277 
00278     _statMon->increment_isAuthorized( );
00279 
00280     if( ! initialize( )) return result;
00281 
00282     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
00283         error( theDomain, "Authorization database is not configured." );
00284         return result;
00285     }
00286 
00287   // Make sure the cache is populated (some actions modifying the contents
00288   // of the database may destroy it).
00289 
00290     bool transactionIsAvailable = false;
00291     if( ! populateCache( transactionIsAvailable )) {
00292         error( theDomain, "Failed to populate transient cache from the database." );
00293         return false;
00294     }
00295 
00296   // Try to find the record in the cache.
00297 
00298     if( tryCache( theDomain,
00299                   theAuthLevel,
00300                   theAuthName,
00301                   theUserName,
00302                   result )) return result;
00303 
00304   // WARNING:
00305   // ========
00306   //
00307   //   The following piece of code is executed within a short read-mode transaction
00308   //   in order to prevent possible locks.
00309   //
00310   //   The code is arranged in "exception-like" while-do loop. This is done in order
00311   //   to close transaction in the end.
00312   //
00313   //   A successfull sequence of execution is indicated by the "result"
00314   //   varisble set to "d_True" value.
00315 
00316     if( ! startShortReadTransaction( )) return result;
00317 
00318     while( true ) {
00319 
00320       // Use handles for better efficiency.
00321 
00322         BdbHandle(BdbAuthRegistry) theRegH;
00323         BdbHandle(BdbAuthGroup)    theGroupH;
00324         BdbHandle(BdbAuthUser)     theUserH;
00325 
00326         theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
00327 
00328       // Try to find this user in the database.
00329 
00330         theUserH = theRegH->getUser( theUserName );
00331         if( BdbIsNull( theUserH )) {
00332             error( theDomain, "User does not exist." );
00333             break;
00334         }
00335 
00336       // Make specific checking for the given authorization level.
00337 
00338         switch( theAuthLevel ) {
00339 
00340         case BdbDomain::System:
00341 
00342           // Verify if the user may assume SYSTEM-level rights.
00343 
00344             if( theUserH->isSystemManager( )) result = true;
00345             break;
00346 
00347         case BdbDomain::Group:
00348 
00349           // Verify if the user belongs to specified group (or is system manager)
00350 
00351             if( theUserH->isSystemManager( )) {
00352                 result = true;
00353             } else {
00354 
00355                 if( 0 == theGroupName ) {
00356                     error( theDomain, "Bad parameters. Group name must be specified." );
00357                 } else {
00358 
00359                     theGroupH = theUserH->getGroup( theGroupName );
00360                     if( BdbIsNull( theGroupH )) {
00361 
00362                         char* buf = new char [ 45 + strlen(theGroupName) ];
00363                         sprintf(buf, "User is not a member of the group \"%s\".", theGroupName);
00364 
00365                         error( theDomain, buf );
00366 
00367                         delete [] buf;
00368 
00369                     } else {
00370                         result = true;
00371                     }
00372                 }
00373             }
00374             break;
00375 
00376         case BdbDomain::User:
00377 
00378           // Here is nothing more to check, because such a user exists.
00379 
00380             result = true;
00381 
00382             break;
00383         }
00384         break;
00385     }
00386 
00387   // End current short transaction.
00388 
00389     commitShortTransaction( );
00390 
00391   // Update the cache.
00392 
00393     updateCache( theDomain,
00394                  theAuthLevel,
00395                  theAuthName,
00396                  theUserName,
00397                  result );
00398 
00399     return result;
00400 }
00401 
00402 d_Boolean
00403 BdbAuthFederation::isSystemManager( BdbDomain::Domains theDomain,
00404                                     const char*        theUserName )
00405 {
00406     d_Boolean result = false;
00407 
00408     assert( BdbDomain::isDomainValid( theDomain ));
00409     assert( 0 != theUserName );
00410 
00411     if( ! initialize( )) return result;
00412 
00413     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
00414         error( theDomain, "Authorization database is not configured." );
00415         return result;
00416     }
00417 
00418   // Use handles for better efficiency.
00419 
00420     BdbHandle(BdbAuthRegistry) theRegH;
00421     BdbHandle(BdbAuthUser)     theUserH;
00422 
00423     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
00424 
00425     theUserH = theRegH->getUser( theUserName );
00426     if( BdbIsNull( theUserH )) {
00427         error( theDomain, "User does not exist." );
00428         return result;
00429     }
00430 
00431   // Obtain and return desired information.
00432 
00433     return theUserH->isSystemManager( );
00434 }
00435 
00436 d_Boolean
00437 BdbAuthFederation::isGroupManager( BdbDomain::Domains theDomain,
00438                                    const char*        theUserName,
00439                                    const char*        theGroupName )
00440 {
00441     d_Boolean result = false;
00442 
00443     assert( BdbDomain::isDomainValid( theDomain ));
00444     assert( 0 != theUserName );
00445     assert( 0 != theGroupName );
00446 
00447     if( ! initialize( )) return result;
00448 
00449     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
00450         error( theDomain, "Authorization database is not configured." );
00451         return result;
00452     }
00453 
00454   // Use handles for better efficiency.
00455 
00456     BdbHandle(BdbAuthRegistry) theRegH;
00457     BdbHandle(BdbAuthUser)     theUserH;
00458     BdbHandle(BdbAuthGroup)    theGroupH;
00459 
00460     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
00461 
00462   // Try to find this user in the database.
00463 
00464     theUserH = theRegH->getUser( theUserName );
00465     if( BdbIsNull( theUserH )) {
00466         error( theDomain, "User does not exist." );
00467         return result;
00468     }
00469 
00470   // Try to find the group.
00471 
00472     theGroupH = theRegH->getGroup( theGroupName );
00473     if( BdbIsNull( theGroupH )) {
00474         error( theDomain, "Group does not exist." );
00475         return result;
00476     }
00477 
00478   // Try to find the user in the group in the list of managers.
00479 
00480     theUserH = theGroupH->getManager( theUserName );
00481 
00482     return ( ! BdbIsNull( theUserH ));
00483 }
00484 
00485 d_Boolean
00486 BdbAuthFederation::isGroupMember( BdbDomain::Domains theDomain,
00487                                   const char*        theUserName,
00488                                   const char*        theGroupName )
00489 {
00490     d_Boolean result = false;
00491 
00492     assert( BdbDomain::isDomainValid( theDomain ));
00493     assert( 0 != theUserName );
00494     assert( 0 != theGroupName );
00495 
00496     if( ! initialize( )) return result;
00497 
00498     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
00499         error( theDomain, "Authorization database is not configured." );
00500         return result;
00501     }
00502 
00503   // Use handles for better efficiency.
00504 
00505     BdbHandle(BdbAuthRegistry) theRegH;
00506     BdbHandle(BdbAuthUser)     theUserH;
00507     BdbHandle(BdbAuthGroup)    theGroupH;
00508 
00509     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
00510 
00511   // Try to find this user in the database.
00512 
00513     theUserH = theRegH->getUser( theUserName );
00514     if( BdbIsNull( theUserH )) {
00515         error( theDomain, "User does not exist." );
00516         return result;
00517     }
00518 
00519   // Try to find the group in the database.
00520 
00521     theGroupH = theRegH->getGroup( theGroupName );
00522     if( BdbIsNull( theGroupH )) {
00523         error( theDomain, "Group does not exist." );
00524         return result;
00525     }
00526 
00527   // Try to find the user in the group.
00528 
00529     theUserH = theGroupH->getUser( theUserName );
00530 
00531     return ( ! BdbIsNull( theUserH ));
00532 }
00533 
00534 d_Boolean
00535 BdbAuthFederation::isDomainMember( BdbDomain::Domains theDomain,
00536                                    const char*        theUserName )
00537 {
00538     d_Boolean result = false;
00539 
00540     assert( BdbDomain::isDomainValid( theDomain ));
00541     assert( 0 != theUserName );
00542 
00543     if( ! initialize( )) return result;
00544 
00545     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
00546         error( theDomain, "Authorization database is not configured." );
00547         return result;
00548     }
00549 
00550   // Use handles for better efficiency.
00551 
00552     BdbHandle(BdbAuthRegistry) theRegH;
00553     BdbHandle(BdbAuthUser)     theUserH;
00554 
00555     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
00556 
00557   // Try to find this user in the database.
00558 
00559     theUserH = theRegH->getUser( theUserName );
00560 
00561     return ( ! BdbIsNull( theUserH ));
00562 }
00563 
00564 d_Boolean
00565 BdbAuthFederation::isAccessAllowed( BdbDomain::Domains theDomain,
00566                                     const char*        theUserName )
00567 {
00568     d_Boolean result = isDomainMember( theDomain, theUserName );
00569     if( ! result ) {
00570         result = ( ! isDomainMember( theDomain, "registered_only" ));
00571     }
00572     return result;
00573 }
00574 
00575 const char*
00576 BdbAuthFederation::getUserDescription( BdbDomain::Domains theDomain,
00577                                        const char*        theUserName )
00578 {
00579     assert( BdbDomain::isDomainValid( theDomain ));
00580     assert( 0 != theUserName );
00581 
00582     if( ! initialize( )) return 0;
00583 
00584     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
00585         error( theDomain, "Authorization database is not configured." );
00586         return 0;
00587     }
00588 
00589   // Use handles for better efficiency.
00590 
00591     BdbHandle(BdbAuthRegistry) theRegH;
00592     BdbHandle(BdbAuthUser)     theUserH;
00593 
00594     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
00595 
00596   // Try to find this user in the database.
00597 
00598     theUserH = theRegH->getUser( theUserName );
00599     if( BdbIsNull( theUserH )) {
00600         error( theDomain, "User does not exist." );
00601         return 0;
00602     }
00603 
00604     return theUserH->getDescription( );
00605 }
00606 
00607 const char*
00608 BdbAuthFederation::getUserCreated( BdbDomain::Domains theDomain,
00609                                    const char*        theUserName )
00610 {
00611     assert( BdbDomain::isDomainValid( theDomain ));
00612     assert( 0 != theUserName );
00613 
00614     if( ! initialize( )) return 0;
00615 
00616     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
00617         error( theDomain, "Authorization database is not configured." );
00618         return 0;
00619     }
00620 
00621   // Use handles for better efficiency.
00622 
00623     BdbHandle(BdbAuthRegistry) theRegH;
00624     BdbHandle(BdbAuthUser)     theUserH;
00625 
00626     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
00627 
00628   // Try to find this user in the database.
00629 
00630     theUserH = theRegH->getUser( theUserName );
00631     if( BdbIsNull( theUserH )) {
00632         error( theDomain, "User does not exist." );
00633         return 0;
00634     }
00635 
00636     return theUserH->getCreated( );
00637 }
00638 
00639 const char*
00640 BdbAuthFederation::getGroupDescription( BdbDomain::Domains theDomain,
00641                                         const char*        theGroupName )
00642 {
00643     assert( BdbDomain::isDomainValid( theDomain ));
00644     assert( 0 != theGroupName );
00645 
00646     if( ! initialize( )) return 0;
00647 
00648     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
00649         error( theDomain, "Authorization database is not configured." );
00650         return 0;
00651     }
00652 
00653   // Use handles for better efficiency.
00654 
00655     BdbHandle(BdbAuthRegistry) theRegH;
00656     BdbHandle(BdbAuthGroup)    theGroupH;
00657 
00658     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
00659 
00660   // Try to find this group in the database.
00661 
00662     theGroupH = theRegH->getGroup( theGroupName );
00663     if( BdbIsNull( theGroupH )) {
00664         error( theDomain, "Group does not exist." );
00665         return 0;
00666     }
00667 
00668     return theGroupH->getDescription( );
00669 }
00670 
00671 const char*
00672 BdbAuthFederation::getGroupCreated( BdbDomain::Domains theDomain,
00673                                     const char*        theGroupName )
00674 {
00675     assert( BdbDomain::isDomainValid( theDomain ));
00676     assert( 0 != theGroupName );
00677 
00678     if( ! initialize( )) return 0;
00679 
00680     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
00681         error( theDomain, "Authorization database is not configured." );
00682         return 0;
00683     }
00684 
00685   // Use handles for better efficiency.
00686 
00687     BdbHandle(BdbAuthRegistry) theRegH;
00688     BdbHandle(BdbAuthGroup)    theGroupH;
00689 
00690     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
00691 
00692   // Try to find this group in the database.
00693 
00694     theGroupH = theRegH->getGroup( theGroupName );
00695     if( BdbIsNull( theGroupH )) {
00696         error( theDomain, "Group does not exist." );
00697         return 0;
00698     }
00699 
00700     return theGroupH->getCreated( );
00701 }
00702 
00703         ////////////////
00704         // Operations //
00705         ////////////////
00706 
00707 d_Boolean
00708 BdbAuthFederation::initialize( BdbDomain::Domains theDomain )
00709 {
00710     d_Boolean result = false;
00711 
00712     assert( BdbDomain::isDomainValid( theDomain ));
00713 
00714     d_ULong status;
00715 
00716     if( ! initialize( )) return result;
00717 
00718   // Invalidate ::isAuthorized( ) cache, for now we are going
00719   // to modify the contents of the database which eventually could
00720   // lead to the cache inconsistancy.
00721 
00722     invalidateCache( );
00723 
00724   // Use handles for better efficiency.
00725 
00726     BdbHandle(BdbAuthRegistry) theRegH;
00727 
00728     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
00729 
00730   // Delete domain information if it still exists (only a System Manager can do this).
00731 
00732     if( ! BdbIsNull( theRegH )) {
00733 
00734         if( ! isSystemManager( theDomain, BdbDomain::userName( ))) {
00735             error( theDomain, "No privileges for this operation." );
00736             return result;
00737         }
00738         BdbDelete( theRegH );
00739     }
00740 
00741   // Open the management database.
00742 
00743     BdbHandle(BdbDBObj) theDbH;
00744     BdbDbAccessMgr      theAccessMgr;
00745 
00746     theAccessMgr.openManagementDb( theDbH, BdbcRead );
00747     if( BdbIsNull( theDbH )) {
00748         error( theDomain, "Unable to open/create Management DB." );
00749         return result;
00750     }
00751 
00752   // Create the authorization container if it doesn't exist
00753 
00754     const char* authContName = "authorization";
00755 
00756     BdbHandle(BdbContObj) theContH;
00757 
00758     if( BdbcSuccess != theContH.exist( theDbH, authContName, BdbcRead )) {
00759         theContH = new( authContName, 0, 1, 1, theDbH ) BdbContObj;
00760         if( BdbIsNull( theContH )) {
00761             error( theDomain, "Unable to create authorization container" );
00762         }
00763     }
00764 
00765   // Create the registry object and give it a name.
00766 
00767     theRegH = new( theContH ) BdbAuthRegistry;
00768     if( BdbIsNull( theRegH )) {
00769         error( theDomain, "Unable to create a registry." );
00770         return result;
00771     }
00772     status = theRegH.nameObj( theDbH, RegistryNames[ theDomain - BdbDomain::FirstDomain ] );
00773     if( BdbcSuccess != status ) {
00774         error( theDomain, "Unable to give a name to the registry." );
00775         return result;
00776     }
00777 
00778   // Create default group. Then add it to the registry.
00779 
00780     BdbHandle(BdbAuthGroup) theGroupH;
00781 
00782     theGroupH = new( theContH ) BdbAuthGroup( "Global", current_time( ), "default group" );
00783     if( BdbIsNull( theGroupH )) {
00784         error( theDomain, "Unable to create default group." );
00785         return result;
00786     }
00787     status = theRegH->addGroup( theGroupH );
00788     if( BdbcSuccess != status ) {
00789         error( theDomain, "Unable to add default group to the registry." );
00790         return result;
00791     }
00792 
00793   // Create initial user. Make him a system manager.
00794   // Then add his record to the registry and to default group.
00795 
00796     BdbHandle(BdbAuthUser) theUserH;
00797 
00798     theUserH = new( theContH ) BdbAuthUser( BdbDomain::userName( ), current_time( ), "initial system manager" );
00799     if( BdbIsNull( theUserH )) {
00800         error( theDomain, "Unable to create initial user." );
00801         return result;
00802     }
00803     theUserH->setSystemManager( true );
00804 
00805     status = theRegH->addUser( theUserH );
00806     if( BdbcSuccess != status ) {
00807         error( theDomain, "Unable to add the user to the registry." );
00808         return result;
00809     }
00810     status = theGroupH->addMember( theUserH );
00811     if( BdbcSuccess != status ) {
00812         error( theDomain, "Unable to add a member to the group." );
00813         return result;
00814     }
00815 
00816   // Create lock container used during db creation.
00817 
00818     BdbHandle(BdbContObj) lockCont;
00819     const char* lockContName = "dbLock";
00820 
00821     if( BdbcSuccess != lockCont.exist( theDbH, lockContName, BdbcNoOpen )) {
00822         new( lockContName, 0, 1, 1, theDbH ) BdbContObj;
00823     }
00824 
00825   // Make the registry reference available.
00826 
00827     _registry[ theDomain - BdbDomain::FirstDomain ] = theRegH;
00828 
00829     return true;
00830 }
00831 
00832 d_Boolean
00833 BdbAuthFederation::createUser( BdbDomain::Domains    theDomain,
00834                                BdbDomain::AuthLevels theAuthLevel,
00835                                const char*           theUserName,
00836                                const char*           theGroupName,
00837                                const char*           theDescription )
00838 {
00839     d_Boolean result = false;
00840 
00841     assert( BdbDomain::isDomainValid( theDomain ));
00842     assert( BdbDomain::isAuthLevelValid( theAuthLevel ));
00843     assert( 0 != theUserName );
00844 
00845     d_ULong status;
00846 
00847     if( ! initialize( )) return result;
00848 
00849     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
00850         error( theDomain, "Authorization database is not configured." );
00851         return result;
00852     }
00853 
00854   // Use handles for better efficiency.
00855 
00856     BdbHandle(BdbAuthRegistry) theRegH;
00857     BdbHandle(BdbAuthUser)     theUserH;
00858     BdbHandle(BdbAuthGroup)    theGroupH;
00859 
00860     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
00861 
00862   // Invalidate ::isAuthorized( ) cache, for now we are going
00863   // to modify the contents of the database which eventually could
00864   // lead to the cache inconsistancy.
00865 
00866     invalidateCache( );
00867 
00868   // Check for the user rights to perform this operation.
00869 
00870     if( ! isSystemManager( theDomain, BdbDomain::userName( ))) {
00871         error( theDomain, "No privileges for this operation." );
00872         return result;
00873     }
00874 
00875   // Try to find this user in the database.
00876 
00877     theUserH = theRegH->getUser( theUserName );
00878     if( ! BdbIsNull( theUserH )) {
00879         error( theDomain, "User already exists." );
00880         return result;
00881     }
00882 
00883   // Create new user record. Tune it.
00884   // Then add the record to the registry.
00885 
00886     theUserH = new( theRegH ) BdbAuthUser( theUserName, current_time( ), theDescription );
00887 
00888     if( BdbIsNull( theUserH )) {
00889         error( theDomain, "Unable to create the user." );
00890         return result;
00891     }
00892     if( BdbDomain::System == theAuthLevel ) {
00893         theUserH->setSystemManager( true );
00894     }
00895 
00896     status = theRegH->addUser( theUserH );
00897     if( BdbcSuccess != status ) {
00898         error( theDomain, "Unable to add the user to the registry." );
00899         return result;
00900     }
00901 
00902   // Obtain the default group.
00903   // Then add user record to the default group.
00904 
00905     theGroupH = theRegH->getGroup( "Global" );
00906     if( BdbIsNull( theGroupH )) {
00907         error( theDomain, "Default group does not exist." );
00908         BdbDelete( theUserH );
00909         return result;
00910     }
00911 
00912     status = theGroupH->addMember( theUserH );
00913     if( BdbcSuccess != status ) {
00914         error( theDomain, "Unable to add a member to the group." );
00915         return result;
00916     }
00917 
00918   // If running on Group authorization level - try to find specified
00919   // group. Then add user there, if it is not the default group.
00920 
00921     if( BdbDomain::Group == theAuthLevel ) {
00922 
00923         if( 0 == theGroupName ) {
00924             error( theDomain, "Illegal parameters. Group name must be specified." );
00925             BdbDelete( theUserH );
00926             return result;
00927         }
00928         if( 0 == strcmp( "Global", theGroupName )) {
00929             error( theDomain, "Can not include the user into default group." );
00930             BdbDelete( theUserH );
00931             return result;
00932         }
00933 
00934         theGroupH = theRegH->getGroup( theGroupName );
00935         if( BdbIsNull( theGroupH )) {
00936             error( theDomain, "The group does not exist." );
00937             BdbDelete( theUserH );
00938             return result;
00939         }
00940 
00941         status = theGroupH->addMember( theUserH );
00942         if( BdbcSuccess != status ) {
00943             error( theDomain, "Unable to add a member to the group." );
00944             BdbDelete( theUserH );
00945             return result;
00946         }
00947     }
00948 
00949     return true;
00950 }
00951 
00952 d_Boolean
00953 BdbAuthFederation::deleteUser( BdbDomain::Domains theDomain,
00954                                const char*        theUserName )
00955 {
00956     d_Boolean result = false;
00957 
00958     assert( BdbDomain::isDomainValid( theDomain ));
00959     assert( 0 != theUserName );
00960 
00961     if( ! initialize( )) return result;
00962 
00963     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
00964         error( theDomain, "Authorization database is not configured." );
00965         return result;
00966     }
00967 
00968   // Use handles for better efficiency.
00969 
00970     BdbHandle(BdbAuthRegistry) theRegH;
00971     BdbHandle(BdbAuthUser)     theUserH;
00972 
00973     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
00974 
00975   // Invalidate ::isAuthorized( ) cache, for now we are going
00976   // to modify the contents of the database which eventually could
00977   // lead to the cache inconsistancy.
00978 
00979     invalidateCache( );
00980 
00981   // Check for the user rights to perform this operation.
00982 
00983     if( ! isSystemManager( theDomain, BdbDomain::userName( ))) {
00984         error( theDomain, "No privileges for this operation." );
00985         return result;
00986     }
00987 
00988   // Try to find specified user in the database. Then delete it
00989   // if exists. The user will be atomatically excluded from
00990   // all the groups it belongs to.
00991 
00992     theUserH = theRegH->getUser( theUserName );
00993     if( BdbIsNull( theUserH )) {
00994         error( theDomain, "User does not exist." );
00995         return result;
00996     }
00997     BdbDelete( theUserH );
00998 
00999     return true;
01000 }
01001 
01002 d_Boolean
01003 BdbAuthFederation::createGroup( BdbDomain::Domains theDomain,
01004                                 const char*        theGroupName,
01005                                 const char*        theDescription )
01006 {
01007     d_Boolean result = false;
01008 
01009     d_ULong status;
01010 
01011     assert( BdbDomain::isDomainValid( theDomain ));
01012     assert( 0 != theGroupName );
01013     assert( 0 != theDescription );
01014 
01015     if( ! initialize( )) return result;
01016 
01017     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
01018         error( theDomain, "Authorization database is not configured." );
01019         return result;
01020     }
01021 
01022   // Use handles for better efficiency.
01023 
01024     BdbHandle(BdbAuthRegistry) theRegH;
01025     BdbHandle(BdbAuthGroup)    theGroupH;
01026 
01027     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
01028 
01029   // Invalidate ::isAuthorized( ) cache, for now we are going
01030   // to modify the contents of the database which eventually could
01031   // lead to the cache inconsistancy.
01032 
01033     invalidateCache( );
01034 
01035   // Check for the user rights to perform this operation.
01036 
01037     if( ! isSystemManager( theDomain, BdbDomain::userName( ))) {
01038         error( theDomain, "No privileges for this operation." );
01039         return result;
01040     }
01041 
01042   // Do not create the default group.
01043 
01044     if( 0 == strcmp( "Global", theGroupName )) {
01045         error( theDomain, "Default group can not be created." );
01046         return result;
01047     }
01048 
01049   // Try to find this group in the database.
01050 
01051     theGroupH = theRegH->getGroup( theGroupName );
01052     if( ! BdbIsNull( theGroupH )) {
01053         error( theDomain, "Group already exists." );
01054         return result;
01055     }
01056 
01057   // Make new group record then add it to registry.
01058 
01059     theGroupH = new( theRegH ) BdbAuthGroup( theGroupName, current_time( ), theDescription );
01060     if( BdbIsNull( theGroupH )) {
01061         error( theDomain, "Unable to create the group." );
01062         return result;
01063     }
01064 
01065     status = theRegH->addGroup( theGroupH );
01066     if( BdbcSuccess != status ) {
01067         error( theDomain, "Unable to add the group to the registry." );
01068         BdbDelete( theGroupH );
01069         return result;
01070     }
01071 
01072     return true;
01073 }
01074 
01075 d_Boolean
01076 BdbAuthFederation::deleteGroup( BdbDomain::Domains theDomain,
01077                                 const char*        theGroupName )
01078 {
01079     d_Boolean result = false;
01080 
01081     assert( BdbDomain::isDomainValid( theDomain ));
01082     assert( 0 != theGroupName );
01083 
01084     if( ! initialize( )) return result;
01085 
01086     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
01087         error( theDomain, "Authorization database is not configured." );
01088         return result;
01089     }
01090 
01091   // Use handles for better efficiency.
01092 
01093     BdbHandle(BdbAuthRegistry) theRegH;
01094     BdbHandle(BdbAuthGroup)    theGroupH;
01095 
01096     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
01097 
01098   // Invalidate ::isAuthorized( ) cache, for now we are going
01099   // to modify the contents of the database which eventually could
01100   // lead to the cache inconsistancy.
01101 
01102     invalidateCache( );
01103 
01104   // Check for the user rights to perform this operation.
01105 
01106     if( ! isSystemManager( theDomain, BdbDomain::userName( ))) {
01107         error( theDomain, "No privileges for this operation." );
01108         return result;
01109     }
01110 
01111   // Do not delete the default group.
01112 
01113     if( 0 == strcmp( "Global", theGroupName )) {
01114         error( theDomain, "Default group can not be deleted." );
01115         return result;
01116     }
01117 
01118   // Try to find specified group in the database. Then delete it
01119   // if exists.
01120   // All the existing group members will be automatically disconnected
01121   // from the group.
01122 
01123     theGroupH = theRegH->getGroup( theGroupName );
01124     if( BdbIsNull( theGroupH )) {
01125         error( theDomain, "Group does not exist." );
01126         return result;
01127     }
01128     BdbDelete( theGroupH );
01129 
01130     return true;
01131 }
01132 
01133 d_Boolean
01134 BdbAuthFederation::includeUser( BdbDomain::Domains theDomain,
01135                                 const char*        theUserName,
01136                                 const char*        theGroupName )
01137 {
01138     d_Boolean result = false;
01139 
01140     d_ULong status;
01141 
01142     assert( BdbDomain::isDomainValid( theDomain ));
01143     assert( 0 != theUserName );
01144     assert( 0 != theGroupName );
01145 
01146     if( ! initialize( )) return result;
01147 
01148     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
01149         error( theDomain, "Authorization database is not configured." );
01150         return result;
01151     }
01152 
01153   // Use handles for better efficiency.
01154 
01155     BdbHandle(BdbAuthRegistry) theRegH;
01156     BdbHandle(BdbAuthUser)     theUserH;
01157     BdbHandle(BdbAuthGroup)    theGroupH;
01158 
01159     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
01160 
01161   // Invalidate ::isAuthorized( ) cache, for now we are going
01162   // to modify the contents of the database which eventually could
01163   // lead to the cache inconsistancy.
01164 
01165     invalidateCache( );
01166 
01167   // Check for the user rights to perform this operation.
01168 
01169     if( ! isSystemManager( theDomain, BdbDomain::userName( ))) {
01170         if( ! isGroupManager( theDomain, BdbDomain::userName( ), theGroupName )) {
01171             error( theDomain, "No privileges for this operation." );
01172             return result;
01173         }
01174     }
01175 
01176   // Do not include into default group.
01177 
01178     if( 0 == strcmp( "Global", theGroupName )) {
01179         error( theDomain, "Cannot include into default group." );
01180         return result;
01181     }
01182 
01183   // Try to find specified group in the databongs
01184 
01185     theGroupH = theRegH->getGroup( theGroupName );
01186     if( BdbIsNull( theGroupH )) {
01187         error( theDomain, "The group does not exist." );
01188         return result;
01189     }
01190 
01191   // Try to find the user in this group.
01192 
01193     theUserH = theGroupH->getUser( theUserName );
01194     if( ! BdbIsNull( theUserH )) {
01195         warning( theDomain, "The user is already a member of this group." );
01196         return true;
01197     }
01198 
01199   // Try to find specified user in all the database.
01200 
01201     theUserH = theRegH->getUser( theUserName );
01202     if( BdbIsNull( theUserH )) {
01203         error( theDomain, "The user does not exist." );
01204         return result;
01205     }
01206 
01207   // Include user into the group.
01208 
01209     status = theGroupH->addMember( theUserH );
01210     if( BdbcSuccess != status ) {
01211         error( theDomain, "Unable to add new member to the group." );
01212         return result;
01213     }
01214 
01215     return true;
01216 }
01217 
01218 d_Boolean
01219 BdbAuthFederation::excludeUser( BdbDomain::Domains theDomain,
01220                                 const char*        theUserName,
01221                                 const char*        theGroupName )
01222 {
01223     d_Boolean result = false;
01224 
01225     d_ULong status;
01226 
01227     assert( BdbDomain::isDomainValid( theDomain ));
01228     assert( 0 != theUserName );
01229     assert( 0 != theGroupName );
01230 
01231     if( ! initialize( )) return result;
01232 
01233     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
01234         error( theDomain, "Authorization database is not configured." );
01235         return result;
01236     }
01237 
01238   // Use handles for better efficiency.
01239 
01240     BdbHandle(BdbAuthRegistry) theRegH;
01241     BdbHandle(BdbAuthUser)     theUserH;
01242     BdbHandle(BdbAuthGroup)    theGroupH;
01243 
01244     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
01245 
01246   // Invalidate ::isAuthorized( ) cache, for now we are going
01247   // to modify the contents of the database which eventually could
01248   // lead to the cache inconsistancy.
01249 
01250     invalidateCache( );
01251 
01252   // Check for the user rights to perform this operation.
01253 
01254     if( ! isSystemManager( theDomain, BdbDomain::userName( ))) {
01255         if( ! isGroupManager( theDomain, BdbDomain::userName( ), theGroupName )) {
01256             error( theDomain, "No privileges for this operation." );
01257             return result;
01258         }
01259     }
01260 
01261   // Do not exclude from default group.
01262 
01263     if( 0 == strcmp( "Global", theGroupName )) {
01264         error( theDomain, "Cannot exclude from default group." );
01265         return result;
01266     }
01267 
01268   // Try to find specified group in the database.
01269 
01270     theGroupH = theRegH->getGroup( theGroupName );
01271     if( BdbIsNull( theGroupH )) {
01272         error( theDomain, "Group does not exist." );
01273         return result;
01274     }
01275 
01276   // Try to find the user in this group.
01277 
01278     theUserH = theGroupH->getUser( theUserName );
01279     if( BdbIsNull( theUserH )) {
01280         warning( theDomain, "User is not a member of this group." );
01281         return true;
01282     }
01283 
01284   // Exclude user from the group.
01285 
01286     status = theUserH->excludeFromGroup( theGroupH );
01287     if( BdbcSuccess != status ) {
01288         error( theDomain, "Unable to remove user from the group." );
01289         return result;
01290     }
01291 
01292     return true;
01293 }
01294 
01295 d_Boolean
01296 BdbAuthFederation::deleteDomain( BdbDomain::Domains theDomain )
01297 {
01298     d_Boolean result = false;
01299 
01300     assert( BdbDomain::isDomainValid( theDomain ));
01301 
01302     if( ! initialize( )) return result;
01303 
01304     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
01305         error( theDomain, "Authorization database is not configured." );
01306         return result;
01307     }
01308 
01309   // Use handles for better efficiency.
01310 
01311     BdbHandle(BdbAuthRegistry) theRegH;
01312 
01313     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
01314 
01315   // Invalidate ::isAuthorized( ) cache, for now we are going
01316   // to modify the contents of the database which eventually could
01317   // lead to the cache inconsistancy.
01318 
01319     invalidateCache( );
01320 
01321   // Check for the user rights to perform this operation.
01322 
01323     if( ! isSystemManager( theDomain, BdbDomain::userName( ))) {
01324         error( theDomain, "No privileges for this operation." );
01325         return result;
01326     }
01327 
01328   // Delete specified registry as a composite object.
01329 
01330     BdbDelete( theRegH );
01331 
01332   // Update information in the persistent cache.
01333 
01334     _registry[ theDomain - BdbDomain::FirstDomain ] = 0;
01335 
01336     return true;
01337 }
01338 
01339 d_Boolean
01340 BdbAuthFederation::setSystemManager( BdbDomain::Domains theDomain,
01341                                      const char*        theUserName,
01342                                      d_Boolean          onOff )
01343 {
01344     d_Boolean result = false;
01345 
01346     assert( BdbDomain::isDomainValid( theDomain ));
01347     assert( 0 != theUserName );
01348 
01349     if( ! initialize( )) return result;
01350 
01351     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
01352         error( theDomain, "Authorization database is not configured." );
01353         return result;
01354     }
01355 
01356   // Use handles for better efficiency.
01357 
01358     BdbHandle(BdbAuthRegistry) theRegH;
01359     BdbHandle(BdbAuthUser)     theUserH;
01360 
01361     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
01362 
01363   // Invalidate ::isAuthorized( ) cache, for now we are going
01364   // to modify the contents of the database which eventually could
01365   // lead to the cache inconsistancy.
01366 
01367     invalidateCache( );
01368 
01369   // Check for the user rights to perform this operation.
01370 
01371     if( ! isSystemManager( theDomain, BdbDomain::userName( ))) {
01372         error( theDomain, "No privileges for this operation." );
01373         return result;
01374     }
01375 
01376   // Try to find this user in the database.
01377   // Then set/reset his system management right.
01378 
01379     theUserH = theRegH->getUser( theUserName );
01380     if( BdbIsNull( theUserH )) {
01381         error( theDomain, "User does not exist." );
01382         return result;
01383     }
01384     theUserH->setSystemManager( onOff );
01385 
01386     return true;
01387 }
01388 
01389 d_Boolean
01390 BdbAuthFederation::setGroupManager( BdbDomain::Domains theDomain,
01391                                     const char*        theUserName,
01392                                     const char*        theGroupName,
01393                                     d_Boolean          onOff )
01394 {
01395     d_Boolean result = false;
01396 
01397     d_ULong status;
01398 
01399     assert( BdbDomain::isDomainValid( theDomain ));
01400     assert( 0 != theUserName );
01401     assert( 0 != theGroupName );
01402 
01403     if( ! initialize( )) return result;
01404 
01405     if( BdbIsNull( _registry[ theDomain - BdbDomain::FirstDomain ] )) {
01406         error( theDomain, "Authorization database is not configured." );
01407         return result;
01408     }
01409 
01410   // Use handles for better efficiency.
01411 
01412     BdbHandle(BdbAuthRegistry) theRegH;
01413     BdbHandle(BdbAuthUser)     theUserH;
01414     BdbHandle(BdbAuthGroup)    theGroupH;
01415 
01416     theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
01417 
01418   // Invalidate ::isAuthorized( ) cache, for now we are going
01419   // to modify the contents of the database which eventually could
01420   // lead to the cache inconsistancy.
01421 
01422     invalidateCache( );
01423 
01424   // Check for the user rights to perform this operation.
01425 
01426     if( ! isSystemManager( theDomain, BdbDomain::userName( ))) {
01427         error( theDomain, "No privileges for this operation." );
01428         return result;
01429     }
01430 
01431   // This operation is not allowed for the default group.
01432 
01433     if( 0 == strcmp( "Global", theGroupName )) {
01434         error( theDomain, "The operation is not allowed for the default group." );
01435         return result;
01436     }
01437   // Try to find this user in the database.
01438 
01439     theUserH = theRegH->getUser( theUserName );
01440     if( BdbIsNull( theUserH )) {
01441         error( theDomain, "User does not exist." );
01442         return result;
01443     }
01444 
01445   // Try to find the group in the database.
01446 
01447     theGroupH = theRegH->getGroup( theGroupName );
01448     if( BdbIsNull( theGroupH )) {
01449         error( theDomain, "Group does not exist." );
01450         return result;
01451     }
01452 
01453   // Add/remove user as a manager of the group.
01454 
01455     if( onOff ) {
01456         status = theGroupH->addManager( theUserH );
01457     } else {
01458         status = theGroupH->removeManager( theUserH );
01459     }
01460     if( BdbcSuccess != status ) {
01461         error( theDomain, "Unable to add/remove user as a group manager." );
01462         return result;
01463     }
01464 
01465     return true;
01466 }
01467 
01468         //////////////////////////////////
01469         // Short transaction management //
01470         //////////////////////////////////
01471 
01472 d_Boolean
01473 BdbAuthFederation::startShortReadTransaction( )
01474 {
01475   // Avoid using short transactions if it's not required.
01476 
01477     if( _shortTransactionIsDisabled ) return true;
01478 
01479   // We allow one more level of nested transactions only.
01480 
01481     if( _shortTransactionIsActive ) {
01482         error( BdbDomain::IllegalDomain, "Short transaction is already active. Internal bug." );
01483         return false;
01484     }
01485 
01486   // Start a transaction in another context.
01487 
01488     BdbApplicationOrDomain* theApp = BdbApplicationOrDomain::activeInstance( );
01489     BdbStatus               status;
01490 
01491     status = theApp->startNestedRead( );
01492     if( BdbcSuccess != status ) {
01493         error( BdbDomain::IllegalDomain, "Failed to start nested transaction." );
01494         return false;
01495     }
01496     _shortTransactionIsActive = true;
01497 
01498     return true;
01499 }
01500 
01501 d_Boolean
01502 BdbAuthFederation::commitShortTransaction( )
01503 {
01504   // Avoid using short transactions if it's not required.
01505 
01506     if( _shortTransactionIsDisabled ) return true;
01507 
01508   // We allow one more level of nested transactions only. At this point this transaction
01509   // should be actiaved.
01510 
01511     if( ! _shortTransactionIsActive ) {
01512         error( BdbDomain::IllegalDomain, "Short transaction is not active. Internal bug." );
01513         return false;
01514     }
01515 
01516   // Commit current transaction.
01517 
01518     BdbApplicationOrDomain* theApp = BdbApplicationOrDomain::activeInstance( );
01519     BdbStatus               status;
01520 
01521     status = theApp->commitNested( );
01522     if( BdbcSuccess != status ) {
01523         error( BdbDomain::IllegalDomain, "Failed to commit nested transaction." );
01524         return false;
01525     }
01526     _shortTransactionIsActive = false;
01527 
01528   // Done.
01529 
01530     return true;
01531 }
01532 
01533         ///////////////////////////////////////
01534         // ::isAuthorized( ) cache management //
01535         ///////////////////////////////////////
01536 
01537 bool
01538 BdbAuthFederation::tryCache( BdbDomain::Domains    theDomain,
01539                              BdbDomain::AuthLevels theAuthLevel,
01540                              const char*           theAuthName,
01541                              const char*           theUserName,
01542                              d_Boolean&            isAuthorizedFlag )
01543 {
01544   // The cache is always empty if caching is disabled.
01545 
01546     if( _cachingIsDisabled ) return false;
01547     if( 0 == _cache )        return false;
01548 
01549     return _cache->tryCache( theDomain,
01550                              theAuthLevel,
01551                              theAuthName,
01552                              theUserName,
01553                              isAuthorizedFlag );
01554 }
01555                        
01556 void
01557 BdbAuthFederation::updateCache( BdbDomain::Domains    theDomain,
01558                                 BdbDomain::AuthLevels theAuthLevel,
01559                                 const char*           theAuthName,
01560                                 const char*           theUserName,
01561                                 d_Boolean             isAuthorizedFlag )
01562 {
01563   // The cache is never updated if caching is disabled.
01564 
01565     if( _cachingIsDisabled ) return;
01566     if( 0 == _cache ) _cache = new BdbAuthCache( );
01567 
01568     _cache->updateCache( theDomain,
01569                          theAuthLevel,
01570                          theAuthName,
01571                          theUserName,
01572                          isAuthorizedFlag );
01573 
01574   // Update statistics.
01575 
01576     _statMon->increment_reloadCache( );
01577 }
01578 
01579 void
01580 BdbAuthFederation::invalidateCache( )
01581 {
01582   // The cache is never touched if caching is disabled.
01583 
01584     if( _cachingIsDisabled ) return;
01585 
01586     delete _cache;
01587     _cache = 0;
01588 }
01589 
01590 bool
01591 BdbAuthFederation::populateCache( bool transactionIsAvailable )
01592 {
01593   // NOTE: The cache is never touched if caching is disabled
01594   //       or if it's already loaded.
01595 
01596     if( _cachingIsDisabled ) return true;
01597     if( 0 != _cache ) return true;
01598 
01599   // Do cache loading in a kind of exception loop to provide the flawless
01600   // transaction management logic (if the one is needed) and cleanup seqeunce
01601   // if the loading will fail.
01602 
01603     bool failed = false;
01604 
01605     if( ! transactionIsAvailable ) {
01606         if( ! startShortReadTransaction( )) return false;
01607     }
01608     _cache = new BdbAuthCache( );
01609 
01610     while( true ) {
01611 
01612       // Use handles for better efficiency.
01613 
01614         BdbHandle(BdbAuthRegistry) theRegH;
01615         BdbHandle(BdbAuthGroup)    theGroupH;
01616         BdbHandle(BdbAuthUser)     theUserH;
01617 
01618         const char* theUserName = BdbDomain::userName( );
01619         const char* theGroupName;
01620 
01621         for( int theDomain = BdbDomain::FirstDomain;
01622                  theDomain < BdbDomain::IllegalDomain;
01623                  theDomain++ ) {
01624 
01625           // Just ignore non-initialized domain. There will be no information
01626           // in the cache about this domain.
01627 
01628             theRegH = _registry[ theDomain - BdbDomain::FirstDomain ];
01629             if( BdbIsNull( theRegH )) continue;
01630 
01631           // Just ignore non-existing user. There will be no information
01632           // in the cache about this domain.
01633 
01634             theUserH = theRegH->getUser( theUserName );
01635             if( BdbIsNull( theUserH )) continue;
01636 
01637           // System
01638 
01639             d_Boolean resultForSystem = theUserH->isSystemManager( );
01640 
01641             updateCache( static_cast<BdbDomain::Domains>( theDomain ),
01642                          BdbDomain::System,
01643                          0,
01644                          theUserName,
01645                          resultForSystem );
01646 
01647           // Group
01648           //
01649           //    NOTE: If a user is a System Manager then he/she is authorized
01650           //          for all the known groups, if not then only for those
01651           //          ones he/she is explicitly registered in.
01652 
01653             BdbItr(BdbAuthGroup) theItr;
01654 
01655             if( resultForSystem ) {
01656                 theRegH->setGroupsItr( theItr );
01657             } else {
01658                 theUserH->setGroupsItr( theItr );
01659             }
01660             while( theItr.next( )) {
01661 
01662                 theGroupH = (const BdbHandle(BdbAuthGroup)&) theItr;
01663                 if( BdbIsNull( theGroupH )) {
01664                     BdbAuthFederation::error( static_cast<BdbDomain::Domains>( theDomain ), "Inconsistency in the Authorization database." );
01665                     failed = true;
01666                     break;
01667                 }
01668                 updateCache( static_cast<BdbDomain::Domains>( theDomain ),
01669                              BdbDomain::Group,
01670                              theGroupH->getName( ),
01671                              theUserName,
01672                              d_True );
01673             }
01674             if( failed ) break;
01675 
01676           // User
01677           //
01678           //    NOTE: There is nothing to check - the user already exist.
01679 
01680             updateCache( static_cast<BdbDomain::Domains>( theDomain ),
01681                          BdbDomain::User,
01682                          0,
01683                          theUserName,
01684                          d_True );
01685         }
01686         break;
01687     }
01688     if( failed ) {
01689         invalidateCache( );
01690     }
01691     if( ! transactionIsAvailable ) {
01692         commitShortTransaction( );
01693     }
01694 
01695     return ! failed;
01696 }
01697 
01698         ////////////////////////
01699         // Messages reporting //
01700         ////////////////////////
01701 
01702 void
01703 BdbAuthFederation::message( BdbDomain::Domains theDomain,
01704                             const char*        theMessage )
01705 {
01706     cout << "BdbAuthFederation::message() " << theMessage << endl
01707          << "    FEDERATION: " << _myName << endl
01708          << "    DOMAIN:     " << BdbDomain::domainName( theDomain ) << endl;
01709 }
01710 
01711 void
01712 BdbAuthFederation::warning( BdbDomain::Domains theDomain,
01713                             const char*        theMessage )
01714 {
01715     cout << "BdbAuthFederation::warning() " << theMessage << endl
01716          << "    FEDERATION: " << _myName << endl
01717          << "    DOMAIN:     " << BdbDomain::domainName( theDomain ) << endl;
01718 }
01719 
01720 void
01721 BdbAuthFederation::error( BdbDomain::Domains theDomain,
01722                           const char*        theMessage )
01723 {
01724     cout << "BdbAuthFederation::error() " << theMessage << endl
01725          << "    FEDERATION: " << _myName << endl
01726          << "    DOMAIN:     " << BdbDomain::domainName( theDomain ) << endl;
01727 }
01728 
01729 void
01730 BdbAuthFederation::fatal( BdbDomain::Domains theDomain,
01731                           const char*        theMessage,
01732                           int                exitCode )
01733 {
01734     cout << "BdbAuthFederation::fatal() " << theMessage << endl
01735          << "    FEDERATION: " << _myName << endl
01736          << "    DOMAIN:     " << BdbDomain::domainName( theDomain ) << endl;
01737 
01738     exit( exitCode );
01739 }
01740 
01741 /////////////////
01742 // End Of File //
01743 /////////////////

 


BaBar Public Site | SLAC | News | Links | Who's Who | Contact Us

Page Owner: Jacek Becla
Last Update: October 04, 2002