"www.kentico.com","web development blog"

Synchronizing User Roles to Other Kentico Sites

By Albert Hovingh On August 02, 2019

Synchronizing User Roles to Other Kentico Sites
In the previous blog post, How to Sync Users and Roles across Multiple servers in Kentico, you can find out how we mapped the users from one system to another, to save you a click, I’ve included a picture of how the environment is set up for syncing. As a reminder, please note that the code is for Kentico v8. Most of it will still apply to later versions, but it may need some adjustment. If you want to see the code that is running for the scheduled task that calls this, head back to part 1 of this series.

Step 4 - Build the User Role Map

Once we’ve set up the User Roles to sync over to the different boat sites, we need to sync over the relationships between those users/roles, but now it gets a little complex. Why? Because we can't use IDs for synchronization, and the only thing that maps those two ... is a table of IDs. 

Table of IDs

So, we need to see a map of how the user roles look on the boat by ID and how the port would look if it used those same IDs. We also need the same map of the port and how the boat would look if it used the IDs for those.

It will look something like this when we are done so that all we have to do is compare the two maps to find out which ones we need to add and which ones to delete.
 
PortUserRoleMap   BoatUserRoleMap

BoatUserID: 60
 PorttUserID: 6 
BoatRoleID: 3 
PortRoleID: 2 ​

BoatUserID: 60
 PorttUserID: 6 
BoatRoleID: 3 
PortRoleID: 2 ​

 BoatUserID: 60
PorttUserID: 6
BoatRoleID: 5
PortRoleID: 4

 BoatUserID: 60
PorttUserID: 6
BoatRoleID: 5
PortRoleID: 4

BoatUserID: 61
PorttUserID: 5
​BoatRoleID: 3
  PortRoleID: 2   ​

 
 

BoatUserID: 61
PorttUserID: 5
BoatRoleID: 5
PortRoleID: 4

 
This will tell us that we need to add the third RoleMap into our boat since it was added on the port, and that we need to delete the fourth one from our boat since it was deleted from the port. Below is the code that I used to actually create the mapping table.
private List<UserRoleMap> GetBoatUserRoleMaps(List<UserRoleInfo> boatRoleInfos)
{
    List<UserRoleMap> userRoleMap=
        boatRoleInfos
            .Join(_mappedUsers,
                boatRoleInfo => boatRoleInfo .UserID,
                mappedUsers => mappedUsers.BoatUser.UserID,
                (boatRoleInfo , mappedUsers) => new UserRoleMap
                {
                    PortUserID = mappedUsers.PortUser.UserID,
                    BoatUserID = mappedUsers.BoatUser.UserID,
                    BoatRoleID = boatRoleInfo .RoleID
                })
            .Join(_mappedRoles,
                userRoleMaps=> userRoleMaps.BoatRoleID,
                roleMaps => roleMaps.BoatRole.RoleID,
                (userRoleMaps, roleMaps) => new UserRoleMap
                {
                    BoatUserID = userRoleMaps.BoatUserID,
                    PortUserID = userRoleMaps.PortUserID,
                    BoatRoleID = userRoleMaps.BoatRoleID,
                    PortRoleID = roleMaps.PortRole.RoleID
                }).ToList();

    return userRoleMap;
}

private List<UserRoleMap> GetPortUserRoleMaps(List<UserRoleInfo> portRoleInfos)
{

    List<UserRoleMap> joinedRoles = portRoleInfos
        .Join(_mappedUsers,
            pri => pri.UserID,
            maps => maps.PortUser.UserID,
            (pri, maps) => new UserRoleMap
            {
                PortUserID = maps.PortUser.UserID,
                BoatUserID = maps.BoatUser.UserID,
                PortRoleID = pri.RoleID
            }).ToList();

    return joinedRoles
        .Join(_mappedRoles,
            urMaps => urMaps.PortRoleID,
            roleMaps => roleMaps.PortRole.RoleID,
            (urMaps, roleMaps) => new UserRoleMap
            {
                BoatUserID = urMaps.BoatUserID,
                PortUserID = urMaps.PortUserID,
                PortRoleID = urMaps.PortRoleID,
                BoatRoleID = roleMaps.BoatRole.RoleID
            }).ToList();
}

Step 5 - Sync the User Roles

The nice thing about this is that we don't need to worry about updating anything since it's just a mapping table of IDs. Adding is just looking for anything that is in our port map that isn't in our boat map. Deleting is just looking for anything that is in our boat map that isn't in our port map.
private List<UserRoleMap> AddUserRoles()
{
    return _portUserRoleMaps
        .Where(rm => !_boatUserRoleMaps.Any(
              bm => bm.BoatRoleID == rm.BoatRoleID &&
                    bm.BoatUserID == rm.BoatUserID &&
                    bm.PortRoleID == rm.PortRoleID &&
                    bm.PortUserID == rm.PortUserID))
        .Select(aur =>
        {
            UserRoleInfoProvider.AddUserToRole(aur.BoatUserID, aur.BoatRoleID);
            return aur;
        }).ToList();
}

private List<UserRoleMap> DeleteUserRoles()
{
    return _boatUserRoleMaps
        .Where(rm => !_portUserRoleMaps.Any(
              bm => bm.BoatRoleID == rm.BoatRoleID &&
                    bm.BoatUserID == rm.BoatUserID &&
                    bm.PortRoleID == rm.PortRoleID &&
                    bm.PortUserID == rm.PortUserID))
        .Select(aur =>
        {
            UserRoleInfoProvider.RemoveUserFromRole(aur.BoatUserID, aur.BoatRoleID);
            return aur;
        }).ToList();
}
The great thing about this method of user import is that it works irrespective of GUIDs, it's all based on the username (or whatever property/set of properties you want to use the maps for).

Let me know what you think!

Well, that’s it, I’ve given the basic structuring on how you can create your own Kentico User Importer with roles. If you wanted to, it wouldn’t be too hard to apply this to non-Kentico applications for any user/role with this mapping structure. I’d be happy to hear if anyone used this approach for their importer. If you have, please drop a comment below and let me know how it went!

Share This Post:

Twitter Pinterest Facebook Google+
Click here to read more Kentico posts
Start a Project with Us

About the author

A Grand Valley State University graduate, Albert is the guy who takes on new technology and learns it inside and out. At BizStream, he mostly does SharePoint and Kentico development, but you can put him on any project and it will be a success. Albert has four adorable kids, and is a shark when it comes to Foosball and anything XBox-related.

View other posts by Albert

Subscribe to Updates

Stay up to date on what BizStream is doing and keep in the loop on the latest with Kentico.