3

I have already raised this question with Kentico devnet and Kentico support and haven't yet received a solution. I'm hoping the wider SO community will come up with something.

For reference, here is the devnet thread: http://devnet.kentico.com/questions/content-staging-how-can-i-stage-role-changes-but-ignore-user-changes

To summarise, I'm building a large multi-site web platform using Kentico. The staging module is configured to deploy Kentico object changes through a linear chain of environments from dev to UAT and on to production. Each of these environments naturally has a different set of users. Therefore I've excluded users and user-role relationships from the staging process as follows:

public class KingspanUserEvents : CMSLoaderAttribute
{
    public override void Init()
    {
        UserInfo.TYPEINFO.LogSynchronization = CMS.DataEngine.SynchronizationTypeEnum.None;
        UserRoleInfo.TYPEINFO.LogSynchronization = CMS.DataEngine.SynchronizationTypeEnum.None;
    }
}

However, I'm finding that when changed roles are logged as staging tasks, part of the serialised role data is its user associations. Remember these users will be users which only exist in the source environment.

This has the effect that when the environments are synced, the role is updated at the target and all users are removed from the role.

Kentico support say "We are already aware of this and it is on the list of future improvements.". However, to me it's a fundamental flaw in a CMS which has enterprise aspirations. A failure to maintain a separation between the application architecture (roles) and live data (users) means that I cannot create reliable deployments for a core part of my application.

So my question is, has anyone found a work-around for this issue? I wonder if it might be possible to hook into the StagingEvents.ProcessTask.Before event handler to somehow prevent users being removed.

Tom Troughton
  • 3,941
  • 2
  • 37
  • 77

2 Answers2

1

I just found one more property, that, according to description, should do what your looking for:

UserRoleInfo.TYPEINFO.IncludeToSynchronizationParentDataSet = false;
Roman Hutnyk
  • 1,549
  • 9
  • 14
  • Thanks Roman, I just tested this and unfortunately it doesn't change the behaviour I've described. Shame, because it looked promising! FYI, that property uses an enum so the syntax is UserRoleInfo.TYPEINFO.IncludeToSynchronizationParentDataSet = IncludeToParentEnum.None – Tom Troughton Feb 18 '16 at 15:37
  • This property should work, are you sure that the Init code executes? Also, try to remove this line if you currently use still have it: UserRoleInfo.TYPEINFO.LogSynchronization = CMS.DataEngine.SynchronizationTypeEnum.None; – martinh_kentico Feb 20 '16 at 19:41
0

However, I'm finding that when changed roles are logged as staging tasks, part of the serialised role data is its user associations.

I believe this is because RoleInfoProvider.SetRoleInfo() is logging UserInfo changes as staging tasks internally, whether or not it's actually making changes to those users.

What you could look at doing is changing the SaveRole() method in /CMSModules/Membership/Controls/Roles/RoleEdit.ascx:

private void SaveRole(RoleInfo ri, string codeName, string displayName)
{
    bool newRole = false;
    // Get object
    if (ri == null)
    {
        ri = RoleInfoProvider.GetRoleInfo(ItemID);
        if (ri == null)
        {
            ri = new RoleInfo();
            // indicate this is new role and should be redirected after safe
            newRole = true;
        }
    }

    if (ri.DisplayName != displayName)
    {
        // Refresh a breadcrumb if used in the tabs layout
        ScriptHelper.RefreshTabHeader(Page, string.Empty);
    }

    // Set the fields
    ri.DisplayName = displayName;
    ri.RoleName = codeName;
    ri.RoleID = ItemID;
    ri.Description = txtDescription.Text;
    ri.SiteID = mSiteId;
    ri.RoleIsDomain = chkIsDomain.Checked;

    // If group id is present then it's group role
    if (GroupID > 0)
    {
        ri.RoleGroupID = mGroupId;
        ri.RoleIsGroupAdministrator = chkIsAdmin.Checked;
    }


    RoleInfoProvider.SetRoleInfo(ri);
    ItemID = ri.RoleID;

    ShowChangesSaved();

    // if new group was created redirect to edit page
    if (newRole)
    {
        RoleID = ri.RoleID;
        RaiseOnSaved();
    }
}

This is the method that's called when you click 'save' in CMSSiteManager. Keep in mind I'm using version 7 here, so it might be a little bit different in v8 and 9, but if a different control is used in those versions you can always 'view frame source' to figure out what ASPX pages are loading what controls in the Kentico UI.

Anyway, inside that method, RoleInfoProvider.SetRoleInfo() is being called. One thing you can look at doing is creating a custom InfoProvider class and either overriding the SetRoleInfo() method or creating your own method that then logs only the synronization tasks you want to log.

However, as a quick fix until you're able to implement this, you can also filter your sync log tasks by Objects > Global Objects > Administration > Users and delete all of those tasks before you stage them out.

Jerreck
  • 2,930
  • 3
  • 24
  • 42
  • Thank you for the detailed answer. I'm afraid your quick fix won't work because the staging tasks that are causing the problem are role tasks. I do want to sync the roles, I just don't want this sync to remove users at the target. Regarding your other answer, I'm not sure your assumption is correct. There are no user tasks being logged. I believe it is because user-role associations are part of the role data model. In any case, I really want to avoid customising Kentico under the hood - my problem requires a future-proof solution. Thank you for your time though. – Tom Troughton Feb 18 '16 at 16:52