import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.onap.ccsdk.features.sdnr.wt.dataprovider.model.HtUserdataManager;
@Override
public String getUserdata(String username, String key) {
+ final String EMPTY_JSON_OBJECT = "{}";
JSONObject o = new JSONObject(this.getUserdata(username));
- return o.has(key) ? o.get(key).toString() : "{}";
+ if(key==null || !key.contains("."))
+ return o.has(key) ? o.get(key).toString() : EMPTY_JSON_OBJECT;
+ final String[] keys = key.split("\\.");
+ Object tmp;
+ for (int i=0;i<keys.length-1;i++){
+ if(!o.has(keys[i])){
+ return EMPTY_JSON_OBJECT;
+ }
+ tmp = o.get(keys[i]);
+ if(!(tmp instanceof JSONObject)) {
+ return EMPTY_JSON_OBJECT;
+ }
+ o = (JSONObject)tmp;
+ }
+ tmp= o.has(keys[keys.length-1])? o.get(keys[keys.length-1]):EMPTY_JSON_OBJECT;
+ if(tmp instanceof JSONObject){
+ return ((JSONObject)tmp).toString();
+ }
+ if(tmp instanceof JSONArray){
+ return ((JSONArray)tmp).toString();
+ }
+ if( tmp instanceof String){
+ return String.format("\"%s\"",tmp);
+ }
+ return String.valueOf(tmp);
}
@Override
public boolean setUserdata(String username, String key, String data) {
+ if(key == null || data == null){
+ return false;
+ }
JSONObject o = new JSONObject(this.getUserdata(username));
- o.put(key, new JSONObject(data));
+ if(!key.contains(".")) {
+ o.put(key, new JSONObject(data));
+ }
+ else{
+ final String[] keys = key.split("\\.");
+ JSONObject tmp = o;
+ Object tmpObject;
+ for(int i=0;i<keys.length-1;i++){
+ if(!tmp.has(keys[i])){
+ tmp.put(keys[i], new JSONObject());
+ }
+ tmpObject = tmp.get(keys[i]);
+ if(!(tmpObject instanceof JSONObject)){
+ return false;
+ }
+ tmp = (JSONObject) tmpObject;
+ }
+ if(data.startsWith("{")){
+ tmp.put(keys[keys.length-1], new JSONObject(data));
+ }
+ else if (data.startsWith("[")){
+ tmp.put(keys[keys.length-1], new JSONArray(data));
+ }
+ else if(data.startsWith("\"") && data.endsWith("\"")){
+ tmp.put(keys[keys.length-1],data.substring(1,data.length()-1));
+ }
+ else if("true".equals(data) || "false".equals(data)){
+ tmp.put(keys[keys.length-1],"true".equals(data));
+ }
+ else {
+ try {
+ tmp.put(keys[keys.length - 1], Double.parseDouble(data));
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+ }
return this.setUserdata(username, o.toString());
}
@Override
public boolean removeUserdata(String username, String key) {
+ if(key == null){
+ return false;
+ }
JSONObject o = new JSONObject(this.getUserdata(username));
- if (o.has(key)) {
- o.remove(key);
+ if(!key.contains(".")) {
+ if (o.has(key)) {
+ o.remove(key);
+ return this.setUserdata(username, o.toString());
+ }
+ }
+ else {
+ final String[] keys = key.split("\\.");
+ JSONObject tmp = o;
+ Object tmpObject;
+ for(int i=0;i<keys.length-1;i++){
+ if(!tmp.has(keys[i])){
+ return false;
+ }
+ tmpObject = tmp.get(keys[i]);
+ if(!(tmpObject instanceof JSONObject)){
+ return false;
+ }
+ tmp = (JSONObject) tmpObject;
+ }
+ if(!tmp.has(keys[keys.length-1])){
+ return false;
+ }
+ tmp.remove(keys[keys.length-1]);
return this.setUserdata(username, o.toString());
+
}
- return true;
+ return false;
}
protected static JSONObject mergeData(JSONObject o, String key, JSONObject subObject) {
+++ /dev/null
-[mariadb]
-url=${SDNRDBURL}
-username=${SDNRDBUSERNAME}
-password=${SDNRDBPASSWORD}
-controllerId=null
-suffix=
-
~ ============LICENSE_END=======================================================
~
-->
+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<application.name>sdnr-wt-data-provider</application.name>
<include.transitive.dependencies>false</include.transitive.dependencies>
</properties>
-
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>installed-odl-bom</artifactId>
+ <version>2.6.0</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(UserdataHttpServlet.class);
- private static final String REGEX = "^\\/userdata[\\/]?([a-zA-Z0-9]+)?$";
+ private static final String REGEX = "^\\/userdata[\\/]?([a-zA-Z0-9\\.]+)?$";
private static final Pattern PATTERN = Pattern.compile(REGEX);
private static final String JWT_PAYLOAD_USERNAME_PROPERTYKEY = "sub";
private static HtUserdataManager dbUserManager;
*/
package org.onap.ccsdk.features.sdnr.wt.dataprovider.test;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import java.io.IOException;
import org.apache.sshd.common.util.io.IoUtils;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import org.junit.BeforeClass;
import org.junit.Test;
import org.onap.ccsdk.features.sdnr.wt.common.database.HtDatabaseClient;
public class TestUserdata {
private static final String USERNAME = "admin132";
+ private static final String USERNAME2 = "admin133";
+
private static HtDatabaseClient dbRawProvider;
private static HtUserdataManagerImpl userDbProvider;
HostInfo[] hosts = HostInfoForTest.get();
dbRawProvider = HtDatabaseClient.getClient(hosts);
userDbProvider = new HtUserdataManagerImpl(dbRawProvider);
+
}
public static void trySleep(long ms) {
JSONAssert.assertEquals(mergedContent, userdata, false);
}
+ @Test
+ public void test2() {
+ String fullContent = "";
+ boolean success = false;
+ try {
+ fullContent = getFileContent("/userdata/full.json");
+ success = userDbProvider.setUserdata(USERNAME2, fullContent);
+ } catch (IOException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ assertTrue("problem writing data into db",success);
+
+ trySleep(2000);
+ // read with complex key
+ String userdata = userDbProvider.getUserdata(USERNAME2, "networkMap.styling");
+ JSONAssert.assertEquals("{\"theme\": \"dark\"}", userdata, false);
+ userdata = userDbProvider.getUserdata(USERNAME2, "networkMap.startupPosition.longitude");
+ assertEquals("\"13.35\"", userdata);
+ userdata = userDbProvider.getUserdata(USERNAME2, "networkMap.tileOpacity");
+ assertEquals("\"26\"", userdata);
+
+ // write with complex key => forbidden
+ success = userDbProvider.setUserdata(USERNAME2,"networkMap.styling.theme",null);
+ assertFalse(success);
+ success = userDbProvider.setUserdata(USERNAME2,"networkMap.themes.key","\"abc\"");
+ assertFalse(success);
+ // write with complex key => allowed
+ success = userDbProvider.setUserdata(USERNAME2,"networkMap.styling.theme","\"test\"");
+ assertTrue(success);
+ userdata = userDbProvider.getUserdata(USERNAME2, "networkMap.styling.theme");
+ assertEquals("\"test\"",userdata);
+ success = userDbProvider.setUserdata(USERNAME2,"networkMap.styling.theme","{\"test\":\"abc\"}");
+ assertTrue(success);
+ userdata = userDbProvider.getUserdata(USERNAME2, "networkMap.styling.theme");
+ assertEquals("{\"test\":\"abc\"}",userdata);
+
+ // delete with complex key => forbidden
+ success = userDbProvider.removeUserdata(USERNAME2,"networkMap.styling.theme2");
+ assertFalse(success);
+ // delete with complex key => allowed
+ success = userDbProvider.removeUserdata(USERNAME2,"networkMap.styling.theme");
+ assertTrue(success);
+ userdata = userDbProvider.getUserdata(USERNAME2, "networkMap.styling");
+ assertEquals("{}",userdata);
+
+
+ }
+
private static String getFileContent(String filename) throws IOException {
return String.join("\n", IoUtils.readAllLines(TestUserdata.class.getResourceAsStream(filename)));
}
"zoom": "10",
"longitude": "13.35"
},
+ "themes": [
+ {
+ "key": "light",
+ "padding": 10,
+ "mainColor": "#ff0000"
+ }
+ ],
"tileOpacity": "26"
}
}
\ No newline at end of file
*/
public class DatabaseInfo7 extends DatabaseInfo {
+ private boolean disableMapping;
+
public DatabaseInfo7(String alias, String doctype, String mapping) {
super(alias, alias, doctype, mapping);
+ this.disableMapping = false;
}
public DatabaseInfo7(String alias, String doctype, String mapping, String settingsformat) {
super(alias, alias, doctype, mapping, settingsformat);
+ this.disableMapping = false;
}
public DatabaseInfo7(String index, String alias, String doctype, String mapping, String settingsformat) {
super(index, alias, doctype, mapping, settingsformat);
+ this.disableMapping = false;
}
@Override
public String getMapping(boolean useStrict) {
+ if(this.disableMapping){
+ return "{\"enabled\": false}";
+ }
return this.mapping == null ? null
: String.format("{%s\"properties\":%s}", useStrict ? "\"dynamic\": false," : "\"dynamic\": true,",
this.mapping);
}
+
+ public DatabaseInfo disableMapping() {
+ this.disableMapping = true;
+ return this;
+ }
}
public static Map<ComponentName, DatabaseInfo> createDBMap() {
Map<ComponentName, DatabaseInfo> map = HonoluluReleaseInformation.createDBMap();
- map.put(ComponentName.USERDATA, new DatabaseInfo7("userdata", "userdata", "{}"));
+ map.put(ComponentName.USERDATA, new DatabaseInfo7("userdata", "userdata", "").disableMapping());
map.put(ComponentName.REQUIRED_NETWORKELEMENT, new DatabaseInfo7("networkelement-connection",
"networkelement-connection",
"{\"node-id\": {\"type\": \"keyword\"},\"host\": {\"type\": \"keyword\"},\"port\": "