I am attempting to implement some logic when users are added to or removed from Administrator roles. The basic idea is that if a user is being added to a role that is structured as {domain}\Administrator, then some logic will fire to grab a number of domains to add to the user's list of managed domains. If the role is structured as {domain}\User Administrator then just that domain should be added. If the user is removed from a role then their managed domains should be recalculated (there is some redundancy in roles managing domains due to the logic).
I have hooked into the roles:usersAdded and roles:usersRemoved events, and can see in the debugger that my code is executing, but for some reason my changes are not being saved. The code reports no errors, but viewing the user's managed domains shows that the changes weren't saved.
public void OnRolesModified(object sender, EventArgs args)
{
//Each user in users is being removed from each role in roles
//If any roles are Admin roles, this affects Managed Domains
//Otherwise do nothing
string[] users = Sitecore.Events.Event.ExtractParameter<string[]>(args, 0);
string[] roles = Sitecore.Events.Event.ExtractParameter<string[]>(args, 1);
//If any roles are Admin roles, this affects Managed Domains. Otherwise do nothing.
if (roles.Any(p => p.Contains("Administrator")))
{
//I would expect this to always be one user, but iterate through the list in case there are more
foreach (string userName in users)
{
Sitecore.Security.Accounts.User user = Sitecore.Security.Accounts.User.FromName(userName, true);
string managedDomains = string.Empty;
foreach (Sitecore.Security.Accounts.Role role in user.Roles.Where(p => p.Name.Contains("Administrator")))
{
//roles are Domain\Role, so grab domain
string domain = role.Domain.Name;
if (role.Name.Contains("\\Administrator"))
{
//If the role has a backslash before the word Administrator, it's a root site
//Add all the subdomains to managed domains.
Sitecore.Data.Items.Item item = Sitecore.Data.Database.GetDatabase("master").SelectSingleItem(string.Format("fast:/sitecore/content/{0}", domain));
if (item != null)
{
IEnumerable<Sitecore.Security.Accounts.Account> acctList = item.Security.GetAccessRules().Helper.GetAccounts();
foreach (Sitecore.Security.Accounts.Account acct in acctList)
{
managedDomains = AddDomain(managedDomains, acct.Domain.Name);
}
}
}
else
{
//If the role doesn't have a backslash before the word Administrator, it's not a root site
//Add just the specific domain to managed domains.
managedDomains = AddDomain(managedDomains, domain);
}
}
//Set the managed domains for the user
SaveDomains(user,managedDomains);
}
}
}
private void SaveDomains(Sitecore.Security.Accounts.User user, string managedDomains)
{
using (new Sitecore.SecurityModel.SecurityDisabler())
{
Sitecore.Security.UserProfile profile = user.Profile;
profile.ManagedDomainNames = managedDomains;
profile.Save();
}
}
private string AddDomain(string managedDoms, string domain)
{
if (managedDoms == "")
{
managedDoms = domain;
}
else if (!managedDoms.Split('|').Any(p => p == domain))
{
managedDoms = string.Format("{0}|{1}", managedDoms, domain);
}
return managedDoms;
}
The only thing I've been able to find that seems suspicious is the value IsSynchronized of the UserProfile is false, but I don't actually know if that matters.