Skip to content
Snippets Groups Projects
Commit bb821c5f authored by Birk Øvstetun Narvhus's avatar Birk Øvstetun Narvhus
Browse files

Merge branch 'feature/165-add-update-user-endpoint' into 'main'

Resolve "Add update user endpoint"

Closes #165

See merge request idatt2106-v23-03/backend!124
parents cf9d2dac 6b1e0667
No related branches found
No related tags found
No related merge requests found
......@@ -5,14 +5,17 @@ import lombok.AllArgsConstructor;
import ntnu.idatt2016.v233.SmartMat.dto.request.AllergyRequest;
import ntnu.idatt2016.v233.SmartMat.dto.request.RegisterUserRequest;
import ntnu.idatt2016.v233.SmartMat.dto.enums.Authority;
import ntnu.idatt2016.v233.SmartMat.dto.request.UpdateUserRequest;
import ntnu.idatt2016.v233.SmartMat.entity.user.User;
import ntnu.idatt2016.v233.SmartMat.service.user.UserService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Optional;
/**
......@@ -102,4 +105,70 @@ public class UserController {
.map(user -> ResponseEntity.ok(user.getAllergies().size() > 0))
.orElseGet(() -> ResponseEntity.notFound().build());
}
/**
* Update a user in the database.
* @param username The username of the user to be updated.
* @param updateUser The new values for the user.
* @param authentication The authentication object of the user.
* @return The updated user.
*/
@PutMapping("/update/{username}")
public ResponseEntity<User> updateUser(@PathVariable String username, @RequestBody UpdateUserRequest updateUser,
Authentication authentication) {
if(!username.equals(authentication.getName()))
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
Optional<User> user = userService.getUserFromUsername(username);
if(user.isEmpty())
return ResponseEntity.notFound().build();
User userEntity = user.get();
if(updateUser.firstName() != null &&
!updateUser.firstName().trim().isEmpty() && updateUser.firstName().length() <= 50){
userEntity.setFirstName(updateUser.firstName());
}
if(updateUser.lastName() != null &&
!updateUser.lastName().trim().isEmpty() && updateUser.lastName().length() <= 50){
userEntity.setLastName(updateUser.lastName());
}
if(updateUser.email() != null &&
!updateUser.email().trim().isEmpty() && updateUser.email().length() <= 50){
userEntity.setEmail(updateUser.email());
}
if(updateUser.password() != null &&
!updateUser.password().trim().isEmpty() && updateUser.password().length() <= 50){
userEntity.setPassword(passwordEncoder.encode(updateUser.password()));
}
if(updateUser.birthDate() != null){
userEntity.setDateOfBirth(updateUser.birthDate());
}
if(updateUser.allergies() != null){
userEntity.getAllergies().stream().filter(allergy -> !updateUser.allergies().contains(allergy.getName()))
.forEach(allergy -> userService.removeAllergyFromUser(username, allergy.getName()));
updateUser.allergies().stream().filter(allergy -> userEntity.getAllergies().stream()
.noneMatch(allergy1 -> allergy1.getName().equals(allergy))).forEach(
allergy -> userService.addAllergyToUser(username, allergy)
);
}
userService.updateUser(userEntity);
userEntity.setPassword(null);
return ResponseEntity.ok(userEntity);
}
}
\ No newline at end of file
package ntnu.idatt2016.v233.SmartMat.dto.request;
import java.sql.Date;
import java.util.List;
/**
* This class represents a request to update a user
* @author Birk
* @version 1.0
* @since 26.04.2023
*
* @param firstName the first name of the user
* @param lastName the last name of the user
* @param email the email of the user
* @param password the password of the user
* @param birthDate the birth date of the user
* @param allergies the allergies of the user
*/
public record UpdateUserRequest(String firstName, String lastName,
String email, String password, Date birthDate,
List<String> allergies) {
}
......@@ -4,10 +4,7 @@ package ntnu.idatt2016.v233.SmartMat.entity.user;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.*;
import ntnu.idatt2016.v233.SmartMat.dto.enums.Authority;
import ntnu.idatt2016.v233.SmartMat.entity.Recipe;
import ntnu.idatt2016.v233.SmartMat.entity.group.UserGroupAsso;
......@@ -31,6 +28,7 @@ import java.util.*;
@Data
@NoArgsConstructor
@EqualsAndHashCode
@AllArgsConstructor
@Entity(name = "users")
@Builder
......
......@@ -173,4 +173,25 @@ public class UserService {
}
return Optional.empty();
}
/**
* Removes allergy from user
* @param username username of user
* @param allergyName name of allergy
* @return user with removed allergy
*/
public Optional<User> removeAllergyFromUser(String username, String allergyName){
Optional<User> user = userRepository.findByUsername(username);
Optional<Allergy> allergy = allergyRepository.findByName(allergyName);
if (user.isPresent() && allergy.isPresent()){
user.get().getAllergies().remove(allergy.get());
return Optional.of(userRepository.save(user.get()));
} else if (user.isEmpty()) {
throw new EntityNotFoundException("User not found");
} else if (allergy.isEmpty()) {
throw new EntityNotFoundException("Allergy not found");
}
return Optional.empty();
}
}
\ No newline at end of file
package ntnu.idatt2016.v233.SmartMat.controller.user;
import ntnu.idatt2016.v233.SmartMat.dto.request.RegisterUserRequest;
import ntnu.idatt2016.v233.SmartMat.dto.request.UpdateUserRequest;
import ntnu.idatt2016.v233.SmartMat.entity.user.User;
import ntnu.idatt2016.v233.SmartMat.repository.user.UserRepository;
import ntnu.idatt2016.v233.SmartMat.service.user.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.sql.Date;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UserControllerTest {
......@@ -25,6 +35,30 @@ class UserControllerTest {
@Autowired
private UserRepository userRepository;
@Mock
private UserService userService;
@Mock
private PasswordEncoder passwordEncoder;
@InjectMocks
private UserController userController;
private UpdateUserRequest updateUser;
private Authentication authentication;
@BeforeEach
public void setup() {
updateUser = new UpdateUserRequest(
"John", "Doe", "johndoe@example.com", "newPassword123",
Date.valueOf("1980-01-01"), List.of("Peanut", "Lactose")
);
authentication = mock(Authentication.class);
}
@Test
void registerUser_validRequest_shouldReturnCreatedUser() {
// Arrange
......@@ -54,4 +88,39 @@ class UserControllerTest {
assertTrue(userOptional.isPresent());
}
@Test
public void testUpdateUserWithValidUsernameAndRequestBodyReturnsOk() {
// Arrange
String username = "johndoe";
User user = new User();
user.setUsername(username);
user.setFirstName("John");
user.setLastName("Doe");
user.setEmail("johndoe@example.com");
user.setPassword("oldPassword123");
user.setAllergies(new ArrayList<>());
user.setDateOfBirth(Date.valueOf("1980-01-01"));
when(authentication.getName()).thenReturn(username);
when(userService.getUserFromUsername(username)).thenReturn(Optional.of(user));
when(passwordEncoder.encode(updateUser.password())).thenReturn("encodedPassword");
when(userService.updateUser(user)).thenReturn(user);
// Act
ResponseEntity<User> response = userController.updateUser(username, updateUser, authentication);
// Assert
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
assertEquals("John", response.getBody().getFirstName());
assertEquals("Doe", response.getBody().getLastName());
assertEquals("johndoe@example.com", response.getBody().getEmail());
assertNull(response.getBody().getPassword());
assertEquals(Date.valueOf("1980-01-01"), response.getBody().getDateOfBirth());
verify(userService, times(1)).updateUser(user);
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment