diff --git a/buisnesslogic/src/main/java/com/plannaplan/entities/User.java b/buisnesslogic/src/main/java/com/plannaplan/entities/User.java index f21db21..d62384c 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/entities/User.java +++ b/buisnesslogic/src/main/java/com/plannaplan/entities/User.java @@ -9,7 +9,6 @@ import javax.persistence.Id; import com.plannaplan.types.UserRoles; -//should setter be public? @Entity public class User { @Id diff --git a/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java b/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java index 150fc49..c792ce7 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java +++ b/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java @@ -1,8 +1,10 @@ package com.plannaplan.repositories; +import java.util.List; import java.util.Optional; import com.plannaplan.entities.User; +import com.plannaplan.types.UserRoles; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -16,4 +18,10 @@ public interface UserRepository extends JpaRepository { @Query("FROM User WHERE token = ?1") Optional getByToken(@Param("token") String token); + + @Query("FROM User WHERE (name LIKE %?1% OR surname LIKE %?1%)") + List searchForUsers(@Param("query") String query); + + @Query("FROM User WHERE (name LIKE %?1% OR surname LIKE %?1%) AND role=?2") + List searchForUsers(@Param("query") String query, @Param("role") UserRoles role); } \ No newline at end of file diff --git a/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java b/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java index 3b3e070..4eaa65e 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java +++ b/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java @@ -1,11 +1,13 @@ package com.plannaplan.services; +import java.util.List; import java.util.Optional; import java.util.UUID; import com.plannaplan.entities.User; import com.plannaplan.exceptions.UserNotFoundException; import com.plannaplan.repositories.UserRepository; +import com.plannaplan.types.UserRoles; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -23,7 +25,7 @@ public class UserService { User user = this.repo.getByAuthority(authority.replace("\n", "").trim()) .orElseThrow(() -> new UserNotFoundException("Can not find user with given authority")); - String token = UUID.randomUUID().toString(); + final String token = UUID.randomUUID().toString(); user.setToken(token); this.repo.save(user); return token; @@ -43,4 +45,8 @@ public class UserService { return this.repo.getByToken(token); } + public List searchForStudents(String query) { + return this.repo.searchForUsers(query, UserRoles.STUDENT); + } + } \ No newline at end of file diff --git a/buisnesslogic/src/test/java/com/plannaplan/services/UserServiceTest.java b/buisnesslogic/src/test/java/com/plannaplan/services/UserServiceTest.java index f24e0d0..256ec90 100755 --- a/buisnesslogic/src/test/java/com/plannaplan/services/UserServiceTest.java +++ b/buisnesslogic/src/test/java/com/plannaplan/services/UserServiceTest.java @@ -7,11 +7,12 @@ import org.springframework.test.context.junit4.SpringRunner; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.List; + import com.plannaplan.entities.User; import com.plannaplan.exceptions.UserNotFoundException; import com.plannaplan.types.UserRoles; -import org.junit.Before; import org.junit.Test; import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; @@ -29,14 +30,10 @@ public class UserServiceTest { @Autowired private UserService userService; - @Before - public void initialize() { - User testUser = new User(TEST_USER_NAME, TEST_USER_SUERNAME, TEST_USER_MAIL, UserRoles.TEST_USER); - this.userService.save(testUser); - } - @Test public void shouldReturnToken() { + final User testUser = new User(TEST_USER_NAME, TEST_USER_SUERNAME, TEST_USER_MAIL, UserRoles.TEST_USER); + this.userService.save(testUser); try { final String token = this.userService.login(TEST_USER_MAIL); System.out.println("Returned token: " + token); @@ -57,4 +54,43 @@ public class UserServiceTest { assertTrue(true); } } + + @Test + public void shouldFindStudents() { + this.userService.save(new User("Nemo", "TheFish", "Nemo@shouldFindStudents.test", UserRoles.STUDENT)); + final List response = this.userService.searchForStudents("Nemo"); + assertTrue(response.size() >= 1); + assertTrue(containsName(response, "Nemo")); + } + + @Test + public void shouldReturnAllStudents() { + final User veryWantedUser = new User("Xavier", "123", "Xavier@shouldReturnAllStudents.test", UserRoles.STUDENT); + final User littleLessWanted = new User("Ravier", "321", "Ravier@shouldReturnAllStudents.test", + UserRoles.STUDENT); + final User notWantadUser = new User("Fiona", "Raskolnikov", "Fiona@shouldReturnAllStudents.test", + UserRoles.DEANERY); + + this.userService.save(veryWantedUser); + this.userService.save(littleLessWanted); + this.userService.save(notWantadUser); + + final List response = this.userService.searchForStudents(""); + assertTrue(response.size() >= 2); + assertTrue(!containsName(response, notWantadUser.getName())); + assertTrue(containsName(response, littleLessWanted.getName())); + assertTrue(containsName(response, veryWantedUser.getName())); + } + + @Test + public void shouldntFindStudents() { + this.userService.save(new User("Nadia", "Ladia", "Nadia@shouldntFindStudents.test", UserRoles.STUDENT)); + final List response = this.userService.searchForStudents( + "THISisIMPOIBLEQUEryThatShouldntReturnAnyPersonAtAllfnjiasdfjivlsdfnjgklsomerandomcharsjustinCaseXD"); + assertTrue(response.size() == 0); + } + + private boolean containsName(final List list, final String name) { + return list.stream().map(User::getName).filter(name::equals).findFirst().isPresent(); + } } diff --git a/buisnesslogic/src/test/resources/application.properties b/buisnesslogic/src/test/resources/application.properties index bd77a4e..0477c97 100755 --- a/buisnesslogic/src/test/resources/application.properties +++ b/buisnesslogic/src/test/resources/application.properties @@ -6,5 +6,6 @@ spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.open-in-view=true spring.jpa.hibernate.ddl-auto=create-drop spring.jackson.serialization.fail-on-empty-beans=false +spring.main.allow-bean-definition-overriding=true server.port=1285 \ No newline at end of file diff --git a/restservice/src/main/java/com/plannaplan/App.java b/restservice/src/main/java/com/plannaplan/App.java index b85cbb9..d63eba5 100755 --- a/restservice/src/main/java/com/plannaplan/App.java +++ b/restservice/src/main/java/com/plannaplan/App.java @@ -32,7 +32,7 @@ public class App { filip.setEmail("filizy@st.amu.edu.pl"); filip.setName("Filip"); filip.setSurname("Izydorczyk"); - filip.setRole(UserRoles.STUDENT); + filip.setRole(UserRoles.DEANERY); this.userService.save(filip); User hub = new User(); diff --git a/restservice/src/main/java/com/plannaplan/controllers/ConfigController.java b/restservice/src/main/java/com/plannaplan/controllers/ConfigController.java index 5682e78..5d5456b 100755 --- a/restservice/src/main/java/com/plannaplan/controllers/ConfigController.java +++ b/restservice/src/main/java/com/plannaplan/controllers/ConfigController.java @@ -12,6 +12,8 @@ import com.plannaplan.services.ConfiguratorService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -20,12 +22,15 @@ import org.springframework.web.multipart.MultipartFile; @RestController @CrossOrigin @RequestMapping("/api/" + App.API_VERSION + "/configurator") +@EnableGlobalMethodSecurity(prePostEnabled = true) public class ConfigController { @Autowired private ConfiguratorService contrl; @PostMapping("/config") + @PreAuthorize("hasRole('ROLE_ADMIN')") + public ResponseEntity configApp(@RequestParam("file") MultipartFile file) { try { final ConfigData data = new ConfigData(null, null, file.getInputStream()); diff --git a/restservice/src/main/java/com/plannaplan/controllers/UsersController.java b/restservice/src/main/java/com/plannaplan/controllers/UsersController.java new file mode 100755 index 0000000..d4a4ae1 --- /dev/null +++ b/restservice/src/main/java/com/plannaplan/controllers/UsersController.java @@ -0,0 +1,38 @@ +package com.plannaplan.controllers; + +import java.util.List; + +import com.plannaplan.App; +import com.plannaplan.entities.User; +import com.plannaplan.responses.mappers.UserResponseMappers; +import com.plannaplan.responses.models.SearchForStudentsResponse; +import com.plannaplan.services.UserService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@RestController +@CrossOrigin +@RequestMapping("/api/" + App.API_VERSION + "/users") +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class UsersController { + @Autowired + private UserService userService; + + @GetMapping("/searchForStudents") + @PreAuthorize("hasRole('ROLE_DEANERY')") + + public ResponseEntity> configApp(@RequestParam("query") String query) { + final List searches = this.userService.searchForStudents(query); + final List response = UserResponseMappers.mapToDefaultResponse(searches); + return new ResponseEntity<>(response, HttpStatus.OK); + } +} diff --git a/restservice/src/main/java/com/plannaplan/responses/mappers/UserResponseMappers.java b/restservice/src/main/java/com/plannaplan/responses/mappers/UserResponseMappers.java new file mode 100755 index 0000000..f039341 --- /dev/null +++ b/restservice/src/main/java/com/plannaplan/responses/mappers/UserResponseMappers.java @@ -0,0 +1,15 @@ +package com.plannaplan.responses.mappers; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import com.plannaplan.entities.User; +import com.plannaplan.responses.models.SearchForStudentsResponse; + +public class UserResponseMappers { + public static List mapToDefaultResponse(List groups) { + return groups.stream().filter(Objects::nonNull).map(SearchForStudentsResponse::new) + .collect(Collectors.toList()); + } +} diff --git a/restservice/src/main/java/com/plannaplan/responses/models/SearchForStudentsResponse.java b/restservice/src/main/java/com/plannaplan/responses/models/SearchForStudentsResponse.java new file mode 100755 index 0000000..01602be --- /dev/null +++ b/restservice/src/main/java/com/plannaplan/responses/models/SearchForStudentsResponse.java @@ -0,0 +1,35 @@ +package com.plannaplan.responses.models; + +import com.plannaplan.entities.User; + +public class SearchForStudentsResponse { + + private Long id; + private String name; + private String surname; + private String email; + + public SearchForStudentsResponse(User user) { + this.id = user.getId(); + this.name = user.getName(); + this.surname = user.getSurname(); + this.email = user.getEmail(); + } + + public String getEmail() { + return email; + } + + public String getSurname() { + return surname; + } + + public String getName() { + return name; + } + + public Long getId() { + return id; + } + +} diff --git a/restservice/src/main/java/com/plannaplan/security/AuthenticationProvider.java b/restservice/src/main/java/com/plannaplan/security/AuthenticationProvider.java index 110098d..ee27492 100755 --- a/restservice/src/main/java/com/plannaplan/security/AuthenticationProvider.java +++ b/restservice/src/main/java/com/plannaplan/security/AuthenticationProvider.java @@ -1,6 +1,8 @@ package com.plannaplan.security; +import java.util.Arrays; import java.util.Collection; +import java.util.List; import com.plannaplan.entities.User; import com.plannaplan.services.UserService; @@ -40,8 +42,10 @@ public class AuthenticationProvider extends AbstractUserDetailsAuthenticationPro @Override public Collection getAuthorities() { - // is being done in other task - return null; + final AuthorityRoles role = AuthorityRoles.getAuthorityRole(user.getRole()) + .orElseThrow(() -> new NullPointerException("Failed to get user role")); + final List response = Arrays.asList(role); + return response; } @Override diff --git a/restservice/src/main/java/com/plannaplan/security/AuthorityRoles.java b/restservice/src/main/java/com/plannaplan/security/AuthorityRoles.java new file mode 100755 index 0000000..7005438 --- /dev/null +++ b/restservice/src/main/java/com/plannaplan/security/AuthorityRoles.java @@ -0,0 +1,38 @@ +package com.plannaplan.security; + +import java.util.Optional; + +import com.plannaplan.types.UserRoles; + +import org.springframework.security.core.GrantedAuthority; + +public enum AuthorityRoles implements GrantedAuthority { + STUDENT("ROLE_STUDENT"), DEANERY("ROLE_DEANERY"), ADMIN("ROLE_ADMIN"), TEST_USER("ROLE_TESTUSER"); + + private String role; + + AuthorityRoles(String role) { + this.role = role; + } + + @Override + public String getAuthority() { + return this.role; + } + + public static final Optional getAuthorityRole(UserRoles role) { + switch (role) { + case ADMIN: + return Optional.of(AuthorityRoles.ADMIN); + case DEANERY: + return Optional.of(AuthorityRoles.DEANERY); + case STUDENT: + return Optional.of(AuthorityRoles.STUDENT); + case TEST_USER: + return Optional.of(AuthorityRoles.TEST_USER); + default: + return Optional.empty(); + } + } + +} diff --git a/restservice/src/main/java/com/plannaplan/security/WebSecurityConfig.java b/restservice/src/main/java/com/plannaplan/security/WebSecurityConfig.java index 25628fb..95b3785 100755 --- a/restservice/src/main/java/com/plannaplan/security/WebSecurityConfig.java +++ b/restservice/src/main/java/com/plannaplan/security/WebSecurityConfig.java @@ -42,9 +42,9 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { - http.csrf().disable().formLogin().disable().httpBasic().disable().logout().disable().sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().exceptionHandling().and() - .authenticationProvider(provider) + http.csrf().disable().cors().and().formLogin().disable().httpBasic().disable().logout().disable() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().exceptionHandling() + .and().authenticationProvider(provider) .addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class).authorizeRequests() .anyRequest().authenticated(); diff --git a/restservice/src/main/resources/application.properties b/restservice/src/main/resources/application.properties index bd77a4e..0477c97 100755 --- a/restservice/src/main/resources/application.properties +++ b/restservice/src/main/resources/application.properties @@ -6,5 +6,6 @@ spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.open-in-view=true spring.jpa.hibernate.ddl-auto=create-drop spring.jackson.serialization.fail-on-empty-beans=false +spring.main.allow-bean-definition-overriding=true server.port=1285 \ No newline at end of file diff --git a/restservice/src/test/java/com/plannaplan/controllers/ConfigControllerTest.java b/restservice/src/test/java/com/plannaplan/controllers/ConfigControllerTest.java index 6fbab62..1c322c8 100755 --- a/restservice/src/test/java/com/plannaplan/controllers/ConfigControllerTest.java +++ b/restservice/src/test/java/com/plannaplan/controllers/ConfigControllerTest.java @@ -37,16 +37,6 @@ public class ConfigControllerTest { @Autowired private UserService service; - @Test - public void shouldReturnOK() throws Exception { - final InputStream inputStream = getClass().getClassLoader().getResourceAsStream(FILE_NAME); - final MockMultipartFile file = new MockMultipartFile("file", inputStream); - - MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); - mockMvc.perform(multipart(CONFIG_ENDPOINT).file(file)).andExpect(status().isOk()); - - } - @Test public void shouldReturnNoAuthorized() throws Exception { final InputStream inputStream = getClass().getClassLoader().getResourceAsStream(FILE_NAME); @@ -59,7 +49,7 @@ public class ConfigControllerTest { @Test public void shouldReturnOKAuthorized() throws Exception { - final User usr = new User(null, null, TEST_MAIL, UserRoles.TEST_USER); + final User usr = new User(null, null, TEST_MAIL, UserRoles.ADMIN); this.service.save(usr); final InputStream inputStream = getClass().getClassLoader().getResourceAsStream(FILE_NAME); diff --git a/restservice/src/test/java/com/plannaplan/controllers/UsersControllerTest.java b/restservice/src/test/java/com/plannaplan/controllers/UsersControllerTest.java new file mode 100755 index 0000000..b55850d --- /dev/null +++ b/restservice/src/test/java/com/plannaplan/controllers/UsersControllerTest.java @@ -0,0 +1,60 @@ +package com.plannaplan.controllers; + +import com.plannaplan.entities.User; +import com.plannaplan.services.UserService; +import com.plannaplan.types.UserRoles; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest +@ContextConfiguration +public class UsersControllerTest { + private static final String ENDPOINT = "/api/v1/users/searchForStudents"; + + @Autowired + private WebApplicationContext webApplicationContext; + + @Autowired + private UserService service; + + @Test + public void shouldRestrun200OK() throws Exception { + final String email = "notexistingassignmentuser@shouldRestrun200OK.test"; + this.service.save(new User(null, null, email, UserRoles.DEANERY)); + final String token = this.service.login(email); + + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + mockMvc.perform(get(ENDPOINT).param("query", "").header("Authorization", "Bearer " + token)) + .andExpect(status().isOk()); + } + + @Test + public void shouldRestrunForbiden() throws Exception { + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + mockMvc.perform(get(ENDPOINT)).andExpect(status().is4xxClientError()); + } + + @Test + public void shouldFailedDueToMissingParam() throws Exception { + final String email = "notexistingassignmentuser@shouldFailedDueToMissingParam.test"; + this.service.save(new User(null, null, email, UserRoles.DEANERY)); + final String token = this.service.login(email); + + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(springSecurity()).build(); + mockMvc.perform(get(ENDPOINT).header("Authorization", "Bearer " + token)) + .andExpect(status().is4xxClientError()); + } +} diff --git a/restservice/src/test/java/com/plannaplan/responses/mappers/UserResponseMappersTest.java b/restservice/src/test/java/com/plannaplan/responses/mappers/UserResponseMappersTest.java new file mode 100755 index 0000000..f393f03 --- /dev/null +++ b/restservice/src/test/java/com/plannaplan/responses/mappers/UserResponseMappersTest.java @@ -0,0 +1,32 @@ +package com.plannaplan.responses.mappers; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.List; + +import com.plannaplan.entities.User; +import com.plannaplan.types.UserRoles; +import com.plannaplan.responses.models.SearchForStudentsResponse; + +import org.junit.Test; + +public class UserResponseMappersTest { + private static final String F_NAME = "Tytus"; + private static final String F_SURNAMENAME = "Romek"; + private static final String F_EMAIL = "i@Atomek.pl"; + + private static final String S_NAME = "Ed"; + private static final String S_SURNAMENAME = "Edd"; + private static final String S_EMAIL = "i@Eddy.pl"; + + @Test + public void shlouldMapListToResponseList() { + final List users = Arrays.asList(new User(F_NAME, F_SURNAMENAME, F_EMAIL, UserRoles.TEST_USER), + new User(S_NAME, S_SURNAMENAME, S_EMAIL, UserRoles.TEST_USER)); + + final List resposne = UserResponseMappers.mapToDefaultResponse(users); + assertTrue(resposne.size() == 2); + assertTrue(resposne.get(0) instanceof SearchForStudentsResponse); + } +} diff --git a/restservice/src/test/java/com/plannaplan/responses/models/SearchForStudentsResponseTest.java b/restservice/src/test/java/com/plannaplan/responses/models/SearchForStudentsResponseTest.java new file mode 100755 index 0000000..d28f51d --- /dev/null +++ b/restservice/src/test/java/com/plannaplan/responses/models/SearchForStudentsResponseTest.java @@ -0,0 +1,23 @@ +package com.plannaplan.responses.models; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.plannaplan.entities.User; +import com.plannaplan.types.UserRoles; + +import org.junit.Test; + +public class SearchForStudentsResponseTest { + private static final String NAME = "Tytus"; + private static final String SURNAMENAME = "Romek"; + private static final String EMAIL = "i@Atomek.pl"; + + @Test + public void shouldMapUserToResponseElement() { + final SearchForStudentsResponse response = new SearchForStudentsResponse( + new User(NAME, SURNAMENAME, EMAIL, UserRoles.TEST_USER)); + assertTrue(response.getName().equals(NAME)); + assertTrue(response.getSurname().equals(SURNAMENAME)); + assertTrue(response.getEmail().equals(EMAIL)); + } +}