Message Boards

Issue with permission checks in own search portlet

SIva Batchu, modified 3 Years ago.

Issue with permission checks in own search portlet

New Member Posts: 6 Join Date: 8/5/20 Recent Posts
Hi,
          We are  trying to develop own search portlet using liferay services . For all users, our search result  displaying  all  documents in  with out considering folder permissions of users. 
But coming to  liferay search results widget,  displaying  documents based on  folder permissions of users.
 Can any one please help us,     do we need to set any thing for permission checks in our own search portlet?
Below is our sample code.


public List<String> search(long userId, long companyId, String keywords)
        throws PortalException {
        System.out.println("Into Search");        //MatchQuery titleQuery = queries.match(Field.getLocalizedName(LocaleUtil.US, Field.TITLE), "siva");
        
        MatchQuery classQuery = QueriesserviceTracker.getService().match("entryClassName", "com.liferay.document.library.kernel.model.DLFileEntry");
        
        SearchRequestBuilder searchRequestBuilder =
                searchRequestBuilderFactoryserviceTracker.getService().builder().postFilterQuery(classQuery);
        searchRequestBuilder.withSearchContext(
            searchContext -> {
                searchContext.setCompanyId(companyId);
                //searchContext.setGroupIds
                searchContext.setKeywords(keywords);
                searchContext.setSorts(new Sort(Field.TITLE, true));
                searchContext.setUserId(userId);
                
            });        SearchRequest searchRequest = searchRequestBuilder.build();        SearchResponse searchResponse = SearcherserviceTracker.getService().search(searchRequest);
        
        System.out.println("getRequestString..."+searchResponse.getRequestString());
        System.out.println("getResponseString..."+searchResponse.getResponseString());        SearchHits searchHits = searchResponse.getSearchHits();        List<SearchHit> searchHitsList = searchHits.getSearchHits();        List<String> resultsList = new ArrayList<>(searchHitsList.size());
        System.out.println("fdfdfdf..."+searchHitsList.size());
        searchHitsList.forEach(
            searchHit -> {
                float hitScore = searchHit.getScore();                Document doc = searchHit.getDocument();                String uid = doc.getString(Field.UID);
                
                String gid = doc.getString(Field.GROUP_ID);
                //String gid = doc.getString(Field.GROUP_ID);
                
                System.out.println(StringBundler.concat("TITLE ", doc.getString(Field.TITLE)));
                System.out.println(StringBundler.concat("MODIFIED_DATE ", doc.getString(Field.MODIFIED_DATE)));
                //String url = "http://utcit-473:8081/web/pwportal" + "/c/document_library/get_file?uuid=" + uid + "&groupId=" +gid;
                //System.out.println(StringBundler.concat("URL ", url));
                System.out.println(
                    StringBundler.concat(
                        "Document ", uid, " had a score of ", hitScore));                resultsList.add(uid);
            });        System.out.println(StringPool.EIGHT_STARS);        /*
         *  // Uncomment to inspect the Request and Response Strings
         * System.out.println( "Request String:\n" + searchResponse.getRequestString() +
         * "\n" + StringPool.EIGHT_STARS);
         * System.out.println( "Response String:\n" +
         * searchResponse.getResponseString() + "\n" + StringPool.EIGHT_STARS);
         */        return resultsList;
    }    private static ServiceTracker
    <Queries, Queries> QueriesserviceTracker;
static {
    Bundle bundle = FrameworkUtil.getBundle(Queries.class);
    ServiceTracker<Queries, Queries>
        serviceTracker =
            new ServiceTracker
                <Queries, Queries>(
                    bundle.getBundleContext(),
                    Queries.class, null);
    serviceTracker.open();
    QueriesserviceTracker = serviceTracker;
}    private static ServiceTracker
<Searcher, Searcher> SearcherserviceTracker;
static {
Bundle bundle = FrameworkUtil.getBundle(Searcher.class);
ServiceTracker<Searcher, Searcher>
    serviceTracker =
        new ServiceTracker
            <Searcher, Searcher>(
                bundle.getBundleContext(),
                Searcher.class, null);
serviceTracker.open();
SearcherserviceTracker = serviceTracker;
}    
private static ServiceTracker
<SearchRequestBuilderFactory, SearchRequestBuilderFactory> searchRequestBuilderFactoryserviceTracker;
static {
Bundle bundle = FrameworkUtil.getBundle(SearchRequestBuilderFactory.class);
ServiceTracker<SearchRequestBuilderFactory, SearchRequestBuilderFactory>
    serviceTracker =
        new ServiceTracker
            <SearchRequestBuilderFactory, SearchRequestBuilderFactory>(
                bundle.getBundleContext(),
                SearchRequestBuilderFactory.class, null);
serviceTracker.open();
searchRequestBuilderFactoryserviceTracker = serviceTracker;
}
thumbnail
Andrew Jardine, modified 3 Years ago.

RE: Issue with permission checks in own search portlet

Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
Hi Slva.Wow. There is a lot to digest here. Before digging into the code you have posted I think I'd like to start with a simple question so that I can understand where you are coming from. Why are you creating your own custom search widget? While I will admit that I have done this in the past as well, I would also add that 90% of the time I have been able to achieve what the business wants to do with the out of the box that Liferay provides + customizations. What is it you feel you need to do with a custom widget that cannot be achieved with the stuff that Liferay provides?
SIva Batchu, modified 3 Years ago.

