diff --git a/server/build.gradle b/server/build.gradle index 85d7791..2e25a29 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -20,6 +20,8 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.security:spring-security-crypto:6.3.3' + implementation 'org.bouncycastle:bcprov-jdk15on:1.70' runtimeOnly 'org.postgresql:postgresql' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' diff --git a/server/src/main/java/com/mixel/docusphere/controller/UserController.java b/server/src/main/java/com/mixel/docusphere/controller/UserController.java index 75b1428..b029682 100644 --- a/server/src/main/java/com/mixel/docusphere/controller/UserController.java +++ b/server/src/main/java/com/mixel/docusphere/controller/UserController.java @@ -35,30 +35,13 @@ public class UserController { @PostMapping public User createUser(@RequestBody UserDTO userDTO) { - User user = new User(); - user.setUsername(userDTO.getUsername()); - user.setName(userDTO.getName()); - user.setEmail(userDTO.getEmail()); - user.setPasswordHash(userDTO.getPassword()); - return userService.save(user); + return userService.save(userDTO); } - // FIXME: Use DTO instead of entity @PutMapping("/{id}") - public ResponseEntity updateUser(@PathVariable UUID id, @RequestBody User userDetails) { - Optional user = userService.findById(id); - if (user.isPresent()) { - User updatedUser = user.get(); - updatedUser.setUsername(userDetails.getUsername()); - updatedUser.setName(userDetails.getName()); - updatedUser.setEmail(userDetails.getEmail()); - updatedUser.setPasswordHash(userDetails.getPasswordHash()); - updatedUser.setPasswordSalt(userDetails.getPasswordSalt()); - userService.save(updatedUser); - return ResponseEntity.ok(updatedUser); - } else { - return ResponseEntity.notFound().build(); - } + public ResponseEntity updateUser(@PathVariable UUID id, @RequestBody UserDTO userDTO) { + Optional updatedUser = userService.update(id, userDTO); + return updatedUser.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build()); } @DeleteMapping("/{id}") diff --git a/server/src/main/java/com/mixel/docusphere/service/UserService.java b/server/src/main/java/com/mixel/docusphere/service/UserService.java index 4a9845a..980a3b1 100644 --- a/server/src/main/java/com/mixel/docusphere/service/UserService.java +++ b/server/src/main/java/com/mixel/docusphere/service/UserService.java @@ -1,8 +1,10 @@ package com.mixel.docusphere.service; +import com.mixel.docusphere.dto.UserDTO; import com.mixel.docusphere.entity.User; import com.mixel.docusphere.repository.UserRepository; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.argon2.Argon2PasswordEncoder; +import org.springframework.security.crypto.keygen.KeyGenerators; import org.springframework.stereotype.Service; import java.util.List; @@ -12,8 +14,16 @@ import java.util.UUID; @Service public class UserService { - @Autowired - private UserRepository userRepository; + private final UserRepository userRepository; + + // init argon2 + private final Argon2PasswordEncoder passwordEncoder; + + // Constructor + public UserService(UserRepository userRepository) { + this.passwordEncoder = new Argon2PasswordEncoder(16, 32, 1, 4096, 3); + this.userRepository = userRepository; + } public List findAll() { return userRepository.findAll(); @@ -23,10 +33,39 @@ public class UserService { return userRepository.findById(id); } - public User save(User user) { + public User save(UserDTO userDTO) { + User user = new User(); + user.setUsername(userDTO.getUsername()); + user.setName(userDTO.getName()); + user.setEmail(userDTO.getEmail()); + + isPasswordAlreadySet(userDTO, user); return userRepository.save(user); } + public Optional update(UUID id, UserDTO userDTO){ + Optional userOptional = userRepository.findById(id); + if (userOptional.isPresent()) { + User user = userOptional.get(); + user.setUsername(userDTO.getUsername()); + user.setName(userDTO.getName()); + user.setEmail(userDTO.getEmail()); + + isPasswordAlreadySet(userDTO, user); + return Optional.of(userRepository.save(user)); + } + return Optional.empty(); + } + + private void isPasswordAlreadySet(UserDTO userDTO, User user) { + if (userDTO.getPassword() != null && !userDTO.getPassword().isEmpty()) { + final String salt = KeyGenerators.string().generateKey(); + user.setPasswordSalt(salt); + final String saltedPassword = salt + userDTO.getPassword(); + user.setPasswordHash(passwordEncoder.encode(saltedPassword)); + } + } + public void deleteById(UUID id) { userRepository.deleteById(id); }