Ask Questions and Find Answers
Important:
Ask is now read-only. You can review any existing questions and answers, but not add anything new.
But - don't panic! While ask is no more, we've replaced it with discuss - the new Liferay Discussion Forum! Read more here here or just visit the site here:
discuss.liferay.com
RE: Issue with permission checks in own search portlet
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;
}
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;
}
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?
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?
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?
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.
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.
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
?
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.
Can't you just write
@Reference
private SearchRequestBuilderFactory 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) {
userId = serviceUserIdForThatUsecase;
}
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?
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?
AH! I didn't understand your question at first.
You need to add a permissionfilter to the query.
I think, I have posted all relevant parts.
You need to add a permissionfilter to the query.
@Reference
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
BooleanQuery query = new BooleanQueryImpl();
criteriaBuilder_.addClassNameFilter(query, DLFileEntry.class.getName());
QueryFilter queryFilter = new QueryFilter(query);
filter.add(queryFilter, BooleanClauseOccur.MUST);
// And now you add this filter as a post filter:
SearchRequestBuilder searchRequestBuilder =
searchRequestBuilderFactoryserviceTracker.getService().builder().postFilterQuery(queryFilter);
...
public void addClassNameFilter(BooleanQuery parent, String className) throws ParseException {
TermQuery query = new TermQueryImpl(Field.ENTRY_CLASS_NAME, className);
parent.add(query, BooleanClauseOccur.SHOULD);
}
public BooleanFilter createPermissionFilter(SearchContext searchContext, String className, BooleanFilter filter) {
return searchPermissionChecker.getPermissionBooleanFilter(searchContext.getCompanyId(), searchContext
.getGroupIds(), searchContext.getUserId(), className, filter, searchContext);
}
I think, I have posted all relevant parts.
Copyright © 2025 Liferay, Inc
• Privacy Policy
Powered by Liferay™