diff --git a/src/main/java/com/tecnalia/urbanite/anonymize/AnonymizerAPI.java b/src/main/java/com/tecnalia/urbanite/anonymize/rest/AnonymizerAPI.java similarity index 54% rename from src/main/java/com/tecnalia/urbanite/anonymize/AnonymizerAPI.java rename to src/main/java/com/tecnalia/urbanite/anonymize/rest/AnonymizerAPI.java index c4036e7ff5f955a356d2dfc5d11c1a48ee5a8ee7..51290deb7fc0d7608da2e98bd72dd4a471e78aac 100644 --- a/src/main/java/com/tecnalia/urbanite/anonymize/AnonymizerAPI.java +++ b/src/main/java/com/tecnalia/urbanite/anonymize/rest/AnonymizerAPI.java @@ -13,16 +13,19 @@ * Initially developed in the context of URBANITE EU project * www.urbanite-project.eu */ -package com.tecnalia.urbanite.anonymize; +package com.tecnalia.urbanite.anonymize.rest; -import org.springframework.http.HttpStatus; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; +import com.tecnalia.urbanite.anonymize.service.AnonymizerService; + import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; @@ -31,27 +34,22 @@ import io.swagger.v3.oas.annotations.tags.Tag; @Tag(name = "Anonymize", description = "Operations to Anonymize Data") public class AnonymizerAPI { + @Autowired + AnonymizerService anonymizerService; - @RequestMapping(method = RequestMethod.POST, value = "/anonymize/{user}") + @RequestMapping(method = RequestMethod.POST, value = "/anonymize/{city}/{model}/{property}/{value}") @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Successful operation."), - @ApiResponse(responseCode = "400", description = "Bad request.")}) - @Operation(summary = "Anonimize user", description = "Change name of user for hash.") - public ResponseEntity<String> anonymizeUser(@PathVariable int user ) throws Exception { - try { + @ApiResponse(responseCode = "400", description = "Bad request. (User unknow)")}) + @Operation(summary = "Anonymize property that has certain value", description = "Change the value {value} of the {property} for a hash.") + public ResponseEntity<String> anonymizeUser( + @Parameter(description = "City where is the model to be anonymized", example = "bilbao") @PathVariable String city, + @Parameter(description = "Model that is going to be anonymized.", example = "vehicle") @PathVariable String model, + @Parameter(description = "Property of the model that is going to be anonymized.", example = "name") @PathVariable String property, + @Parameter(description = "Only the properties with this value are going to be modified.", example = "Jonh") @PathVariable String value) throws Exception { + + return anonymizerService.anonymizeProperty(city,model,property,value); - boolean respuesta = true; - if (respuesta ) { - - - return new ResponseEntity<>("User anonymizied successfully !!", HttpStatus.OK); - } else { - return new ResponseEntity<>("User not anonymizied", HttpStatus.INTERNAL_SERVER_ERROR); - } - - } catch (Exception e) { - return new ResponseEntity<>("Error while anonymizig:" + user + ". Please try again !! " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); - } } } diff --git a/src/main/java/com/tecnalia/urbanite/anonymize/service/AnonymizerService.java b/src/main/java/com/tecnalia/urbanite/anonymize/service/AnonymizerService.java new file mode 100644 index 0000000000000000000000000000000000000000..b70a552c09097a67277737669d697cc172ed13fc --- /dev/null +++ b/src/main/java/com/tecnalia/urbanite/anonymize/service/AnonymizerService.java @@ -0,0 +1,69 @@ +package com.tecnalia.urbanite.anonymize.service; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.security.NoSuchAlgorithmException; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import com.tecnalia.urbanite.anonymize.utils.Crypto; + +@Service +public class AnonymizerService { + + @Autowired + DataService dataService; + + + public ResponseEntity<String> anonymizeProperty (String city,String model, String property, String valueToAnonimize) { + + try { + JSONArray objects = dataService.getObjectsByName(property,valueToAnonimize, model, city); + if (objects == null || objects.length() ==0) { + return new ResponseEntity<>("User not found !!", HttpStatus.BAD_REQUEST); + } + else { + + for (int i=0; i < objects.length();i++) { + JSONObject object = objects.getJSONObject(i); + String propertyAnonimizied = Crypto.generateHash((String) object.get(property)); + object.put(property, propertyAnonimizied); + JSONObject result = dataService.updateObjects(object, model, city,object.getString("id")); + + if (result.has("Error")) { + return new ResponseEntity<>("Error while anonymizig:" + property + ". Please try again !!\n " + result.getString("Error"), HttpStatus.INTERNAL_SERVER_ERROR); + } + else { + System.out.println(result.toString()); + } + + } + } + return new ResponseEntity<>("User anonymizied successfully !!\n", HttpStatus.OK); + + } catch (JSONException e) { + e.printStackTrace(); + return new ResponseEntity<>("Error while anonymizig:" + property + ". Please try again !! " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (URISyntaxException e) { + + e.printStackTrace(); + return new ResponseEntity<>("Error while anonymizig:" + property + ". Please try again !! " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (IOException e) { + e.printStackTrace(); + return new ResponseEntity<>("Error while anonymizig:" + property + ". Please try again !! " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (InterruptedException e) { + e.printStackTrace(); + return new ResponseEntity<>("Error while anonymizig:" + property + ". Please try again !! " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return new ResponseEntity<>("Error while anonymizig:" + property + ". Please try again !! " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); + } + + } +} diff --git a/src/main/java/com/tecnalia/urbanite/anonymize/service/DataService.java b/src/main/java/com/tecnalia/urbanite/anonymize/service/DataService.java new file mode 100644 index 0000000000000000000000000000000000000000..e8dbfcd34e737dbe6045044fad63099649dde63c --- /dev/null +++ b/src/main/java/com/tecnalia/urbanite/anonymize/service/DataService.java @@ -0,0 +1,65 @@ +package com.tecnalia.urbanite.anonymize.service; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.nio.charset.StandardCharsets; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.springframework.stereotype.Service; + +import com.tecnalia.urbanite.anonymize.utils.Configuration; + +@Service +public class DataService { + + public JSONArray getObjectsByName(String property, String value, String model, String city) throws JSONException, URISyntaxException, IOException, InterruptedException { + String URL = Configuration.getExporterUrl(); + //String filter = "%7B%22name%22%3A%20%22"+name+"%22%7D"; + String filter = encode("{\""+property+"\":\""+value+"\"}"); + + //https://bilbao.urbanite.esilab.org/data/getTData/mapLayer/bilbao?filters=%7B%22alternateName%22%3A%20%22test.geojson%22%7D + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI(URL+"/data/getTData/"+model+"/"+city+"?filters="+filter)) + .GET() + .build(); + + HttpResponse<String> response = HttpClient + .newBuilder() + .build() + .send(request, BodyHandlers.ofString()); + return new JSONArray(response.body()); + } + + public JSONObject updateObjects(JSONObject name, String model, String city, String id) throws JSONException, URISyntaxException, IOException, InterruptedException { + String URL = Configuration.getExporterUrl(); + + //http://localhost:8080/data/updateTData/vehicle/bilbao/vehicle%3AWasteManagement%3A1 + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI(URL+"/data/updateTData/"+model+"/"+city+"/"+id)) + .PUT(HttpRequest.BodyPublishers.ofString(name.toString())) + .setHeader("Content-Type", "application/json") + .build(); + + HttpResponse<String> response = HttpClient + .newBuilder() + .build() + .send(request, BodyHandlers.ofString()); + System.out.println(response.body()); + return new JSONObject(response.body()); + } + + + private String encode(String value) throws UnsupportedEncodingException { + + return URLEncoder.encode(value, StandardCharsets.UTF_8.toString()); + } +} diff --git a/src/main/java/com/tecnalia/urbanite/anonymize/utils/Configuration.java b/src/main/java/com/tecnalia/urbanite/anonymize/utils/Configuration.java new file mode 100644 index 0000000000000000000000000000000000000000..8b2005e1efc99cea3b0865881ff4d2baed31aad1 --- /dev/null +++ b/src/main/java/com/tecnalia/urbanite/anonymize/utils/Configuration.java @@ -0,0 +1,10 @@ +package com.tecnalia.urbanite.anonymize.utils; + +public class Configuration { + + public static String getExporterUrl() + { + return System.getenv("DATA_STORAGE_URL") != null ? System.getenv("OPENTSDB_URL") : "http://localhost:8080"; + } + +} diff --git a/src/main/java/com/tecnalia/urbanite/anonymize/utils/Crypto.java b/src/main/java/com/tecnalia/urbanite/anonymize/utils/Crypto.java new file mode 100644 index 0000000000000000000000000000000000000000..c68549ddd007e17d2cb1488bb71aef97718d7b40 --- /dev/null +++ b/src/main/java/com/tecnalia/urbanite/anonymize/utils/Crypto.java @@ -0,0 +1,29 @@ +package com.tecnalia.urbanite.anonymize.utils; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class Crypto { + + + public static String generateHash(String original) throws NoSuchAlgorithmException { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] encodedhash = digest.digest(original.getBytes(StandardCharsets.UTF_8)); + return bytesToHex(encodedhash); + } + + + + private static String bytesToHex(byte[] hash) { + StringBuilder hexString = new StringBuilder(2 * hash.length); + for (int i = 0; i < hash.length; i++) { + String hex = Integer.toHexString(0xff & hash[i]); + if(hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 4d49550045ba9524ef59c29fb86efd755695ab52..3b0eda2c694adfc2f0e9b9606f856d668c02746e 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -3,5 +3,5 @@ application-version=@project.version@ logging.level.org.springframework.boot.autoconfigure=ERROR server.servlet.context-path=/data server.port=80 -logging.level.com.tecnalia.urbanite.storage=DEBUG +logging.level.com.tecnalia.urbanite.anonymize=DEBUG