Skip to content
This repository was archived by the owner on Apr 25, 2023. It is now read-only.

Commit 3955ae6

Browse files
authored
Merge pull request #44 from HumanBrainProject/develop
Develop
2 parents eca8b62 + 5694ae4 commit 3955ae6

File tree

78 files changed

+3407
-2157
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+3407
-2157
lines changed

src/main/java/org/humanbrainproject/knowledgegraph/KgQueryApplication.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,20 @@
55
import org.springframework.beans.factory.annotation.Qualifier;
66
import org.springframework.boot.SpringApplication;
77
import org.springframework.boot.autoconfigure.SpringBootApplication;
8+
import org.springframework.cache.annotation.EnableCaching;
89
import org.springframework.context.annotation.Bean;
910
import org.springframework.context.annotation.ComponentScan;
11+
import org.springframework.scheduling.annotation.EnableAsync;
12+
import org.springframework.scheduling.annotation.EnableScheduling;
1013
import org.springframework.web.context.request.RequestContextListener;
1114

1215

1316
@SpringBootApplication
1417
@ComponentScan("org.humanbrainproject.knowledgegraph")
1518
@NoTests(NoTests.NO_LOGIC)
19+
@EnableCaching
20+
@EnableScheduling
21+
@EnableAsync
1622
public class KgQueryApplication {
1723

1824
public static void main(String[] args) {
@@ -77,4 +83,5 @@ public ArangoConnection createReleasedDb() {
7783
return new ArangoConnection("kg_released", false);
7884
}
7985

86+
8087
}

src/main/java/org/humanbrainproject/knowledgegraph/commons/api/ParameterConstants.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.humanbrainproject.knowledgegraph.commons.api;
22

33
import org.humanbrainproject.knowledgegraph.annotations.NoTests;
4+
import org.humanbrainproject.knowledgegraph.query.entity.fieldFilter.ExampleValues;
45

56
@NoTests(NoTests.NO_LOGIC)
67
public class ParameterConstants {
@@ -34,6 +35,6 @@ public class ParameterConstants {
3435
public static final String RESTRICTED_ORGANIZATION_DOC = "Restrict the results to explicitly defined organizations - the main use case is if a user with broad access permissions wants to simulate restricted read access (e.g. the indexing functionality of the KG search UI)";
3536
public static final String SEARCH_DOC = "A search string checking for instances with names which match this term (includes wildcards)";
3637

37-
public static final String BOUNDING_BOX_DOC = "A minimal bounding box - if defined, only results which are spatially anchored and are part of the given region are returned. Needs to be defined in combination with referenceSpace";
38-
public static final String REFERENCE_SPACE_DOC = "The reference space for the defined minimal bounding box (mbb)";
38+
public static final String BOUNDING_BOX_DOC = "A minimal bounding box - if defined, only results which are spatially anchored and are part of the given region are returned. Follow the pattern \""+ ExampleValues.MBB_EXAMPLE+"\"";
39+
3940
}

src/main/java/org/humanbrainproject/knowledgegraph/commons/authorization/control/AuthorizationContext.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public interface AuthorizationContext {
1818

1919
Set<String> getReadableOrganizations();
2020

21+
Set<String> getReadableOrganizations(Credential credential, List<String> whitelistedOrganizations);
22+
2123
Set<String> getReadableOrganizations(List<String> whitelistedOrganizations);
2224

2325
void populateAuthorizationContext(String authorizationToken);

src/main/java/org/humanbrainproject/knowledgegraph/commons/authorization/control/DefaultAuthorizationContext.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ public Set<String> getReadableOrganizations(){
5555
return authorizationController.getReadableOrganizations(getCredential(), null);
5656
}
5757

58+
@Override
59+
public Set<String> getReadableOrganizations(Credential credential, List<String> whitelistedOrganizations){
60+
return authorizationController.getReadableOrganizations(credential, whitelistedOrganizations);
61+
}
62+
5863
@Override
5964
public Set<String> getReadableOrganizations(List<String> whitelistedOrganizations) {
6065
return authorizationController.getReadableOrganizations(getCredential(), whitelistedOrganizations);

src/main/java/org/humanbrainproject/knowledgegraph/commons/jsonld/control/JsonLdStandardization.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public <T> T filterKeysByVocabBlacklists(T input) {
172172
* @throws IOException
173173
*/
174174
public Map fullyQualify(String jsonPayload) {
175-
return fullyQualify(jsonTransformer.parseToMap(jsonPayload));
175+
return jsonPayload == null ? null : fullyQualify(jsonTransformer.parseToMap(jsonPayload));
176176
}
177177

178178
/**

src/main/java/org/humanbrainproject/knowledgegraph/commons/propertyGraph/arango/control/ArangoInternalRepository.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
import org.humanbrainproject.knowledgegraph.commons.propertyGraph.arango.control.query.ArangoQueryFactory;
1313
import org.humanbrainproject.knowledgegraph.commons.propertyGraph.arango.entity.ArangoCollectionReference;
1414
import org.humanbrainproject.knowledgegraph.commons.propertyGraph.arango.entity.ArangoDocumentReference;
15+
import org.humanbrainproject.knowledgegraph.commons.propertyGraph.arango.exceptions.StoredQueryNotFoundException;
1516
import org.humanbrainproject.knowledgegraph.commons.vocabulary.ArangoVocabulary;
1617
import org.slf4j.Logger;
1718
import org.slf4j.LoggerFactory;
1819
import org.springframework.beans.factory.annotation.Autowired;
1920
import org.springframework.stereotype.Component;
2021

22+
import javax.ws.rs.NotFoundException;
2123
import java.util.List;
2224
import java.util.Map;
2325

@@ -126,4 +128,18 @@ public boolean doesDocumentExist(ArangoCollectionReference collectionReference,
126128
}
127129
return false;
128130
}
131+
132+
public void removeInternalDocument(ArangoDocumentReference document) throws IllegalAccessException, StoredQueryNotFoundException {
133+
String userId = authorizationContext.getUserId();
134+
if(userId==null){
135+
throw new IllegalAccessException("You have to be authenticated if you want to execute this operation");
136+
}
137+
ArangoDatabase db = getDB();
138+
ArangoCollection collection = db.collection(document.getCollection().getName());
139+
if ( collection.exists() && collection.documentExists(document.getKey())) {
140+
collection.deleteDocument(document.getKey());
141+
} else {
142+
throw new StoredQueryNotFoundException("Query not found");
143+
}
144+
}
129145
}

src/main/java/org/humanbrainproject/knowledgegraph/commons/propertyGraph/arango/control/ArangoNativeRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import org.springframework.stereotype.Component;
2222

2323
import java.util.*;
24+
import java.util.regex.Matcher;
25+
import java.util.regex.Pattern;
2426
import java.util.stream.Collectors;
2527

2628
@Component

src/main/java/org/humanbrainproject/knowledgegraph/commons/propertyGraph/arango/control/ArangoToNexusLookupMap.java

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33
import org.humanbrainproject.knowledgegraph.annotations.ToBeTested;
44
import org.humanbrainproject.knowledgegraph.commons.propertyGraph.arango.entity.ArangoCollectionReference;
55
import org.humanbrainproject.knowledgegraph.indexing.entity.nexus.NexusSchemaReference;
6-
import org.humanbrainproject.knowledgegraph.structure.boundary.Structure;
6+
import org.humanbrainproject.knowledgegraph.structure.boundary.StructureFromNexus;
77
import org.slf4j.Logger;
88
import org.slf4j.LoggerFactory;
9-
import org.springframework.beans.factory.InitializingBean;
109
import org.springframework.beans.factory.annotation.Autowired;
11-
import org.springframework.beans.factory.annotation.Value;
1210
import org.springframework.stereotype.Component;
1311

1412
import java.util.Collections;
@@ -17,30 +15,16 @@
1715

1816
@Component
1917
@ToBeTested
20-
public class ArangoToNexusLookupMap implements InitializingBean {
18+
public class ArangoToNexusLookupMap {
2119

2220
@Autowired
23-
Structure structure;
24-
25-
@Value("${org.humanbrainproject.knowledgegraph.cache.populate}")
26-
boolean populateCache = true;
27-
21+
StructureFromNexus structureFromNexus;
2822

2923
protected Logger logger = LoggerFactory.getLogger(ArangoToNexusLookupMap.class);
3024

31-
@Override
32-
public void afterPropertiesSet() {
33-
try {
34-
if(populateCache) {
35-
refetch();
36-
}
37-
}
38-
catch(Exception e){
39-
logger.error("Failed to load schema cache", e);
40-
}
41-
}
42-
4325
private static final Map<String, NexusSchemaReference> schemaReferenceMap = Collections.synchronizedMap(new HashMap<>());
26+
private static boolean initialFetch = false;
27+
4428

4529
public static void addToSchemaReferenceMap(ArangoCollectionReference arangoName, NexusSchemaReference schemaReference){
4630
if(!schemaReferenceMap.containsKey(arangoName.getName())) {
@@ -59,18 +43,18 @@ public synchronized NexusSchemaReference getNexusSchema(ArangoCollectionReferenc
5943
}
6044

6145
private void refetch(){
46+
initialFetch = true;
6247
logger.info("Start fetching schemas - cache population in process");
63-
structure.getAllSchemasInMainSpace().forEach(ArangoCollectionReference::fromNexusSchemaReference);
48+
structureFromNexus.getAllSchemasInMainSpace().forEach(ArangoCollectionReference::fromNexusSchemaReference);
6449
logger.info("Done fetching schemas - the cache is populated");
6550
}
6651

52+
6753
public Map<String, NexusSchemaReference> getLookupTable(boolean refetch){
68-
if(schemaReferenceMap.isEmpty() || refetch){
54+
if(!initialFetch || schemaReferenceMap.isEmpty() || refetch){
6955
refetch();
7056
}
7157
return schemaReferenceMap;
7258
}
7359

74-
75-
7660
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
package org.humanbrainproject.knowledgegraph.commons.propertyGraph.arango.control.aql;
2+
3+
import org.apache.commons.text.StringSubstitutor;
4+
import org.humanbrainproject.knowledgegraph.annotations.NoTests;
5+
import org.humanbrainproject.knowledgegraph.annotations.ToBeTested;
6+
import org.humanbrainproject.knowledgegraph.commons.propertyGraph.arango.entity.ArangoAlias;
7+
import org.humanbrainproject.knowledgegraph.commons.vocabulary.ArangoVocabulary;
8+
9+
import java.util.Arrays;
10+
import java.util.LinkedHashMap;
11+
import java.util.Map;
12+
import java.util.Set;
13+
import java.util.stream.Collectors;
14+
15+
@ToBeTested(easy = true)
16+
public class AQL {
17+
18+
public final String WHITELIST_ALIAS = "whitelist";
19+
20+
final Map<String, String> parameters = new LinkedHashMap<>();
21+
private StringBuilder query = new StringBuilder();
22+
private int indent = 0;
23+
24+
/**
25+
* With applying this method to a string, you state that you have checked, the provided string does not contain any unchecked "dynamic" part (such as user inputs).
26+
*
27+
* The string should consist only of string constants, other trusted values and concatenations out of them. Dynamic parts can be defined with property placeholders - such as ${foo} since they are checked before insertion for their trustworthiness.
28+
*
29+
* Please be careful when executing your checks! Passing non-validated strings to this method can introduce vulnerabilities to the system!!!
30+
*/
31+
public final static TrustedAqlValue trust(String trustedString){
32+
return new TrustedAqlValue(trustedString);
33+
}
34+
35+
36+
@NoTests(NoTests.TRIVIAL)
37+
public AQL indent() {
38+
this.indent++;
39+
return this;
40+
}
41+
42+
@NoTests(NoTests.TRIVIAL)
43+
public AQL outdent() {
44+
this.indent = Math.max(this.indent - 1, 0);
45+
return this;
46+
}
47+
48+
public AQL setParameter(String key, String value) {
49+
setTrustedParameter(key, preventAqlInjection(value));
50+
return this;
51+
}
52+
53+
/**
54+
* Use with caution! The passed parameter will not be further checked for AQL injection but rather immediately added to the query!
55+
*/
56+
public AQL setTrustedParameter(String key, TrustedAqlValue trustedAqlValue) {
57+
parameters.put(key, trustedAqlValue!=null ? trustedAqlValue.getValue() : null);
58+
return this;
59+
}
60+
61+
@NoTests(NoTests.TRIVIAL)
62+
public AQL addLine(TrustedAqlValue queryLine) {
63+
if(queryLine!=null) {
64+
query.append(createIndent());
65+
add(queryLine);
66+
query.append('\n');
67+
}
68+
return this;
69+
}
70+
71+
public AQL add(TrustedAqlValue trustedAqlValue){
72+
if(trustedAqlValue!=null) {
73+
query.append(trustedAqlValue.getValue());
74+
}
75+
return this;
76+
}
77+
78+
public AQL addComma(){
79+
query.append(", ");
80+
return this;
81+
}
82+
83+
84+
public TrustedAqlValue listCollections(Set<String> values) {
85+
return listValuesWithQuote('`', values);
86+
}
87+
88+
public TrustedAqlValue listValues(Set<String> values) {
89+
return listValuesWithQuote('"', values);
90+
}
91+
92+
public TrustedAqlValue listFields(Set<String> values){
93+
return listValuesWithQuote(null, values);
94+
}
95+
96+
97+
private TrustedAqlValue listValuesWithQuote(Character quote, Set<String> values) {
98+
if(values!=null && values.size()>0){
99+
String q = quote!=null ? String.valueOf(quote) : "";
100+
return new TrustedAqlValue(q+String.join(q + "," + q, values.stream().map(v -> preventAqlInjection(v).getValue()).collect(Collectors.toSet()))+q);
101+
}
102+
else{
103+
return new TrustedAqlValue("");
104+
}
105+
}
106+
107+
public TrustedAqlValue preventAqlInjection(String value){
108+
return value!=null ? new TrustedAqlValue(value.replaceAll("[^A-Za-z0-9\\-_:.#/@]", "")) : null;
109+
}
110+
111+
public TrustedAqlValue preventAqlInjectionForSearchQuery(String value){
112+
String f = value.replaceAll("[^\\sA-Za-z0-9\\-_:.#/@]", "");
113+
return new TrustedAqlValue(f);
114+
}
115+
116+
public TrustedAqlValue generateSearchTermQuery(TrustedAqlValue value){
117+
String f = String.join(" ", Arrays.stream(value.getValue().split(" ")).map(el -> String.format("%%%s%%", el.trim().toLowerCase())).collect(Collectors.toList()));
118+
if(f.isEmpty()){
119+
f = "%";
120+
}
121+
return new TrustedAqlValue(f);
122+
}
123+
124+
125+
public TrustedAqlValue build() {
126+
return new TrustedAqlValue(StringSubstitutor.replace(query.toString(), parameters));
127+
}
128+
129+
private String createIndent() {
130+
StringBuilder sb = new StringBuilder();
131+
for (int i = 0; i < this.indent; i++) {
132+
sb.append(" ");
133+
}
134+
return sb.toString();
135+
}
136+
137+
public AQL addDocumentFilter(TrustedAqlValue documentAlias) {
138+
addLine(new TrustedAqlValue("FILTER "+documentAlias.getValue()+" != NULL"));
139+
return this;
140+
}
141+
142+
public AQL addDocumentFilter(ArangoAlias alias){
143+
return addDocumentFilter(preventAqlInjection(alias.getArangoDocName()));
144+
}
145+
public AQL addDocumentFilterWithWhitelistFilter(ArangoAlias alias) {
146+
return addDocumentFilterWithWhitelistFilter(preventAqlInjection(alias.getArangoDocName()));
147+
}
148+
149+
150+
public AQL addDocumentFilterWithWhitelistFilter(TrustedAqlValue documentAlias) {
151+
addDocumentFilter(documentAlias);
152+
addLine(trust("FILTER "+documentAlias.getValue()+"."+ ArangoVocabulary.PERMISSION_GROUP+" IN "+WHITELIST_ALIAS));
153+
return this;
154+
}
155+
}
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
package org.humanbrainproject.knowledgegraph.commons.propertyGraph.arango.control.aql;
22

33
import org.humanbrainproject.knowledgegraph.annotations.ToBeTested;
4+
import org.humanbrainproject.knowledgegraph.commons.vocabulary.ArangoVocabulary;
45

56
import java.util.Set;
67

78
@ToBeTested(easy = true)
8-
public class AuthorizedArangoQuery extends UnauthorizedArangoQuery {
9+
public class AuthorizedArangoQuery extends AQL {
910

10-
public final String WHITELIST_ALIAS = "whitelist";
1111

1212
public AuthorizedArangoQuery(Set<String> permissionGroupsWithReadAccess){
1313
this(permissionGroupsWithReadAccess, false);
1414
}
1515

1616
public AuthorizedArangoQuery(Set<String> permissionGroupsWithReadAccess, boolean subQuery) {
1717
if(!subQuery){
18-
addLine("LET "+WHITELIST_ALIAS+"=[${"+WHITELIST_ALIAS+"}]");
18+
addLine(trust("LET "+WHITELIST_ALIAS+"=[${"+WHITELIST_ALIAS+"}]"));
1919
setTrustedParameter(WHITELIST_ALIAS, listValues(permissionGroupsWithReadAccess));
2020
}
2121
}
2222

2323
@Override
2424
public AuthorizedArangoQuery addDocumentFilter(TrustedAqlValue documentAlias) {
2525
super.addDocumentFilter(documentAlias);
26-
addLine("FILTER "+documentAlias.getValue()+"._permissionGroup IN "+WHITELIST_ALIAS);
26+
addLine(trust("FILTER "+documentAlias.getValue()+"."+ ArangoVocabulary.PERMISSION_GROUP+" IN "+WHITELIST_ALIAS));
2727
return this;
2828
}
2929
}

0 commit comments

Comments
 (0)