Merge pull request 'scurity-roles' (#13) from scurity-roles into master

Reviewed-on: http://git.plannaplan.pl/filipizydorczyk/backend/pulls/13
LGMT
This commit is contained in:
Marcin Woźniak 2020-10-24 18:01:29 +02:00
commit f71715fd6b
18 changed files with 317 additions and 26 deletions

View File

@ -9,7 +9,6 @@ import javax.persistence.Id;
import com.plannaplan.types.UserRoles;
//should setter be public?
@Entity
public class User {
@Id

View File

@ -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<User, Long> {
@Query("FROM User WHERE token = ?1")
Optional<User> getByToken(@Param("token") String token);
@Query("FROM User WHERE (name LIKE %?1% OR surname LIKE %?1%)")
List<User> searchForUsers(@Param("query") String query);
@Query("FROM User WHERE (name LIKE %?1% OR surname LIKE %?1%) AND role=?2")
List<User> searchForUsers(@Param("query") String query, @Param("role") UserRoles role);
}

View File

@ -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<User> searchForStudents(String query) {
return this.repo.searchForUsers(query, UserRoles.STUDENT);
}
}

View File

@ -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<User> 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<User> 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<User> response = this.userService.searchForStudents(
"THISisIMPOIBLEQUEryThatShouldntReturnAnyPersonAtAllfnjiasdfjivlsdfnjgklsomerandomcharsjustinCaseXD");
assertTrue(response.size() == 0);
}
private boolean containsName(final List<User> list, final String name) {
return list.stream().map(User::getName).filter(name::equals).findFirst().isPresent();
}
}

View File

@ -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

View File

@ -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();

View File

@ -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<String> configApp(@RequestParam("file") MultipartFile file) {
try {
final ConfigData data = new ConfigData(null, null, file.getInputStream());

View File

@ -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<List<SearchForStudentsResponse>> configApp(@RequestParam("query") String query) {
final List<User> searches = this.userService.searchForStudents(query);
final List<SearchForStudentsResponse> response = UserResponseMappers.mapToDefaultResponse(searches);
return new ResponseEntity<>(response, HttpStatus.OK);
}
}

View File

@ -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<SearchForStudentsResponse> mapToDefaultResponse(List<User> groups) {
return groups.stream().filter(Objects::nonNull).map(SearchForStudentsResponse::new)
.collect(Collectors.toList());
}
}

View File

@ -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;
}
}

View File

@ -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<? extends GrantedAuthority> 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<AuthorityRoles> response = Arrays.asList(role);
return response;
}
@Override

View File

@ -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<AuthorityRoles> 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();
}
}
}

View File

@ -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();

View File

@ -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

View File

@ -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);

View File

@ -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());
}
}

View File

@ -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<User> 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<SearchForStudentsResponse> resposne = UserResponseMappers.mapToDefaultResponse(users);
assertTrue(resposne.size() == 2);
assertTrue(resposne.get(0) instanceof SearchForStudentsResponse);
}
}

View File

@ -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));
}
}