commit d5b85831dd68dd0ebe4352368f2b12bb983555e6
Author: Jiri Trefil <badjokke@gmail.com>
Date:   Sun Apr 30 10:36:48 2023 +0200

    #10517 repository a controller + service vytvořena.

diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/controller/ConfigurationController.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/controller/ConfigurationController.java
index ad6c5d2..fa7d339 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/controller/ConfigurationController.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/controller/ConfigurationController.java
@@ -23,8 +23,7 @@ public class ConfigurationController {
     @PostMapping(value="/upload_configuration")
     public ResponseEntity<String> test(@RequestBody UserConfiguration userConfiguration) {
         ResponseEntity<String> response = configurationService.addConfiguration(userConfiguration);
-
-        return null;
+        return response;
     }
 
     @GetMapping(value="/get_configuration")
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigurationServiceImplementation.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigurationServiceImplementation.java
index 6d59654..2e28b4b 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigurationServiceImplementation.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigurationServiceImplementation.java
@@ -3,22 +3,26 @@ package cz.zcu.fav.kiv.antipatterndetectionapp.v2.service;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.*;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository.ConfigRepository;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository.UserConfigurationJoinRepository;
-import cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository.UserRepository;
 import cz.zcu.fav.kiv.antipatterndetectionapp.v2.utils.Crypto;
+import cz.zcu.fav.kiv.antipatterndetectionapp.v2.utils.JSONBuilder;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 @Service
 public class ConfigurationServiceImplementation implements ConfigurationService{
-
+    //repository which represents connection to database and the configuration table in particular
     @Autowired
     private ConfigRepository configurationRepository;
+    //repository for Join table, necessary to add associations between users and configurations
     @Autowired
     private UserConfigurationJoinRepository userConfigurationJoinRepository;
-
+    //user service is also necessary for retrieving information about users (primarily database query for fetching id)
     @Autowired
     private UserService userService;
     /**
@@ -42,13 +46,18 @@ public class ConfigurationServiceImplementation implements ConfigurationService{
         User user = cfg.getUser();
         Configuration configuration = cfg.getConfiguration();
 
+        Map<String,Object> json = new HashMap<>();
         String userName = user.getName();
+        //fetch the user from db because user in UserConfiguration does not contain id
         user = this.userService.getUserByName(userName);
         String configurationDefinition = configuration.getConfig();
+        //if the request is missing the configuration definition then we kill it
         if(configurationDefinition == null){
-            //todo konfigurace neni poslana, chyba requestu
-
+            json.put("message","no configuration definition provided.");
+            String jsonString = JSONBuilder.buildJSON(json);
+            return new ResponseEntity<>(jsonString,HttpStatus.BAD_REQUEST);
         }
+        //create the hash of the configuration (w/o salting)
         String configHash = Crypto.hashString(configurationDefinition);
         Configuration existingConfiguration = this.configurationRepository.findConfigurationByConfigHash(configHash);
         //configuration definition does not exist => upload the configuration into database
@@ -56,27 +65,44 @@ public class ConfigurationServiceImplementation implements ConfigurationService{
             configuration.setHash(configHash);
             //save the configuration itself
             Configuration tmp = this.configurationRepository.save(configuration);
+            //can only happen if db server fails or a constraint is breached
             if(tmp == null){
-                //todo selhal insert do databaze
+                json.put("message","fatal server failure");
+                return new ResponseEntity<>(JSONBuilder.buildJSON(json),HttpStatus.INTERNAL_SERVER_ERROR);
             }
         }
-
         //pair the configuration to the user
-        return pairConfigurationWithUser(user,configuration);
+        pairConfigurationWithUser(user,configuration);
+        json.put("message","configuration uploaded successfully");
+        return new ResponseEntity<>(JSONBuilder.buildJSON(json),HttpStatus.OK);
 
 
     }
 
+    /**
+     * This method saves user and configuration id into join table
+     * creates association between user and configuration in the sense of: "User @param user owns configuration @param configuration"
+     * (Multiple users can own the same configuration but the configuration is not public)
+     * @param user User - user who will be associated with configuration @param configuration.
+     * @param configuration Configuration - the configuration that will be associated with user (just the id is necessary)
+     * @return ResponseEntity<String> - Http response with status code and message about the operation
+     */
     @Override
     public ResponseEntity<String> pairConfigurationWithUser(User user, Configuration configuration) {
+        Map<String,Object> json = new HashMap<>();
         final UserConfigKey key = new UserConfigKey(user.getId(),configuration.getId());
         boolean exists = this.userConfigurationJoinRepository.existsById(key);
+        //the configuration pairing already exists, we do not have to do anything
+        //request like this should not happen from client, something fishy might be going on
+        //or the request is a duplicate
         if(exists){
-            //todo uzivatel se chce sparovat s konfiguraci se kterou je jiz sparovan, jenom poslat ok nebo error
+            json.put("message","configuration already exists in your collection!");
+            return new ResponseEntity<>(JSONBuilder.buildJSON(json),HttpStatus.BAD_REQUEST);
         }
         //save the relation between user and configuration
         this.userConfigurationJoinRepository.save(new UserConfigurationJoin(key));
-        return null;
+        json.put("message","configuration added to collection.");
+        return new ResponseEntity<>(JSONBuilder.buildJSON(json),HttpStatus.OK);
     }
 
     @Override
@@ -87,6 +113,14 @@ public class ConfigurationServiceImplementation implements ConfigurationService{
         //fetch all configurations this particular user can see
         //ie all public configs + configurations uploaded by this particular user
         List<Configuration> configurations = this.configurationRepository.getAllUserConfigurations(userInfo.getId());
-        return null;
+        StringBuilder sb = new StringBuilder();
+        for(int i = 0; i < configurations.size(); i++){
+            sb.append(configurations.get(i).getConfig());
+        }
+        Map<String,Object> json = new HashMap<>();
+        json.put("message","configuration retrived");
+        json.put("configurations",sb.toString());
+        String jsonString = JSONBuilder.buildJSON(json);
+        return new ResponseEntity<>(jsonString,HttpStatus.OK);
     }
 }
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/Crypto.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/Crypto.java
index 181a48d..4e470f7 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/Crypto.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/Crypto.java
@@ -4,9 +4,11 @@ import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
-
+import java.util.Random;
+//TODO should probably be replaced by some third party encryption lib in the future
 public class Crypto {
-
+    protected static final int SALT_LEN = 32;
+    protected static final int PASS_LEN = 64;
     /**
      * Method to hash password
      * @param password  password from client
@@ -28,6 +30,26 @@ public class Crypto {
         return (new HexBinaryAdapter()).marshal(tmp);
     }
 
+    /**
+     * Hash string and add salt to the end
+     * prevention against rainbow table attacks
+     * @param password String to be hashed
+     * @return String salted hash of the input
+     */
+    public static String hashStringSalt(String password){
+        String hash = hashString(password);
+        Random r = new Random();
+        StringBuffer sb = new StringBuffer();
+        while(sb.length() < SALT_LEN){
+            sb.append(Integer.toHexString(r.nextInt()));
+        }
+        String salt = sb.substring(0,SALT_LEN);
+        hash += salt;
+        return hash;
+    }
+
+
+
     /**
      * Method compares user password with stored hash
      * @param password String user provided password
@@ -39,5 +61,17 @@ public class Crypto {
         return hash.equals(passwordHash);
     }
 
+    /**
+     * Method compares user password with stored hash with salt
+     * @param password String user provided password
+     * @param hash String hash saved in database
+     * @return true if hashes are the same
+     */
+    public static boolean compareHashesSalt(String password, String hash){
+        //toss the salt aside
+        String strippedHash = hash.substring(0,PASS_LEN);
+        return compareHashes(password,strippedHash);
+    }
+
 
 }
