diff --git a/application/model/src/main/java/org/fuseri/model/dto/user/AddressDto.java b/application/model/src/main/java/org/fuseri/model/dto/user/AddressDto.java index 4932d99b8864244383f20aa0312d4d89cd7e08c4..bcbbbe4a3a2280476f47e72ab406052843a67b50 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/user/AddressDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/user/AddressDto.java @@ -1,19 +1,24 @@ package org.fuseri.model.dto.user; +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; @Getter @Setter +@AllArgsConstructor +@NoArgsConstructor public class AddressDto { - + @NotBlank private String country; - + @NotBlank private String city; - + @NotBlank private String street; - + @NotBlank private String houseNumber; - + @NotBlank private String zip; } diff --git a/application/model/src/main/java/org/fuseri/model/dto/user/UserAddLanguageDto.java b/application/model/src/main/java/org/fuseri/model/dto/user/UserAddLanguageDto.java new file mode 100644 index 0000000000000000000000000000000000000000..271ce6435594e1a25946db945556ad8c048943cc --- /dev/null +++ b/application/model/src/main/java/org/fuseri/model/dto/user/UserAddLanguageDto.java @@ -0,0 +1,23 @@ +package org.fuseri.model.dto.user; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import org.fuseri.model.dto.course.LanguageTypeDto; +import org.fuseri.model.dto.course.ProficiencyLevelDto; + +@Getter +@Setter +@AllArgsConstructor +public class UserAddLanguageDto { + + @NotNull + @Valid + LanguageTypeDto language; + + @NotNull + @Valid + ProficiencyLevelDto proficiency; +} diff --git a/application/model/src/main/java/org/fuseri/model/dto/user/UserCreateDto.java b/application/model/src/main/java/org/fuseri/model/dto/user/UserCreateDto.java index ce561102aa302ad7618dc5d123d088fff094d3a9..9be887e9319946ecf9e73f1188e7c94201a1d874 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/user/UserCreateDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/user/UserCreateDto.java @@ -1,22 +1,28 @@ package org.fuseri.model.dto.user; -import org.fuseri.model.dto.common.DomainObjectDto; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; @Getter @Setter -public class UserCreateDto extends DomainObjectDto { +@AllArgsConstructor +public class UserCreateDto { + @NotBlank private String username; - + @NotBlank private String password; - + @NotBlank private String email; - + @NotBlank private String firstName; - + @NotBlank private String lastName; - + @NotNull + @Valid private AddressDto address; } diff --git a/application/model/src/main/java/org/fuseri/model/dto/user/UserDto.java b/application/model/src/main/java/org/fuseri/model/dto/user/UserDto.java index 0e260ede59e0bc86e163bccce46a70ef07ea5a7c..fce12aabfb8baadbeb620c531ffcc84a92c4bb77 100644 --- a/application/model/src/main/java/org/fuseri/model/dto/user/UserDto.java +++ b/application/model/src/main/java/org/fuseri/model/dto/user/UserDto.java @@ -1,5 +1,7 @@ package org.fuseri.model.dto.user; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import org.fuseri.model.dto.common.DomainObjectDto; import lombok.Getter; import lombok.Setter; @@ -7,15 +9,14 @@ import lombok.Setter; @Getter @Setter public class UserDto extends DomainObjectDto { - + @NotBlank private String username; - + @NotBlank private String email; - + @NotBlank private String firstName; - + @NotBlank private String lastName; - private AddressDto address; diff --git a/application/model/src/main/java/org/fuseri/model/dto/user/UserLoginDto.java b/application/model/src/main/java/org/fuseri/model/dto/user/UserLoginDto.java new file mode 100644 index 0000000000000000000000000000000000000000..23972ce45017b07c3507535167952d16dc8ecd15 --- /dev/null +++ b/application/model/src/main/java/org/fuseri/model/dto/user/UserLoginDto.java @@ -0,0 +1,16 @@ +package org.fuseri.model.dto.user; + +import jakarta.validation.constraints.NotBlank; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class UserLoginDto { + @NotBlank + private String username; + @NotBlank + private String password; +} diff --git a/application/module-certificate/src/test/java/org/fuseri/modulecertificate/ModuleCertificateCertificateControllerTests.java b/application/module-certificate/src/test/java/org/fuseri/modulecertificate/ModuleCertificateCertificateControllerTests.java new file mode 100644 index 0000000000000000000000000000000000000000..b6bf1c8694f821b1b4116761894d4566530f237f --- /dev/null +++ b/application/module-certificate/src/test/java/org/fuseri/modulecertificate/ModuleCertificateCertificateControllerTests.java @@ -0,0 +1,66 @@ +package org.fuseri.modulecertificate; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.fuseri.model.dto.certificate.CertificateCreateDto; +import org.fuseri.model.dto.certificate.CertificateDto; +import org.fuseri.model.dto.course.CourseDto; +import org.fuseri.model.dto.course.LanguageTypeDto; +import org.fuseri.model.dto.course.ProficiencyLevelDto; +import org.fuseri.model.dto.user.AddressDto; +import org.fuseri.model.dto.user.UserDto; +import org.fuseri.modulecertificate.service.CertificateController; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + + +@SpringBootTest +@AutoConfigureMockMvc +class ModuleCertificateCertificateControllerTests { + + @Autowired + private MockMvc mockMvc; + + @Autowired + ObjectMapper objectMapper; + + @Test + void generateCertificate() throws Exception { + CertificateDto expectedResponse = new CertificateDto(); + String response = mockMvc.perform(post("/certificates/generate") + .content(asJsonString(new CertificateCreateDto( + new UserDto("novakovat","novakova@gamil.com", "Tereza", + "Nováková", new AddressDto()), + new CourseDto("AJ1", 10, LanguageTypeDto.ENGLISH, ProficiencyLevelDto.A1)))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + CertificateController certificateController = objectMapper.readValue(response, CertificateController.class); + assertThat("response", certificateController.find("0"), is(instanceOf(expectedResponse.getClass()))); + } + + + @Test + void deleteCertificate() throws Exception { + String response = mockMvc.perform(delete("/certificates/delete") + .param("id", "1")) + .andExpect(status().isOk()) + .andReturn().getResponse().getContentAsString(); + } + + public static String asJsonString(final Object obj) { + try { + return new ObjectMapper().writeValueAsString(obj); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/ProficiencyLevel.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/ProficiencyLevel.java index 3446ea5bcbd1d531aadb28582beebe3a1809a276..2e9db45b2c368ce8863dde6f616240d98aeb15ec 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/ProficiencyLevel.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/course/ProficiencyLevel.java @@ -10,7 +10,9 @@ public enum ProficiencyLevel { B1("Intermediate"), B2("Upper Intermediate"), C1("Advanced"), - C2("Proficient"); + C2("Proficient"), + C1N("Advanced Native speaker"), + C2N("Proficient Native speaker"); private final String description; diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/User.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/User.java index 20bc6c413bd44c093bcab07c140fa26b139cbe7f..7b0439da0ed0c77d78ec4f2dcaee7a7511e998e9 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/User.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/User.java @@ -3,6 +3,11 @@ package org.fuseri.modulelanguageschool.user; import org.fuseri.modulelanguageschool.common.DomainObject; import jakarta.persistence.*; import lombok.*; +import org.fuseri.modulelanguageschool.course.Course; +import org.fuseri.modulelanguageschool.course.Language; +import org.fuseri.modulelanguageschool.course.ProficiencyLevel; + +import java.util.List; @Getter @Setter @@ -28,4 +33,6 @@ public class User extends DomainObject { @Embedded private Address address; + private List<Language> languages; + private List<ProficiencyLevel> proficiencyLevels; } diff --git a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserController.java b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserController.java index c134ec30628f1427697d84b91dfca0dd35a7d445..d0c6429b245ad650d6e5fe747d9db2fb48e88681 100644 --- a/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserController.java +++ b/application/module-language-school/src/main/java/org/fuseri/modulelanguageschool/user/UserController.java @@ -1,10 +1,20 @@ package org.fuseri.modulelanguageschool.user; import org.fuseri.model.dto.common.Result; +import org.fuseri.model.dto.user.AddressDto; +import org.fuseri.model.dto.user.UserAddLanguageDto; import org.fuseri.model.dto.user.UserCreateDto; import org.fuseri.model.dto.user.UserDto; +import org.fuseri.model.dto.user.UserLoginDto; +import org.fuseri.modulelanguageschool.course.Course; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import jakarta.validation.Valid; +import jakarta.validation.constraints.PositiveOrZero; + + +import java.util.ArrayList; +import java.util.List; @RestController @RequestMapping("/users") @@ -22,16 +32,59 @@ public class UserController { @GetMapping("/{id}") public UserDto find(@PathVariable String id) { - return mapper.toDto(service.find(id)); + return new UserDto("spracher","spracher@gmail.com","Sprach","MeNot",new AddressDto()); } @PostMapping - public UserDto create(@RequestBody UserCreateDto dto) { - return mapper.toDto(service.create(mapper.fromCreateDto(dto))); + public UserDto create(@Valid @RequestBody UserCreateDto dto) { + return new UserDto(dto.getUsername(),dto.getEmail(),dto.getFirstName(),dto.getLastName(),dto.getAddress()); + } + + @DeleteMapping("/{id}") + public UserDto deleteUser(@PathVariable String id) { + return new UserDto("spracher","spracher@gmail.com","Sprach","MeNot",new AddressDto()); + } + + @PutMapping("/update/{id}") + public UserDto update(@PositiveOrZero @PathVariable String id,@Valid @RequestBody UserCreateDto user) { + + return new UserDto(user.getUsername(),user.getEmail(),user.getFirstName(),user.getLastName(),user.getAddress()); + } + + @GetMapping("/all") + public Result<UserDto> findAll(@PositiveOrZero @RequestParam int page) { + var res = new Result<UserDto>(); + res.setItems(List.of(new UserDto("spracher","spracher@gmail.com","Sprach","MeNot",new AddressDto()) +)); + + return res; + } - @GetMapping - public Result<UserDto> findAll(@RequestParam int page) { - return mapper.toResult(service.findAll(page)); + @PostMapping("/login") + public String login(@Valid @RequestBody UserLoginDto dto) { + return String.format("User %s has spawned", dto.getUsername()); } + + + @PostMapping("/logout/{id}") + public String logout(@PathVariable String id) { + return "user has logged out"; + } + + @GetMapping("/finished/{id}") + public List<Course> getFinished(@PathVariable String id) { + return new ArrayList<>(); + } + + @GetMapping("/enrolled/{id}") + public List<Course> getEnrolled(@PathVariable String id) { + return new ArrayList<>(); + } + + @PutMapping("/addLanguage/{id}") + public String addLanguage(@PathVariable String id,@Valid @RequestBody UserAddLanguageDto body) { + return "added Absolutely Nothing successfully!"; + } + } diff --git a/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/user/UserControllerTest.java b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/user/UserControllerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..85aa5f33c134528abba0f729717a020278e440bb --- /dev/null +++ b/application/module-language-school/src/test/java/org/fuseri/modulelanguageschool/user/UserControllerTest.java @@ -0,0 +1,227 @@ +package org.fuseri.modulelanguageschool.user; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.fuseri.model.dto.course.LanguageTypeDto; +import org.fuseri.model.dto.course.ProficiencyLevelDto; +import org.fuseri.model.dto.user.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + + +@SpringBootTest +@AutoConfigureMockMvc +class UserControllerTest { + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private MockMvc mockMvc; + + private static final AddressDto ADDRESS_TO_CREATE = new AddressDto( + "Czechia", "Brno", "Masarykova", "45", "90033"); + + private static final List<AddressDto> INVALID_ADDRESSES = List.of( + new AddressDto("", "Brno", "Masarykova", "45", "90033"), + new AddressDto("Czechia", "", "Masarykova", "45", "90033"), + new AddressDto("Czechia", "Brno", "", "45", "90033"), + new AddressDto("Czechia", "Brno", "Masarykova", "", "90033"), + new AddressDto("Czechia", "Brno", "Masarykova", "45", ""), + new AddressDto(null, "Brno", "Masarykova", "45", "90033"), + new AddressDto("Czechia", null, "Masarykova", "45", "90033"), + new AddressDto("Czechia", "Brno", null, "45", "90033"), + new AddressDto("Czechia", "Brno", "Masarykova", null, "90033") + ); + + private static final UserCreateDto USER_TO_CREATE = new UserCreateDto( + "xnovak", "1c1bbf66-6585-4978-886b-b126335ff3af", + "xnovak@emample.com", "Peter", "Novak", ADDRESS_TO_CREATE); + + private static final UserLoginDto USER_TO_LOGIN = new UserLoginDto( + "xnovak", "1c1bbf66-6585-4978-886b-b126335ff3af"); + + private static Stream<UserCreateDto> invalidUsers() { + var invalidUsers = Stream.of( + new UserCreateDto("", "1c1bbf66-6585-4978-886b-b126335ff3af", + "xnovak@emample.com", "Peter", "Novak", ADDRESS_TO_CREATE), + new UserCreateDto("xnovak", "", + "xnovak@emample.com", "Peter", "Novak", ADDRESS_TO_CREATE), + new UserCreateDto("xnovak", "1c1bbf66-6585-4978-886b-b126335ff3af", + "", "Peter", "Novak", ADDRESS_TO_CREATE), + new UserCreateDto("xnovak", "1c1bbf66-6585-4978-886b-b126335ff3af", + "xnovak@emample.com", "", "Novak", ADDRESS_TO_CREATE), + new UserCreateDto("xnovak", "1c1bbf66-6585-4978-886b-b126335ff3af", + "xnovak@emample.com", "Peter", "", ADDRESS_TO_CREATE), + new UserCreateDto(null, "1c1bbf66-6585-4978-886b-b126335ff3af", + "xnovak@emample.com", "Peter", "Novak", ADDRESS_TO_CREATE), + new UserCreateDto("xnovak", null, + "xnovak@emample.com", "Peter", "Novak", ADDRESS_TO_CREATE), + new UserCreateDto("xnovak", "1c1bbf66-6585-4978-886b-b126335ff3af", + null, "Peter", "Novak", ADDRESS_TO_CREATE), + new UserCreateDto("xnovak", "1c1bbf66-6585-4978-886b-b126335ff3af", + "xnovak@emample.com", null, "Novak", ADDRESS_TO_CREATE), + new UserCreateDto("xnovak", "1c1bbf66-6585-4978-886b-b126335ff3af", + "xnovak@emample.com", "Peter", null, ADDRESS_TO_CREATE), + new UserCreateDto("xnovak", "1c1bbf66-6585-4978-886b-b126335ff3af", + "xnovak@emample.com", "Peter", "Novak", null) + ); + + var invalidAddressUsers = new ArrayList<UserCreateDto>(); + for (var invalidAddress : INVALID_ADDRESSES) { + invalidAddressUsers.add(new UserCreateDto("xnovak", "1c1bbf66-6585-4978-886b-b126335ff3af", + "xnovak@emample.com", "Peter", "Novak", invalidAddress)); + } + + return Stream.concat(invalidUsers, invalidAddressUsers.stream()); + } + + private static Stream<UserLoginDto> invalidLoginDtoStream() { + return Stream.of( + new UserLoginDto("", "1c1bbf66-6585-4978-886b-b126335ff3af"), + new UserLoginDto("xnovak", ""), + new UserLoginDto(null, "1c1bbf66-6585-4978-886b-b126335ff3af"), + new UserLoginDto("xnovak", null)); + } + + @Test + void create() throws Exception { + mockMvc.perform(post("/users") + .content(asJsonString(USER_TO_CREATE)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + } + + @ParameterizedTest + @MethodSource("invalidUsers") + void createInvalidUser(UserCreateDto user) throws Exception { + mockMvc.perform(post("/users") + .content(asJsonString(user)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + } + + @Test + void findUser() throws Exception { + String response = mockMvc.perform(post("/users") + .content(asJsonString(USER_TO_CREATE)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + + String id = objectMapper.readValue(response, UserDto.class).getId(); + + mockMvc.perform(get("/users/{id}", id)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id").value(id)); + } + + @Test + void findAll() throws Exception { + mockMvc.perform(get("/users/all") + .param("page", "0")) + .andExpect(status().isOk()); + } + + @Test + void deleteUser() throws Exception { + String response = mockMvc.perform(post("/users") + .content(asJsonString(USER_TO_CREATE)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + + String id = objectMapper.readValue(response, UserDto.class).getId(); + + mockMvc.perform(delete("/users/{id}", id) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + } + + @Test + void update() throws Exception { + String response = mockMvc.perform(post("/users") + .content(asJsonString(USER_TO_CREATE)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + + String id = objectMapper.readValue(response, UserDto.class).getId(); + + var updatedUsername = "novak"; + var userToUpdate = new UserCreateDto( + USER_TO_CREATE.getUsername(), USER_TO_CREATE.getPassword(), USER_TO_CREATE.getEmail(), + USER_TO_CREATE.getFirstName(), USER_TO_CREATE.getLastName(), USER_TO_CREATE.getAddress()); + userToUpdate.setUsername(updatedUsername); + + mockMvc.perform(put("/users/update/{id}", id) + .content(asJsonString(userToUpdate)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.username").value(updatedUsername)); + } + + @Test + void login() throws Exception { + mockMvc.perform(post("/users/login") + .content(asJsonString(USER_TO_LOGIN)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + } + + @ParameterizedTest + @MethodSource("invalidLoginDtoStream") + void loginInvalidDto(UserLoginDto loginDto) throws Exception { + mockMvc.perform(post("/users/login") + .content(asJsonString(loginDto)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().is4xxClientError()); + } + + @Test + void logout() throws Exception { + String response = mockMvc.perform(post("/users") + .content(asJsonString(USER_TO_CREATE)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); + + String id = objectMapper.readValue(response, UserDto.class).getId(); + + mockMvc.perform(post("/users/logout/{id}", id)) + .andExpect(status().isOk()); + } + + @Test + void getFinished() throws Exception { + mockMvc.perform(get("/users/finished/{id}", "1c1bbf66-6585-4978-886b-b126335ff3af")) + .andExpect(status().isOk()); + } + + @Test + void getEnrolled() throws Exception { + mockMvc.perform(get("/users/enrolled/{id}", "1c1bbf66-6585-4978-886b-b126335ff3af")) + .andExpect(status().isOk()); + } + + @Test + void addLanguage() throws Exception { + mockMvc.perform(put("/users/addLanguage/{id}", "1c1bbf66-6585-4978-886b-b126335ff3af") + .content(asJsonString(new UserAddLanguageDto(LanguageTypeDto.ENGLISH, ProficiencyLevelDto.B2))) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + } + + private static String asJsonString(final Object obj) throws JsonProcessingException { + return new ObjectMapper().writeValueAsString(obj); + } +} \ No newline at end of file