Added maximum number of user persistent virtual corpora and queries
Change-Id: I6bbf17ed9cc68203908208c0bc46f81e55fe0d8a
diff --git a/full/Changes b/full/Changes
index 5ca29e5..8c18899 100644
--- a/full/Changes
+++ b/full/Changes
@@ -6,7 +6,11 @@
when it has been included in the authorization request.
- Added tests for VC sharing and for OAuth2 client using VC services
- Added and updated VC controller tests
+<<<<<<< Upstream, based on master
- Moved hibernate.properties
+=======
+- Added maximum number of user persistent virtual corpora and queries
+>>>>>>> 4db5bf8 Added maximum number of user persistent virtual corpora and queries
# version 0.69.4
diff --git a/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java b/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
index 77108d8..175202a 100644
--- a/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
+++ b/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
@@ -82,7 +82,9 @@
private int refreshTokenLongExpiry;
private int refreshTokenExpiry;
private int authorizationCodeExpiry;
-
+
+ private int maxNumberOfUserQueries;
+
private URL issuer;
private URI issuerURI;
private OpenIdConfiguration openidConfig;
@@ -129,13 +131,15 @@
config.setMaxBytesLocalDisk(properties.getProperty("cache.max.bytes.local.disk", "2G"));
jlog.info("max local heap:"+config.getMaxBytesLocalHeapAsString());
jlog.info("max local disk:"+config.getMaxBytesLocalDiskAsString());
+
+ setMaxNumberOfUserQueries(Integer.parseInt(
+ properties.getProperty("max.user.persistent.queries", "20")));
}
private void setSecurityConfiguration (Properties properties) {
setSecureHashAlgorithm(Enum.valueOf(EncryptionIface.Encryption.class,
properties.getProperty("security.secure.hash.algorithm",
"BCRYPT")));
-
}
private void setOpenIdConfiguration (Properties properties)
@@ -685,6 +689,13 @@
public void setCreateInitialSuperClient (boolean initialSuperClient) {
this.createInitialSuperClient = initialSuperClient;
}
-
+
+ public int getMaxNumberOfUserQueries () {
+ return maxNumberOfUserQueries;
+ }
+
+ public void setMaxNumberOfUserQueries (int maxNumberOfUserQueries) {
+ this.maxNumberOfUserQueries = maxNumberOfUserQueries;
+ }
}
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/QueryDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/QueryDao.java
index c8ae459..50d5b98 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/QueryDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/QueryDao.java
@@ -11,6 +11,7 @@
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
+import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
@@ -21,18 +22,18 @@
import org.springframework.transaction.annotation.Transactional;
import de.ids_mannheim.korap.constant.GroupMemberStatus;
+import de.ids_mannheim.korap.constant.QueryAccessStatus;
import de.ids_mannheim.korap.constant.QueryType;
import de.ids_mannheim.korap.constant.ResourceType;
import de.ids_mannheim.korap.constant.UserGroupStatus;
-import de.ids_mannheim.korap.constant.QueryAccessStatus;
+import de.ids_mannheim.korap.entity.QueryAccess;
+import de.ids_mannheim.korap.entity.QueryAccess_;
import de.ids_mannheim.korap.entity.QueryDO;
import de.ids_mannheim.korap.entity.QueryDO_;
import de.ids_mannheim.korap.entity.UserGroup;
import de.ids_mannheim.korap.entity.UserGroupMember;
import de.ids_mannheim.korap.entity.UserGroupMember_;
import de.ids_mannheim.korap.entity.UserGroup_;
-import de.ids_mannheim.korap.entity.QueryAccess;
-import de.ids_mannheim.korap.entity.QueryAccess_;
import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.exceptions.StatusCodes;
import de.ids_mannheim.korap.user.User.CorpusAccess;
@@ -375,4 +376,24 @@
return q.getResultList();
}
+ public Long countNumberOfQuery (String userId, QueryType queryType)
+ throws KustvaktException {
+ ParameterChecker.checkStringValue(userId, "userId");
+ ParameterChecker.checkObjectValue(queryType, "queryType");
+
+ CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+ CriteriaQuery<Long> cq = builder.createQuery(Long.class);
+
+ Root<QueryDO> query = cq.from(QueryDO.class);
+ Predicate conditions = builder.and(
+ builder.equal(query.get(QueryDO_.createdBy), userId),
+ builder.equal(query.get(QueryDO_.queryType), queryType));
+
+ cq.select(builder.count(query));
+ cq.where(conditions);
+
+ TypedQuery<Long> q = entityManager.createQuery(cq);
+ return q.getSingleResult();
+ }
+
}
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/QueryService.java b/full/src/main/java/de/ids_mannheim/korap/service/QueryService.java
index 419f374..8b339ed 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/QueryService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/QueryService.java
@@ -267,25 +267,45 @@
public void storeQuery (QueryJson query, String queryName,
String queryCreator, String username) throws KustvaktException {
- String koralQuery = null;
- if (query.getQueryType().equals(QueryType.VIRTUAL_CORPUS)) {
- ParameterChecker.checkStringValue(query.getCorpusQuery(),
- "corpusQuery");
- koralQuery = serializeCorpusQuery(query.getCorpusQuery());
+ QueryType queryType = query.getQueryType();
+ if (!checkNumberOfQueryLimit(username, queryType)) {
+ String type = queryType.displayName().toLowerCase();
+ throw new KustvaktException(StatusCodes.NOT_ALLOWED,
+ "Cannot create "+type+". The maximum number "
+ + "of "+type+" has been reached.");
}
- else if (query.getQueryType().equals(QueryType.QUERY)) {
- ParameterChecker.checkStringValue(query.getQuery(), "query");
- ParameterChecker.checkStringValue(query.getQueryLanguage(),
- "queryLanguage");
- koralQuery =
- serializeQuery(query.getQuery(), query.getQueryLanguage());
- }
-
+
+ String koralQuery = computeKoralQuery(query);
storeQuery(username, queryName, query.getType(), query.getQueryType(),
koralQuery, query.getDefinition(), query.getDescription(),
query.getStatus(), query.isCached(), queryCreator,
query.getQuery(), query.getQueryLanguage());
}
+
+ private boolean checkNumberOfQueryLimit (String username,
+ QueryType queryType) throws KustvaktException {
+ Long num = queryDao.countNumberOfQuery(username, queryType);
+ if (num < config.getMaxNumberOfUserQueries()) return true;
+ else return false;
+ }
+
+ private String computeKoralQuery (QueryJson query) throws KustvaktException {
+ if (query.getQueryType().equals(QueryType.VIRTUAL_CORPUS)) {
+ ParameterChecker.checkStringValue(query.getCorpusQuery(),
+ "corpusQuery");
+ return serializeCorpusQuery(query.getCorpusQuery());
+ }
+
+ if (query.getQueryType().equals(QueryType.QUERY)) {
+ ParameterChecker.checkStringValue(query.getQuery(), "query");
+ ParameterChecker.checkStringValue(query.getQueryLanguage(),
+ "queryLanguage");
+ return
+ serializeQuery(query.getQuery(), query.getQueryLanguage());
+ }
+
+ return null;
+ }
public void storeQuery (String username, String queryName,
ResourceType type, QueryType queryType, String koralQuery,
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
index 3c67974..4106a7a 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
@@ -381,6 +381,47 @@
"Cannot deserialize value of type `de.ids_mannheim.korap.constant."
+ "ResourceType` from String \"PRIVAT\""));
}
+
+ @Test
+ public void testMaxNumberOfVC () throws KustvaktException {
+ String json = "{\"type\": \"PRIVATE\""
+ + ",\"queryType\": \"VIRTUAL_CORPUS\""
+ + ",\"corpusQuery\": \"corpusSigle=GOE\"}";
+
+ for (int i=1; i<6; i++) {
+ createVC(authHeader,testUser, "new_vc_"+i, json);
+ }
+
+ Response response = target().path(API_VERSION).path("vc")
+ .path("~" + testUser).path("new_vc_6").request()
+ .header(Attributes.AUTHORIZATION, authHeader)
+ .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
+ .put(Entity.json(json));
+
+ assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+ String entity = response.readEntity(String.class);
+ JsonNode node = JsonUtils.readTree(entity);
+
+ assertEquals(StatusCodes.NOT_ALLOWED,
+ node.at("/errors/0/0").asInt());
+ assertEquals("Cannot create virtual corpus. The maximum number of "
+ + "virtual corpus has been reached.",
+ node.at("/errors/0/1").asText());
+
+ // list user VC
+ node = listVC(testUser);
+ assertEquals(6, node.size()); // including 1 system-vc
+
+ // delete new VC
+ for (int i=1; i<6; i++) {
+ deleteVC("new_vc_"+i, testUser, testUser);
+ }
+
+ // list VC
+ node = listVC(testUser);
+ assertEquals(1, node.size()); // system-vc
+ }
@Test
public void testDeleteVC_unauthorized () throws KustvaktException {
diff --git a/full/src/test/resources/kustvakt-test.conf b/full/src/test/resources/kustvakt-test.conf
index 430ad5f..893d04b 100644
--- a/full/src/test/resources/kustvakt-test.conf
+++ b/full/src/test/resources/kustvakt-test.conf
@@ -52,6 +52,9 @@
delete.group = soft
delete.group.member = soft
+# Virtual corpus and queries
+max.user.persistent.queries = 5
+
# Availability regex only support |
# It should be removed/commented when the data doesn't contain availability field.
#