1

Background:

  1. We have a public page on Napili community where guest user can type the search term into the custom search component and see the results.
  2. If we use the OOB Napili search functionality, it is not showing all the articles matching the search term but only what guest user can see.
  3. So we built a custom search component as mentioned in this link hoping that we can bypass user permissions.

But still we are getting results based on user permissions.

Here is the complete code for the component:

CommunityCustomSearch.cmp:

<aura:component implements="forceCommunity:searchInterface" 
                access="global" 
                controller="ComunityCustomSearchApexController">

    <div class="search">
        <div class="search-wrapper">
            <form class="search-form">
                <div class="search-input-wrapper" style="display:inline-block">
                    <input  style="width:100%" 
                            aura:id="search-input" 
                            type="text" 
                            placeholder="My Search"/>
                </div>
                <button type="button" 
                        onclick="{!c.searchBtnHandler}">
                    <span   class=" label bBody truncate" 
                            dir="ltr">Search</span>
                </button>
            </form>
        </div>
    </div>
</aura:component>

CommunityCustomSearchController.js:

({
    searchBtnHandler : function(component, event, helper) {

        var searchText = component.find('search-input').getElement().value;
        console.log(searchText);

        var action = component.get("c.searchArticles");
        action.setParams({  searchTerm : searchText});

        action.setCallback(this, function(response) {
            var state = response.getState();
            if(state === "SUCCESS"){
                console.log('Server call SUCCESS');
                console.log('Results returned from server ');
                console.log(response.getReturnValue().length);
                console.log(response.getReturnValue()[0].articleTitle);
            }else{
                console.log('Server call for getting Search Results failed');
            }
        });

        $A.enqueueAction(action);
    }
})

ComunityCustomSearchApexController.cls:

public without sharing class ComunityCustomSearchApexController {

    @AuraEnabled
    public static List<SearchResultsWrapper> searchArticles(String searchTerm){

        String sosl = 'FIND \'*' + searchTerm + '*\' IN ALL FIELDs';
        sosl = sosl + ' Returning Knowledge__kav(ID, Title,UrlName ';
        sosl = sosl + ' WHERE PublishStatus = \'Online\'';
        sosl = sosl + ' AND Language = \'en_US\')  WITH SNIPPET (target_length=120)';
        Search.SearchResults searchResults = search.find(sosl);

        List<Search.SearchResult> articleList = searchResults.get('Knowledge__kav');

        List<SearchResultsWrapper> wrapperList = new List<SearchResultsWrapper>();

        for (Search.SearchResult searchResult : articleList) {
            Knowledge__kav article = (Knowledge__kav) searchResult.getSObject();
            SearchResultsWrapper obj = new SearchResultsWrapper();
            obj.articleTitle = article.Title;
            wrapperList.add(obj);
        }

        System.debug(JSON.serialize(wrapperList));
        return wrapperList;
    }

    public class SearchResultsWrapper{
        @AuraEnabled
        public String articleTitle;
    }

}

Data:

  1. I have two articles in the system.
  2. One article is accessible by Guest users(IsVisibleInPkb = TRUE)
  3. Another article is accessible only for Community users(IsVisibleInCsp = TRUE).

Results:

  1. If I access this component as guest user and type the search term, I am seeing only one result in the console.
  2. When I access the same component wrapped in a aura:application as an internal user and for the same search term, I am seeing two results in the console.

Any clues?

1

This is quite obvious that user won't get access to Article, until unless it is published for user's channel.

For public community users, you will have to publish the second article for PKB (Public Knowledge Base) channel.

Regarding the link, you can customise the search component to control your search behaviour for other standard and custom objects, but Article sharing and permissions are designed in more controlled manner and are managed by Salesforce.

For example, you can control following operations for articles in your customised search component:

  • Display only specific type of article types
  • Display only 2 records out of available 5 records, based on certain conditions

However article sharing with user will be controlled by Channels and Data category access.

A possible workaround to search Articles with Guest user profile:

  • Implement a custom object to store Article Title, Summary, URL and ID and keep it in sync with Knowledge Articles, even they are not published for Public Knowledge base
  • Grant access to Guest user to this custom object. So even an article is not accessible, he would be able query the title
  • If the user selects the article, navigate to login page or article URL
  • I understand that user does not have access to the article thats why I am using controller so that user permissions are ignored. You don't think so? – javanoob Apr 29 '17 at 3:50
  • Just by using Without sharing controller, user will not gain access to all articles. I have updated my answer to include a bit more detail. – Salesforcesmarty Apr 29 '17 at 3:57
  • Is it documented that knowledge articles always respect user permissions even though it is without sharing?? – javanoob Apr 29 '17 at 3:59
  • You are confusing in two different things - You will be able to query the article type using Without Sharing keyword, if user doesn't have access to that type (Results into articleName__kav object), given article is published for that channel and user has access to associated data categories. But you won't be able to bypass channel and Data category sharing by any means. – Salesforcesmarty Apr 29 '17 at 4:02
  • Please see this answer salesforce.stackexchange.com/a/58360/16304 I am trying to implement this functionality. If user clicks on the article thay he doesn't have access then I am planning to show login page as mentioned in this answer. Do you think the idea mentioned in this answer won't work? – javanoob Apr 29 '17 at 4:02
0

I am going to accept @Salesforcesmarty answer as it led me in the right direction but below are things I learnt and wanted to share as a separate answer.

From Troubleshooting Article Visibility - Salesforce help article

An article will not be searchable if the user cannot open the direct link to the article. If the user navigates to the direct link to the article, and the article is displayed, the above conditions will be met for the given article. Conversely, the article will be returned in SOSL searches performed by this user (through API or via Apex code invoked by the controller of a Visualforce page) if the article is visible to the user.

I was wrong in thinking that custom search component runs in system mode we can show at least title of the Knowledge article though user does not have permission to see the actual record.

Two options:

  1. Have a custom object storing the title and name of the Knowledge articles and do a search in this object when guest user types search term in custom component.
  2. Once the guest user types the search term into custom component and hits the search button, on the server side, Do a REST callout to the actual method which does the SOSL under different user session Id.

We implemented option 2 because there are lot of SOQL and SOSL features that are specific to Knowledge Articles and we will lose those if we go with custom object approach. Downside of option 2 is it consumes API calls but thats ok for us as this functionality is used by very few people in production.

The ultimate goal in showing the title of Knowledge article for which guest user does not have access to is to show login screen when guest user clicks on the article link to see the actual record.

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.