Skip to content

Commit e6ce0ba

Browse files
committed
Ref #25533: Test provided parameter validation
1 parent 460786c commit e6ce0ba

9 files changed

Lines changed: 262 additions & 27 deletions

File tree

src/main/java/eu/openanalytics/containerproxy/api/ProxyController.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import javax.inject.Inject;
2929

30+
import eu.openanalytics.containerproxy.service.InvalidParametersException;
3031
import org.springframework.http.HttpStatus;
3132
import org.springframework.http.MediaType;
3233
import org.springframework.http.ResponseEntity;
@@ -77,7 +78,7 @@ public ResponseEntity<Proxy> getProxy(@PathVariable String proxyId) {
7778
}
7879

7980
@RequestMapping(value="/api/proxy/{proxySpecId}", method=RequestMethod.POST, produces=MediaType.APPLICATION_JSON_VALUE)
80-
public ResponseEntity<Proxy> startProxy(@PathVariable String proxySpecId) {
81+
public ResponseEntity<Proxy> startProxy(@PathVariable String proxySpecId) throws InvalidParametersException {
8182
ProxySpec baseSpec = proxyService.findProxySpec(s -> s.getId().equals(proxySpecId), false);
8283
if (baseSpec == null) return new ResponseEntity<>(HttpStatus.NOT_FOUND);
8384

src/main/java/eu/openanalytics/containerproxy/model/runtime/ProvidedParameters.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,33 @@
2020
*/
2121
package eu.openanalytics.containerproxy.model.runtime;
2222

23+
import com.fasterxml.jackson.annotation.JsonCreator;
24+
2325
import java.util.HashMap;
2426
import java.util.Map;
2527

26-
public class ProvidedParameters extends HashMap<String, String> {
28+
public class ProvidedParameters {
29+
30+
private final Map<String, String> map;
31+
32+
@JsonCreator
33+
public ProvidedParameters(Map<String, String> map) {
34+
this.map = map;
35+
}
36+
37+
public ProvidedParameters() {
38+
this.map = new HashMap<>();
39+
}
40+
41+
public int size() {
42+
return map.size();
43+
}
44+
45+
public boolean containsParameter(String parameterId) {
46+
return map.containsKey(parameterId);
47+
}
48+
49+
public String getValue(String parameterId) {
50+
return map.get(parameterId);
51+
}
2752
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* ContainerProxy
3+
*
4+
* Copyright (C) 2016-2021 Open Analytics
5+
*
6+
* ===========================================================================
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the Apache License as published by
10+
* The Apache Software Foundation, either version 2 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* Apache License for more details.
17+
*
18+
* You should have received a copy of the Apache License
19+
* along with this program. If not, see <http://www.apache.org/licenses/>
20+
*/
21+
package eu.openanalytics.containerproxy.service;
22+
23+
public class InvalidParametersException extends Exception {
24+
25+
private final String error;
26+
27+
public InvalidParametersException(String error) {
28+
super(error);
29+
this.error = error;
30+
}
31+
32+
public String getError() {
33+
return error;
34+
}
35+
}

src/main/java/eu/openanalytics/containerproxy/service/ParametersService.java

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ private void validateSpec(ProxySpec spec) {
5959
return;
6060
}
6161

62+
// TODO validate parameter id
63+
6264
// Validate Parameter Definitions
6365
HashSet<String> parameterIds = new HashSet<>();
6466
for (ParameterDefinition definition : spec.getParameters().getDefinitions()) {
@@ -98,41 +100,45 @@ private void validateSpec(ProxySpec spec) {
98100

99101
}
100102

101-
public ProvidedParameters parseAndValidateRequest(ProxySpec resolvedSpec, ProvidedParameters providedParameters) {
103+
public boolean validateRequest(ProxySpec resolvedSpec, ProvidedParameters providedParameters) throws InvalidParametersException {
102104
Parameters parameters = resolvedSpec.getParameters();
103105
if (parameters == null) {
104-
return new ProvidedParameters();
106+
return false;
105107
}
106108

107-
// check if all keys are provided
108-
// TODO check if no other keys are provided
109-
for (String key : parameters.getIds()) {
110-
if (!providedParameters.containsKey(key)) {
111-
throw new IllegalArgumentException("Provided User Parameters does not contain key " + key);
112-
}
109+
// check if correct number of parameters is provided
110+
if (providedParameters.size() != parameters.getIds().size()) {
111+
throw new InvalidParametersException("Invalid number of parameters provided");
113112
}
114113

115-
// TODO
116-
for (Map<String, List<String>> values : parameters.getValues()) {
117-
if (isAllowedValue(values, providedParameters)) {
118-
return providedParameters;
114+
// check if all parameter ids are provided
115+
for (String parameterId : parameters.getIds()) {
116+
if (!providedParameters.containsParameter(parameterId)) {
117+
throw new InvalidParametersException("Missing value for parameter " + parameterId);
119118
}
120119
}
121120

122-
throw new IllegalArgumentException("Provided User Parameters is not allowed");
121+
// check if the combination of values is allowed
122+
for (Map<String, List<String>> valueSet : parameters.getValues()) {
123+
if (areParametersAllowedByValueSet(valueSet, providedParameters)) {
124+
return true; // parameters are allowed
125+
}
126+
}
123127

128+
throw new InvalidParametersException("Provided parameter values are not allowed");
124129
}
125130

126-
public boolean isAllowedValue(Map<String, List<String>> values, ProvidedParameters providedParameters) {
127-
for (Map.Entry<String, List<String>> keyWithValue : values.entrySet()) {
128-
if (!providedParameters.containsKey(keyWithValue.getKey())) {
129-
return false; // TODO check above that all keys present and no other additional keys
131+
private boolean areParametersAllowedByValueSet(Map<String, List<String>> valueSet, ProvidedParameters providedParameters) {
132+
for (Map.Entry<String, List<String>> keyWithValues : valueSet.entrySet()) {
133+
if (!providedParameters.containsParameter(keyWithValues.getKey())) {
134+
throw new IllegalStateException("Could not find value for key " + keyWithValues.getKey());
130135
}
131-
String providedValue = providedParameters.get(keyWithValue.getKey());
132-
if (!keyWithValue.getValue().contains(providedValue)) {
136+
String providedValue = providedParameters.getValue(keyWithValues.getKey());
137+
if (!keyWithValues.getValue().contains(providedValue)) {
133138
return false;
134139
}
135140
}
141+
// providedParameters contains an allowed value for every parameter
136142
return true;
137143
}
138144

src/main/java/eu/openanalytics/containerproxy/service/ProxyService.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import java.util.Collections;
2828
import java.util.List;
2929
import java.util.Map.Entry;
30-
import java.util.Set;
3130
import java.util.UUID;
3231
import java.util.concurrent.ExecutorService;
3332
import java.util.concurrent.Executors;
@@ -234,7 +233,7 @@ public List<Proxy> getProxiesOfCurrentUser(Predicate<Proxy> filter) {
234233
* @return The newly launched proxy.
235234
* @throws ContainerProxyException If the proxy fails to start for any reason.
236235
*/
237-
public Proxy startProxy(ProxySpec spec, boolean ignoreAccessControl) throws ContainerProxyException {
236+
public Proxy startProxy(ProxySpec spec, boolean ignoreAccessControl) throws ContainerProxyException, InvalidParametersException {
238237
return startProxy(spec, ignoreAccessControl, null, UUID.randomUUID().toString(), null);
239238
}
240239

@@ -247,7 +246,7 @@ public Proxy startProxy(ProxySpec spec, boolean ignoreAccessControl) throws Cont
247246
* @return The newly launched proxy.
248247
* @throws ContainerProxyException If the proxy fails to start for any reason.
249248
*/
250-
public Proxy startProxy(ProxySpec spec, boolean ignoreAccessControl, List<RuntimeValue> runtimeValues, String proxyId, ProvidedParameters parameters) throws ContainerProxyException {
249+
public Proxy startProxy(ProxySpec spec, boolean ignoreAccessControl, List<RuntimeValue> runtimeValues, String proxyId, ProvidedParameters parameters) throws ContainerProxyException, InvalidParametersException {
251250
if (!ignoreAccessControl && !userService.canAccess(spec)) {
252251
throw new AccessDeniedException(String.format("Cannot start proxy %s: access denied", spec.getId()));
253252
}
@@ -261,7 +260,9 @@ public Proxy startProxy(ProxySpec spec, boolean ignoreAccessControl, List<Runtim
261260
proxy.addRuntimeValues(runtimeValues);
262261
}
263262
if (parameters != null) {
264-
proxy.addRuntimeValue(new RuntimeValue(ParametersKey.inst, parametersService.parseAndValidateRequest(spec, parameters)));
263+
if (parametersService.validateRequest(spec, parameters)) {
264+
proxy.addRuntimeValue(new RuntimeValue(ParametersKey.inst, parameters));
265+
}
265266
}
266267

267268
activeProxies.add(proxy);

src/test/java/eu/openanalytics/containerproxy/test/proxy/TestProxyService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import javax.inject.Inject;
2626

27+
import eu.openanalytics.containerproxy.service.InvalidParametersException;
2728
import eu.openanalytics.containerproxy.service.UserService;
2829
import org.junit.jupiter.api.Test;
2930
import org.junit.jupiter.api.extension.ExtendWith;
@@ -56,7 +57,7 @@ public class TestProxyService {
5657
private ProxyService proxyService;
5758

5859
@Test
59-
public void launchProxy() {
60+
public void launchProxy() throws InvalidParametersException {
6061
String specId = environment.getProperty("proxy.specs[0].id");
6162

6263
ProxySpec baseSpec = proxyService.findProxySpec(s -> s.getId().equals(specId), true);

src/test/java/eu/openanalytics/containerproxy/test/unit/TestParameterValidationService.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
/**
2+
* ContainerProxy
3+
*
4+
* Copyright (C) 2016-2021 Open Analytics
5+
*
6+
* ===========================================================================
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the Apache License as published by
10+
* The Apache Software Foundation, either version 2 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* Apache License for more details.
17+
*
18+
* You should have received a copy of the Apache License
19+
* along with this program. If not, see <http://www.apache.org/licenses/>
20+
*/
121
package eu.openanalytics.containerproxy.test.unit;
222

323
import eu.openanalytics.containerproxy.ContainerProxyApplication;

0 commit comments

Comments
 (0)