[SalesForce] Clone User with Queues and PermissionSetAssignemnts

I am trying to create a functionality to clone existing user, wherein i want to assign Public groups, queue and permission sets too. All the features along with profile and role id i would be assigning to new user, just by clicking a button named clone. Here i am not able to assign Queue and permission set of existing user to new one.

Please find below my method which is throwing an error, apart from this i have just created a VF page wherein i am taking a mirror id to clone and user is created first before assigning all details from existing user:

public PageReference cloneuser()
{
    User newus = [Select id from user where Bid__C =: bid];
    mirrorId = newus.Id;
    User newUser = createUser();
    User mirrorUser = getMirrorUserDetails();
    newUser.ProfileId =  mirrorUser.ProfileId;
    newUser.UserRoleId =  mirrorUser.UserRoleId;
    List <GroupMember> g = new List<GroupMember>();  
    g = [SELECT GroupId,UserOrGroupId FROM GroupMember Where UserOrGroupId = :mirrorId ];
    for(GroupMember g1: g){
        g1.UserOrGroupId = newUser.Id;
    }

    PermissionSet ps = new PermissionSet();
    ps = [SELECT Id,Label,Name FROM PermissionSet Where ProfileId = :mirrorUser.ProfileId];
    List <PermissionSetAssignment> psa = new List<PermissionSetAssignment>();
    psa = [SELECT PermissionSetId,AssigneeId FROM PermissionSetAssignment Where AssigneeId = :mirrorId ];
    for(PermissionSetAssignment psa1: psa){
        psa1.AssigneeId  = newUser.Id;
        psa1.PermissionSetId = ps.Id;
    } 

    update newUser;
    return null;     
}

For UserOrGroupId and AssigneeId, i am getting below error:

System.SObjectException: Field is not writeable: PermissionSetAssignment.AssigneeId

Best Answer

You are trying to update the existing GroupMember and PermissionSetAssignment records, rather than adding new ones. If you want to remove the old records, you will have to delete and replace, as they do not allow reparenting (based on your error message). You will also have to act on these related objects, not the User record itself. Something more like:

List<GroupMember> newGroupMembers = new List<GroupMember>();
for (GroupMember member : [
    SELECT GroupId FROM GroupMember WHERE UserOrGroupId = :mirrorUser
]){
    newGroupMembers.add(new GroupMember(
        GroupId=member.GroupId, UserOrGroupId=newUserId
    ));
}
insert newGroupMembers;

Same idea for PermissionSetAssignment:

List<PermissionSetAssignment> newAssignments = new List<PermissionSetAssignment>();
for (PermissionSetAssignment assignment : [
    SELECT PermissionSetId FROM PermissionSetAssignment WHERE AssigneeId = :mirrorUser
]){
    newAssignments.add(new PermissionSetAssignment(
        PermissionSetId=assignment.PermissionSetId, AssigneeId=newUserId
    ));
}
insert newAssignments;