Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 9e82bc8a

Přidáno uživatelem Jiri Trefil před téměř 2 roky(ů)

#10517 repository a controller + service vytvořena. Chybí dodělat verifikace uživ parametrů a různé corner cases.

Zobrazit rozdíly:

pom.xml
124 124
			<version>${org.junit.jupiter.version}</version>
125 125
			<scope>test</scope>
126 126
		</dependency>
127

  
128 127
		<!-- json library with minimal overhead -->
129 128
		<dependency>
130 129
			<groupId>com.googlecode.json-simple</groupId>
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/controller/ConfigurationController.java
1 1
package cz.zcu.fav.kiv.antipatterndetectionapp.v2.controller;
2 2

  
3
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.Configuration;
4
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.User;
5
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.UserConfigKey;
6
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.UserConfiguration;
7
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository.UserConfigurationRepository;
3
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.*;
4
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository.ConfigRepository;
5
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository.UserConfigurationJoinRepository;
6
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.service.ConfigurationService;
8 7
import org.springframework.beans.factory.annotation.Autowired;
9
import org.springframework.web.bind.annotation.GetMapping;
10
import org.springframework.web.bind.annotation.RequestMapping;
11
import org.springframework.web.bind.annotation.RestController;
8
import org.springframework.http.ResponseEntity;
9
import org.springframework.web.bind.annotation.*;
10

  
11
import java.util.List;
12 12

  
13 13
/**
14 14
 * @Author Jiri Trefil
......
18 18
@RequestMapping("v2/configuration")
19 19
public class ConfigurationController {
20 20
    @Autowired
21
    private UserConfigurationRepository userConfigurationRepository ;
21
    private ConfigurationService configurationService;
22

  
23
    @PostMapping(value="/upload_configuration")
24
    public ResponseEntity<String> test(@RequestBody UserConfiguration userConfiguration) {
25
        ResponseEntity<String> response = configurationService.addConfiguration(userConfiguration);
22 26

  
23
    @GetMapping(value="/test")
24
    public String test(){
25
        UserConfigKey key = new UserConfigKey(1,1);
26
        UserConfiguration tmp = userConfigurationRepository.save(new UserConfiguration(key));
27
        return "test";
27
        return null;
28 28
    }
29 29

  
30
    @GetMapping(value="/get_configuration")
31
    public ResponseEntity<String> getUserConfigurations(@RequestParam(name="name") String userName){
32
        User user = new User(userName);
33
        ResponseEntity<String> response = this.configurationService.getUserConfigurations(user);
34
        return response;
35
    }
36

  
37

  
30 38

  
31 39

  
32 40

  
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/model/Configuration.java
3 3
import javax.persistence.*;
4 4

  
5 5
@Entity
6
@Table(name="configuration")
6
@Table(name="configurations")
7 7
public class Configuration {
8 8
    @Id
9 9
    @GeneratedValue(strategy = GenerationType.IDENTITY)
......
13 13
    //hash of the configuration so users cant upload duplicates
14 14
    private String configHash;
15 15
    // 'Y' if the configuration is accessible to everyone, 'N' if its user defined
16
    private char isDefault;
16
    private String isDefault;
17 17

  
18 18
    public Configuration(){}
19
    public Configuration(String config, String configHash, boolean isDefault){
19
    public Configuration(String config, String configHash, String isDefault){
20 20
        this.config = config;
21 21
        this.configHash = configHash;
22
        this.isDefault = isDefault?'Y':'N';
22
        this.isDefault = isDefault;
23 23
    }
24 24

  
25
    public Configuration(int id){
26
        this.id = id;
27
    }
28

  
29
    public Configuration(String config, String isDefault){
30
        this.config = config;
31
        this.configHash = null;
32
        this.isDefault = isDefault;
33
    }
25 34

  
26 35
    public int getId() {
27 36
        return id;
......
35 44
        return configHash;
36 45
    }
37 46

  
38
    public char getIsDefault() {
47
    public String getIsDefault() {
39 48
        return isDefault;
40 49
    }
50

  
51

  
52
    public void setHash(String hash){
53
        this.configHash = hash;
54
    }
55

  
56

  
41 57
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/model/User.java
55 55
        this.name = name;
56 56
        this.token = token;
57 57
    }
58

  
58
    public User(String name){
59
        this.name = name;
60
    }
59 61
    public User(String name, String email, String password){
60 62
        this.name = name;
61 63
        this.email = email;
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/model/UserConfigKey.java
3 3
import javax.persistence.Embeddable;
4 4
import java.io.Serializable;
5 5

  
6
/**
7
 * @Author Jiri Trefil
8
 * primary key of table user_configuration is compound (userId,configurationId) pair is unique
9
 * @Deprecated not being used (29.04.2023)
10
 * the business logic involving this table is in ConfigurationRepository interface
11
 */
