Category Archives: DFFS

Break permission inheritance on a new list item and assign edit rights to users selected in a people picker

I got a request for a solution to break inheritance of permissions on a new list item and assign edit rights to users selected in a people picker.

IMPORTANT INFORMATION:

Unfortunately users must have Manage Permissions rights to be able to use this code. You must assign this right to the users by going to Site settings > Site permissions > Permission levels > Edit permission level > Site permissions > Manage permissions. Do this with caution as it will give general Mange permission rights if you don’t add a custom permission level and assign it to a specific SharePoint user group.

This example requires a list with a multichoice people picker where you select the users to assign edit item permissions – the name of this people picker is in this code is EditRightsPeoplePicker, but you can specify the name in the bottom of the code snippet.

Add the below snippet to the Custom JS textarea of your DFFS Enabled NewForm. When saving the item the default save function will be cancelled and the custom function will create an item, break permission inheritance and assign edit rights to the users selected in the people picker. In addition, the current user will get full control over the list item.

Please note that this is not a complete fully functional solution – it is only a proof of concept and you can use it as a starting point for making your own solution.

// Don't edit this function
 function breakroleinheritance(arg) {
     var deferred = jQuery.Deferred();
     jQuery.ajax({
         "url": arg.listBaseUrl + "/_api/web/lists/getbyid('" + arg.listGuid + "')/items(" + arg.itemId + ")/breakroleinheritance(false)",
         "type": 'POST',
         "headers": {
             'X-RequestDigest': jQuery('#__REQUESTDIGEST').val(),
             "accept": "application/json;odata=verbose",
             "content-type": "application/json;odata=verbose"
         },
         "success": function(data) {
             deferred.resolve(true);
         },
         "error": function(err) {
             console.log(err);
             deferred.reject(err);
         }
     });
     return deferred.promise();
 }
 // Don't edit this function
 function doAssignNewRole(arg) {
     var deferred = jQuery.Deferred(),
         ticker = 1;
     jQuery.each(arg.roles, function(i, r) {
         jQuery.ajax({
             "url": arg.listBaseUrl + "/_api/web/lists/getbyid('" + arg.listGuid + "')/items(" + arg.itemId + ")/roleassignments/addroleassignment(principalid=" + r.principalid + ",roledefid=" + r.roledefid + ")",
             "type": 'POST',
             "headers": {
                 'X-RequestDigest': jQuery('#__REQUESTDIGEST').val()
             },
             "success": function(data) {
                 if (ticker === arg.roles.length) {
                     deferred.resolve(true);
                 } else {
                     ticker += 1;
                 }
             },
             "error": function(err) {
                 console.log(err);
                 deferred.reject(err);
             }
         });
     });
     return deferred.promise();
 }
 // Don't edit this function
 function setItemLevelSecurity(arg) {
     var deferred = jQuery.Deferred();
     breakroleinheritance(arg).done(function() {
         doAssignNewRole(arg).done(function(success) {
             deferred.resolve(arg.itemId);
         }).fail(function(err) {
             spjs.dffs.alert({
                 "title": "Add roles error",
                 "msg": JSON.stringify(err)
             });
         });
     });
     return deferred.promise();
 }
 // Don't edit this function
 function init_setItemLevelSecurity(arg) {
     var deferred = jQuery.Deferred();
     var users = spjs.utility.getFieldValue({
         "fin": arg.peoplePicker,
         "key": "loginName"
     });
     var roleArr = [],
         userIdArr = [];
     jQuery.each(users, function(i, login) {
         var userId = spjs.utility.userInfo(login).ID;
         roleArr.push({
             "principalid": userId,
             "roledefid": "1073741830" // 1073741830 = edit
         });
         userIdArr.push(userId);
     });
     // Create new item
     var newItemData = {};
     newItemData.Title = getFieldValue("Title");
     newItemData[arg.peoplePicker] = userIdArr.join(";#;#");
     var res = spjs.utility.addItem({
         "listName": _spPageContextInfo.pageListId,
         "data": newItemData
     });
     arg.roles = roleArr;
     if (res.success) {
         arg.itemId = res.id;
         setItemLevelSecurity(arg).done(function(id) {
             deferred.resolve(id);
         });
     }
     return deferred.promise();
 }
 function dffs_PreSaveAction() {
     createNewItemWithItemLevelSecurity();
     return false;
 }
 // Edit this function
 function createNewItemWithItemLevelSecurity() {
     init_setItemLevelSecurity({
         "listBaseUrl": _spPageContextInfo.webServerRelativeUrl,
         "listGuid": _spPageContextInfo.pageListId,
         "peoplePicker": "EditRightsPeoplePicker"
     }).done(function(itemId) {
         // Done
         location.href = location.href.split("NewForm.aspx")[0] + "EditForm.aspx?ID=" + itemId;
     });
 }

