3

I am creating a new list inside SharePoint server 2013, which have these columns:-

  1. Title
  2. Description
  3. Price
  4. Other…

Now I want to only allow users within a specific group to be able to view and modify the price field inside these locations:-

  1. View/edit/add forms.
  2. Inside the list views.

So can anyone advice if SharePoint support this requirement, to hide list columns based on permissions? if there is not any option to do so , is there any workaround ? baring in mind that i am using on-premise SharePoint enterprise 2013 , and i have full access to the farm..

5

Yes and yes.

You can hide the columns on the forms by adding custom action to each of the forms like this:

<CustomAction Id="Project.DisplayForm"
            Location="DisplayFormToolbar"
            ControlAssembly="$SharePoint.Project.AssemblyFullName$"
            ControlClass="Project.ProjectListFormCustomActions"
            RegistrationType="ContentType"
            RegistrationId="0x010020CA30C66D23475D926915EB818F52B905">
</CustomAction>

Alternatively, you can use EditFormToolbar and NewFormToolbar.

This will attach a custom action to the Display Form of a specified content type. What you do next is add a control class and override OnLoad function. There you check if the user is allowed to view the field by checking which group the current user is in. Then depending on that you hide the whole column row from the form:

namespace Project.CustomActions
{
    class ProjectListFormCustomActions : Control
    {
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (IsUserAllowedToViewTheField() == false)
            {
                HideControlRow(projectLinkField, "{E989D599-7476-4036-A1E8-2C5B8D334412}");
            }
        }
    }
}

And you hide the row from the form like this:

private void HideControlRow(SPField field, String scriptId)
{
    if (field != null)
    {
        string controlId = field.InternalName;

        StringBuilder text = new StringBuilder(String.Empty);

        text.AppendFormat("_spBodyOnLoadFunctionNames.push('Hide{0}ControlRow');", controlId);
        text.AppendFormat("function Hide{0}ControlRow()", controlId);
        text.AppendLine("{");
        text.AppendFormat("$('.ms-formtable td').each(function()");
        text.AppendLine("{");
        text.AppendFormat("var s = $(this).html();");
        text.AppendFormat("if(s.indexOf('{0}')!= -1)", controlId);
        text.AppendLine("{");
        text.AppendFormat("$(this).closest('tr').hide();");
        text.AppendLine("}})}");

        this.Page.ClientScript.RegisterStartupScript(typeof(ProjectListFormCustomActions), scriptId, text.ToString(), true);
    }
}

I believe you can achieve the same thing using Client Side Rendering by setting BaseFieldControl properties in SPContext.Current.FormContext.FieldControlCollection (which is avaible from the custom action code-behind as well).

As for the views, what I would suggest is to have a library with the .aspx files and custom item permissions where you would allow one group of people to access one kind of views (with the price column) and another group of people (who are not price-worthy) would have access to view files without the column in them. And then have a page where users would click on the view links. Other people achieve this by using audience targeting feature:

  1. Create view A, B, C for list TestList
  2. Create user group X, Y, Z
  3. Open the TestList, bu default all items will display in AllItems.aspx page
  4. Edit the page by using Site Action
  5. Click on the Modify Shared Web Part link of TestList . Now select the View A from selected dropdown
  6. Go to Advanced section and select user group in the target audience. Apply the changes
  7. Add the TestList web part again to the same AllItems.aspx page.
  8. Repeat the step 5 and 6 for other two views and set the target audience respectively.
  9. Now the AllItems.aspx page will have three web part for one list i.e TestList

To do a custom form validation, override the OnSaveHandler in the OnInit function in the custom action:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    SPContext.Current.FormContext.OnSaveHandler += new EventHandler(FormContext_OnSave);
}

