diff --git a/server/src/main/java/com/usatiuk/tjv/y/server/controller/PostController.java b/server/src/main/java/com/usatiuk/tjv/y/server/controller/PostController.java index f4b8663..ccf85d4 100644 --- a/server/src/main/java/com/usatiuk/tjv/y/server/controller/PostController.java +++ b/server/src/main/java/com/usatiuk/tjv/y/server/controller/PostController.java @@ -6,11 +6,14 @@ import com.usatiuk.tjv.y.server.entity.Person; import com.usatiuk.tjv.y.server.entity.Post; import com.usatiuk.tjv.y.server.service.PostService; import jakarta.persistence.EntityManager; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; import java.security.Principal; import java.util.Optional; +import java.util.stream.Stream; @RestController @RequestMapping(value = "/post", produces = MediaType.APPLICATION_JSON_VALUE) @@ -32,11 +35,18 @@ public class PostController { } @GetMapping - public Iterable readAllOrByAuthor(@RequestParam Optional author) { + public Stream readAllByAuthor(@RequestParam Optional author) { if (author.isPresent()) - return postService.readByAuthorId(author.get()); + return postService.readByAuthorId(author.get()).stream().map(PostTo::new); else - return postService.readAll(); + throw new ResponseStatusException(HttpStatus.BAD_REQUEST); + } + + @GetMapping(path = "/{id}") + public PostTo get(@PathVariable long id) { + var post = postService.readById(id); + if (post.isEmpty()) throw new ResponseStatusException(HttpStatus.NOT_FOUND); + return new PostTo(post.get()); } } diff --git a/server/src/main/java/com/usatiuk/tjv/y/server/repository/PersonRepository.java b/server/src/main/java/com/usatiuk/tjv/y/server/repository/PersonRepository.java index 2f9456d..a3c5fa5 100644 --- a/server/src/main/java/com/usatiuk/tjv/y/server/repository/PersonRepository.java +++ b/server/src/main/java/com/usatiuk/tjv/y/server/repository/PersonRepository.java @@ -3,5 +3,8 @@ package com.usatiuk.tjv.y.server.repository; import com.usatiuk.tjv.y.server.entity.Person; import org.springframework.data.repository.CrudRepository; +import java.util.Optional; + public interface PersonRepository extends CrudRepository { + Optional findByUsername(String username); } diff --git a/server/src/main/java/com/usatiuk/tjv/y/server/security/WebSecurityConfig.java b/server/src/main/java/com/usatiuk/tjv/y/server/security/WebSecurityConfig.java index a27c745..87c3e20 100644 --- a/server/src/main/java/com/usatiuk/tjv/y/server/security/WebSecurityConfig.java +++ b/server/src/main/java/com/usatiuk/tjv/y/server/security/WebSecurityConfig.java @@ -2,8 +2,10 @@ package com.usatiuk.tjv.y.server.security; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @@ -29,9 +31,11 @@ public class WebSecurityConfig { @Bean public SecurityFilterChain configure(HttpSecurity http, MvcRequestMatcher.Builder mvc) throws Exception { return http.cors(withDefaults()) - .csrf((csrf) -> csrf.disable()) + .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests((authorize) -> authorize - .requestMatchers(mvc.pattern("/person")).permitAll() + .requestMatchers(mvc.pattern(HttpMethod.GET, "/post/*")).permitAll() + .requestMatchers(mvc.pattern(HttpMethod.POST, "/person")).permitAll() + .requestMatchers(mvc.pattern(HttpMethod.GET, "/person")).permitAll() .anyRequest().hasAuthority(UserRoles.ROLE_USER.name())) .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class) diff --git a/server/src/test/java/com/usatiuk/tjv/y/server/controller/DemoDataDbTest.java b/server/src/test/java/com/usatiuk/tjv/y/server/controller/DemoDataDbTest.java new file mode 100644 index 0000000..0f69c40 --- /dev/null +++ b/server/src/test/java/com/usatiuk/tjv/y/server/controller/DemoDataDbTest.java @@ -0,0 +1,79 @@ +package com.usatiuk.tjv.y.server.controller; + +import com.usatiuk.tjv.y.server.dto.PersonAuthResponse; +import com.usatiuk.tjv.y.server.entity.Person; +import com.usatiuk.tjv.y.server.entity.Post; +import com.usatiuk.tjv.y.server.repository.PersonRepository; +import com.usatiuk.tjv.y.server.repository.PostRepository; +import com.usatiuk.tjv.y.server.service.PersonTokenService; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.test.jdbc.JdbcTestUtils; + +import java.util.Collections; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public abstract class DemoDataDbTest { + @Value("http://localhost:${local.server.port}") + protected String addr; + @Autowired + protected TestRestTemplate restTemplate; + @Autowired + private JdbcTemplate jdbcTemplate; + @Autowired + private PasswordEncoder passwordEncoder; + @Autowired + private PersonTokenService personTokenService; + @Autowired + private PersonRepository personRepository; + @Autowired + private PostRepository postRepository; + + protected Person person1; + protected PersonAuthResponse person1Auth; + protected Person person2; + protected PersonAuthResponse person2Auth; + + protected Post post1; + protected Post post2; + + protected HttpHeaders createAuthHeaders(PersonAuthResponse personAuth) { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + personAuth.token()); + return headers; + } + + @BeforeEach + void setup() { + person1 = personRepository.save( + new Person() + .setUsername("person1") + .setFullName("Person 1") + .setPassword(passwordEncoder.encode("p1p"))); + person1Auth = new PersonAuthResponse(person1, personTokenService.generateToken(person1.getUuid())); + person2 = personRepository.save( + new Person() + .setUsername("person2") + .setFullName("Person 2") + .setPassword(passwordEncoder.encode("p2p"))); + person2Auth = new PersonAuthResponse(person1, personTokenService.generateToken(person1.getUuid())); + + post1 = postRepository.save(new Post().setAuthor(person1).setText("post 1")); + post2 = postRepository.save(new Post().setAuthor(person2).setText("post 2")); + } + + @AfterEach + void erase() { + JdbcTestUtils.deleteFromTables(jdbcTemplate, "post", "person"); + } + +} diff --git a/server/src/test/java/com/usatiuk/tjv/y/server/controller/PersonControllerTest.java b/server/src/test/java/com/usatiuk/tjv/y/server/controller/PersonControllerTest.java index 3612457..d93376e 100644 --- a/server/src/test/java/com/usatiuk/tjv/y/server/controller/PersonControllerTest.java +++ b/server/src/test/java/com/usatiuk/tjv/y/server/controller/PersonControllerTest.java @@ -2,37 +2,27 @@ package com.usatiuk.tjv.y.server.controller; import com.usatiuk.tjv.y.server.dto.PersonAuthResponse; import com.usatiuk.tjv.y.server.dto.PersonSignupRequest; +import com.usatiuk.tjv.y.server.repository.PersonRepository; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.test.web.server.LocalServerPort; - - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class PersonControllerTest { - @LocalServerPort - private int port; +import org.springframework.test.annotation.DirtiesContext; +public class PersonControllerTest extends DemoDataDbTest { @Autowired - private TestRestTemplate restTemplate; - - private String addr; - - @BeforeEach - void beforeEach() { - addr = "http://localhost:" + port; - } + private PersonRepository personRepository; @Test void shouldSignUp() { var response = restTemplate.postForObject(addr + "/person", - new PersonSignupRequest("name", "full name", "pass"), PersonAuthResponse.class); + new PersonSignupRequest("usernew", "full name", "pass"), PersonAuthResponse.class); Assertions.assertNotNull(response); - Assertions.assertEquals(response.username(), "name"); + Assertions.assertEquals(response.username(), "usernew"); Assertions.assertEquals(response.fullName(), "full name"); + Assertions.assertTrue(personRepository.findByUsername("usernew").isPresent()); } } diff --git a/server/src/test/java/com/usatiuk/tjv/y/server/controller/PostControllerTest.java b/server/src/test/java/com/usatiuk/tjv/y/server/controller/PostControllerTest.java index 86a1738..5980b01 100644 --- a/server/src/test/java/com/usatiuk/tjv/y/server/controller/PostControllerTest.java +++ b/server/src/test/java/com/usatiuk/tjv/y/server/controller/PostControllerTest.java @@ -1,71 +1,52 @@ package com.usatiuk.tjv.y.server.controller; -import com.usatiuk.tjv.y.server.dto.PersonAuthResponse; -import com.usatiuk.tjv.y.server.dto.PersonSignupRequest; import com.usatiuk.tjv.y.server.dto.PostCreate; import com.usatiuk.tjv.y.server.dto.PostTo; -import com.usatiuk.tjv.y.server.service.PostService; +import com.usatiuk.tjv.y.server.repository.PostRepository; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; 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.boot.test.web.server.LocalServerPort; import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; +import org.springframework.http.HttpStatus; -import java.util.Collections; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class PostControllerTest { - @LocalServerPort - private int port; +public class PostControllerTest extends DemoDataDbTest { @Autowired - private TestRestTemplate restTemplate; - - @Autowired - private PostService postService; - - private String addr; - private PersonAuthResponse personAuth; - - @BeforeEach - void beforeEach() { - addr = "http://localhost:" + port; - - // Signup a user - var response = restTemplate.postForObject(addr + "/person", - new PersonSignupRequest("name", "full name", "pass"), PersonAuthResponse.class); - - personAuth = response; - } + private PostRepository postRepository; @Test void shouldNotCreatePostWithoutAuth() { + Long postsBefore = postRepository.count(); var response = restTemplate.postForObject(addr + "/post", new PostCreate("test text"), PostTo.class); Assertions.assertNull(response); - Assertions.assertEquals(postService.readAll().spliterator().estimateSize(), 0); + Assertions.assertEquals(postRepository.count(), postsBefore); } @Test void shouldCreatePost() { - HttpHeaders headers = new HttpHeaders(); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + personAuth.token()); - var entity = new HttpEntity<>(new PostCreate("test text"), headers); + var entity = new HttpEntity<>(new PostCreate("test text"), createAuthHeaders(person1Auth)); var response = restTemplate.exchange(addr + "/post", HttpMethod.POST, entity, PostTo.class); + Assertions.assertNotNull(response); + Assertions.assertEquals(response.getStatusCode(), HttpStatus.OK); PostTo reponsePostTo = response.getBody(); + Assertions.assertNotNull(reponsePostTo); + + Assertions.assertEquals(reponsePostTo.text(), "test text"); + Assertions.assertEquals(reponsePostTo.authorUuid(), person1Auth.uuid()); + } + + @Test + void shouldGetPost() { + PostTo response = restTemplate.getForObject(addr + "/post/" + post1.getId(), PostTo.class); Assertions.assertNotNull(response); - Assertions.assertEquals(reponsePostTo.text(), "test text"); - Assertions.assertEquals(reponsePostTo.authorUuid(), personAuth.uuid()); + Assertions.assertEquals(response.text(), post1.getText()); + Assertions.assertEquals(response.authorUuid(), person1Auth.uuid()); } + } diff --git a/server/src/test/resources/application.properties b/server/src/test/resources/application.properties new file mode 100644 index 0000000..1a6220a --- /dev/null +++ b/server/src/test/resources/application.properties @@ -0,0 +1 @@ +jwt.secret=FLJKDSDKLJFJKLISDAHJKFHOUIJOHUIJFHUOI$UIHGOUIOFG$#UIOYFOUYIG#$UIOHDUGHIOHUGIHJFHJLKDFHJLKDHJLKFSJDHKFHJKLSH \ No newline at end of file