Please post any questions in the comments below.

Alexander

Keep track of assigned and unassigned keys for office locations

I got a request for a solution to solve the following question:

I break down the columns in the two lists below. What I’m trying to accomplish is to get the “key designation” field in the key log list to drive the number of assigned, unassigned and total keys in the inventory. For example, if “assign” is chosen in the key designation field of the key log, it automatically increases the number of keys assigned by one key, while decreasing the number of keys unassigned. If “return” is selected, it automatically decreases the number of assigned keys and increases the number of unassigned keys. The inventory holds information detailing keys across two different locations/offices. The columns in the inventory are:

  • Site (Boston, New York, etc.) 
  • Protected Area (the area to which the keys provide access)
  • Identifier (corresponding symbol on the key that ties that key to the protected area [identifier x = broom closet protected area for example])
  • Number of Keys Assigned (5)
  • Number of Keys Unassigned (4)
  • Total Keys (sum of the number of assigned and unassigned keys [9])

The Key Log tracks when a key is assigned, returned, added or deleted and who assigned the key (with 2 person or group fields to account for dual control). The columns in the log are:

  • Site
  • Protected Area
  • Identifier
  • Key number
  • key designation (if we’re assigning, returning, adding or deleting a key)
  • person or group #1 (to show who assigned the key)
  • person or group #2 (to show dual control for 2nd person assigning the key)

I have created two lists with the essential fields to make the relationship like this:

inventory list

The TotKeys is a calculated column that sums the NumberAssigned and NumberUnassigned.

keylog list

The KeyDesignation field has these choices:

assigning
returning
adding
deleting

Now install DFFS in the keylog list and set up a cascading dropdown like this:

Cascading dropdown config

Then add this in your Custom JS of both NewForm and EditForm in the keylog list:

When adding or editing a keylog item the corresponding item in the inventory will be updated with the correct count.

// Reset KeyDesignation field on load
setFieldValue("KeyDesignation", "");

function dffs_PreSaveAction() {
    var site = getFieldValue("Site");
    var protectedArea = getFieldValue("ProtectedArea");
    var inventoryItem = spjs.utility.queryItems({
        "listName": "inventory",
        "query": "<Where><And><Eq><FieldRef Name='Site' /><Value Type='Text'>" + site + "</Value></Eq><Eq><FieldRef Name='ProtectedArea' /><Value Type='Text'>" + protectedArea + "</Value></Eq></And></Where>",
        "viewFields": ["ID", "NumberAssigned", "NumberUnassigned"]
    });
    var pass = true;
    if (inventoryItem.count > 0) {
        var item = inventoryItem.items[0];
        var assigned = item.NumberAssigned !== null ? parseInt(item.NumberAssigned, 10) : 0;
        var unassigned = item.NumberUnassigned !== null ? parseInt(item.NumberUnassigned, 10) : 0;
        var keyDesignation = getFieldValue("KeyDesignation");
        switch (keyDesignation) {
            case "assigning":
                if (unassigned > 0) {
                    assigned += 1;
                    unassigned -= 1;
                } else {
                    pass = false;
                    spjs.dffs.alert({
                        "title": "No keys available",
                        "msg": "You are trying to assign a key, but no unassigned keys are available.",
                        "ok": function() {
                            // Close dlg
                        }
                    });
                }
                break;
            case "returning":
                if (assigned > 0) {
                    assigned -= 1;
                    unassigned += 1;
                } else {
                    pass = false;
                    spjs.dffs.alert({
                        "title": "No keys assigned",
                        "msg": "You are trying to unassign a key, but no keys are assigned.",
                        "ok": function() {
                            // Close dlg
                        }
                    });
                }
                break;
            case "adding":
                unassigned += 1;
                break;
            case "deleting":
                unassigned -= 1;
                break;
        }
        // Update list item with new count
        spjs.utility.updateItem({
            "listName": "inventory",
            "id": item.ID,
            "data": {
                "NumberAssigned": assigned,
                "NumberUnassigned": unassigned
            }
        });
    }
    if (pass) {
        return true;
    } else {
        return false;
    }
}
keylog list NewForm

Let me know in the comments below if you have any questions.

Alexander