6 12
@Embeddable
7 13
public class UserConfigKey implements Serializable {
8 14

  
......
14 20
    this.configId = configId;
15 21
}
16 22

  
23
    public int getUserId() {
24
        return userId;
25
    }
26

  
27
    public int getConfigId() {
28
        return configId;
29
    }
30

  
31
    public void setUserId(int userId) {
32
        this.userId = userId;
33
    }
34

  
35
    public void setConfigId(int configId) {
36
        this.configId = configId;
37
    }
17 38

  
18 39
    public UserConfigKey() {
19 40

  
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/model/UserConfiguration.java
1 1
package cz.zcu.fav.kiv.antipatterndetectionapp.v2.model;
2 2

  
3
import javax.persistence.*;
4
import java.io.Serializable;
5 3

  
6 4
/**
7
 * @Author Jiri Trefil
8
 * Join table between user and configuration
9
 * One user can have multiple (or none) configurations associated with him
10
 * One configuration can have associated multiple users
11
 * there this Many:Many relationship has to be decomposed with this table
12
 * Primary key is a Composite key (userId+configId is always a unique pair)
5
 * @author Jiri Trefil
6
 * Wrapper for http request for uploading a new configuration by user
13 7
 */
14
@Entity
15
@Table(name="user_configurations")
16 8
public class UserConfiguration {
17
    @EmbeddedId
18
    private UserConfigKey id;
9
    private User user;
10
    private Configuration configuration;
19 11

  
20 12

  
21
    public UserConfiguration(){
13
    public UserConfiguration(User user, Configuration configuration){
14
        this.user = user;
15
        this.configuration = configuration;
22 16
    }
17
    public UserConfiguration(){}
23 18

  
24
    public UserConfiguration(UserConfigKey id){
25
        this.id = id;
19

  
20
    public User getUser() {
21
        return user;
22
    }
23

  
24
    public Configuration getConfiguration() {
25
        return configuration;
26 26
    }
27
    public UserConfigKey getUserConfigKey(){
28
        return this.id;
27

  
28
    public void setUser(User user) {
29
        this.user = user;
30
    }
31

  
32
    public void setConfiguration(Configuration configuration) {
33
        this.configuration = configuration;
29 34
    }
30 35
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/model/UserConfigurationJoin.java
1
package cz.zcu.fav.kiv.antipatterndetectionapp.v2.model;
2

  
3
import javax.persistence.*;
4

  
5
/**
6
 * @Author Jiri Trefil
7
 * Join table between user and configuration
8
 * One user can have multiple (or none) configurations associated with him
9
 * One configuration can have associated multiple users
10
 * there this Many:Many relationship has to be decomposed with this table
11
 * Primary key is a Composite key (userId+configId is always a unique pair)
12
 */
13
@Entity
14
@Table(name="user_configurations")
15
public class UserConfigurationJoin {
16
    @EmbeddedId
17
    private UserConfigKey id;
18

  
19

  
20
    public UserConfigurationJoin(){
21
    }
22

  
23
    public UserConfigurationJoin(UserConfigKey id){
24
        this.id = id;
25
    }
26
    public UserConfigKey getUserConfigKey(){
27
        return this.id;
28
    }
29
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/repository/ConfigRepository.java
1
package cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository;
2

  
3
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.Configuration;
4
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.UserConfigKey;
5
import org.springframework.data.jpa.repository.JpaRepository;
6
import org.springframework.data.jpa.repository.Modifying;
7
import org.springframework.data.jpa.repository.Query;
8
import org.springframework.stereotype.Repository;
9

  
10
import java.util.List;
11
@Repository
12
public interface ConfigRepository extends JpaRepository<Configuration,Integer> {
13
    Configuration findConfigurationById(int id);
14
    Configuration findConfigurationByConfigHash(String hash);
15
    //query to get all public configurations
16
    @Query("Select config from Configuration config where config.isDefault = 'Y'")
17
    List<Configuration> getPublicConfigurations();
18
    //retrieve all public configurations and configurations available to the user
19
    //assumption - default configurations are not assigned to any user explicitly
20
    @Query("select config from Configuration config where config.isDefault = 'Y' " +
21
            "or config.id in (select userconfig.id.userId from UserConfigurationJoin userconfig where userconfig.id.userId = ?1)")
22
    List<Configuration> getAllUserConfigurations(int userId);
23

  
24

  
25
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/repository/UserConfigurationJoinRepository.java
1
package cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository;
2

  
3
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.UserConfigKey;
4
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.UserConfigurationJoin;
5
import org.springframework.data.jpa.repository.JpaRepository;
6

  
7
/**
8
 * this repository is not being used (29.04.2023)
9
 * but it provides and API to work with Join table user_configurations
10
 * the logic is contained in ConfigurationRepository interface (the pairing of user and configuration)
11
 */
12
public interface UserConfigurationJoinRepository extends JpaRepository<UserConfigurationJoin, UserConfigKey> {
13
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/repository/UserConfigurationRepository.java
1
package cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository;
2

  
3
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.UserConfigKey;
4
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.UserConfiguration;
5
import org.springframework.data.jpa.repository.JpaRepository;
6

  
7
public interface UserConfigurationRepository extends JpaRepository<UserConfiguration, UserConfigKey> {
8
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/JwtAuthenticationFilter.java
1 1
package cz.zcu.fav.kiv.antipatterndetectionapp.v2.security;
2

  
3
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.httpExceptions.CustomExceptionHandler;
4 2
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.service.OAuthService;
5
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.utils.JSONBuilder;
6
import org.json.simple.JSONObject;
7
import org.json.simple.parser.ParseException;
8 3
import org.springframework.http.*;
9 4
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
10 5
import org.springframework.security.core.Authentication;
......
37 32

  
38 33
        String authorizationHeader = request.getHeader("Authorization");
39 34
        if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
40
//            chain.doFilter(request, response);
41 35
            SecurityContextHolder.clearContext();
42 36
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
43 37
            response.getOutputStream().println("{\"error\" : \"Some other error related to jwt token!\"}");
......
56 50

  
57 51
                Authentication auth = new UsernamePasswordAuthenticationToken(userDetails, token, userDetails.getAuthorities());
58 52
                SecurityContextHolder.getContext().setAuthentication(auth);
59
    /*
60
            else {
61
                SecurityContextHolder.clearContext();
62
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
63
                response.getOutputStream().println("{\"error\" : \"Token timed out!\"}");
64
                return;
65
            }*/
66 53
        }
67 54
        //4xx or 5xx http response from auth application
68 55
        //basically copies the response from auth app and send it to client
......
79 66
    }
80 67

  
81 68
    @Override
82
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
69
    protected boolean shouldNotFilter(HttpServletRequest request) {
83 70
            String path = request.getRequestURI().substring(request.getContextPath().length());
84 71
        return path.startsWith("/v2/user/login") || path.startsWith("/v2/user/register");
85 72
    }
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/security/WebSecurityConfig.java
16 16
import org.springframework.security.core.userdetails.UserDetailsService;
17 17
import org.springframework.security.web.SecurityFilterChain;
18 18
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
19
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
19 20
import org.springframework.web.client.RestTemplate;
20 21
import org.springframework.web.cors.CorsConfiguration;
21 22
import org.springframework.web.cors.CorsConfigurationSource;
......
70 71
    @Override
71 72
    protected void configure(HttpSecurity httpSecurity) throws Exception {
72 73
        httpSecurity
74
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
73 75
                .cors().configurationSource(corsConfigurationSource())
74 76
                .and()
75 77
                .csrf().disable()
76 78
                .authorizeRequests()
77
                .mvcMatchers("/v2/user/register", "/v2/user/login", "/v2/user/refresh", "/v2/user/logout","/v2/configuration//test").permitAll()
79
                .mvcMatchers("/v2/user/register", "/v2/user/login", "/v2/user/refresh", "/v2/user/logout","/v2/configuration//get_configuration","v2/configuration/upload_configuration").permitAll()
78 80
                .anyRequest().authenticated()
79 81
                .and()
80 82
                .sessionManagement()
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigurationService.java
1
package cz.zcu.fav.kiv.antipatterndetectionapp.v2.service;
2
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.Configuration;
3
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.User;
4
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.UserConfiguration;
5
import org.springframework.http.ResponseEntity;
6

  
7
public interface ConfigurationService {
8
    //upload configuration
9
    ResponseEntity<String> addConfiguration(Configuration cfg);
10
    ResponseEntity<String> addConfiguration(UserConfiguration cfg);
11

  
12
    ResponseEntity<String> pairConfigurationWithUser(User user, Configuration configuration);
13
    //get all configurations available to user
14
    ResponseEntity<String> getUserConfigurations(User user);
15

  
16

  
17

  
18

  
19

  
20

  
21
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/ConfigurationServiceImplementation.java
1
package cz.zcu.fav.kiv.antipatterndetectionapp.v2.service;
2

  
3
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.*;
4
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository.ConfigRepository;
5
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository.UserConfigurationJoinRepository;
6
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository.UserRepository;
7
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.utils.Crypto;
8
import org.springframework.beans.factory.annotation.Autowired;
9
import org.springframework.http.ResponseEntity;
10
import org.springframework.stereotype.Service;
11

  
12
import java.util.List;
13

  
14
@Service
15
public class ConfigurationServiceImplementation implements ConfigurationService{
16

  
17
    @Autowired
18
    private ConfigRepository configurationRepository;
19
    @Autowired
20
    private UserConfigurationJoinRepository userConfigurationJoinRepository;
21

  
22
    @Autowired
23
    private UserService userService;
24
    /**
25
     * Saves configuration to database
26
     * the configuration is default to everyone
27
     * @param cfg Configuration - JSON format of configuration with antipatterns and thresholds
28
     * @return ResponseEntity with status code and message with more information about operation
29
     */
30
    @Override
31
    public ResponseEntity<String> addConfiguration(Configuration cfg) {
32
        return null;
33
    }
34
    /**
35
     * Saves configuration to database
36
     * the configuration is available to the user who sent the request
37
     * @param cfg Configuration - JSON format of configuration with antipatterns and thresholds
38
     * @return ResponseEntity with status code and message with more information about operation
39
     */
40
    @Override
41
    public ResponseEntity<String> addConfiguration(UserConfiguration cfg) {
42
        User user = cfg.getUser();
43
        Configuration configuration = cfg.getConfiguration();
44

  
45
        String userName = user.getName();
46
        user = this.userService.getUserByName(userName);
47
        String configurationDefinition = configuration.getConfig();
48
        if(configurationDefinition == null){
49
            //todo konfigurace neni poslana, chyba requestu
50

  
51
        }
52
        String configHash = Crypto.hashString(configurationDefinition);
53
        Configuration existingConfiguration = this.configurationRepository.findConfigurationByConfigHash(configHash);
54
        //configuration definition does not exist => upload the configuration into database
55
        if(existingConfiguration == null){
56
            configuration.setHash(configHash);
57
            //save the configuration itself
58
            Configuration tmp = this.configurationRepository.save(configuration);
59
            if(tmp == null){
60
                //todo selhal insert do databaze
61
            }
62
        }
63

  
64
        //pair the configuration to the user
65
        return pairConfigurationWithUser(user,configuration);
66

  
67

  
68
    }
69

  
70
    @Override
71
    public ResponseEntity<String> pairConfigurationWithUser(User user, Configuration configuration) {
72
        final UserConfigKey key = new UserConfigKey(user.getId(),configuration.getId());
73
        boolean exists = this.userConfigurationJoinRepository.existsById(key);
74
        if(exists){
75
            //todo uzivatel se chce sparovat s konfiguraci se kterou je jiz sparovan, jenom poslat ok nebo error
76
        }
77
        //save the relation between user and configuration
78
        this.userConfigurationJoinRepository.save(new UserConfigurationJoin(key));
79
        return null;
80
    }
81

  
82
    @Override
83
    public ResponseEntity<String> getUserConfigurations(User user) {
84
        final String userName = user.getName();
85
        //client can only send his name - he obviously does not know his id in db, we have to query that
86
        User userInfo = this.userService.getUserByName(userName);
87
        //fetch all configurations this particular user can see
88
        //ie all public configs + configurations uploaded by this particular user
89
        List<Configuration> configurations = this.configurationRepository.getAllUserConfigurations(userInfo.getId());
90
        return null;
91
    }
92
}
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/service/UserServiceImpl.java
3 3
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.dials.UserModelStatusCodes;
4 4
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.model.User;
5 5
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.repository.UserRepository;
6
import cz.zcu.fav.kiv.antipatterndetectionapp.v2.utils.Crypto;
6 7
import org.springframework.beans.factory.annotation.Autowired;
7 8
import org.springframework.stereotype.Service;
8 9

  
......
46 47
            return UserModelStatusCodes.USER_EXISTS;
47 48
        }
48 49

  
49
        String passwordHash = hashPassword(password);
50
        String passwordHash = Crypto.hashString(password);
50 51
        //server side fault
51 52
        if (passwordHash == null) {
52 53
            return UserModelStatusCodes.HASH_FAILED;
......
83 84
        return emailPattern.matcher(email).find();
84 85
    }
85 86

  
86
    /**
87
     * Method to hash password
88
     * @param password  password from client
89
     * @return          hashed password for database
90
     */
91
    public String hashPassword(String password) {
92
        //standard java security encryption module
93
        MessageDigest digest = null;
94
        try {
95
            //try to instance the class - throws an error if algorithm
96
            digest = MessageDigest.getInstance("SHA3-256");
97
        }
98
        catch(NoSuchAlgorithmException exception){
99
            exception.printStackTrace();
100
            return null;
101
        }
102
        byte [] tmp = digest.digest(password.getBytes(StandardCharsets.UTF_8));
103
        //convert byte array into string
104
        return (new HexBinaryAdapter()).marshal(tmp);
105
    }
87

  
106 88

  
107 89
    /**
108 90
     * Method
......
125 107
        if (u == null) {
126 108
            return UserModelStatusCodes.USER_LOGIN_FAILED;
127 109
        }
128
        final boolean passwordMatches = comparePassword(password,u.getPassword());
110
        final boolean passwordMatches = Crypto.compareHashes(password, u.getPassword());
129 111

  
130 112
        return (!passwordMatches ? UserModelStatusCodes.USER_LOGIN_FAILED : UserModelStatusCodes.USER_LOGGED_IN);
131 113
    }
132 114

  
133
    /**
134
     * Method compares user password with stored hash
135
     * @param password String user provided password
136
     * @param hash String hash saved in database
137
     * @return true if hashes are the same
138
     */
139
    boolean comparePassword(String password, String hash) {
140
        final String passwordHash = this.hashPassword(password);
141
        return hash.equals(passwordHash);
142
    }
115

  
143 116

  
144 117
    @Override
145 118
    public User getUserByName(String name) {
src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/v2/utils/Crypto.java
1
package cz.zcu.fav.kiv.antipatterndetectionapp.v2.utils;
2

  
3
import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
4
import java.nio.charset.StandardCharsets;
5
import java.security.MessageDigest;
6
import java.security.NoSuchAlgorithmException;
7

  
8
public class Crypto {
9

  
10
    /**
11
     * Method to hash password
12
     * @param password  password from client
13
     * @return          hashed password for database
14
     */
15
    public static String hashString(String password) {
16
        //standard java security encryption module
17
        MessageDigest digest = null;
18
        try {
19
            //try to instance the class - throws an error if algorithm
20
            digest = MessageDigest.getInstance("SHA3-256");
21
        }
22
        catch(NoSuchAlgorithmException exception){
23
            exception.printStackTrace();
24
            return null;
25
        }
26
        byte [] tmp = digest.digest(password.getBytes(StandardCharsets.UTF_8));
27
        //convert byte array into string
28
        return (new HexBinaryAdapter()).marshal(tmp);
29
    }
30

  
31
    /**
32
     * Method compares user password with stored hash
33
     * @param password String user provided password
34
     * @param hash String hash saved in database
35
     * @return true if hashes are the same
36
     */
37
    public static boolean compareHashes(String password, String hash) {
38
        final String passwordHash = hashString(password);
39
        return hash.equals(passwordHash);
40
    }
41

  
42

  
43
}

Také k dispozici: Unified diff