The idea of this project is to create a module to help automate one of the most common of integration tasks: userbase synchronization. Each integration (e.g. G2 in Drupal) has to synchronize its Drupal users with the G2 users. This is about minimizing the amount of code that has to be written per new integration. This module will be a common point for synchronization logic.
You can find all the user stories and use cases here.
Bob downloads Gallery 2 to integrate into his current supported emApp. He installs an existing G2 integration module into his emApp. He then configures it so that it may find G2. He then configures it so that it may find G2. The integration will then automatically check if the version of the G2 installation is compatible, check if the Integration Manager Module is active and if not, try to install and activate it. It will proceed to register its implementation of the user synchronization class with G2 which also includes default values for the synchronization options. At this point, the integration synchronizes special users first (admin and anonymous/guest.) Once the synchronization process is initiated, Bob sees a progress bar, and waits for syncing to complete. Once this is done, he is taken back to the status view. There a list of conflicts/errors is presented. If there had been no errors, it would have transparently gone from a "dry run" to actual commitment of synchronization. If there are conflicts/errors, an option to manually correct any error in the user mapping is available. Once this is done, he proceeds with a real synchronization run.
Bob goes to the status view from G2 admin. The status view is currently indicating that Bob has not done a user synchronization before. It also indicates there are currently no known conflicts. Furthermore, it currently states no users listed in G2 aren't listed in emApp. He selects the synchronization view. He changes the defaults to select the option to make G2 the master for user synchronization, which will override user data in emApp if there are any conflicts. He clicks the "Synchronize" button, which does a dry run to better prepare for any errors or conflicts that may occur.
Anthony Administrator Wants To Synchronize
Anthony Wants to Solve Conflicts
Isaac Integrator Wants To Make His Code Embed-module Compatible
This module is divided up into two parts. A GalleryEmbedSynchronization class that contains all the necessary logic for this project, and one interface for integrations to use to communicate with this module. Below you will find the specifications for these classes.
This class must be instantiated. The first call must be to init() to set up the class. If the integration coder wishes to override any options the user may have selected via a view, they can call the setOptions() method.
array _g2Users
List of all users in G2 as GalleryUser objects.
array _emAppUsers
Array of users in emApp in the format of GalleryUser::getMemberData().
array _options
* Synchronize options will be carried in this variable. * * @var array('ignorePasswordMismatches' => bool, 'ignoreLanguageMismatches' => bool, * 'allowExternalIdMapAdditions' => bool)
array _conflicts
* Conflict array. Contains one or more of the following types of arrays. * * @var array('type' => CONFLICT_USERDATA, 'g2User' => $g2UserData, 'emAppUser' => * $emAppUserData) * OR * array('type' => CONFLICT_ORPHAN, 'entityId' => $entityId, 'message' => $message)
init()
* Init function. Sets up class-related options. * * @return object GalleryStatus
addConflict($conflictData)
* Add a conflict to the conflicts array. * * This function performs basic validation checks before passing on the data to the conflict * array. If 'type' == CONFLICT_ORPHAN, will show first param as an id of some sort and second * param as an error message in which first param is involved. If 'type' == CONFLICT_USERDATA, * will compare them by key/value pairs, because they're two conflicting user arrays. * * @param array('type' => CONFLICT_USERDATA, 'g2User' => $g2UserData, 'emAppUser' => * $emAppUserData) * OR * array('type' => CONFLICT_ORPHAN, 'entityId' => $entityId, 'message' => $message) * @return object GalleryStatus
getConflictsArray()
* A function to retrieve all conflicts in $this->_conflicts * * @return array(object GalleryStatus, array $this->_conflicts)
compareUsers($g2User, $emAppUser, $params)
* Compare a G2 user with an integration app user by user properties. * * Set any or all of the array params to true to compare by those properties. * If 'case' is true, then compare will be case-sensitive. 'case' is determined within this * function by calling UserSynchronizationInterface_1_0::isCompareCaseSensitive(). * * @param object GalleryUser * @param array ('userName' => string the user name, 'fullName' => string full name, * 'email' => string user's e-mail, 'language' => string user's language, * 'hashedPassword' => string user's hashed password) * @param array('byUserName' => bool, 'byEmail' => bool, 'byLanguage' => bool, * 'byFullName' => bool, 'byHashedPassword' => bool, 'case' => bool) * @return array('userName' => 1, 'email' => 1, etc.) Any conflicts are entered here.
setOptions($params)
* Set options via this method. Can be used by integration coders to override any user-selected * options. * * @param array(any options from $this->_options => appropriate value)
synchronizeUsers($isDryRun=true)
* Synchronize $this->_emAppUsers and $this->_g2Users * * @param bool isDryRun determines if we are doing a dry run to check for errors * @return array object GalleryStatus a status code * array results array (..., 'g2Users' => $this->_g2Users) This function instantiates the following class: list($ret, $this->_emApp) = GalleryCoreApi::newFactoryInstance('UserSynchronizationInterface_1_0');
This is the interface which the integrator will use to implement integration app-related (emApp-related) tasks such as creating, deleting, and updating users in the emApp.
createUser($g2Data)
* Create a user in the emApp with the supplied user data and return the id of the new user. * @param array new user data ('userName' => string, 'fullName' => string, 'email' => string, * 'language' => string, 'hashedPassword' => string) * @return array (object GalleryStatus status code, mixed (string, integer) externalId of new user
updateUser($externalId, $userData)
* Update a user in the emApp. * @param mixed, external user Id * @param array new user data ('userName' => string, 'fullName' => string, 'email' => string, * 'language' => string, 'hashedPassword' => string) * @return array object GalleryStatus a status code
deleteUser($externalId)
* Delete a user from the emApp. * @param mixed external user Id * @return object GalleryStatus a status code
getUser($externalId) Currently in limbo
getGuestUser()
* Get user properties for emApp's 'guest' user. * * @return array object GalleryStatus status code * mixed (string, integer) externalId of user
getSiteAdmin()
* Get user properties for emApp's admin user. * * @return array object GalleryStatus status code * mixed (string, integer) externalId of user
getUsers()
* Get list of users from emApp. * * @return array (object GalleryStatus a status code, * array (mixed id => array('userName' => string, 'email' => string, * 'language' => string, 'hashedPassword' => string, * 'fullName' => string, 'id' => mixed)))
getRequiredUserProperties()
* Return which user properties are required when creating/comparing users. * * @return array ('userName' => bool, 'email' => bool, 'language' => bool, * 'hashedPassword' => bool, 'fullName' => bool)
isCompareCaseSensitive()
* Will we compare users in a case-sensitive fashion? * * @return array (object GalleryStatus status code, * bool isCaseSensitive)