0

I am attempting to hide a field from a newform, but only if the user is not a site collection administrator and not assigned full control of the (sub)web currently on. I am not well experienced in JavaScript/jQuery, but I hoping I am on the right path. I am on a Sharepoint 2013 on-premise environment.

The main thought here was that I check if a user is site collection administrator first - if so set the global var isSiteAdmin to true, same goes for check on subweb. If both of these return false, the field is hidden.

However, when the script runs I always get false on these two variables when running the function hideSiteManagerField(), even though I am both site administrator and have full control on web. It seems as if the checks aren't ready when that function is firing, but in the console I see that my messages are showing (the console.log ones in code below).

This might be because of the async nature of the requests I am thinking. To ensure I have run the functions isUserSiteAdmin() and isUserWebAdmin() before running the last function that hides the field, I had this notion that I could use the deferred method in jQuery? Being a novice at this I do not know if I am using it correctly? If not could someone please help me?

Also - is there a better/safer/cleaner way to do this?

$(document).ready(function () {
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', readyFunction);
});

var isSiteAdmin = false;
var isWebAdmin = false;
var context;
var web;

function readyFunction() {
    $.when(isUserSiteAdmin(), isUserWebAdmin()).done(hideSiteManagerField)   
}

function isUserSiteAdmin() {
  return $.Deferred(function () {
    var currentSite = _spPageContextInfo.siteAbsoluteUrl;
    var currentUserID = _spPageContextInfo.userId;
    $.ajax({
        url: currentSite + "/_api/web/siteUsers?$select=Id,IsSiteAdmin&$filter=id eq " + currentUserID,
        method: "GET",
        dataType: "JSON",
        headers: { "accept": "application/json; odata=verbose" },
        success: function (data) {

            $.each(data.d.results, function (index, item1) {
                isSiteAdmin = item1.IsSiteAdmin;
                console.log("User is admin on site: " + item1.IsSiteAdmin)
            });
        },
        error: function (error) {
            alert(JSON.stringify(error));
        }
    })
})
}

//If a user is admin he/she will have manageWeb permissions.
function isUserWebAdmin() {
  return $.Deferred(function () {
    context = new SP.ClientContext.get_current();
    web = context.get_web();
    context.load(web, 'EffectiveBasePermissions');
    context.executeQueryAsync(onSuccess, onFailure);

    function onSuccess() {
        if (web.get_effectiveBasePermissions().has(SP.PermissionKind.manageWeb)) {
            isWebAdmin = true;
            console.log("User is admin on web: true");
        }
    }
    function onFailure(sender, args) {
        alert('failed: ' + args.get_message() + 'n' + args.get_stackTrace());
    }
})
}

function hideSiteManagerField() {
//hide field Site Manager if permissions != full access or administator on site collection
if (!isSiteAdmin && !isWebAdmin) {
    $('div[title="SiteManager"]').parents().eq(2).hide()
  }
}
2

Here is a working version of your code:

$(document).ready(function () {
    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', readyFunction);
});

var isSiteAdmin = false;
var isWebAdmin = false;
var context;
var web;

function readyFunction() {
    $.when(isUserSiteAdmin(), isUserWebAdmin()).done(hideSiteManagerField)
}

function isUserSiteAdmin() {
    var currentSite = _spPageContextInfo.siteAbsoluteUrl;
    var currentUserID = _spPageContextInfo.userId;

    return $.ajax({
        url: currentSite + "/_api/web/siteUsers?$select=Id,IsSiteAdmin&$filter=id eq " + currentUserID,
        method: "GET",
        dataType: "JSON",
        headers: { "accept": "application/json; odata=verbose" },
        success: function (data) {
            $.each(data.d.results, function (index, item1) {
                isSiteAdmin = item1.IsSiteAdmin;
                console.log("User is admin on site: " + item1.IsSiteAdmin)
            });
        },
        error: function (error) {
            alert(JSON.stringify(error));
        }
    })
}

//If a user is admin he/she will have manageWeb permissions.
function isUserWebAdmin() {
    var deferred = $.Deferred(function () {
        context = new SP.ClientContext.get_current();
        web = context.get_web();
        context.load(web, 'EffectiveBasePermissions');
        context.executeQueryAsync(onSuccess, onFailure);

        function onSuccess() {
            if (web.get_effectiveBasePermissions().has(SP.PermissionKind.manageWeb)) {
                isWebAdmin = true;
                console.log("User is admin on web: true");
                deferred.resolve();
            }
        }

        function onFailure(sender, args) {
            alert('failed: ' + args.get_message() + 'n' + args.get_stackTrace());
        }
    });

    return deferred.promise();
}

function hideSiteManagerField() {
    //hide field Site Manager if permissions != full access or administator on site collection
    if (!isSiteAdmin && !isWebAdmin) {
        $('div[title="SiteManager"]').parents().eq(2).hide()
    }
}

The hideSiteManagerField will be called only when the deferred objects returned by isUserSiteAdmin and isUserWebAdmin are both resolved. But in your code, you didn't call $.Deferred().resolve().

In isUserSiteAdmin, I removed $.Deferred, you can return $.ajax directly. It is deferred compatible. The internal jQuery code will call resolve for you.

In isUserWebAdmin, I created a Deferred object first, then add deferred.resolve() in the onSuccess callback and at last it returns deferred.promise(). (You can attach callbacks to promise object as deferred object, but you cannot call resolve or reject on a promise object, so it ensures that the state of the deferred object will not be changed outside your function).

  • Thank you for your help with this and for useful comments. I was not aware you could return $.ajax directly like that. Good to know! – user3463093 Apr 25 '15 at 12:16
  • @user3463093 I'm glad it solves your problem. – Xiaodan Mao Apr 25 '15 at 13:18
1

I always use this regarding deferreds, sure there will be a better looking way but it always works for me:

function fxRun() {
    Step1().then(Step2);
}

With:

function Step1() {
    var dfd = $.Deferred(function () {
        setTimeout(function () {
            //your code here to determine isWebAdmin
            dfd.resolve()
        }, 2000);
    });
    return dfd.promise();
}

function Step2() {
    var dfd = $.Deferred(function () {
        setTimeout(function () {
            //your code here 
            dfd.resolve()
        }, 2000);
    });
    return dfd.promise();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.