如何更新给定用户列表的角色?

How can I update the roles for a given list of users?

我正在尝试将全部用户从 1 个业务部门转移到新设置的 1。我无论如何都不是 CRM 专家,而且我被告知要转移我们需要的用户首先存储他们现有的角色,然后将他们移动到新的 BU,然后恢复他们不是特定于 BU 的角色,然后修改特定的角色。用户的示例是:

BU1
角色:
BU1Admin
BU1只读
合约

将这些移动到: BU2
角色:
BU2Admin
BU2只读
合约

因此,在此示例中,用户需要将其管理员角色和只读角色修改为 BU2,但合同保持不变。我最初的想法是构建一个查询来检索 systemuserid 以及使用这样的角色名称:

            Dictionary<Guid, string> UserRoles = new Dictionary<Guid, string>();

            QueryExpression query = new QueryExpression();
            query.EntityName = "systemuserroles";
            ColumnSet cols = new ColumnSet();
            cols.Attributes = new string[] { "systemuserid", "roleid" };
            query.ColumnSet = cols;

            LinkEntity le = new LinkEntity();
            le.LinkFromEntityName = "systemuserroles";
            le.LinkFromAttributeName = "roleid";
            le.LinkToEntityName = "role";
            le.LinkToAttributeName = "roleid";

            LinkEntity le2 = new LinkEntity();
            le2.LinkFromEntityName = "systemuserroles";
            le2.LinkFromAttributeName = "systemuserid";
            le2.LinkToEntityName = "systemuser";
            le2.LinkToAttributeName = "systemuserid";

            // Find only users in BU1
            ConditionExpression ce = new ConditionExpression();
            ce.AttributeName = "businessunitid";
            ce.Operator = ConditionOperator.Equal;
            ce.Values = new string[] { BU1 Guid };

            le2.LinkCriteria = new FilterExpression();
            le2.LinkCriteria.Conditions = new ConditionExpression[] { ce };

            query.LinkEntities = new LinkEntity[] { le, le2 };

            try
            {
                //This call doesn't work and fails saying RetrieveMultiple doesn't support entities of type systemuserroles.
                BusinessEntityCollection UserRolesCollection = crmService.RetrieveMultiple(query);
                foreach (BusinessEntity be in UserRolesCollection.BusinessEntities)
                {
                     //Do my stuff here     
                }
            }
            catch (SoapException se)
            {
                throw new Exception("Error occurred." + se.Detail);
            }

我希望能够做的下一步是用新角色更新用户。我什至不知道这是否可以根据我遇到的上述问题来完成。任何帮助将非常感激。我想知道在阅读 this?

之后 DynamicEntity 在这里是否有用

更新:

您似乎可以使用 AssignUserRolesRole 请求更新用户角色 class here。但是,我现在也仍然停留在检索位上。我想知道是否需要求助于 sql?

这是一个不受支持的 SQL 解决方案,用于移动您的用户。我刚刚试了一下,一切似乎都很好。您可以先在开发环境中试用它以证明它有效,或者它可能是您混合解决方案的起点。

/* Switch Business Unit */
update su set businessunitid = (select top 1 businessunitid from businessunit where name = '[New Business Unit Name]')
--select fullname, businessunitidname 
from systemuser su
where businessunitidname =  '[Current Business Unit Name]'

/* Identifies users who have roles where the business unit does not match the user's business unit and updates them to match */
update bridge set roleid = newRole.roleid
--select su.fullname, oldRole.name, oldRole.businessunitidname, newRole.name, newRole.businessunitidname
from systemuser su
JOIN systemuserroles bridge ON su.systemuserid = bridge.systemuserid
JOIN [role] oldRole ON bridge.roleid = oldRole.roleid
JOIN [role] newRole ON oldRole.name = newRole.Name and newRole.BusinessUnitIdName = '[New Business Unit Name]'
where oldRole.BusinessUnitId <> su.BusinessUnitId

我终于设法通过 API 找到了一种方法。它本质上是 2 个查询,第一个是获取所有用户的 systemuserid,第二个是获取每个 systemuserid 的角色标识。这将给我所有用户的当前角色。

我创建了一个字典,将旧角色 guid 映射到新角色 guid。

然后我更改了他们的业务部门,这摆脱了他们所有的角色,然后使用字典和以前存储的用户角色我可以为每个用户映射到新角色。我为处于类似情况的任何人想出了这个代码:

