So I have figured out how to do this, and even though the flow is a bit crazy, it seems to work everytime:
first I create a new group which will be the group even eventually set on the item:
var projGroupId = 0;
var projGroupMemberObj = [];
var projGroup = '';
//id is my unique parent id, probably replace with GUID I generate that maps to Id
function updatePermissions(thisId) {
//this is my example scheme for dynamic group creation
varn groupName = "project-" + thisId + "-Group";
var clientContext = new SP.ClientContext.get_current();
this.oWebsite = clientContext.get_web();
var groupCreationInfo = new SP.GroupCreationInformation();
groupCreationInfo.set_title(groupName);
groupCreationInfo.set_description('Group for project ' + thisId);
this.oGroup = oWebsite.get_siteGroups().add(groupCreationInfo);
var collRoleDefinitionBinding = SP.RoleDefinitionBindingCollection.newObject(clientContext);
this.oRoleDefinition = oWebsite.get_roleDefinitions().getByType(SP.RoleType.contributor);
collRoleDefinitionBinding.add(oRoleDefinition);
var collRollAssignment = oWebsite.get_roleAssignments();
collRollAssignment.add(oGroup, collRoleDefinitionBinding);
clientContext.load(oGroup, 'Title');
clientContext.load(oRoleDefinition, 'Name');
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onCreateGroupQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed));
}
//after group is created set the global to the new name to ensure it is what it was supposed to be
function onCreateGroupQuerySucceeded() {
projGroup = oGroup.get_title();
getProjectUserGroupId();
}
//get all the site groups and then match by name in order to get id
function getProjectUserGroupId() {
var clientContext = new SP.ClientContext.get_current();
this.collGroup = clientContext.get_web().get_siteGroups();
clientContext.load(collGroup);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onGetProjectGroupIdSucceeded), Function.createDelegate(this, this.onQueryFailed));
}
//get the results, match by name and create the group object
function onGetProjectGroupIdSucceeded(sender, args) {
var groupDataObj = [];
var groupEnumerator = collGroup.getEnumerator();
while (groupEnumerator.moveNext()) {
var thisGroup = groupEnumerator.get_current();
var thisObj = { groupId: thisGroup.get_id(),
groupTitle: thisGroup.get_title()
};
if (thisObj.groupTitle == projGroup) {
projGroupId = thisObj.groupId;
groupDataObj.push(thisObj);
}
}
if (!projGroupId == 0) {
//start loading the group with users, starting with static groups
getAdminUsers();
}
}
function getAdminUsers() {
var clientContext = new SP.ClientContext.get_current();
var collGroup = clientContext.get_web().get_siteGroups();
var oGroup = collGroup.getById(10);
this.collUser = oGroup.get_users();
clientContext.load(oGroup);
clientContext.load(collUser);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onGetAdminsQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onGetAdminsQuerySucceeded() {
var userEnumerator = collUser.getEnumerator();
while (userEnumerator.moveNext()) {
var oUser = userEnumerator.get_current();
var thisObj = {
userID : oUser.get_id(),
userLogin : oUser.get_loginName(),
userEmail : oUser.get_email(),
userTitle: oUser.get_title()
};
projGroupMemberObj.push(thisObj);
}
var clientContext = new SP.ClientContext.get_current();
var collGroup = clientContext.get_web().get_siteGroups();
var oGroup = collGroup.getById(14);
this.collUser = oGroup.get_users();
clientContext.load(oGroup);
clientContext.load(collUser);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onGetSupportGroupCallback), Function.createDelegate(this, this.onQueryFailed));
}
so its really the same last functions as I go through the groups I need to add to the object, then I use this to break inheritance and apply the group to permissions
//what I use to build the user group object
function onGetCurrentUserSuccessMethod(sender, args) {
var userObject = web.get_currentUser();
var thisObj = { userID : userObject.get_id(), userLogin : userObject.get_loginName(), userEmail : userObject.get_email(), userTitle: userObject.get_title() };
projGroupMemberObj.push(thisObj);
for ( var i = 0; i < projGroupMemberObj.length; i++ )
{
var thisDataObj = projGroupMemberObj[i];
setProjectGroupUsers(thisDataObj);
}
}
//load all these users from object to group I created
function setProjectGroupUsers(dataObj) {
var clientContext = new SP.ClientContext.get_current();
var collGroup = clientContext.get_web().get_siteGroups();
var oGroup = collGroup.getById(projGroupId);
var userCreationInfo = new SP.UserCreationInformation();
userCreationInfo.set_email(dataObj.userEmail);
userCreationInfo.set_loginName(dataObj.userLogin);
userCreationInfo.set_title(dataObj.userTitle);
this.oUser = oGroup.get_users().add(userCreationInfo);
clientContext.load(oUser);
clientContext.executeQueryAsync(Function.createDelegate(this, this.setProjectGroupUsersSuceeded), Function.createDelegate(this, this.onQueryFailed));
}
then I use this ridiculous counter to c ompare the length of object, so that when all the objects in the array have reached callback it fires the function that sets the permissions
function setProjectPermissionsScheme() {
var clientContext = new SP.ClientContext.get_current();
var oList = clientContext.get_web().get_lists().getByTitle('Projects');
var itemId = globProjectID;
this.oListItem = oList.getItemById(itemId);
oListItem.breakRoleInheritance(false);
var collGroup = clientContext.get_web().get_siteGroups();
var oGroup = collGroup.getById(projGroupId);
var collRoleDefinitionBinding = SP.RoleDefinitionBindingCollection.newObject(clientContext);
collRoleDefinitionBinding.add(clientContext.get_web().get_roleDefinitions().getByType(SP.RoleType.reader));
oListItem.get_roleAssignments().add(oUser, collRoleDefinitionBinding);
clientContext.load(oUser);
clientContext.load(oListItem);
oListItem.get_roleAssignments().getByPrincipal(oUser).deleteObject();
var collRoleDefinitionBinding = SP.RoleDefinitionBindingCollection.newObject(clientContext);
collRoleDefinitionBinding.add(clientContext.get_web().get_roleDefinitions().getByType(SP.RoleType.administrator));
oListItem.get_roleAssignments().add(oGroup, collRoleDefinitionBinding);
clientContext.load(oUser);
clientContext.load(oListItem);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onSetProjectPermissionsSucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onSetProjectPermissionsSucceeded(sender, args) {
alert('Role inheritance broken for item ' +
this.oListItem.get_item('Title') +
' and new role assignment for ' +
this.oUser.get_loginName());
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
this ridiculous (perhaps?) flow is working consistently, however since I am novice at best I would welcome comments or advice on improving it in anyway.