protected void FormContext_OnSave(object sender, EventArgs e)
{
    this.Page.Validate();

    if (DoesTheUserHavePermissionsToSave() == true) //This is where you check for user permissions
    {
        SaveButton.SaveItem(SPContext.Current, false, String.Empty);
    }
    else //the user doesn't have permissions to edit the price field
    {
        var list = SPContext.Current.List;
        var item = list.GetItemById(SPContext.Current.ListItem.Id);
        SPContext.Current.ListItem["Price"] = item["Price"]
        SaveButton.SaveItem(SPContext.Current, false, String.Empty);
        //this would need testing but the idea is to reassign previous Price value before saving the item.
        //Or check if the value has changed and cancel the save completely since there might be something other messed up as well.
    }
}
  • 1
    It should be the place where you check if the user is allowed to view the field. I don't know exact requirements or AD/SP groups used. It might look something like this: var group = web.Groups["Specific Group"]; var isInTheGroup = web.IsCurrentUserMemberOfGroup(group .ID); – Paul Strupeikis Feb 26 '16 at 15:16
  • 1
    I believe you could. CSR is hard typed - I personally prefer that but I don't think there are any disadvantages of using custom actions as you can achieve even more with them. – Paul Strupeikis Feb 26 '16 at 16:40
  • 1
    Just because the field is hidden on the form, doesn't mean the user can not modify those values. You can't lock down columns using JavaScript. Only server side code can do that. – iOnline247 Feb 28 '16 at 1:08
  • 1
    Override the Save button: "SPContext.Current.FormContext.OnSaveHandler += new EventHandler(FormContext_OnSave);" with a custom function where you would validate the form or add an event receiver with an additional check - handle ItemAdding event and assign empty value to the price field or cancel the addition of the item if user doesn't have permissions. There are many ways to do that and I believe this is going off topic already :) – Paul Strupeikis Feb 29 '16 at 9:24
  • 1
    The title says "Approaches to hide certain list columns from certain users groups" and this might be misleading for other site users as they might find different things being discussed here than the title describes - as the form validation and etc.. Anyway, is the Save button override or an event receiver will work for your needs or is there a need to explore more options? – Paul Strupeikis Feb 29 '16 at 10:45
1

Using Jquery and REST api to check permissions:

 var userID = _spPageContextInfo.userId, authorised = false, groupName = "Admin";
    $.when($.ajax({
        url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/sitegroups/getByName('" + groupName + "')/Users?$filter=Id eq " + userID,
        method: "GET",
        headers: { "Accept": "application/json; odata=verbose" }
    })).then(function (data) {
        if (data.d.results[0] != undefined) {
            authorised = true;
        }
        else {
        }
    }).done(function () {

                if (!authorised) {


                        $("input[id^='Complete'],input[id^='Strength'],input[id^='DevArea']").each(function () {
                            if ($(this).length) {
                                $(this).closest("tr").remove();
                            }
                        });


                }

            });

Requirement1 : View/edit/add view --> this can controlled by permission levels. users with contribute permissions can still edit the content but cant change/add views.

Requirement2: this can controlled by Attaching a JSLink file to the fields Example:

    (function () { 

    // jQuery library is required in this sample 
    // Fallback to loading jQuery from a CDN path if the local is unavailable 
    (window.jQuery || document.write('<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-1.10.0.min.js"><\/script>')); 

    // Create object that have the context information about the field that we want to change it's output render  
    var hiddenFiledContext = {}; 
    hiddenFiledContext.Templates = {};  
    hiddenFiledContext.Templates.OnPostRender = hiddenFiledOnPreRender; 
    hiddenFiledContext.Templates.Fields = { 
        // Apply the new rendering for Age field on New and Edit forms 
        "Predecessors": { 
            "NewForm": hiddenFiledTemplate, 
            "EditForm": hiddenFiledTemplate,
             "View":hiddenFiledTemplate 
        } 
    }; 

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(hiddenFiledContext); 

})(); 


// This function provides the rendering logic 
function hiddenFiledTemplate() { 
    return "<span class='csrHiddenField'></span>"; 
} 

// This function provides the rendering logic 
function hiddenFiledOnPreRender(ctx) { 
    jQuery(".csrHiddenField").closest("tr").hide(); 
} 

