2

I have placed a SEWP in an editform and the code is supposed to do the following: check if the logged in user is site administrator and web administrator - if not then hide a specific field. These two checks runs async and the method that does the hiding should not execute until it is checked that the user is siteadmin and webadmin.

$(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()
  }
}

When I debug I see that isSiteAdmin and isWebAdmin always returns false inside the isUserWebAdmin method, and some time later it runs the content inside success and gives me the console.log message. The problem with this is of course that the field has already been hidden, and it doesn't wait until I get the result from my two other methods.

Can anyone see what is wrong here? I have tried linking to newer jQuery versions to see if that helped, but nothing so far. I had an understanding that one can return $.ajax directly as it is deferred compatible and that the internal jQuery code will call resolve for me. Is this not the case?

1

Is the problem not that you should also have a deferred object for the IsSiteAdmin()?

It will complete and run through to the next step and the ISSiteAdmin function will never have a chance to evaluate and change the IsSiteAdmin Boolean.

I would add a deferred object to the first function call and then the when statement will wait both checks have been made.

See https://api.jquery.com/jquery.when/

1

By default jQuery.ajax() is an asynchronous call. So, you may need to set async property to false. However, there is already a SharePoint ctx object which has a boolean property named CurrentUserIsSiteAdmin. You can use it instead of making a REST call. So the modified code will look like this:

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

var isWebAdmin = false;
var context;
var web;

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


//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 (!ctx.CurrentUserIsSiteAdmin && !isWebAdmin) {
    $('div[title="SiteManager"]').parents().eq(2).hide()
  }
}
  • 1
    I like your answer but I would never recommend to set the async property to false while using deferred variables. That totally defeats the purpose of a deferred/promise. Not to mention that jQuery synchronous operations have been deprecated since jquery 1.8 api.jquery.com/jQuery.ajax/#jQuery-ajax-settings – Bryan Mathews May 27 '15 at 12:39
  • @BryanMathews, Thanks for the correction. I was trying to convey to OP that his understanding that $.ajax is a deferred call isn't correct. That is the reason I mention in the answer that So, you may need to set async property to false. And also gave the alternative approach. – Nadeem Yousuf May 27 '15 at 13:21

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.