Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply role based search filters in existing endpoints #442

Merged
merged 6 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.servlet.annotation.WebServlet;

Expand All @@ -28,6 +29,8 @@
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngineException;
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchQuery;
import edu.cornell.mannlib.vitro.webapp.search.controller.SearchFilter;
import edu.cornell.mannlib.vitro.webapp.search.controller.SearchFiltering;
import edu.cornell.mannlib.vitro.webapp.utils.searchengine.SearchQueryUtils;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individuallist.ListedIndividual;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individuallist.ListedIndividualBuilder;
Expand Down Expand Up @@ -188,15 +191,15 @@ private static IndividualListResults buildAndExecuteVClassQuery(List<String> cla
boolean languageFilter = Boolean.valueOf(props.getProperty(LANGUAGE_FILTER_PROPERTY, "false"));
IndividualListQueryResults results = buildAndExecuteVClassQuery(classUris, alpha,
((languageFilter) ? vreq.getLocale() : null), page, pageSize,
vreq.getWebappDaoFactory().getIndividualDao());
vreq);
IndividualListResults indListResults = getResultsForVClassQuery(results, page, pageSize, alpha, vreq);
return indListResults;
}

public static IndividualListResults getRandomResultsForVClass(String vclassURI, int page, int pageSize, VitroRequest vreq) {
try{
List<String> classUris = Collections.singletonList(vclassURI);
IndividualListQueryResults results = buildAndExecuteRandomVClassQuery(classUris, page, pageSize, vreq.getWebappDaoFactory().getIndividualDao());
IndividualListQueryResults results = buildAndExecuteRandomVClassQuery(classUris, page, pageSize, vreq);
return getResultsForVClassQuery(results, page, pageSize, "", vreq);
} catch(Throwable th) {
log.error("An error occurred retrieving random results for vclass query", th);
Expand All @@ -216,9 +219,12 @@ private static IndividualListResults getResultsForVClassQuery(IndividualListQuer

private static IndividualListQueryResults buildAndExecuteVClassQuery(
List<String> vclassURIs, String alpha, Locale locale, int page,
int pageSize, IndividualDao indDao)
int pageSize, VitroRequest vreq)
throws SearchEngineException {
IndividualDao indDao = vreq.getWebappDaoFactory().getIndividualDao();
SearchQuery query = SearchQueryUtils.getQuery(vclassURIs, alpha, locale, page, pageSize);
Set<String> currentRoles = SearchFiltering.getCurrentUserRoles(vreq);
SearchFiltering.addDefaultFilters(query, currentRoles);
IndividualListQueryResults results = IndividualListQueryResults.runQuery(query, indDao);
log.debug("Executed search query for " + vclassURIs);
if (results.getIndividuals().isEmpty()) {
Expand All @@ -228,9 +234,12 @@ private static IndividualListQueryResults buildAndExecuteVClassQuery(
}

private static IndividualListQueryResults buildAndExecuteRandomVClassQuery(
List<String> vclassURIs, int page, int pageSize, IndividualDao indDao)
List<String> vclassURIs, int page, int pageSize, VitroRequest vreq)
throws SearchEngineException {
IndividualDao indDao = vreq.getWebappDaoFactory().getIndividualDao();
SearchQuery query = SearchQueryUtils.getRandomQuery(vclassURIs, page, pageSize);
Set<String> currentRoles = SearchFiltering.getCurrentUserRoles(vreq);
SearchFiltering.addDefaultFilters(query, currentRoles);
IndividualListQueryResults results = IndividualListQueryResults.runQuery(query, indDao);
log.debug("Executed search query for " + vclassURIs);
if (results.getIndividuals().isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@

package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators;

import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.LANGUAGE_NEUTRAL;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.POLICY_NEUTRAL;
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.DISPLAY;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpSession;

Expand Down Expand Up @@ -45,6 +44,7 @@
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchResponse;
import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchResultDocumentList;
import edu.cornell.mannlib.vitro.webapp.search.VitroSearchTermNames;
import edu.cornell.mannlib.vitro.webapp.search.controller.SearchFiltering;
import edu.cornell.mannlib.vitro.webapp.utils.FrontEndEditingUtils;
import edu.cornell.mannlib.vitro.webapp.utils.FrontEndEditingUtils.EditMode;

Expand Down Expand Up @@ -187,7 +187,7 @@ private boolean tooManyRangeOptions(VitroRequest vreq, HttpSession session ) thr
if(types.size() == 0 ){
types.add(VitroVocabulary.OWL_THING);
}

Set<String> currentRoles = SearchFiltering.getCurrentUserRoles(vreq);
long count = 0;
for( String type:types){
//search query for type count.
Expand All @@ -198,6 +198,7 @@ private boolean tooManyRangeOptions(VitroRequest vreq, HttpSession session ) thr
query.setQuery( VitroSearchTermNames.RDFTYPE + ":" + type);
}
query.setRows(0);
SearchFiltering.addDefaultFilters(query, currentRoles);
SearchResponse rsp = searchEngine.query(query);
SearchResultDocumentList docs = rsp.getResults();
long found = docs.getNumFound();
Expand Down Expand Up @@ -549,9 +550,9 @@ public void addFormSpecificDataForAC(EditConfigurationVTwo editConfiguration, Vi
String objectLabel = EditConfigurationUtils.getObjectIndividual(vreq).getName();
formSpecificData.put("objectLabel", objectLabel);
}

Set<String> currentRoles = SearchFiltering.getCurrentUserRoles(vreq);
//TODO: find out if there are any individuals in the classes of objectTypes
formSpecificData.put("rangeIndividualsExist", rangeIndividualsExist(types) );
formSpecificData.put("rangeIndividualsExist", rangeIndividualsExist(types, currentRoles) );

formSpecificData.put("sparqlForAcFilter", getSparqlForAcFilter(vreq));
if(customErrorMessages != null && !customErrorMessages.isEmpty()) {
Expand All @@ -561,7 +562,7 @@ public void addFormSpecificDataForAC(EditConfigurationVTwo editConfiguration, Vi
editConfiguration.setFormSpecificData(formSpecificData);
}

private Object rangeIndividualsExist(List<VClass> types) throws SearchEngineException {
private Object rangeIndividualsExist(List<VClass> types, Set<String> currentRoles) throws SearchEngineException {
SearchEngine searchEngine = ApplicationUtils.instance().getSearchEngine();

boolean rangeIndividualsFound = false;
Expand All @@ -570,6 +571,7 @@ private Object rangeIndividualsExist(List<VClass> types) throws SearchEngineExce
SearchQuery query = searchEngine.createQuery();
query.setQuery( VitroSearchTermNames.RDFTYPE + ":" + type.getURI());
query.setRows(0);
SearchFiltering.addDefaultFilters(query, currentRoles);

SearchResponse rsp = searchEngine.query(query);
SearchResultDocumentList docs = rsp.getResults();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
Expand Down Expand Up @@ -99,6 +101,8 @@ else if ( parts.length == 1 ) {
return;
}
log.debug("query for '" + qtxt +"' is " + query.toString());
Set<String> currentRoles = SearchFiltering.getCurrentUserRoles(vreq);
SearchFiltering.addDefaultFilters( query, currentRoles);

SearchEngine search = ApplicationUtils.instance().getSearchEngine();
SearchResponse queryResponse = search.query(query);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,29 @@
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.jena.ontology.OntModel;
import org.apache.jena.query.Dataset;
import org.apache.jena.query.DatasetFactory;
import org.apache.jena.query.ParameterizedSparqlString;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryExecutionFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model;

import org.apache.jena.rdf.model.RDFNode;
import edu.cornell.mannlib.vitro.webapp.auth.attributes.AccessOperation;
import edu.cornell.mannlib.vitro.webapp.auth.objects.AccessObject;
import edu.cornell.mannlib.vitro.webapp.auth.objects.DataPropertyStatementAccessObject;
import edu.cornell.mannlib.vitro.webapp.auth.objects.IndividualAccessObject;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AuthorizationRequest;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.SimpleAuthorizationRequest;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.ajax.SparqlUtils;
import edu.cornell.mannlib.vitro.webapp.controller.ajax.SparqlUtils.AjaxControllerException;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.controller.ajax.VitroAjaxController;

/**
Expand All @@ -49,17 +56,25 @@ public class DataAutocompleteController extends VitroAjaxController {
private static final String PARAM_QUERY = "term";
//To get the data property
private static final String PARAM_PROPERTY = "property";

private static final int DEFAULT_MAX_HIT_COUNT = 1000;

private static final String QUERY_TEXT = ""
+ "SELECT DISTINCT ?subject ?prop ?object ?dataLiteral \n"
+ "WHERE {\n"
+ " ?subject ?prop ?object .\n"
+ " VALUES ?prop { ?property }\n"
+ " BIND(STR(?object) as ?dataLiteral )\n"
+ " FILTER(REGEX(?dataLiteral, ?term, \"i\"))\n"
+ "}\n"
+ "ORDER BY ?dataLiteral\n "
+ "LIMIT " + DEFAULT_MAX_HIT_COUNT;

String NORESULT_MSG = "";
private static final int DEFAULT_MAX_HIT_COUNT = 1000;

public static final int MAX_QUERY_LENGTH = 500;

@Override
protected AuthorizationRequest requiredActions(VitroRequest vreq) {
//used to be basic vitro ajax permission but need to query full model
return SimplePermission.QUERY_FULL_MODEL.ACTION;
return SimplePermission.USE_BASIC_AJAX_CONTROLLERS.ACTION;
}

@Override
Expand All @@ -72,17 +87,10 @@ protected void doRequest(VitroRequest vreq, HttpServletResponse response)
String property = vreq.getParameter(PARAM_PROPERTY);
//Get sparql query for this property
String sparqlQuery = getSparqlQuery(qtxt, property);
//Forward this to SparqlQueryAjaxController as that already
//handles execution of query and will return json results
// String encodedQuery = URLEncoder.encode(sparqlQuery, "UTF-8");
// response.sendRedirect(vreq.getContextPath() + "/ajax/sparqlQuery?query=" + encodedQuery);
//RequestDispatcher dispatcher = vreq.getRequestDispatcher("/ajax/sparqlQuery?query=" + encodedQuery );
//dispatcher.forward(vreq, response);

//Get Model and execute query
Model model = getModel(vreq);
OntModel model = getModel(vreq);
Query query = SparqlUtils.createQuery(sparqlQuery);
outputResults(response, query, model);
outputResults(response, query, model, vreq);
} catch(AjaxControllerException ex) {
log.error(ex, ex);
response.sendError(ex.getStatusCode());
Expand All @@ -94,7 +102,7 @@ protected void doRequest(VitroRequest vreq, HttpServletResponse response)
}

private void outputResults(HttpServletResponse response, Query query,
Model model) throws IOException{
OntModel model, VitroRequest vreq) throws IOException{
Dataset dataset = DatasetFactory.create(model);
//Iterate through results and print out array of strings
List<String> outputResults = new ArrayList<String>();
Expand All @@ -103,6 +111,24 @@ private void outputResults(HttpServletResponse response, Query query,
ResultSet results = qe.execSelect();
while(results.hasNext()) {
QuerySolution qs = results.nextSolution();
RDFNode subject = qs.get("subject");
if (!subject.isResource() || subject.isAnon()) {
continue;
}
RDFNode property = qs.get("prop");
if (!property.isResource() || property.isAnon()) {
continue;
}
RDFNode object = qs.get("object");
if (!object.isLiteral()) {
continue;
}
String subjectUri = subject.asResource().getURI();
String propertyUri = property.asResource().getURI();
String objectValue = object.asLiteral().getLexicalForm();
if (!isAuthorized(vreq, qs, model, subjectUri, propertyUri, objectValue)) {
continue;
}
Literal dataLiteral = qs.getLiteral("dataLiteral");
String dataValue = dataLiteral.getString();
outputResults.add(dataValue);
Expand All @@ -120,12 +146,23 @@ private void outputResults(HttpServletResponse response, Query query,
} finally {
qe.close();
}
}


private boolean isAuthorized(VitroRequest vreq, QuerySolution qs, OntModel model, String subjectUri, String propertyUri, String objectValue) {
AccessObject dataPropertyStatementAccessObject = new DataPropertyStatementAccessObject(model, subjectUri, propertyUri, objectValue);
AuthorizationRequest dataPropertyRequest = new SimpleAuthorizationRequest(dataPropertyStatementAccessObject, AccessOperation.DISPLAY);
if (VitroVocabulary.LABEL.equals(propertyUri)) {
AccessObject individualAccessObject = new IndividualAccessObject(subjectUri);
individualAccessObject.setModel(model);
AuthorizationRequest individualRequest = new SimpleAuthorizationRequest(individualAccessObject, AccessOperation.DISPLAY);
AuthorizationRequest requests = dataPropertyRequest.and(individualRequest);
return PolicyHelper.isAuthorizedForActions(vreq, requests);
}
return PolicyHelper.isAuthorizedForActions(vreq, dataPropertyRequest);
}

private Model getModel(VitroRequest vreq) throws AjaxControllerException{
Model model = vreq.getJenaOntModel();
private OntModel getModel(VitroRequest vreq) throws AjaxControllerException{
OntModel model = vreq.getJenaOntModel();

if (model == null) {
throw new AjaxControllerException(SC_INTERNAL_SERVER_ERROR,
Expand All @@ -135,12 +172,11 @@ private Model getModel(VitroRequest vreq) throws AjaxControllerException{
}

private String getSparqlQuery(String qtxt, String property) {
//"i" denotes case insensitive
//Searches for data literals whose string version begins with the text denoted
String query = "SELECT DISTINCT ?dataLiteral where {" +
"?s <" + property + "> ?dataLiteral . " +
"FILTER(regex(str(?dataLiteral), \"^" + qtxt + "\", \"i\")) } ORDER BY ?dataLiteral";
return query;
ParameterizedSparqlString pss = new ParameterizedSparqlString(QUERY_TEXT);
pss.setIri(PARAM_PROPERTY, property);
pss.setLiteral(PARAM_QUERY, "^" + qtxt);
return pss.toString();
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,24 @@ protected ResponseValues processRequest(VitroRequest vreq) {
if (log.isDebugEnabled()) {
log.debug(getSpentTime(startTime) + "ms spent before read filter configurations.");
}
Map<String, SearchFilter> filterConfigurationsByField = SearchFiltering.readFilterConfigurations(vreq);
Set<String> currentRoles = SearchFiltering.getCurrentUserRoles(vreq);
Map<String, SearchFilter> filterConfigurationsByField = SearchFiltering.readFilterConfigurations(currentRoles);
if (log.isDebugEnabled()) {
log.debug(getSpentTime(startTime) + "ms spent before get sort configurations.");
}
Map<String, SortConfiguration> sortConfigurations = SearchFiltering.getSortConfigurations(vreq);
for (SearchFilter filter: filterConfigurationsByField.values()) {
filter.setInputText(SearchFiltering.getFilterInputText(vreq, filter.getId()));
filter.setRangeValues(SearchFiltering.getFilterRangeText(vreq, filter.getId()));
}
Map<String, List<String>> requestFilters = SearchFiltering.getRequestFilters(vreq);
if (log.isDebugEnabled()) {
log.debug(getSpentTime(startTime) + "ms spent after getRequestFilters.");
}
SearchFiltering.setSelectedFilters(filterConfigurationsByField, requestFilters);
if (log.isDebugEnabled()) {
log.debug(getSpentTime(startTime) + "ms spent after setSelectedFilters.");
}
Map<String, SortConfiguration> sortConfigurations = SearchFiltering.getSortConfigurations();
if (log.isDebugEnabled()) {
log.debug(getSpentTime(startTime) + "ms spent before get query configurations.");
}
Expand Down Expand Up @@ -257,7 +270,7 @@ protected ResponseValues processRequest(VitroRequest vreq) {
Map<String, SearchFilter> filtersForTemplateById =
SearchFiltering.getFiltersForTemplate(filterConfigurationsByField);
body.put("filters", filtersForTemplateById);
body.put("filterGroups", SearchFiltering.readFilterGroupsConfigurations(vreq, filtersForTemplateById));
body.put("filterGroups", SearchFiltering.readFilterGroupsConfigurations(filtersForTemplateById));
body.put("sorting", sortConfigurations.values());
body.put("emptySearch", isEmptySearchFilters(filterConfigurationsByField));
}
Expand Down Expand Up @@ -352,7 +365,7 @@ private void addFacetCountersFromRequest(SearchResponse response, Map<String, Se
}
}
if (searchFilter.isLocalizationRequired() && StringUtils.isBlank(filterValue.getName())) {
String label = SearchFiltering.getUriLabel(value.getName(), vreq);
String label = SearchFiltering.getUriLabel(value.getName());
if (!StringUtils.isBlank(label)) {
filterValue.setName(label);
}
Expand Down
Loading
Loading