RE: Issue with permission checks in own search portlet

New Member Posts: 6 Join Date: 8/5/20 Recent Posts
Hi Jardine, 
Thank you for quick response.
As per our requirement,  we need to pass two or more  dynamic  query inputs(custom inputs) to search engine  in addition to  general keywords. That is  why we are going for own search portlet.
Actually we do not know how to pass dynamic query inputs to liferay provided search widgets.
Can you please help us is there any way is there to pass dynamic query inputs to liferay provided search widgets?
thumbnail
Andrew Jardine, modified 3 Years ago.

RE: Issue with permission checks in own search portlet

Liferay Legend Posts: 2416 Join Date: 12/22/10 Recent Posts
When you say dynamic query inputs, you mean you want to adjust the search query to also include not just the keywords that the user has entered but something else? (like a checkbox selection and a drop down or something like that?)

Liferay provides several ways to adjust the search result before it is executed. The most correct approach will depend on the version you are using though -- can you share with me which version you are working with?

For example, in 7.1 and earlier, you would use an IndexerPostProcessor: https://help.liferay.com/hc/en-us/articles/360017902672-Indexer-Post-Processor

Starting in 7.2 I believe the most correct way to achieve this is to use SearchContextContributor service. I can't seem to find the docs on this one but there are a few examples in Liferay's source code if you just lookup the classes that with this name in them. 
thumbnail
Christoph Rabel, modified 3 Years ago.

RE: Issue with permission checks in own search portlet

Liferay Legend Posts: 1554 Join Date: 9/24/09 Recent Posts
Your code looks awfully complicated to me. We did implement our own searches before, but we never had use service trackers.
Can't you just write

@Reference &nbsp;&nbsp; &nbsp;
private SearchRequestBuilderFactory&nbsp; searchRequestBuilderFactory;

?
If you are outside of a component, why don't you create one?
Anyway:
So, you want to circumvent the permissionchecker and show documents where the user has no access? Right?
I would switch the user to a dedicated service user who has the relevant permissions for that usecase. That way, you can still leverage the permission system and configure that service user (or maybe even more than one of them) to find exactly what you need.
if (something) {
&nbsp;&nbsp;&nbsp; userId = serviceUserIdForThatUsecase;
}
SIva Batchu, modified 3 Years ago.

RE: Issue with permission checks in own search portlet

New Member Posts: 6 Join Date: 8/5/20 Recent Posts
Hi Rabel,
     Thank you for quick response.     
We are created above custom search portlet  with Spring MVC . That is why we have used service tracker to  get reference  of  OSGI services like SearchRequestBuilderFactory , Queries etc.

With above own search portlet, we are  trying to search keywords  in the documents/files within the document and media.Document and media contains  with different folders structure and each folder has different view/access permission for different user groups.

Our requirement is when specific group user log in  to the portal and he is trying to search keywords using custom search portlet, he should only see the search results(documents/files  in folder structures within the document and media)  as per his view/access  permissions on folders.

With liferay default search results widget,  we are achieving correct results as per the permission. But with above custom code user see all the files irrespective of permission he has on folders.
Can you please let us know what we are missing in above code?
thumbnail
Christoph Rabel, modified 3 Years ago.

RE: Issue with permission checks in own search portlet

Liferay Legend Posts: 1554 Join Date: 9/24/09 Recent Posts
AH! I didn't understand your question at first.
You need to add a permissionfilter to the query.
&nbsp;
&nbsp; @Reference
&nbsp; private SearchPermissionChecker searchPermissionChecker;
...
BooleanFilter filter = createPermissionFilter(searchContext, DLFileEntry.class.getName(), new BooleanFilter());
filter = createPermissionFilter(searchContext, DLFolder.class.getName(), filter);
// and so on, till you have added all permission filters you want
// then you create a query and a queryfilter
&nbsp;&nbsp;&nbsp; BooleanQuery query = new BooleanQueryImpl();
&nbsp;&nbsp;&nbsp; criteriaBuilder_.addClassNameFilter(query, DLFileEntry.class.getName());
&nbsp;&nbsp;&nbsp; QueryFilter queryFilter = new QueryFilter(query);
&nbsp;&nbsp;&nbsp; filter.add(queryFilter, BooleanClauseOccur.MUST);
// And now you add this filter as a post filter:
&nbsp;SearchRequestBuilder searchRequestBuilder =
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;searchRequestBuilderFactoryserviceTracker.getService().builder().postFilterQuery(queryFilter);
...
&nbsp; public void addClassNameFilter(BooleanQuery parent, String className) throws ParseException {
&nbsp;&nbsp;&nbsp; TermQuery query = new TermQueryImpl(Field.ENTRY_CLASS_NAME, className);
&nbsp;&nbsp;&nbsp; parent.add(query, BooleanClauseOccur.SHOULD);
&nbsp; }
 public BooleanFilter createPermissionFilter(SearchContext searchContext, String className, BooleanFilter filter) {
&nbsp;&nbsp;&nbsp; return searchPermissionChecker.getPermissionBooleanFilter(searchContext.getCompanyId(), searchContext
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getGroupIds(), searchContext.getUserId(), className, filter, searchContext);
&nbsp; }

I think, I have posted all relevant parts.