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;
}
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;
}
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?
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?
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.
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.
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
?
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;
}
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?
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?
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.
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.