From e34cbd309cf800589533bffc79cfc2092c712534 Mon Sep 17 00:00:00 2001 From: Michael Cavellier Date: Fri, 21 May 2021 18:37:29 -0400 Subject: [PATCH 1/4] role access and resource exception done --- README.md | 4 ++-- pom.xml | 20 +++++++++++++++++++ .../config/ResourceServerConfig.java | 3 +++ .../bookstore/controllers/BookController.java | 4 ++++ .../bookstore/services/BookServiceImpl.java | 3 ++- src/main/resources/application.properties | 2 ++ target/classes/application.properties | 2 ++ 7 files changed, 35 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e6710360..57cf83ce 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Java Frameworks Sprint Challenge - +//test for codegrade **Read these instructions carefully. Understand exactly what is expected _before_ starting this Sprint Challenge.** This challenge allows you to practice the concepts and techniques learned over the past sprint and apply them in a concrete project. This sprint explored **using Frameworks in Java**. During this sprint, you studied **Exception Handling, User Authentication, Automated Testing, and Deployment**. In your challenge this week, you will demonstrate your mastery of these skills by creating **a Java Spring REST API Application**. @@ -12,7 +12,7 @@ _You have **three hours** to complete this challenge. Plan your time accordingly ## Introduction -This is a basic bookstore database scheme with books that have authors. Books may have many authors and many authors may have written many books. The relationship between books and authors is called `wrote`. Each book can be found in only one section of the bookstore. +This is a basic bookstore database scheme with books that have authors. Books may have many authors and many authors may have written many books. The relationship between books and authors is called `wrote`. Each book can be found in only one section of the bookstore. ### Commits diff --git a/pom.xml b/pom.xml index e7bfa119..2872d54c 100644 --- a/pom.xml +++ b/pom.xml @@ -19,6 +19,10 @@ + + org.postgresql + postgresql + org.springframework.boot spring-boot-starter-data-jpa @@ -100,6 +104,22 @@ + + com.heroku.sdk + heroku-maven-plugin + 3.0.2 + + ${project.build.finalName} + false + + ${project.build.directory}/${project.build.finalName}.jar + + ${java.version} + + java $JAVA_OPTS -Dserver.port=$PORT -jar target/${project.build.finalName}.jar + + + org.springframework.boot spring-boot-maven-plugin diff --git a/src/main/java/com/lambdaschool/bookstore/config/ResourceServerConfig.java b/src/main/java/com/lambdaschool/bookstore/config/ResourceServerConfig.java index 3ba8cdaf..e8cd201e 100644 --- a/src/main/java/com/lambdaschool/bookstore/config/ResourceServerConfig.java +++ b/src/main/java/com/lambdaschool/bookstore/config/ResourceServerConfig.java @@ -57,6 +57,9 @@ public void configure(HttpSecurity http) "/oauth/revoke-token", "/logout") .authenticated() + .antMatchers("/books/books", + "/books/book/**") + .hasAnyRole("ADMIN", "DATA", "USER") .antMatchers("/roles/**") .hasAnyRole("ADMIN", "DATA") .anyRequest().denyAll() diff --git a/src/main/java/com/lambdaschool/bookstore/controllers/BookController.java b/src/main/java/com/lambdaschool/bookstore/controllers/BookController.java index 9afc07f5..ef59c893 100644 --- a/src/main/java/com/lambdaschool/bookstore/controllers/BookController.java +++ b/src/main/java/com/lambdaschool/bookstore/controllers/BookController.java @@ -6,6 +6,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -52,6 +53,7 @@ public ResponseEntity getBookById(HttpServletRequest request, } // POST http://localhost:2019/books/book + @PreAuthorize("hasAnyRole('ADMIN')") @PostMapping(value = "/book", consumes = "application/json") public ResponseEntity addNewBook(@Valid @RequestBody Book newBook) throws URISyntaxException @@ -73,6 +75,7 @@ public ResponseEntity addNewBook(@Valid @RequestBody Book newBook) throws } // PUT http://localhost:2019/books/book/1 + @PreAuthorize("hasAnyRole('ADMIN')") @PutMapping(value = "/book/{bookid}", consumes = "application/json") public ResponseEntity updateFullBook( @@ -89,6 +92,7 @@ public ResponseEntity updateFullBook( } // DELETE http://localhost:2019/books/book/1 + @PreAuthorize("hasAnyRole('ADMIN')") @DeleteMapping(value = "/book/{id}") public ResponseEntity deleteBookById( @PathVariable diff --git a/src/main/java/com/lambdaschool/bookstore/services/BookServiceImpl.java b/src/main/java/com/lambdaschool/bookstore/services/BookServiceImpl.java index d5a1ca23..a514484e 100644 --- a/src/main/java/com/lambdaschool/bookstore/services/BookServiceImpl.java +++ b/src/main/java/com/lambdaschool/bookstore/services/BookServiceImpl.java @@ -1,5 +1,6 @@ package com.lambdaschool.bookstore.services; +import com.lambdaschool.bookstore.exceptions.ResourceNotFoundException; import com.lambdaschool.bookstore.models.Author; import com.lambdaschool.bookstore.models.Book; import com.lambdaschool.bookstore.models.Wrote; @@ -45,7 +46,7 @@ public List findAll() public Book findBookById(long id) { return bookrepos.findById(id) - .orElseThrow(() -> new EntityNotFoundException("Book with id " + id + " Not Found!")); + .orElseThrow(() -> new ResourceNotFoundException("Book with id " + id + " Not Found!")); } @Transactional diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index dbcc5344..e4a4d167 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,3 +1,5 @@ +#local.run.db=H2 +local.run.db=POSTGRESQL # Configurations useful for working with H2 spring.h2.console.enabled=true spring.h2.console.path=/h2-console diff --git a/target/classes/application.properties b/target/classes/application.properties index dbcc5344..e4a4d167 100644 --- a/target/classes/application.properties +++ b/target/classes/application.properties @@ -1,3 +1,5 @@ +#local.run.db=H2 +local.run.db=POSTGRESQL # Configurations useful for working with H2 spring.h2.console.enabled=true spring.h2.console.path=/h2-console From 131d8ecaade2d2d8e931e29fe349fce5b04d4d88 Mon Sep 17 00:00:00 2001 From: Michael Cavellier Date: Fri, 21 May 2021 19:05:51 -0400 Subject: [PATCH 2/4] done some tests --- .../services/BookServiceImplUnitTestNoDB.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/test/java/com/lambdaschool/bookstore/services/BookServiceImplUnitTestNoDB.java b/src/test/java/com/lambdaschool/bookstore/services/BookServiceImplUnitTestNoDB.java index 0d812ffa..655adb2f 100644 --- a/src/test/java/com/lambdaschool/bookstore/services/BookServiceImplUnitTestNoDB.java +++ b/src/test/java/com/lambdaschool/bookstore/services/BookServiceImplUnitTestNoDB.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; import static junit.framework.TestCase.assertEquals; @@ -115,21 +116,39 @@ public void tearDown() throws @Test public void findAll() { + + Mockito.when((bookrepos.findAll())).thenReturn(myBookList); + assertEquals(5, bookService.findAll().size()); + } @Test public void findBookById() { + + Mockito.when(bookrepos.findById(2L)).thenReturn(Optional.of(myBookList.get(0))); + assertEquals("Flatterland", bookService.findBookById(2).getTitle()); + } @Test(expected = ResourceNotFoundException.class) public void notFindBookById() { + + Mockito.when(bookrepos.findById(1000L)).thenThrow(ResourceNotFoundException.class); + assertEquals("Flatterland", bookService.findBookById(1000).getTitle()); + } @Test public void delete() { + + Mockito.when(bookrepos.findById(2L)).thenReturn(Optional.of(myBookList.get(0))); + Mockito.doNothing().when(bookrepos).deleteById(2L); + bookService.delete(2); + assertEquals(5, myBookList.size()); + } @Test From a2db8a79dd061ba8d3f364c59ecaedf011556d0c Mon Sep 17 00:00:00 2001 From: Michael Cavellier Date: Fri, 21 May 2021 19:21:25 -0400 Subject: [PATCH 3/4] authentication error --- .../controllers/BookControllerUnitTestNoDB.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/test/java/com/lambdaschool/bookstore/controllers/BookControllerUnitTestNoDB.java b/src/test/java/com/lambdaschool/bookstore/controllers/BookControllerUnitTestNoDB.java index 4724b241..d41412d0 100644 --- a/src/test/java/com/lambdaschool/bookstore/controllers/BookControllerUnitTestNoDB.java +++ b/src/test/java/com/lambdaschool/bookstore/controllers/BookControllerUnitTestNoDB.java @@ -1,5 +1,6 @@ package com.lambdaschool.bookstore.controllers; +import com.fasterxml.jackson.databind.ObjectMapper; import com.lambdaschool.bookstore.BookstoreApplicationTest; import com.lambdaschool.bookstore.models.Author; import com.lambdaschool.bookstore.models.Book; @@ -8,23 +9,31 @@ import com.lambdaschool.bookstore.services.BookService; import io.restassured.module.mockmvc.RestAssuredMockMvc; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; 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.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.RequestBuilder; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import java.util.ArrayList; import java.util.List; +import static org.junit.Assert.assertEquals; + @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = BookstoreApplicationTest.class) @AutoConfigureMockMvc @@ -124,12 +133,18 @@ public void tearDown() throws public void listAllBooks() throws Exception { + + + } @Test public void getBookById() throws Exception { + + + } @Test From 90f3a2c8ac8b484b521828c93d54b16b12658541 Mon Sep 17 00:00:00 2001 From: Michael Cavellier Date: Fri, 21 May 2021 19:44:34 -0400 Subject: [PATCH 4/4] done mvp --- .../BookControllerUnitTestNoDB.java | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/lambdaschool/bookstore/controllers/BookControllerUnitTestNoDB.java b/src/test/java/com/lambdaschool/bookstore/controllers/BookControllerUnitTestNoDB.java index d41412d0..637328ef 100644 --- a/src/test/java/com/lambdaschool/bookstore/controllers/BookControllerUnitTestNoDB.java +++ b/src/test/java/com/lambdaschool/bookstore/controllers/BookControllerUnitTestNoDB.java @@ -26,6 +26,7 @@ import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.RequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; @@ -33,7 +34,9 @@ import java.util.List; import static org.junit.Assert.assertEquals; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +@WithMockUser(username = "admin", roles = {"ADMIN", "DATA"}) @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = BookstoreApplicationTest.class) @AutoConfigureMockMvc @@ -134,7 +137,14 @@ public void listAllBooks() throws Exception { - + String apiURL = "/books/books"; + Mockito.when(bookService.findAll()).thenReturn(myBookList); + RequestBuilder rb = MockMvcRequestBuilders.get(apiURL).accept(MediaType.APPLICATION_JSON); + MvcResult r = mockMvc.perform(rb).andReturn(); + String tr = r.getResponse().getContentAsString(); + ObjectMapper mapper = new ObjectMapper(); + String er = mapper.writeValueAsString(myBookList); + Assert.assertEquals(er, tr); } @@ -143,7 +153,14 @@ public void getBookById() throws Exception { - + String apiURL = "/books/book/1/"; + Mockito.when(bookService.findBookById(1)).thenReturn(myBookList.get(0)); + RequestBuilder rb = MockMvcRequestBuilders.get(apiURL).accept(MediaType.APPLICATION_JSON); + MvcResult r = mockMvc.perform(rb).andReturn(); + String tr = r.getResponse().getContentAsString(); + ObjectMapper mapper = new ObjectMapper(); + String er = mapper.writeValueAsString(myBookList.get(0)); + Assert.assertEquals(er,tr); } @@ -151,6 +168,15 @@ public void getBookById() throws public void getNoBookById() throws Exception { + + String apiUrl = "/books/book/198"; + Mockito.when(bookService.findBookById(1000)).thenReturn(null); + RequestBuilder rb = MockMvcRequestBuilders.get(apiUrl).accept(MediaType.APPLICATION_JSON); + MvcResult r = mockMvc.perform(rb).andReturn(); + String tr = r.getResponse().getContentAsString(); + String er = ""; + Assert.assertEquals(er, tr); + } @Test @@ -168,5 +194,10 @@ public void updateFullBook() public void deleteBookById() throws Exception { + + String apiUrl = "/books/book/{bookid}"; + RequestBuilder rb = MockMvcRequestBuilders.delete(apiUrl, 1).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON); + mockMvc.perform(rb).andExpect(status().isOk()).andDo(MockMvcResultHandlers.print()); + } } \ No newline at end of file