private void UpdateUsers()
{
    //Create mapping of old guid to new guid.
    Dictionary<Guid, Guid> LookupRoleGuids = new Dictionary<Guid, Guid>();
    //Add guid mapping
    LookupRoleGuids.Add(new Guid(Old Guid), new Guid(New Guid));

    QueryExpression query = new QueryExpression();
    query.EntityName = "systemuser";
    query.ColumnSet = new AllColumns();

    ConditionExpression ce2 = new ConditionExpression();
    ce2.AttributeName = "systemuserid";
    ce2.Operator = ConditionOperator.Equal;
    ce2.Values = new string[] { User Id }; //Can alter to retrieve for a BU

    FilterExpression filter = new FilterExpression();
    filter.Conditions = new ConditionExpression[] { ce2 };
    query.Criteria = filter;

    try
    {
        BusinessEntityCollection UserCollection = crmService.RetrieveMultiple(query);

        //store the roles of the Users.
        StoreUserRoles(UserCollection);

        foreach (BusinessEntity be in UserCollection.BusinessEntities)
        {
            //Update users BU.
            Guid newBu = new Guid(New BU Guid);
            systemuser su = (systemuser)be;
            SetBusinessSystemUserRequest setBUreq = new SetBusinessSystemUserRequest();
            setBUreq.BusinessId = newBu;
            setBUreq.UserId = su.systemuserid.Value;
            SecurityPrincipal assignee = new SecurityPrincipal();
            assignee.PrincipalId = new Guid(su.systemuserid.Value.ToString());
            setBUreq.ReassignPrincipal = assignee;
            SetBusinessSystemUserResponse assigned = (SetBusinessSystemUserResponse)crmService.Execute(setBUreq);

            //Get users existing roles
            if (UserRolesList.Count() > 0)
            {
                UserRoles ur = UserRolesList.Where(x => x.Value == su.systemuserid.Value)
                                            .Select(x => x).First();

                //Get new role guids based on mapping
                Guid[] roleguids = LookupRoleGuids.Where(x => ur.Roles.Contains(x.Key))
                                                  .Select(x => x.Value)
                                                  .ToArray();

                //Assign new roles 
                AssignUserRolesRoleRequest addRoles = new AssignUserRolesRoleRequest();
                addRoles.UserId = su.systemuserid.Value;
                addRoles.RoleIds = roleguids;
                crmService.Execute(addRoles);
            }
        }
    }
    catch (Exception ex)
    {
        throw new Exception("Error occurred updating users BU or assigning new roles. Error: " + ex.Message);
    }
}

public void StoreUserRoles(BusinessEntityCollection UserRolesCollection)
{
    UserRolesList = new List<UserRoles>(); 

    foreach (BusinessEntity be in UserRolesCollection.BusinessEntities)
    {
        systemuser u = (systemuser)be;
        UserRoles ur = new UserRoles();
        ur.Username = u.domainname;
        ur.Value = u.systemuserid.Value;
        UserRolesList.Add(ur);
    }

    AddRolesToList(ref UserRolesList);
}

private void AddRolesToList(ref List<UserRoles> URList)
{
    //Get all roles for a given user guid
    QueryExpression query = new QueryExpression();
    query.EntityName = "role";
    ColumnSet cols = new ColumnSet();
    cols.Attributes = new string[] { "roleid" };
    query.ColumnSet = cols;

    LinkEntity le = new LinkEntity();
    le.LinkFromEntityName = "role";
    le.LinkToEntityName = "systemuserroles";
    le.LinkFromAttributeName = "roleid";
    le.LinkToAttributeName = "roleid";

    LinkEntity le2 = new LinkEntity();
    le2.LinkFromEntityName = "systemuserroles";
    le2.LinkToEntityName = "systemuser";
    le2.LinkFromAttributeName = "systemuserid";
    le2.LinkToAttributeName = "systemuserid";

    foreach(UserRoles ur in URList)
    {
        //loop through the list of userroles and alter the conditional expression with the user's guid.
        ConditionExpression ce = new ConditionExpression();
        ce.AttributeName = "systemuserid";
        ce.Operator = ConditionOperator.Equal;
        ce.Values = new string[] { ur.Value.ToString() };

        le2.LinkCriteria = new FilterExpression();
        le2.LinkCriteria.Conditions = new ConditionExpression[] { ce };

        le.LinkEntities = new LinkEntity[] { le2 };
        query.LinkEntities = new LinkEntity[] { le };

        try
        {
            BusinessEntityCollection RoleGuidsCollection = crmService.RetrieveMultiple(query);
            foreach (BusinessEntity be in RoleGuidsCollection.BusinessEntities)
            {
                role r = (role)be;
                ur.Roles.Add(r.roleid.Value);
            }
        }
        catch (SoapException se)
        {
            throw new Exception("Error occurred retrieving Role Ids for " + ur.Username + " (" + ur.Value + "). " + se.Detail.InnerXml);
        }
        catch (Exception ex)
        {
            throw new Exception("Error occurred retrieving Role Guids for " + ur.Username + " (" + ur.Value + "). " + ex.Message);
        }
    }
}

为了存储每个用户的角色,我创建了一个名为 UserRoles 的 class:

class UserRoles
{
    public string Username { get; set; }
    public Guid Value { get; set; }
    public List<Guid> Roles { get; set; }

    public UserRoles()
    {
        Roles = new List<Guid>();
    }
}

注意:这还没有经过全面测试,但似乎确实符合我的要求,即允许我将用户移动到不同的 BU 并为他们基于旧的。