Added authentication to metadata controller (issue #38) & updated search
krill error handling
Change-Id: I2937de0223561246c3af078e9ada1258e4fae7d2
diff --git a/core/Changes b/core/Changes
index 3f2d0b7..378a85e 100644
--- a/core/Changes
+++ b/core/Changes
@@ -1,7 +1,8 @@
# version 0.61.6
-
06/02/2018
- Added default foundry for structure layer (margaretha)
+ - Added authentication to metadata controller (margaretha, issue #38)
+ - Updated search krill error handling (margaretha)
# version 0.61.5
17/12/2018
diff --git a/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java b/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
index 72b8cfc..446137c 100644
--- a/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
+++ b/core/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
@@ -111,7 +111,8 @@
public static final int STATUS_OK = 1000;
public static final int NOTHING_CHANGED = 1001;
public static final int REQUEST_INVALID = 1002;
- public static final int ACCESS_DENIED = 1003;
+
+// public static final int ACCESS_DENIED = 1003;
// User group and member
diff --git a/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java b/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java
index fa6a680..ca63c08 100644
--- a/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java
+++ b/core/src/main/java/de/ids_mannheim/korap/service/SearchService.java
@@ -193,14 +193,7 @@
}
- public String retrieveMatchInfo (String corpusId, String docId,
- String textId, String matchId, Set<String> foundries,
- String username, HttpHeaders headers, Set<String> layers,
- boolean spans, boolean highlights) throws KustvaktException {
- String matchid =
- searchKrill.getMatchId(corpusId, docId, textId, matchId);
-
- User user = createUser(username, headers);
+ private Pattern determineAvailabilityPattern (User user) {
Pattern p = null;
if (user != null) {
CorpusAccess corpusAccess = user.getCorpusAccess();
@@ -216,9 +209,22 @@
break;
}
}
+ return p;
+ }
+
+ public String retrieveMatchInfo (String corpusId, String docId,
+ String textId, String matchId, Set<String> foundries,
+ String username, HttpHeaders headers, Set<String> layers,
+ boolean spans, boolean highlights) throws KustvaktException {
+ String matchid =
+ searchKrill.getMatchId(corpusId, docId, textId, matchId);
+
+ User user = createUser(username, headers);
+ Pattern p = determineAvailabilityPattern(user);
+
boolean match_only = foundries == null || foundries.isEmpty();
String results;
- try {
+// try {
if (!match_only) {
ArrayList<String> foundryList = new ArrayList<String>();
@@ -241,12 +247,12 @@
else {
results = searchKrill.getMatch(matchid, p);
}
- }
- catch (Exception e) {
- jlog.error("Exception in the MatchInfo service encountered!", e);
- throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
- e.getMessage());
- }
+// }
+// catch (Exception e) {
+// jlog.error("Exception in the MatchInfo service encountered!", e);
+// throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
+// e.getMessage());
+// }
if (DEBUG){
jlog.debug("MatchInfo results: " + results);
}
@@ -254,9 +260,12 @@
}
public String retrieveDocMetadata (String corpusId, String docId,
- String textId) {
+ String textId, String username, HttpHeaders headers)
+ throws KustvaktException {
+ User user = createUser(username, headers);
+ Pattern p = determineAvailabilityPattern(user);
String textSigle = searchKrill.getTextSigle(corpusId, docId, textId);
- return searchKrill.getFields(textSigle);
+ return searchKrill.getFields(textSigle, p);
}
public String getCollocationBase (String query) throws KustvaktException {
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/SearchKrill.java b/core/src/main/java/de/ids_mannheim/korap/web/SearchKrill.java
index f81b5aa..0580d7e 100644
--- a/core/src/main/java/de/ids_mannheim/korap/web/SearchKrill.java
+++ b/core/src/main/java/de/ids_mannheim/korap/web/SearchKrill.java
@@ -29,8 +29,7 @@
* @author Nils Diewald
*/
public class SearchKrill {
- private final static Logger jlog = LogManager
- .getLogger(SearchKrill.class);
+ private final static Logger jlog = LogManager.getLogger(SearchKrill.class);
private static final boolean DEBUG = false;
@@ -39,13 +38,13 @@
String i = "/Users/hanl/Projects/prep_corpus";
String klinux10 = "/vol/work/hanl/indices";
public static KrillIndex index;
-
+
/**
* Constructor
*/
// todo: use korap.config to get index location
public SearchKrill (String path) {
-
+
try {
if (path.equals(":temp:")) {
index = new KrillIndex();
@@ -61,7 +60,7 @@
};
}
catch (IOException e) {
- jlog.error("Unable to loadSubTypes index:"+ e.getMessage());
+ jlog.error("Unable to loadSubTypes index:" + e.getMessage());
};
};
@@ -69,7 +68,6 @@
return index;
};
-
/**
* Search in the Lucene index.
*
@@ -78,12 +76,12 @@
* filters.
*/
public String search (String json) {
- if (DEBUG){
+ if (DEBUG) {
jlog.debug(json);
}
- if (index != null){
+ if (index != null) {
String result = new Krill(json).apply(index).toJsonString();
- if (DEBUG){
+ if (DEBUG) {
jlog.debug(result);
}
return result;
@@ -93,7 +91,6 @@
return kr.toJsonString();
};
-
/**
* Search in the Lucene index and return matches as token lists.
*
@@ -103,7 +100,7 @@
*/
@Deprecated
public String searchTokenList (String json) {
- if (DEBUG){
+ if (DEBUG) {
jlog.debug(json);
}
if (index != null)
@@ -113,116 +110,106 @@
return kr.toJsonString();
};
-
/**
* Get info on a match - by means of a richly annotated html
* snippet.
*
* @param id
* match id
- * @param availabilityList
- * @throws KustvaktException
+ * @param availabilityList
+ * @throws KustvaktException
*/
- public String getMatch (String id, Pattern licensePattern) {
- Match km;
+ public String getMatch (String id, Pattern licensePattern) throws KustvaktException {
+ Match km;
if (index != null) {
try {
- km = index.getMatch(id);
- String availability = km.getAvailability();
- if (licensePattern!=null && availability != null){
- Matcher m = licensePattern.matcher(availability);
- if (!m.matches()){
- if (DEBUG){
- jlog.debug("availability: "+availability);
- }
- if (availability.isEmpty()){
- km.addError(StatusCodes.MISSING_ATTRIBUTE,
- "Availability for "+ id +"is empty.", id);
- }
- km = new Match();
- km.addError(StatusCodes.ACCESS_DENIED,
- "Retrieving match info with ID "+id+" is not allowed.", id);
- }
- }
+ km = index.getMatch(id);
+ String availability = km.getAvailability();
+ checkAvailability(licensePattern, availability, id);
}
catch (QueryException qe) {
km = new Match();
km.addError(qe.getErrorCode(), qe.getMessage());
}
}
- else{
- km = new Match();
- km.addError(601, "Unable to find index");
+ else {
+ km = new Match();
+ km.addError(601, "Unable to find index");
}
return km.toJsonString();
};
+ private void checkAvailability (Pattern licensePattern, String availability,
+ String id) throws KustvaktException {
+ if (DEBUG) {
+ jlog.debug("pattern: " + licensePattern.toString()
+ + ", availability: " + availability);
+ }
+ if (licensePattern != null && availability != null) {
+ Matcher m = licensePattern.matcher(availability);
+ if (!m.matches()) {
+ if (availability.isEmpty()) {
+ throw new KustvaktException(StatusCodes.MISSING_ATTRIBUTE,
+ "Availability for " + id + "is empty.", id);
+ }
+ throw new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
+ "Retrieving resource with ID " + id
+ + " is not allowed.",
+ id);
+ }
+ }
- /*
- * Retrieve the meta fields for a certain document
- */
- public String getFields (String id) {
- MetaFields meta;
+ }
+
+ /*
+ * Retrieve the meta fields for a certain document
+ */
+ public String getFields (String id, Pattern licensePattern)
+ throws KustvaktException {
+ MetaFields meta;
- // No index found
- if (index == null) {
- meta = new MetaFields(id);
- meta.addError(601, "Unable to find index");
- }
+ // No index found
+ if (index == null) {
+ meta = new MetaFields(id);
+ meta.addError(601, "Unable to find index");
+ }
- // Index available
- else {
+ // Index available
+ else {
+ // Get fields
+ meta = index.getFields(id);
+ };
- //Get fields
- meta = index.getFields(id);
- };
- return meta.toJsonString();
- };
+ String availability = meta.getFieldValue("availability");
+ checkAvailability(licensePattern, availability, id);
+ return meta.toJsonString();
+ };
-
public String getMatch (String id, List<String> foundries,
List<String> layers, boolean includeSpans,
- boolean includeHighlights, boolean sentenceExpansion,
- Pattern licensePattern) {
- Match km;
+ boolean includeHighlights, boolean sentenceExpansion,
+ Pattern licensePattern) throws KustvaktException {
+ Match km;
if (index != null) {
try {
- km = index.getMatchInfo(id, "tokens", true, foundries,
- layers, includeSpans, includeHighlights,
- sentenceExpansion);
- String availability = km.getAvailability();
-
- if (licensePattern !=null && availability != null){
- if (availability.isEmpty()){
- km.addError(StatusCodes.MISSING_ATTRIBUTE,
- "Availability for "+ id +"is empty.", id);
- }
- Matcher m = licensePattern.matcher(availability);
- if (!m.matches()){
- if (DEBUG){
- jlog.debug("pattern: "+ licensePattern.toString() + ", availability: "+availability);
- }
- km = new Match();
- km.addError(StatusCodes.ACCESS_DENIED,
- "Retrieving match info with ID "+id+" is not allowed.", id);
- }
- }
-
+ km = index.getMatchInfo(id, "tokens", true, foundries, layers,
+ includeSpans, includeHighlights, sentenceExpansion);
+ String availability = km.getAvailability();
+ checkAvailability(licensePattern, availability, id);
}
catch (QueryException qe) {
km = new Match();
km.addError(qe.getErrorCode(), qe.getMessage());
}
}
- else{
- km = new Match();
- km.addError(601, "Unable to find index");
+ else {
+ km = new Match();
+ km.addError(601, "Unable to find index");
}
return km.toJsonString();
};
-
/**
* Get info on a match - by means of a richly annotated html
* snippet.
@@ -270,7 +257,6 @@
return km.toJsonString();
};
-
/**
* Get statistics on (virtual) collections.
*
@@ -284,23 +270,23 @@
return "{\"documents\" : -1, error\" : \"No index given\" }";
};
- // Define a virtual corpus
- KrillCollection kc;
- if (json != null && !json.equals("")) {
- if (DEBUG){
- jlog.debug(json);
- }
+ // Define a virtual corpus
+ KrillCollection kc;
+ if (json != null && !json.equals("")) {
+ if (DEBUG) {
+ jlog.debug(json);
+ }
- // Create Virtual collection from json search
- kc = new KrillCollection(json);
- }
+ // Create Virtual collection from json search
+ kc = new KrillCollection(json);
+ }
- // There is no json string defined
- else {
+ // There is no json string defined
+ else {
- // Create Virtual collection of everything
- kc = new KrillCollection();
- };
+ // Create Virtual collection of everything
+ kc = new KrillCollection();
+ };
// Set index
kc.setIndex(index);
@@ -308,11 +294,11 @@
// Get numbers from index (currently slow)
try {
docs = kc.numberOf("documents");
- if (docs > 0) {
- tokens = kc.numberOf("tokens");
- sentences = kc.numberOf("base/sentences");
- paragraphs = kc.numberOf("base/paragraphs");
- };
+ if (docs > 0) {
+ tokens = kc.numberOf("tokens");
+ sentences = kc.numberOf("base/sentences");
+ paragraphs = kc.numberOf("base/paragraphs");
+ };
}
catch (IOException e) {
e.printStackTrace();
@@ -325,7 +311,6 @@
return sb.toString();
};
-
/**
* Return the match identifier as a string.
* This is a convenient method to deal with legacy instantiation
@@ -334,22 +319,21 @@
*/
public String getMatchId (String corpusID, String docID, String textID,
String matchID) {
- // Create a string representation of the match
+ // Create a string representation of the match
StringBuilder sb = new StringBuilder();
sb.append("match-").append(corpusID).append('/').append(docID)
.append('/').append(textID).append('-').append(matchID);
return sb.toString();
};
-
/**
* Return the text sigle as a string.
*/
public String getTextSigle (String corpusID, String docID, String textID) {
- // Create a string representation of the match
+ // Create a string representation of the match
StringBuilder sb = new StringBuilder();
- sb.append(corpusID).append('/').append(docID)
- .append('/').append(textID);
+ sb.append(corpusID).append('/').append(docID).append('/')
+ .append(textID);
return sb.toString();
};
};
diff --git a/core/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java b/core/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java
index 0cd61a3..f3299a8 100644
--- a/core/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java
+++ b/core/src/main/java/de/ids_mannheim/korap/web/controller/SearchController.java
@@ -163,6 +163,8 @@
return Response.ok(result).build();
}
+ // EM: legacy support
+ @Deprecated
@GET
@Path("{version}/corpus/{corpusId}/{docId}/{textId}/{matchId}/matchInfo")
public Response getMatchInfo (@Context SecurityContext ctx,
@@ -177,16 +179,40 @@
// Highlights may also be a list of valid highlight classes
@QueryParam("hls") Boolean highlights) throws KustvaktException {
+ return retrieveMatchInfo(ctx, headers, locale, corpusId, docId, textId,
+ matchId, foundries, layers, spans, highlights);
+ }
+
+ @GET
+ @Path("{version}/corpus/{corpusId}/{docId}/{textId}/{matchId}")
+ public Response retrieveMatchInfo (@Context SecurityContext ctx,
+ @Context HttpHeaders headers, @Context Locale locale,
+ @PathParam("corpusId") String corpusId,
+ @PathParam("docId") String docId,
+ @PathParam("textId") String textId,
+ @PathParam("matchId") String matchId,
+ @QueryParam("foundry") Set<String> foundries,
+ @QueryParam("layer") Set<String> layers,
+ @QueryParam("spans") Boolean spans,
+ // Highlights may also be a list of valid highlight classes
+ @QueryParam("hls") Boolean highlights) throws KustvaktException {
+
TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
scopeService.verifyScope(tokenContext, OAuth2Scope.MATCH_INFO);
spans = spans != null ? spans : false;
highlights = highlights != null ? highlights : false;
if (layers == null || layers.isEmpty()) layers = new HashSet<>();
- String results = searchService.retrieveMatchInfo(corpusId, docId,
- textId, matchId, foundries, tokenContext.getUsername(), headers,
- layers, spans, highlights);
- return Response.ok(results).build();
+ try{
+ String results = searchService.retrieveMatchInfo(corpusId, docId,
+ textId, matchId, foundries, tokenContext.getUsername(),
+ headers, layers, spans, highlights);
+ return Response.ok(results).build();
+ }
+ catch (KustvaktException e) {
+ throw kustvaktResponseHandler.throwit(e);
+ }
+
}
/*
@@ -197,12 +223,21 @@
@GET
@Path("{version}/corpus/{corpusId}/{docId}/{textId}")
public Response getMetadata (@PathParam("corpusId") String corpusId,
- @PathParam("docId") String docId, @PathParam("textId") String textId
- // @QueryParam("fields") Set<String> fields
+ @PathParam("docId") String docId,
+ @PathParam("textId") String textId,
+ @Context SecurityContext ctx,
+ @Context HttpHeaders headers
+ // @QueryParam("fields") Set<String> fields
) throws KustvaktException {
- String results =
- searchService.retrieveDocMetadata(corpusId, docId, textId);
- return Response.ok(results).build();
+ TokenContext tokenContext = (TokenContext) ctx.getUserPrincipal();
+ try {
+ String results = searchService.retrieveDocMetadata(corpusId, docId,
+ textId, tokenContext.getUsername(), headers);
+ return Response.ok(results).build();
+ }
+ catch (KustvaktException e) {
+ throw kustvaktResponseHandler.throwit(e);
+ }
}
@POST