diff --git a/README.md b/README.md index e6710360..1679e6bf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Java Frameworks Sprint Challenge **Read these instructions carefully. Understand exactly what is expected _before_ starting this Sprint Challenge.** +//test for Codegrade adsfasdf 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 +13,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/src/main/java/com/lambdaschool/bookstore/controllers/BookController.java b/src/main/java/com/lambdaschool/bookstore/controllers/BookController.java index 9afc07f5..538ec2c4 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; @@ -30,8 +31,10 @@ public class BookController BookService bookService; // http://localhost:2019/books/books + @PreAuthorize(value = "hasAnyRole('ADMIN', 'DATA')") @GetMapping(value = "/books", produces = {"application/json"}) + public ResponseEntity listAllBooks(HttpServletRequest request) { List myBooks = bookService.findAll(); @@ -40,6 +43,7 @@ public ResponseEntity listAllBooks(HttpServletRequest request) } // http://localhost:2019/books/book/{bookId} + @PreAuthorize(value = "hasAnyRole('ADMIN', 'DATA')") @GetMapping(value = "/book/{bookId}", produces = {"application/json"}) public ResponseEntity getBookById(HttpServletRequest request, @@ -53,6 +57,7 @@ public ResponseEntity getBookById(HttpServletRequest request, // POST http://localhost:2019/books/book @PostMapping(value = "/book", consumes = "application/json") + @PreAuthorize(value = "hasAnyRole('ADMIN')") public ResponseEntity addNewBook(@Valid @RequestBody Book newBook) throws URISyntaxException { @@ -73,6 +78,7 @@ public ResponseEntity addNewBook(@Valid @RequestBody Book newBook) throws } // PUT http://localhost:2019/books/book/1 + @PreAuthorize(value = "hasAnyRole('ADMIN')") @PutMapping(value = "/book/{bookid}", consumes = "application/json") public ResponseEntity updateFullBook( @@ -90,6 +96,7 @@ public ResponseEntity updateFullBook( // DELETE http://localhost:2019/books/book/1 @DeleteMapping(value = "/book/{id}") + @PreAuthorize(value = "hasAnyRole('ADMIN')") public ResponseEntity deleteBookById( @PathVariable long id) diff --git a/src/main/java/com/lambdaschool/bookstore/controllers/BookControllerTest.java b/src/main/java/com/lambdaschool/bookstore/controllers/BookControllerTest.java new file mode 100644 index 00000000..e69de29b diff --git a/src/main/java/com/lambdaschool/bookstore/exceptions/CustomErrorDetails.java b/src/main/java/com/lambdaschool/bookstore/exceptions/CustomErrorDetails.java index d6f0b121..9d65efb5 100644 --- a/src/main/java/com/lambdaschool/bookstore/exceptions/CustomErrorDetails.java +++ b/src/main/java/com/lambdaschool/bookstore/exceptions/CustomErrorDetails.java @@ -1,7 +1,7 @@ package com.lambdaschool.bookstore.exceptions; -import com.lambdaschool.bookstore.services.HelperFunctions; +import com.lambdaschool.bookstore.services.HelperFunctions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.servlet.error.DefaultErrorAttributes; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/lambdaschool/bookstore/models/Auditable.java b/src/main/java/com/lambdaschool/bookstore/models/Auditable.java index 4cade773..62027762 100644 --- a/src/main/java/com/lambdaschool/bookstore/models/Auditable.java +++ b/src/main/java/com/lambdaschool/bookstore/models/Auditable.java @@ -57,4 +57,6 @@ abstract class Auditable @LastModifiedDate @Temporal(TIMESTAMP) protected Date lastmodifieddate; + + public abstract String getName(); } \ No newline at end of file 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..3e362fa5 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -2,6 +2,7 @@ spring.h2.console.enabled=true spring.h2.console.path=/h2-console spring.h2.console.settings.web-allow-others=true +local.run.db=H2 # # We set a port that is not frequently used server.port=${PORT:2019} diff --git a/src/test/java/com/lambdaschool/bookstore/controllers/BookControllerUnitTestNoDB.java b/src/test/java/com/lambdaschool/bookstore/controllers/BookControllerUnitTestNoDB.java index 4724b241..ec2e7eef 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,33 @@ 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.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.result.StatusResultMatchers; 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.mockito.ArgumentMatchers.any; + @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = BookstoreApplicationTest.class) @AutoConfigureMockMvc @@ -124,24 +135,65 @@ public void tearDown() throws 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 testResult = r.getResponse().getContentAsString(); + + ObjectMapper mapper = new ObjectMapper(); + String expectedResult = mapper.writeValueAsString(myBookList); + + assertEquals(expectedResult, testResult); + } + + private void assertEquals(String expectedResult, String testResult) { } @Test public void getBookById() throws Exception { + String apiUrl = "/books/book/1"; + Mockito.when(bookService.findBookById(1)).thenReturn(null); + + RequestBuilder rb = MockMvcRequestBuilders.get(apiUrl).accept(MediaType.APPLICATION_JSON); + MvcResult r = mockMvc.perform(rb).andReturn(); + String testResult = r.getResponse().getContentAsString(); + + ObjectMapper mapper = new ObjectMapper(); + String expectedResult = ""; + + assertEquals(expectedResult, testResult); } @Test public void getNoBookById() throws Exception { + + String apiUrl = "/books/book/101"; + Mockito.when(bookService.findBookById(101)).thenReturn(null); + RequestBuilder rb = MockMvcRequestBuilders.get(apiUrl).accept(MediaType.APPLICATION_JSON); + MvcResult r = mockMvc.perform(rb).andReturn(); + String testResult = r.getResponse().getContentAsString(); + + ObjectMapper mapper = new ObjectMapper(); + String expectedResult = ""; + assertEquals(expectedResult, testResult); + } @Test public void addNewBook() throws Exception { + + + } + + private StatusResultMatchers status() { } @Test diff --git a/src/test/java/com/lambdaschool/bookstore/services/BookServiceImplUnitTestNoDB.java b/src/test/java/com/lambdaschool/bookstore/services/BookServiceImplUnitTestNoDB.java index 0d812ffa..33999a92 100644 --- a/src/test/java/com/lambdaschool/bookstore/services/BookServiceImplUnitTestNoDB.java +++ b/src/test/java/com/lambdaschool/bookstore/services/BookServiceImplUnitTestNoDB.java @@ -115,26 +115,41 @@ public void tearDown() throws @Test public void findAll() { + assertEquals(5, bookService.findAll().size()); } @Test public void findBookById() { + assertEquals("Flatterland", bookService.findBookById(2).getTitle()); } @Test(expected = ResourceNotFoundException.class) public void notFindBookById() { + assertEquals("Flatterland", bookService.findBookById(16).getTitle()); } @Test public void delete() { + bookService.delete(3); + assertEquals(2, bookService.findAll().size()); } @Test public void save() { + + String bName = "test book" + Book btest + + Book addBook = bookService.save(btest); + assertNotNull(addBook); + assertEquals(bName, addBook.getName()); + } + + private void assertNotNull(Book addBook) { } @Test