Reference: https://code.msdn.microsoft.com/office/Client-side-rendering-code-a52cf8a7

  • I think you misunderstood my whole question , I am not asking how to prevent users from adding list views,, also your jslink will always hide the field from the view/add/edit forms,, while my question is how i can hide certain field/s from list forms and list views based on users permission (security group )... can you read my question again? – john Gu Feb 26 '16 at 15:13
  • 1
    Ofcourse you want to hide them for selective users - this is an example which you can extend to your needs. I have added option 2 which uses SharePoint REST api to check if a users is in a group and applies html modifications accordingly. extend it according to your needs. – HarryB Feb 26 '16 at 15:33
  • but what will be the differences between using Rest API and using custom actions on the view/add/edit forms ? – john Gu Feb 26 '16 at 16:31
  • 1
    Reason1 : Server side object model is not the current best practice for SharePoint development. REST API is simple to use and very powerful – HarryB Feb 26 '16 at 16:40
  • 1
    Just because the field is hidden on the form, doesn't mean the user can not modify those values. You can't lock down columns using JavaScript. Only server side code can do that. – iOnline247 Feb 28 '16 at 1:06
1

SharePoint does not have the ability to apply permissions to a column. There are third-party tools that claim to be able to do this; Google them if you want.

But I had these conceptual ideas that I haven't tried:

  1. Have 2 separate lists with different permissions. Use a workflow or event receiver to keep them in sync. List A would have not have price, but list B would. The workaround is to direct the two different user groups to the correct list. You could use a link list with item level permissions for this.
  2. Set the column as hidden to remove the column from forms. Turn off datasheet view. Remove the column from all but 1 view that has inline editing enabled. Finally, use audiences to allow that view to be displayed to your select few. -edit: may also need to disallow personal views
  • i was thinking if this can be achieved using the following approaches; to add a JSLINK to my field and to hide it from forms and list views based on users' permissions... this will make sure that users will not see the field,, now using JSLINK will not prevent users from hacking the system and get the value ,, is this correct ?so now i need a way to do a server-side checking to prevent unauthorized users from view/add/edit the field value ?is this possible? – john Gu Mar 3 '16 at 16:22
  • Feel free to correct me, your primary motivation is to have 1 list in 1 location. That is an admirable goal. But SharePoint is intended to work together on information, not create divisions. Users won't need to 'hack' your system; the contents will be searchable. Depending on the security and the motivation of your users, this may be an acceptable risk for internal company use. I don't use JS in random places of production as that would be an administrative nightmare. This path may be possible, but I cannot guide you. Good luck. – Jammin4CO Mar 8 '16 at 17:09
0

When you need to hide fields (due to access permissions or business logic), I prefer the following approach:

1) Hide the field programmatically

2) Develop a custom edit form

Both with Server Object Model.

1) Hide the field programmatically

A first option is to hide the field so that it is not seen anywhere. Even in the configuration of the list

Hidden = true;

Another is hiding on each form

ShowInNewForm = true;
ShowInEditForm = true;
ShowInDisplayForm = true;

2) Develop a custom edit form

Create an ASPX page that allows editing the item. In these screens you can: - Hide information based on access permissions - Disable information according to the state of the item or the business logic

In general I try to keep the standard new formSharePoint. But hidden many fields with ShowInNewForm option.

I hope you find it useful!

  • i did not get your point exactly,,, now if i define the options such as showInNewForm = true this will be applied to all users regardless of their permission .. is this correct ? i am not asking how to hide a field from the display form,, i am asking how to show/hide columns based on users permission !! – john Gu Feb 24 '16 at 15:22
  • In this case I would use the "Hidden" option to hide fields and then develop custom forms and views. The field will not appear on standard forms (views, forms and even the configuration of the list). But you can display it in the customs screens, based on the user profile. It is expensive to implement. – Juan Pablo Pussacq Laborde Feb 24 '16 at 15:30

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.