users = new ArrayList<>();
+// users.add(new UserRoles(new User(), r2));
+// User u3 = new User("barnbarn", "ILuvM4th!", users);
+// u3.getQuotes().add(new Quote("Live long and prosper", u3));
+// u3.getQuotes().add(new Quote("The enemy of my enemy is the enemy I kill last", u3));
+// u3.getQuotes().add(new Quote("Beam me up", u3));
+// userService.save(u3);
+//
+// users = new ArrayList<>();
+// users.add(new UserRoles(new User(), r2));
+// User u4 = new User("Bob", "password", users);
+// userService.save(u4);
+//
+// users = new ArrayList<>();
+// users.add(new UserRoles(new User(), r2));
+// User u5 = new User("Jane", "password", users);
+// userService.save(u5);
+// }
+//}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/StartHereApplication.java b/StartHere/src/main/java/com/lambdaschool/starthere/StartHereApplication.java
new file mode 100644
index 00000000..49516924
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/StartHereApplication.java
@@ -0,0 +1,27 @@
+package com.lambdaschool.starthere;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ApplicationContext;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.web.servlet.DispatcherServlet;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@EnableWebMvc
+@EnableJpaAuditing
+@SpringBootApplication
+@EnableSwagger2
+public class StartHereApplication
+{
+
+ public static void main(String[] args)
+ {
+ ApplicationContext ctx = SpringApplication.run(StartHereApplication.class, args);
+
+ DispatcherServlet dispatcherServlet = (DispatcherServlet) ctx.getBean("dispatcherServlet");
+ dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
+
+ }
+
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/config/AuthorizationServerConfig.java b/StartHere/src/main/java/com/lambdaschool/starthere/config/AuthorizationServerConfig.java
new file mode 100644
index 00000000..f639db89
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/config/AuthorizationServerConfig.java
@@ -0,0 +1,54 @@
+package com.lambdaschool.starthere.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
+import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+
+@Configuration
+@EnableAuthorizationServer
+public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter
+{
+ // static final String CLIENT_ID = System.getenv("OAUTHCLIENTID"); // read from environment variable
+ // static final String CLIENT_SECRET = System.getenv("OAUTHCLIENTSECRET"); // read from environment variable
+ static final String CLIENT_ID = "lambda-client";
+ static final String CLIENT_SECRET = "lambda-secret";
+
+ static final String GRANT_TYPE_PASSWORD = "password";
+ static final String AUTHORIZATION_CODE = "authorization_code";
+ static final String REFRESH_TOKEN = "refresh_token";
+ static final String IMPLICIT = "implicit";
+ static final String SCOPE_READ = "read";
+ static final String SCOPE_WRITE = "write";
+ static final String TRUST = "trust";
+ static final int ACCESS_TOKEN_VALIDITY_SECONDS = 1 * 60 * 60;
+ static final int FREFRESH_TOKEN_VALIDITY_SECONDS = 6 * 60 * 60;
+
+ @Autowired
+ private TokenStore tokenStore;
+
+ @Autowired
+ private AuthenticationManager authenticationManager;
+
+ @Autowired
+ private PasswordEncoder encoder;
+
+ @Override
+ public void configure(ClientDetailsServiceConfigurer configurer) throws Exception
+ {
+ // .authorizedGrantTypes(GRANT_TYPE_PASSWORD, AUTHORIZATION_CODE, REFRESH_TOKEN, IMPLICIT)
+
+ configurer.inMemory().withClient(CLIENT_ID).secret(encoder.encode(CLIENT_SECRET)).authorizedGrantTypes(GRANT_TYPE_PASSWORD, AUTHORIZATION_CODE, IMPLICIT).scopes(SCOPE_READ, SCOPE_WRITE, TRUST).accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS).refreshTokenValiditySeconds(FREFRESH_TOKEN_VALIDITY_SECONDS);
+ }
+
+ @Override
+ public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception
+ {
+ endpoints.tokenStore(tokenStore).authenticationManager(authenticationManager);
+ }
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/config/H2ServerConfiguration.java b/StartHere/src/main/java/com/lambdaschool/starthere/config/H2ServerConfiguration.java
new file mode 100644
index 00000000..73984a41
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/config/H2ServerConfiguration.java
@@ -0,0 +1,48 @@
+package com.lambdaschool.starthere.config;
+
+import org.h2.tools.Server;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.sql.SQLException;
+
+@Configuration
+// taken from https://techdev.io/en/developer-blog/querying-the-embedded-h2-database-of-a-spring-boot-application
+// necessary for using the database tool built into intellij
+public class H2ServerConfiguration
+{
+
+ // TCP port for remote connections, default 9092
+ @Value("${h2.tcp.port:9092}")
+ private String h2TcpPort;
+
+ // Web port, default 8082
+ @Value("${h2.web.port:8082}")
+ private String h2WebPort;
+
+ /**
+ * TCP connection to connect with SQL clients to the embedded h2 database.
+ *
+ * Connect to "jdbc:h2:tcp://localhost:9092/mem:testdb", username "sa", password empty.
+ */
+ @Bean
+ @ConditionalOnExpression("${h2.tcp.enabled:true}")
+ public Server h2TcpServer() throws SQLException
+ {
+ return Server.createTcpServer("-tcp", "-tcpAllowOthers", "-tcpPort", h2TcpPort).start();
+ }
+
+ /**
+ * Web console for the embedded h2 database.
+ *
+ * Go to http://localhost:8082 and connect to the database "jdbc:h2:mem:testdb", username "sa", password empty.
+ */
+ @Bean
+ @ConditionalOnExpression("${h2.web.enabled:true}")
+ public Server h2WebServer() throws SQLException
+ {
+ return Server.createWebServer("-web", "-webAllowOthers", "-webPort", h2WebPort).start();
+ }
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/config/ResourceServerConfig.java b/StartHere/src/main/java/com/lambdaschool/starthere/config/ResourceServerConfig.java
new file mode 100644
index 00000000..995c8c57
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/config/ResourceServerConfig.java
@@ -0,0 +1,43 @@
+package com.lambdaschool.starthere.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
+import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
+
+@Configuration
+@EnableResourceServer
+public class ResourceServerConfig extends ResourceServerConfigurerAdapter
+{
+
+ private static final String RESOURCE_ID = "resource_id";
+
+ @Override
+ public void configure(ResourceServerSecurityConfigurer resources)
+ {
+ resources.resourceId(RESOURCE_ID).stateless(false);
+ }
+
+ @Override
+ public void configure(HttpSecurity http) throws Exception
+ {
+ // http.anonymous().disable();
+ http.authorizeRequests().antMatchers("/",
+ "/h2-console/**",
+ "/swagger-resources/**",
+ "/swagger-resources/configuration/ui",
+ "/swagger-resources/configuration/security",
+ "/swagger-resource/**",
+ "/swagger-ui.html",
+ "/v2/api-docs",
+ "/webjars/**",
+ "/createnewuser",
+ "/otherapis/**").permitAll().antMatchers("/users/**", "/oauth/revoke-token").authenticated().antMatchers("/roles/**").hasAnyRole("ADMIN", "USER", "DATA").antMatchers("/actuator/**").hasAnyRole("ADMIN").and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
+
+ // http.requiresChannel().anyRequest().requiresSecure();
+ http.csrf().disable();
+ http.headers().frameOptions().disable();
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/config/SecurityConfig.java b/StartHere/src/main/java/com/lambdaschool/starthere/config/SecurityConfig.java
new file mode 100644
index 00000000..b9c05eb5
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/config/SecurityConfig.java
@@ -0,0 +1,52 @@
+package com.lambdaschool.starthere.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
+
+import javax.annotation.Resource;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class SecurityConfig extends WebSecurityConfigurerAdapter
+{
+
+ @Resource(name = "userService")
+ private UserDetailsService userDetailsService;
+
+ @Override
+ @Bean
+ public AuthenticationManager authenticationManagerBean() throws Exception
+ {
+ return super.authenticationManagerBean();
+ }
+
+ @Autowired
+ public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception
+ {
+ auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
+ }
+
+ @Bean
+ public TokenStore tokenStore()
+ {
+ return new InMemoryTokenStore();
+ }
+
+ @Bean
+ public PasswordEncoder encoder()
+ {
+ return new BCryptPasswordEncoder();
+ }
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/config/SimpleCorsFilter.java b/StartHere/src/main/java/com/lambdaschool/starthere/config/SimpleCorsFilter.java
new file mode 100644
index 00000000..e6ece179
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/config/SimpleCorsFilter.java
@@ -0,0 +1,52 @@
+package com.lambdaschool.starthere.config;
+
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.HttpMethod;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+@Order(Ordered.HIGHEST_PRECEDENCE)
+public class SimpleCorsFilter implements Filter
+{
+
+ public SimpleCorsFilter()
+ {
+ }
+
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
+ {
+ HttpServletResponse response = (HttpServletResponse) res;
+ HttpServletRequest request = (HttpServletRequest) req;
+ response.setHeader("Access-Control-Allow-Origin", "*");
+ // response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
+ response.setHeader("Access-Control-Allow-Methods", "*");
+ // response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, content-type, access_token");
+ response.setHeader("Access-Control-Allow-Headers", "*");
+ response.setHeader("Access-Control-Max-Age", "3600");
+
+ if (HttpMethod.OPTIONS.name().equalsIgnoreCase(((HttpServletRequest) req).getMethod()))
+ {
+ response.setStatus(HttpServletResponse.SC_OK);
+ } else
+ {
+ chain.doFilter(req, res);
+ }
+ }
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException
+ {
+ }
+
+ @Override
+ public void destroy()
+ {
+ }
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/config/Swagger2Config.java b/StartHere/src/main/java/com/lambdaschool/starthere/config/Swagger2Config.java
new file mode 100644
index 00000000..a49e6391
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/config/Swagger2Config.java
@@ -0,0 +1,33 @@
+package com.lambdaschool.starthere.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.domain.Pageable;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+
+// http://localhost:2019/swagger-ui.html
+@Configuration
+public class Swagger2Config
+{
+ @Bean
+ public Docket api()
+ {
+ return new Docket(DocumentationType.SWAGGER_2)
+ .select().apis(RequestHandlerSelectors.any())
+ .paths(PathSelectors.any()).build()
+ .useDefaultResponseMessages(false) // Allows only my exception responses
+ .ignoredParameterTypes(Pageable.class) // allows only my paging parameter list
+ .apiInfo(apiEndPointsInfo());
+ }
+
+ private ApiInfo apiEndPointsInfo()
+ {
+ return new ApiInfoBuilder().title("Java String Back End Starting Project").description("A starting application for developing Java Spring Back End Projects").contact(new Contact("John Mitchell", "http://www.lambdaschool.com", "john@lambdaschool.com")).license("MIT").licenseUrl("https://github.com/LambdaSchool/java-starthere/blob/master/LICENSE").version("1.0.0").build();
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/config/WebConfig.java b/StartHere/src/main/java/com/lambdaschool/starthere/config/WebConfig.java
new file mode 100644
index 00000000..1c9ba680
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/config/WebConfig.java
@@ -0,0 +1,17 @@
+package com.lambdaschool.starthere.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer
+{
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry)
+ {
+ registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
+
+ registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/controllers/APIsController.java b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/APIsController.java
new file mode 100644
index 00000000..9b2c47e8
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/APIsController.java
@@ -0,0 +1,56 @@
+package com.lambdaschool.starthere.controllers;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.lambdaschool.starthere.models.APIOpenLibrary;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/otherapis")
+public class APIsController
+{
+ private static final Logger logger = LoggerFactory.getLogger(RolesController.class);
+ private RestTemplate restTemplate = new RestTemplate();
+
+ // taken from https://openlibrary.org/dev/docs/api/books
+ // returns a list of books - you can include multiple ISBNs in a single request
+ // This API returns a map instead of the standard list
+ //
+ // localhost:2019/otherapis/openlibrary/0982477562
+
+ @GetMapping(value = "/openlibrary/{isbn}",
+ produces = {"application/json"})
+ public ResponseEntity> listABookGivenISBN(HttpServletRequest request, @PathVariable String isbn)
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ String requestURL = "https://openlibrary.org/api/books?bibkeys=" + "ISBN:" + isbn + "&format=json";
+
+ ParameterizedTypeReference> responseType =
+ new ParameterizedTypeReference>() {};
+ ResponseEntity> responseEntity =
+ restTemplate.exchange(requestURL,
+ HttpMethod.GET, null, responseType);
+
+ Map ourBooks = responseEntity.getBody();
+
+ System.out.println(ourBooks);
+ return new ResponseEntity<>(ourBooks, HttpStatus.OK);
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/controllers/AuthorController.java b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/AuthorController.java
new file mode 100644
index 00000000..45b1a183
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/AuthorController.java
@@ -0,0 +1,39 @@
+package com.lambdaschool.starthere.controllers;
+
+import com.lambdaschool.starthere.models.Author;
+import com.lambdaschool.starthere.services.AuthorService;
+
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@RestController
+public class AuthorController {
+
+ @Autowired
+ private AuthorService authorService;
+
+ @ApiOperation(value = "Return all Authors", response = Author.class, responseContainer = "List")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "page", dataType = "integr", paramType = "query",
+ value = "Results page you want to retrieve (0..N)"),
+ @ApiImplicitParam(name = "size", dataType = "integer", paramType = "query",
+ value = "Number of records per page."),
+ @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query",
+ value = "Sorting criteria in the format: property(,asc|desc). " +
+ "Default sort order is ascending. " +
+ "Multiple sort criteria are supported.")})
+ @GetMapping(value = "/authors")
+ public ResponseEntity> findAllAuthors(Pageable pageable) {
+ List authorList = authorService.findAll(pageable);
+ return new ResponseEntity<>(authorList, HttpStatus.OK);
+ }
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/controllers/BookController.java b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/BookController.java
new file mode 100644
index 00000000..2ba8bd6d
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/BookController.java
@@ -0,0 +1,67 @@
+package com.lambdaschool.starthere.controllers;
+
+import com.lambdaschool.starthere.models.Author;
+import com.lambdaschool.starthere.models.Book;
+import com.lambdaschool.starthere.models.ErrorDetail;
+import com.lambdaschool.starthere.services.BookService;
+import io.swagger.annotations.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Pageable;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+public class BookController {
+
+ @Autowired
+ private BookService bookService;
+
+ @ApiOperation(value = "Return all Books", response = Book.class, responseContainer = "List")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "page", dataType = "integr", paramType = "query",
+ value = "Results page you want to retrieve (0..N)"),
+ @ApiImplicitParam(name = "size", dataType = "integer", paramType = "query",
+ value = "Number of records per page."),
+ @ApiImplicitParam(name = "sort", allowMultiple = true, dataType = "string", paramType = "query",
+ value = "Sorting criteria in the format: property(,asc|desc). " +
+ "Default sort order is ascending. " +
+ "Multiple sort criteria are supported.")})
+ @GetMapping(value = "/books")
+ public ResponseEntity> findAllBooks(Pageable pageable){
+ return new ResponseEntity<>(bookService.findAll(pageable), HttpStatus.OK);
+ }
+
+ @ApiOperation(value = "Update a current Book", response = Book.class)
+ @ApiResponses(value = {
+ @ApiResponse(code = 201, message = "Successfully updated book", response = void.class),
+ @ApiResponse(code = 500, message = "Failed to update book", response = ErrorDetail.class)
+ })
+ @PutMapping(value = "/data/books/{id}")
+ public ResponseEntity> updateBook(@PathVariable long id, @RequestBody Book book){
+ bookService.updateBook(book, id);
+ return new ResponseEntity<>(book, HttpStatus.OK);
+ }
+
+ @ApiOperation(value = "Match an existing book, with an existing author", response = void.class)
+ @ApiResponses(value = {
+ @ApiResponse(code = 201, message = "Successfully matched book with author", response = void.class),
+ @ApiResponse(code = 500, message = "Failed to match book with author", response = ErrorDetail.class)
+ })
+ @PostMapping(value = "/data/books/{id}")
+ public ResponseEntity> matchBookWithAuthor(@PathVariable long id, @RequestBody Author author){
+ bookService.assignAuthor(id, author.getAuthorid());
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+
+ @ApiOperation(value = "Delete a current book", response = void.class)
+ @ApiResponses(value = {
+ @ApiResponse(code = 201, message = "Succesfully deleted book", response = void.class),
+ @ApiResponse(code = 500, message = "Failed to delete book", response = ErrorDetail.class)
+ })
+ @DeleteMapping(value = "/data/books/{id}")
+ public ResponseEntity> deleteBook(@PathVariable long id){
+ bookService.delete(id);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/controllers/LogoutController.java b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/LogoutController.java
new file mode 100644
index 00000000..ce35115c
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/LogoutController.java
@@ -0,0 +1,33 @@
+package com.lambdaschool.starthere.controllers;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+import javax.servlet.http.HttpServletRequest;
+
+@Controller
+public class LogoutController
+{
+ @Autowired
+ private TokenStore tokenStore;
+
+ @RequestMapping(value = "/oauth/revoke-token",
+ method = RequestMethod.GET)
+ @ResponseStatus(HttpStatus.OK)
+ public void logout(HttpServletRequest request)
+ {
+ String authHeader = request.getHeader("Authorization");
+ if (authHeader != null)
+ {
+ String tokenValue = authHeader.replace("Bearer", "").trim();
+ OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
+ tokenStore.removeAccessToken(accessToken);
+ }
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/controllers/OpenController.java b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/OpenController.java
new file mode 100644
index 00000000..f5a8038b
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/OpenController.java
@@ -0,0 +1,59 @@
+package com.lambdaschool.starthere.controllers;
+
+import com.lambdaschool.starthere.models.User;
+import com.lambdaschool.starthere.models.UserRoles;
+import com.lambdaschool.starthere.services.RoleService;
+import com.lambdaschool.starthere.services.UserService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+
+@RestController
+public class OpenController
+{
+ private static final Logger logger = LoggerFactory.getLogger(RolesController.class);
+
+ @Autowired
+ private UserService userService;
+
+ @Autowired
+ private RoleService roleService;
+
+ @PostMapping(value = "/createnewuser",
+ consumes = {"application/json"},
+ produces = {"application/json"})
+ public ResponseEntity> addNewUser(HttpServletRequest request, @Valid
+ @RequestBody
+ User newuser) throws URISyntaxException
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ ArrayList newRoles = new ArrayList<>();
+ newRoles.add(new UserRoles(newuser, roleService.findByName("user")));
+ newuser.setUserRoles(newRoles);
+
+ newuser = userService.save(newuser);
+
+ // set the location header for the newly created resource - to another controller!
+ HttpHeaders responseHeaders = new HttpHeaders();
+ URI newRestaurantURI = ServletUriComponentsBuilder.fromUriString(request.getServerName() + ":" + request.getLocalPort() + "/users/user/{userId}").buildAndExpand(newuser.getUserid()).toUri();
+ responseHeaders.setLocation(newRestaurantURI);
+
+
+ return new ResponseEntity<>(null, responseHeaders, HttpStatus.CREATED);
+ }
+
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/controllers/QuotesController.java b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/QuotesController.java
new file mode 100644
index 00000000..24fa8817
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/QuotesController.java
@@ -0,0 +1,94 @@
+package com.lambdaschool.starthere.controllers;
+
+import com.lambdaschool.starthere.models.Quote;
+import com.lambdaschool.starthere.services.QuoteService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+@RestController
+@RequestMapping("/quotes")
+public class QuotesController
+{
+ private static final Logger logger = LoggerFactory.getLogger(RolesController.class);
+
+ @Autowired
+ QuoteService quoteService;
+
+ @GetMapping(value = "/quotes",
+ produces = {"application/json"})
+ public ResponseEntity> listAllQuotes(HttpServletRequest request)
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ List allQuotes = quoteService.findAll();
+ return new ResponseEntity<>(allQuotes, HttpStatus.OK);
+ }
+
+
+ @GetMapping(value = "/quote/{quoteId}",
+ produces = {"application/json"})
+ public ResponseEntity> getQuote(HttpServletRequest request,
+ @PathVariable
+ Long quoteId)
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ Quote q = quoteService.findQuoteById(quoteId);
+ return new ResponseEntity<>(q, HttpStatus.OK);
+ }
+
+
+ @GetMapping(value = "/username/{userName}",
+ produces = {"application/json"})
+ public ResponseEntity> findQuoteByUserName(HttpServletRequest request,
+ @PathVariable
+ String userName)
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ List theQuotes = quoteService.findByUserName(userName);
+ return new ResponseEntity<>(theQuotes, HttpStatus.OK);
+ }
+
+
+ @PostMapping(value = "/quote")
+ public ResponseEntity> addNewQuote(HttpServletRequest request, @Valid
+ @RequestBody
+ Quote newQuote) throws URISyntaxException
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ newQuote = quoteService.save(newQuote);
+
+ // set the location header for the newly created resource
+ HttpHeaders responseHeaders = new HttpHeaders();
+ URI newQuoteURI = ServletUriComponentsBuilder.fromCurrentRequest().path("/{quoteid}").buildAndExpand(newQuote.getQuotesid()).toUri();
+ responseHeaders.setLocation(newQuoteURI);
+
+ return new ResponseEntity<>(null, responseHeaders, HttpStatus.CREATED);
+ }
+
+
+ @DeleteMapping("/quote/{id}")
+ public ResponseEntity> deleteQuoteById(HttpServletRequest request,
+ @PathVariable
+ long id)
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ quoteService.delete(id);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/controllers/RolesController.java b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/RolesController.java
new file mode 100644
index 00000000..fd5f6743
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/RolesController.java
@@ -0,0 +1,84 @@
+package com.lambdaschool.starthere.controllers;
+
+import com.lambdaschool.starthere.models.Role;
+import com.lambdaschool.starthere.services.RoleService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+@RestController
+@RequestMapping("/roles")
+public class RolesController
+{
+ private static final Logger logger = LoggerFactory.getLogger(RolesController.class);
+ @Autowired
+ RoleService roleService;
+
+ @GetMapping(value = "/roles",
+ produces = {"application/json"})
+ public ResponseEntity> listRoles(HttpServletRequest request)
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ List allRoles = roleService.findAll();
+ return new ResponseEntity<>(allRoles, HttpStatus.OK);
+ }
+
+
+ @GetMapping(value = "/role/{roleId}",
+ produces = {"application/json"})
+ public ResponseEntity> getRole(HttpServletRequest request,
+ @PathVariable
+ Long roleId)
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ Role r = roleService.findRoleById(roleId);
+ return new ResponseEntity<>(r, HttpStatus.OK);
+ }
+
+
+ @PostMapping(value = "/role")
+ public ResponseEntity> addNewRole(HttpServletRequest request, @Valid
+ @RequestBody
+ Role newRole) throws URISyntaxException
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ newRole = roleService.save(newRole);
+
+ // set the location header for the newly created resource
+ HttpHeaders responseHeaders = new HttpHeaders();
+ URI newRoleURI = ServletUriComponentsBuilder.fromCurrentRequest().path("/{roleid}").buildAndExpand(newRole.getRoleid()).toUri();
+ responseHeaders.setLocation(newRoleURI);
+
+ return new ResponseEntity<>(null, responseHeaders, HttpStatus.CREATED);
+ }
+
+
+// @PostMapping(value = "/user/{userid}/role/{roleid}")
+
+
+
+ @DeleteMapping("/role/{id}")
+ public ResponseEntity> deleteRoleById(HttpServletRequest request,
+ @PathVariable
+ long id)
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ roleService.delete(id);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/controllers/UserController.java b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/UserController.java
new file mode 100644
index 00000000..66446698
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/controllers/UserController.java
@@ -0,0 +1,114 @@
+package com.lambdaschool.starthere.controllers;
+
+import com.lambdaschool.starthere.models.User;
+import com.lambdaschool.starthere.services.UserService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+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.security.core.Authentication;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+@RestController
+@RequestMapping("/users")
+public class UserController
+{
+ private static final Logger logger = LoggerFactory.getLogger(RolesController.class);
+
+ @Autowired
+ private UserService userService;
+
+ @PreAuthorize("hasAuthority('ROLE_ADMIN')")
+ @GetMapping(value = "/users",
+ produces = {"application/json"})
+ public ResponseEntity> listAllUsers(HttpServletRequest request)
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ List myUsers = userService.findAll();
+ return new ResponseEntity<>(myUsers, HttpStatus.OK);
+ }
+
+
+ @PreAuthorize("hasAuthority('ROLE_ADMIN')")
+ @GetMapping(value = "/user/{userId}",
+ produces = {"application/json"})
+ public ResponseEntity> getUser(HttpServletRequest request,
+ @PathVariable
+ Long userId)
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ User u = userService.findUserById(userId);
+ return new ResponseEntity<>(u, HttpStatus.OK);
+ }
+
+
+ @GetMapping(value = "/getusername",
+ produces = {"application/json"})
+ @ResponseBody
+ public ResponseEntity> getCurrentUserName(HttpServletRequest request, Authentication authentication)
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ return new ResponseEntity<>(authentication.getPrincipal(), HttpStatus.OK);
+ }
+
+
+ @PreAuthorize("hasAuthority('ROLE_ADMIN')")
+ @PostMapping(value = "/user",
+ consumes = {"application/json"},
+ produces = {"application/json"})
+ public ResponseEntity> addNewUser(HttpServletRequest request, @Valid
+ @RequestBody
+ User newuser) throws URISyntaxException
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ newuser = userService.save(newuser);
+
+ // set the location header for the newly created resource
+ HttpHeaders responseHeaders = new HttpHeaders();
+ URI newUserURI = ServletUriComponentsBuilder.fromCurrentRequest().path("/{userid}").buildAndExpand(newuser.getUserid()).toUri();
+ responseHeaders.setLocation(newUserURI);
+
+ return new ResponseEntity<>(null, responseHeaders, HttpStatus.CREATED);
+ }
+
+
+ @PutMapping(value = "/user/{id}")
+ public ResponseEntity> updateUser(HttpServletRequest request,
+ @RequestBody
+ User updateUser,
+ @PathVariable
+ long id)
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ userService.update(updateUser, id);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+
+
+ @PreAuthorize("hasAuthority('ROLE_ADMIN')")
+ @DeleteMapping("/user/{id}")
+ public ResponseEntity> deleteUserById(HttpServletRequest request,
+ @PathVariable
+ long id)
+ {
+ logger.trace(request.getRequestURI() + " accessed");
+
+ userService.delete(id);
+ return new ResponseEntity<>(HttpStatus.OK);
+ }
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/exceptions/ResourceNotFoundException.java b/StartHere/src/main/java/com/lambdaschool/starthere/exceptions/ResourceNotFoundException.java
new file mode 100644
index 00000000..b9cc5018
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/exceptions/ResourceNotFoundException.java
@@ -0,0 +1,20 @@
+package com.lambdaschool.starthere.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(value = HttpStatus.NOT_FOUND)
+public class ResourceNotFoundException extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+
+ public ResourceNotFoundException(String message)
+ {
+ super(message);
+ }
+
+ public ResourceNotFoundException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/exceptions/ValidationError.java b/StartHere/src/main/java/com/lambdaschool/starthere/exceptions/ValidationError.java
new file mode 100644
index 00000000..8094994e
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/exceptions/ValidationError.java
@@ -0,0 +1,27 @@
+package com.lambdaschool.starthere.exceptions;
+
+public class ValidationError
+{
+ private String Code;
+ private String message;
+
+ public String getCode()
+ {
+ return Code;
+ }
+
+ public void setCode(String code)
+ {
+ Code = code;
+ }
+
+ public String getMessage()
+ {
+ return message;
+ }
+
+ public void setMessage(String message)
+ {
+ this.message = message;
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/handlers/RestExceptionHandler.java b/StartHere/src/main/java/com/lambdaschool/starthere/handlers/RestExceptionHandler.java
new file mode 100644
index 00000000..73344928
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/handlers/RestExceptionHandler.java
@@ -0,0 +1,82 @@
+package com.lambdaschool.starthere.handlers;
+
+import com.lambdaschool.starthere.exceptions.ResourceNotFoundException;
+import com.lambdaschool.starthere.models.ErrorDetail;
+import org.springframework.beans.TypeMismatchException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.MessageSource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.context.request.WebRequest;
+import org.springframework.web.servlet.NoHandlerFoundException;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
+
+import javax.persistence.EntityNotFoundException;
+import javax.servlet.http.HttpServletRequest;
+import java.util.Date;
+
+// bean shared across controller classes
+@ControllerAdvice
+public class RestExceptionHandler extends ResponseEntityExceptionHandler
+{
+ @Autowired
+ private MessageSource messageSource;
+
+ @ExceptionHandler({ResourceNotFoundException.class, EntityNotFoundException.class, UsernameNotFoundException.class})
+ public ResponseEntity> handleResourceNotFoundException(ResourceNotFoundException rnfe, HttpServletRequest request)
+ {
+ ErrorDetail errorDetail = new ErrorDetail();
+ errorDetail.setTimestamp(new Date().getTime());
+ errorDetail.setStatus(HttpStatus.NOT_FOUND.value());
+ errorDetail.setTitle("Resource Not Found");
+ errorDetail.setDetail(rnfe.getMessage());
+ errorDetail.setDeveloperMessage(rnfe.getClass().getName());
+
+ return new ResponseEntity<>(errorDetail, null, HttpStatus.NOT_FOUND);
+ }
+
+
+ @Override
+ protected ResponseEntity handleTypeMismatch(TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
+ {
+ ErrorDetail errorDetail = new ErrorDetail();
+ errorDetail.setTimestamp(new Date().getTime());
+ errorDetail.setStatus(HttpStatus.BAD_REQUEST.value());
+ errorDetail.setTitle(ex.getPropertyName());
+ errorDetail.setDetail(ex.getMessage());
+ errorDetail.setDeveloperMessage(request.getDescription(true));
+
+ return new ResponseEntity<>(errorDetail, null, HttpStatus.NOT_FOUND);
+ }
+
+ @Override
+ protected ResponseEntity handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
+ {
+ ErrorDetail errorDetail = new ErrorDetail();
+ errorDetail.setTimestamp(new Date().getTime());
+ errorDetail.setStatus(HttpStatus.NOT_FOUND.value());
+ errorDetail.setTitle(ex.getRequestURL());
+ errorDetail.setDetail(request.getDescription(true));
+ errorDetail.setDeveloperMessage("Rest Handler Not Found (check for valid URI)");
+
+ return new ResponseEntity<>(errorDetail, null, HttpStatus.NOT_FOUND);
+ }
+
+ @Override
+ protected ResponseEntity handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
+ {
+ ErrorDetail errorDetail = new ErrorDetail();
+ errorDetail.setTimestamp(new Date().getTime());
+ errorDetail.setStatus(HttpStatus.NOT_FOUND.value());
+ errorDetail.setTitle(ex.getMethod());
+ errorDetail.setDetail(request.getDescription(true));
+ errorDetail.setDeveloperMessage("HTTP Method Not Valid for Endpoint (check for valid URI and proper HTTP Method)");
+
+ return new ResponseEntity<>(errorDetail, null, HttpStatus.NOT_FOUND);
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/models/APIOpenLibrary.java b/StartHere/src/main/java/com/lambdaschool/starthere/models/APIOpenLibrary.java
new file mode 100644
index 00000000..91879d0b
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/models/APIOpenLibrary.java
@@ -0,0 +1,72 @@
+package com.lambdaschool.starthere.models;
+
+// Taken from the output of https://openlibrary.org/api/books?bibkeys=ISBN:0982477562&format=json
+// This class must match the JSON object
+public class APIOpenLibrary
+{
+ private String bib_key;
+ private String preview;
+ private String thumbnail_url;
+ private String preview_url;
+ private String info_url;
+
+ public APIOpenLibrary()
+ {
+ }
+
+ public String getBib_key()
+ {
+ return bib_key;
+ }
+
+ public void setBib_key(String bib_key)
+ {
+ this.bib_key = bib_key;
+ }
+
+ public String getThumbnail_url()
+ {
+ return thumbnail_url;
+ }
+
+ public void setThumbnail_url(String thumbnail_url)
+ {
+ this.thumbnail_url = thumbnail_url;
+ }
+
+ public String getPreview()
+ {
+ return preview;
+ }
+
+ public void setPreview(String preview)
+ {
+ this.preview = preview;
+ }
+
+ public String getPreview_url()
+ {
+ return preview_url;
+ }
+
+ public void setPreview_url(String preview_url)
+ {
+ this.preview_url = preview_url;
+ }
+
+ public String getInfo_url()
+ {
+ return info_url;
+ }
+
+ public void setInfo_url(String info_url)
+ {
+ this.info_url = info_url;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "APIOpenLibrary{" + "bib_key='" + bib_key + '\'' + ", preview='" + preview + '\'' + ", thumbnail_url='" + thumbnail_url + '\'' + ", preview_url='" + preview_url + '\'' + ", info_url='" + info_url + '\'' + '}';
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/models/Auditable.java b/StartHere/src/main/java/com/lambdaschool/starthere/models/Auditable.java
new file mode 100644
index 00000000..8004fe50
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/models/Auditable.java
@@ -0,0 +1,33 @@
+package com.lambdaschool.starthere.models;
+
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedBy;
+import org.springframework.data.annotation.LastModifiedDate;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+import javax.persistence.EntityListeners;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Temporal;
+import java.util.Date;
+
+import static javax.persistence.TemporalType.TIMESTAMP;
+
+@MappedSuperclass
+@EntityListeners(AuditingEntityListener.class)
+abstract class Auditable
+{
+ @CreatedBy
+ protected String createdBy;
+
+ @CreatedDate
+ @Temporal(TIMESTAMP)
+ protected Date createdDate;
+
+ @LastModifiedBy
+ protected String lastModifiedBy;
+
+ @LastModifiedDate
+ @Temporal(TIMESTAMP)
+ protected Date lastModifiedDate;
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/models/Author.java b/StartHere/src/main/java/com/lambdaschool/starthere/models/Author.java
new file mode 100644
index 00000000..3d714904
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/models/Author.java
@@ -0,0 +1,68 @@
+package com.lambdaschool.starthere.models;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import javax.persistence.*;
+import java.util.ArrayList;
+import java.util.List;
+
+@Entity
+public class Author extends Auditable {
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long authorid;
+
+ private String lastname;
+
+ private String firstname;
+
+ @ManyToMany(mappedBy = "authorList")
+ @JsonIgnoreProperties(value = "authorList")
+ List bookList = new ArrayList<>();
+
+ public Author() {
+ }
+
+ public Author(String lastname, String firstname) {
+ this.lastname = lastname;
+ this.firstname = firstname;
+ }
+
+ public Author(String lastname, String firstname, List bookList) {
+ this.lastname = lastname;
+ this.firstname = firstname;
+ this.bookList = bookList;
+ }
+
+ public long getAuthorid() {
+ return authorid;
+ }
+
+ public void setAuthorid(long authorid) {
+ this.authorid = authorid;
+ }
+
+ public String getLastname() {
+ return lastname;
+ }
+
+ public void setLastname(String lastname) {
+ this.lastname = lastname;
+ }
+
+ public String getFirstname() {
+ return firstname;
+ }
+
+ public void setFirstname(String firstname) {
+ this.firstname = firstname;
+ }
+
+ public List getBookList() {
+ return bookList;
+ }
+
+ public void setBookList(List bookList) {
+ this.bookList = bookList;
+ }
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/models/Book.java b/StartHere/src/main/java/com/lambdaschool/starthere/models/Book.java
new file mode 100644
index 00000000..ba551d1c
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/models/Book.java
@@ -0,0 +1,82 @@
+package com.lambdaschool.starthere.models;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import javax.persistence.*;
+import java.util.ArrayList;
+import java.util.List;
+
+@Entity
+public class Book extends Auditable {
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long bookid;
+
+ @Column(nullable = false)
+ private String booktitle;
+
+ private String isbn;
+
+ private String copy;
+
+ @ManyToMany
+ @JsonIgnoreProperties(value = "bookList")
+ @JoinTable(name = "wrote", joinColumns = {@JoinColumn(name = "bookid")}, inverseJoinColumns = {@JoinColumn(name = "authorid")})
+ List authorList = new ArrayList<>();
+
+ public Book() {
+ }
+
+ public Book(String booktitle, String isbn, String copy) {
+ this.booktitle = booktitle;
+ this.isbn = isbn;
+ this.copy = copy;
+ }
+
+ public Book(String booktitle, String isbn, String copy, List authorList) {
+ this.booktitle = booktitle;
+ this.isbn = isbn;
+ this.copy = copy;
+ this.authorList = authorList;
+ }
+
+ public long getBookid() {
+ return bookid;
+ }
+
+ public void setBookid(long bookid) {
+ this.bookid = bookid;
+ }
+
+ public String getBooktitle() {
+ return booktitle;
+ }
+
+ public void setBooktitle(String booktitle) {
+ this.booktitle = booktitle;
+ }
+
+ public String getIsbn() {
+ return isbn;
+ }
+
+ public void setIsbn(String isbn) {
+ this.isbn = isbn;
+ }
+
+ public String getCopy() {
+ return copy;
+ }
+
+ public void setCopy(String copy) {
+ this.copy = copy;
+ }
+
+ public List getAuthorList() {
+ return authorList;
+ }
+
+ public void setAuthorList(List authorList) {
+ this.authorList = authorList;
+ }
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/models/ErrorDetail.java b/StartHere/src/main/java/com/lambdaschool/starthere/models/ErrorDetail.java
new file mode 100644
index 00000000..e5fb648b
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/models/ErrorDetail.java
@@ -0,0 +1,82 @@
+package com.lambdaschool.starthere.models;
+
+
+import com.lambdaschool.starthere.exceptions.ValidationError;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+// adapted from https://tools.ietf.org/html/rfc7807
+public class ErrorDetail
+{
+ private String title;
+ private int status;
+ private String detail;
+ private String timestamp;
+ private String developerMessage;
+ private Map> errors = new HashMap>();
+
+ public String getTitle()
+ {
+ return title;
+ }
+
+ public void setTitle(String title)
+ {
+ this.title = title;
+ }
+
+ public int getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(int status)
+ {
+ this.status = status;
+ }
+
+ public String getDetail()
+ {
+ return detail;
+ }
+
+ public void setDetail(String detail)
+ {
+ this.detail = detail;
+ }
+
+ public String getTimestamp()
+ {
+ return timestamp;
+ }
+
+ public void setTimestamp(Long timestamp)
+ {
+ this.timestamp = new SimpleDateFormat("dd MMM yyyy HH:mm:ss:SSS Z").format(new Date(timestamp));
+ }
+
+ public String getDeveloperMessage()
+ {
+ return developerMessage;
+ }
+
+ public void setDeveloperMessage(String developerMessage)
+ {
+ this.developerMessage = developerMessage;
+ }
+
+ public Map> getErrors()
+ {
+ return errors;
+ }
+
+ public void setErrors(Map> errors)
+ {
+ this.errors = errors;
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/models/Quote.java b/StartHere/src/main/java/com/lambdaschool/starthere/models/Quote.java
new file mode 100644
index 00000000..26d264dd
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/models/Quote.java
@@ -0,0 +1,63 @@
+package com.lambdaschool.starthere.models;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "quotes")
+public class Quote extends Auditable
+{
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long quotesid;
+
+ @Column(nullable = false)
+ private String quote;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "userid",
+ nullable = false)
+ @JsonIgnoreProperties({"quotes", "hibernateLazyInitializer"})
+ private User user;
+
+ public Quote()
+ {
+ }
+
+ public Quote(String quote, User user)
+ {
+ this.quote = quote;
+ this.user = user;
+ }
+
+ public long getQuotesid()
+ {
+ return quotesid;
+ }
+
+ public void setQuotesid(long quotesid)
+ {
+ this.quotesid = quotesid;
+ }
+
+ public String getQuote()
+ {
+ return quote;
+ }
+
+ public void setQuote(String quote)
+ {
+ this.quote = quote;
+ }
+
+ public User getUser()
+ {
+ return user;
+ }
+
+ public void setUser(User user)
+ {
+ this.user = user;
+ }
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/models/Role.java b/StartHere/src/main/java/com/lambdaschool/starthere/models/Role.java
new file mode 100644
index 00000000..9584c1b2
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/models/Role.java
@@ -0,0 +1,64 @@
+package com.lambdaschool.starthere.models;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import javax.persistence.*;
+import java.util.ArrayList;
+import java.util.List;
+
+@Entity
+@Table(name = "roles")
+public class Role extends Auditable
+{
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long roleid;
+
+ @Column(nullable = false,
+ unique = true)
+ private String name;
+
+ @OneToMany(mappedBy = "role",
+ cascade = CascadeType.ALL)
+ @JsonIgnoreProperties("role")
+ private List userRoles = new ArrayList<>();
+
+ public Role()
+ {
+ }
+
+ public Role(String name)
+ {
+ this.name = name;
+ }
+
+ public long getRoleid()
+ {
+ return roleid;
+ }
+
+ public void setRoleid(long roleid)
+ {
+ this.roleid = roleid;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public List getUserRoles()
+ {
+ return userRoles;
+ }
+
+ public void setUserRoles(List userRoles)
+ {
+ this.userRoles = userRoles;
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/models/User.java b/StartHere/src/main/java/com/lambdaschool/starthere/models/User.java
new file mode 100644
index 00000000..a267e7b0
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/models/User.java
@@ -0,0 +1,124 @@
+package com.lambdaschool.starthere.models;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+
+import javax.persistence.*;
+import java.util.ArrayList;
+import java.util.List;
+
+// User is considered the parent entity
+
+@Entity
+@Table(name = "users")
+public class User extends Auditable
+{
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long userid;
+
+ @Column(nullable = false,
+ unique = true)
+ private String username;
+
+ @Column(nullable = false)
+ @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
+ private String password;
+
+ @OneToMany(mappedBy = "user",
+ cascade = CascadeType.ALL)
+ @JsonIgnoreProperties("user")
+ private List userRoles = new ArrayList<>();
+
+ @OneToMany(mappedBy = "user",
+ cascade = CascadeType.ALL,
+ orphanRemoval = true)
+ @JsonIgnoreProperties("user")
+ private List quotes = new ArrayList<>();
+
+ public User()
+ {
+ }
+
+ public User(String username, String password, List userRoles)
+ {
+ setUsername(username);
+ setPassword(password);
+ for (UserRoles ur : userRoles)
+ {
+ ur.setUser(this);
+ }
+ this.userRoles = userRoles;
+ }
+
+ public long getUserid()
+ {
+ return userid;
+ }
+
+ public void setUserid(long userid)
+ {
+ this.userid = userid;
+ }
+
+ public String getUsername()
+ {
+ return username;
+ }
+
+ public void setUsername(String username)
+ {
+ this.username = username;
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public void setPassword(String password)
+ {
+ BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+ this.password = passwordEncoder.encode(password);
+ }
+
+ public void setPasswordNoEncrypt(String password)
+ {
+ this.password = password;
+ }
+
+ public List getUserRoles()
+ {
+ return userRoles;
+ }
+
+ public void setUserRoles(List userRoles)
+ {
+ this.userRoles = userRoles;
+ }
+
+ public List getQuotes()
+ {
+ return quotes;
+ }
+
+ public void setQuotes(List quotes)
+ {
+ this.quotes = quotes;
+ }
+
+ public List getAuthority()
+ {
+ List rtnList = new ArrayList<>();
+
+ for (UserRoles r : this.userRoles)
+ {
+ String myRole = "ROLE_" + r.getRole().getName().toUpperCase();
+ rtnList.add(new SimpleGrantedAuthority(myRole));
+ }
+
+ return rtnList;
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/models/UserRoles.java b/StartHere/src/main/java/com/lambdaschool/starthere/models/UserRoles.java
new file mode 100644
index 00000000..460fea56
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/models/UserRoles.java
@@ -0,0 +1,75 @@
+package com.lambdaschool.starthere.models;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Objects;
+
+@Entity
+@Table(name = "userroles")
+public class UserRoles extends Auditable implements Serializable
+{
+ @Id
+ @ManyToOne
+ @JoinColumn(name = "userid")
+ @JsonIgnoreProperties("userRoles")
+ private User user;
+
+ @Id
+ @ManyToOne
+ @JoinColumn(name = "roleid")
+ @JsonIgnoreProperties("userRoles")
+ private Role role;
+
+ public UserRoles()
+ {
+ }
+
+ public UserRoles(User user, Role role)
+ {
+ this.user = user;
+ this.role = role;
+ }
+
+ public User getUser()
+ {
+ return user;
+ }
+
+ public void setUser(User user)
+ {
+ this.user = user;
+ }
+
+ public Role getRole()
+ {
+ return role;
+ }
+
+ public void setRole(Role role)
+ {
+ this.role = role;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (!(o instanceof UserRoles))
+ {
+ return false;
+ }
+ UserRoles userRoles = (UserRoles) o;
+ return getUser().equals(userRoles.getUser()) && getRole().equals(userRoles.getRole());
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(getUser(), getRole());
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/models/UserTypes.java b/StartHere/src/main/java/com/lambdaschool/starthere/models/UserTypes.java
new file mode 100644
index 00000000..5d76bff5
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/models/UserTypes.java
@@ -0,0 +1,6 @@
+package com.lambdaschool.starthere.models;
+
+abstract class UserTypes
+{
+ protected String UserName;
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/repository/AuthorRepository.java b/StartHere/src/main/java/com/lambdaschool/starthere/repository/AuthorRepository.java
new file mode 100644
index 00000000..40076103
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/repository/AuthorRepository.java
@@ -0,0 +1,7 @@
+package com.lambdaschool.starthere.repository;
+
+import com.lambdaschool.starthere.models.Author;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+public interface AuthorRepository extends PagingAndSortingRepository {
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/repository/BookRepository.java b/StartHere/src/main/java/com/lambdaschool/starthere/repository/BookRepository.java
new file mode 100644
index 00000000..cc4d800f
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/repository/BookRepository.java
@@ -0,0 +1,7 @@
+package com.lambdaschool.starthere.repository;
+
+import com.lambdaschool.starthere.models.Book;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+public interface BookRepository extends PagingAndSortingRepository {
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/repository/QuoteRepository.java b/StartHere/src/main/java/com/lambdaschool/starthere/repository/QuoteRepository.java
new file mode 100644
index 00000000..2e30676c
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/repository/QuoteRepository.java
@@ -0,0 +1,9 @@
+package com.lambdaschool.starthere.repository;
+
+import com.lambdaschool.starthere.models.Quote;
+import org.springframework.data.repository.CrudRepository;
+
+public interface QuoteRepository extends CrudRepository
+{
+
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/repository/RoleRepository.java b/StartHere/src/main/java/com/lambdaschool/starthere/repository/RoleRepository.java
new file mode 100644
index 00000000..39cc2a83
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/repository/RoleRepository.java
@@ -0,0 +1,23 @@
+package com.lambdaschool.starthere.repository;
+
+import com.lambdaschool.starthere.models.Role;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.transaction.annotation.Transactional;
+
+public interface RoleRepository extends CrudRepository
+{
+ @Transactional
+ @Modifying
+ @Query(value = "DELETE from UserRoles where userid = :userid")
+ void deleteUserRolesByUserId(long userid);
+
+ @Transactional
+ @Modifying
+ @Query(value = "INSERT INTO UserRoles(userid, roleid) values (:userid, :roleid)",
+ nativeQuery = true)
+ void insertUserRoles(long userid, long roleid);
+
+ Role findByNameIgnoreCase(String name);
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/repository/UserRepository.java b/StartHere/src/main/java/com/lambdaschool/starthere/repository/UserRepository.java
new file mode 100644
index 00000000..84160b73
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/repository/UserRepository.java
@@ -0,0 +1,9 @@
+package com.lambdaschool.starthere.repository;
+
+import com.lambdaschool.starthere.models.User;
+import org.springframework.data.repository.CrudRepository;
+
+public interface UserRepository extends CrudRepository
+{
+ User findByUsername(String username);
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/services/AuthorService.java b/StartHere/src/main/java/com/lambdaschool/starthere/services/AuthorService.java
new file mode 100644
index 00000000..d58bcfaa
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/services/AuthorService.java
@@ -0,0 +1,13 @@
+package com.lambdaschool.starthere.services;
+
+import com.lambdaschool.starthere.models.Author;
+import org.springframework.data.domain.Pageable;
+
+import java.util.List;
+
+public interface AuthorService {
+
+ List findAll(Pageable pageable);
+
+ void save(Author author);
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/services/AuthorServiceImpl.java b/StartHere/src/main/java/com/lambdaschool/starthere/services/AuthorServiceImpl.java
new file mode 100644
index 00000000..246223ac
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/services/AuthorServiceImpl.java
@@ -0,0 +1,30 @@
+package com.lambdaschool.starthere.services;
+
+
+import com.lambdaschool.starthere.models.Author;
+import com.lambdaschool.starthere.repository.AuthorRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service(value = "authorService")
+public class AuthorServiceImpl implements AuthorService {
+ @Autowired
+ private AuthorRepository repo;
+
+
+ @Override
+ public List findAll(Pageable pageable) {
+ List authorList = new ArrayList<>();
+ repo.findAll(pageable).iterator().forEachRemaining(authorList::add);
+ return authorList;
+ }
+
+ @Override
+ public void save(Author author) {
+ repo.save(author);
+ }
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/services/BookService.java b/StartHere/src/main/java/com/lambdaschool/starthere/services/BookService.java
new file mode 100644
index 00000000..8604a484
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/services/BookService.java
@@ -0,0 +1,19 @@
+package com.lambdaschool.starthere.services;
+
+
+import com.lambdaschool.starthere.models.Book;
+import org.springframework.data.domain.Pageable;
+
+import java.util.List;
+
+public interface BookService {
+ List findAll(Pageable pageable);
+
+ Book updateBook(Book book, long id);
+
+ void delete(long id);
+
+ void assignAuthor(long bookid, long authorid);
+
+ void save(Book book);
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/services/BookServiceImpl.java b/StartHere/src/main/java/com/lambdaschool/starthere/services/BookServiceImpl.java
new file mode 100644
index 00000000..7a180a76
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/services/BookServiceImpl.java
@@ -0,0 +1,74 @@
+package com.lambdaschool.starthere.services;
+
+import com.lambdaschool.starthere.models.Book;
+import com.lambdaschool.starthere.repository.AuthorRepository;
+import com.lambdaschool.starthere.repository.BookRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.EntityNotFoundException;
+import javax.transaction.Transactional;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service(value = "bookService")
+public class BookServiceImpl implements BookService {
+
+ @Autowired
+ private BookRepository repo;
+
+ @Autowired
+ private AuthorRepository authorRepo;
+
+ @Override
+ public List findAll(Pageable pageable) {
+ List bookList = new ArrayList<>();
+ repo.findAll(pageable).iterator().forEachRemaining(bookList::add);
+ return bookList;
+ }
+
+ @Transactional
+ @Override
+ public Book updateBook(Book book, long id) {
+ Book currentBook = repo.findById(id).orElseThrow(EntityNotFoundException::new);
+ if(book.getBooktitle() != null){
+ currentBook.setBooktitle(book.getBooktitle());
+ }
+ if(book.getCopy() != null){
+ currentBook.setCopy(book.getCopy());
+ }
+ if (book.getIsbn() != null){
+ currentBook.setIsbn(book.getIsbn());
+ }
+ if (book.getAuthorList() != null && book.getAuthorList().size() > 0){
+ currentBook.setAuthorList(book.getAuthorList());
+ }
+
+ repo.save(currentBook);
+ return currentBook;
+ }
+
+ @Transactional
+ @Override
+ public void delete(long id) {
+ if (repo.findById(id).isPresent()){
+ repo.deleteById(id);
+ }else{
+ throw new EntityNotFoundException();
+ }
+
+ }
+
+ @Transactional
+ @Override
+ public void assignAuthor(long bookid, long authorid) {
+ Book currentBook = repo.findById(bookid).orElseThrow(EntityNotFoundException::new);
+ currentBook.getAuthorList().add(authorRepo.findById(authorid).orElseThrow(EntityNotFoundException::new));
+ }
+
+ @Override
+ public void save(Book book) {
+ repo.save(book);
+ }
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/services/QuoteService.java b/StartHere/src/main/java/com/lambdaschool/starthere/services/QuoteService.java
new file mode 100644
index 00000000..0d7cc7b7
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/services/QuoteService.java
@@ -0,0 +1,18 @@
+package com.lambdaschool.starthere.services;
+
+import com.lambdaschool.starthere.models.Quote;
+
+import java.util.List;
+
+public interface QuoteService
+{
+ List findAll();
+
+ Quote findQuoteById(long id);
+
+ List findByUserName(String username);
+
+ void delete(long id);
+
+ Quote save(Quote quote);
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/services/QuoteServiceImpl.java b/StartHere/src/main/java/com/lambdaschool/starthere/services/QuoteServiceImpl.java
new file mode 100644
index 00000000..c95b7596
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/services/QuoteServiceImpl.java
@@ -0,0 +1,70 @@
+package com.lambdaschool.starthere.services;
+
+import com.lambdaschool.starthere.exceptions.ResourceNotFoundException;
+import com.lambdaschool.starthere.models.Quote;
+import com.lambdaschool.starthere.repository.QuoteRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service(value = "quoteService")
+public class QuoteServiceImpl implements QuoteService
+{
+ @Autowired
+ private QuoteRepository quoterepos;
+
+ @Override
+ public List findAll()
+ {
+ List list = new ArrayList<>();
+ quoterepos.findAll().iterator().forEachRemaining(list::add);
+ return list;
+ }
+
+ @Override
+ public Quote findQuoteById(long id)
+ {
+ return quoterepos.findById(id).orElseThrow(() -> new ResourceNotFoundException(Long.toString(id)));
+ }
+
+ @Override
+ public void delete(long id)
+ {
+ if (quoterepos.findById(id).isPresent())
+ {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (quoterepos.findById(id).get().getUser().getUsername().equalsIgnoreCase(authentication.getName()))
+ {
+ quoterepos.deleteById(id);
+ } else
+ {
+ throw new ResourceNotFoundException(id + " " + authentication.getName());
+ }
+ } else
+ {
+ throw new ResourceNotFoundException(Long.toString(id));
+ }
+ }
+
+ @Transactional
+ @Override
+ public Quote save(Quote quote)
+ {
+ return quoterepos.save(quote);
+ }
+
+ @Override
+ public List findByUserName(String username)
+ {
+ List list = new ArrayList<>();
+ quoterepos.findAll().iterator().forEachRemaining(list::add);
+
+ list.removeIf(q -> !q.getUser().getUsername().equalsIgnoreCase(username));
+ return list;
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/services/RoleService.java b/StartHere/src/main/java/com/lambdaschool/starthere/services/RoleService.java
new file mode 100644
index 00000000..ac7a8626
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/services/RoleService.java
@@ -0,0 +1,18 @@
+package com.lambdaschool.starthere.services;
+
+import com.lambdaschool.starthere.models.Role;
+
+import java.util.List;
+
+public interface RoleService
+{
+ List findAll();
+
+ Role findRoleById(long id);
+
+ void delete(long id);
+
+ Role save(Role role);
+
+ Role findByName(String name);
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/services/RoleServiceImpl.java b/StartHere/src/main/java/com/lambdaschool/starthere/services/RoleServiceImpl.java
new file mode 100644
index 00000000..7019d630
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/services/RoleServiceImpl.java
@@ -0,0 +1,62 @@
+package com.lambdaschool.starthere.services;
+
+import com.lambdaschool.starthere.exceptions.ResourceNotFoundException;
+import com.lambdaschool.starthere.models.Role;
+import com.lambdaschool.starthere.repository.RoleRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service(value = "roleService")
+public class RoleServiceImpl implements RoleService
+{
+ @Autowired
+ RoleRepository rolerepos;
+
+ @Override
+ public List findAll()
+ {
+ List list = new ArrayList<>();
+ rolerepos.findAll().iterator().forEachRemaining(list::add);
+ return list;
+ }
+
+
+ @Override
+ public Role findRoleById(long id)
+ {
+ return rolerepos.findById(id).orElseThrow(() -> new ResourceNotFoundException(Long.toString(id)));
+ }
+
+ @Override
+ public Role findByName(String name)
+ {
+ Role rr = rolerepos.findByNameIgnoreCase(name);
+
+ if (rr != null)
+ {
+ return rr;
+ } else
+ {
+ throw new ResourceNotFoundException(name);
+ }
+ }
+
+ @Override
+ public void delete(long id)
+ {
+ rolerepos.findById(id).orElseThrow(() -> new ResourceNotFoundException(Long.toString(id)));
+ rolerepos.deleteById(id);
+ }
+
+
+ @Transactional
+ @Override
+ public Role save(Role role)
+ {
+ return rolerepos.save(role);
+ }
+}
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/services/UserAuditing.java b/StartHere/src/main/java/com/lambdaschool/starthere/services/UserAuditing.java
new file mode 100644
index 00000000..cb4beb74
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/services/UserAuditing.java
@@ -0,0 +1,29 @@
+package com.lambdaschool.starthere.services;
+
+import org.springframework.data.domain.AuditorAware;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+import java.util.Optional;
+
+@Component
+public class UserAuditing implements AuditorAware
+{
+
+ @Override
+ public Optional getCurrentAuditor()
+ {
+ String uname;
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (authentication != null)
+ {
+ uname = authentication.getName();
+ } else
+ {
+ uname = "SYSTEM";
+ }
+ return Optional.of(uname);
+ }
+
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/services/UserService.java b/StartHere/src/main/java/com/lambdaschool/starthere/services/UserService.java
new file mode 100644
index 00000000..9f7ba10b
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/services/UserService.java
@@ -0,0 +1,19 @@
+package com.lambdaschool.starthere.services;
+
+import com.lambdaschool.starthere.models.User;
+
+import java.util.List;
+
+public interface UserService
+{
+
+ List findAll();
+
+ User findUserById(long id);
+
+ void delete(long id);
+
+ User save(User user);
+
+ User update(User user, long id);
+}
\ No newline at end of file
diff --git a/StartHere/src/main/java/com/lambdaschool/starthere/services/UserServiceImpl.java b/StartHere/src/main/java/com/lambdaschool/starthere/services/UserServiceImpl.java
new file mode 100644
index 00000000..25c65f0a
--- /dev/null
+++ b/StartHere/src/main/java/com/lambdaschool/starthere/services/UserServiceImpl.java
@@ -0,0 +1,145 @@
+package com.lambdaschool.starthere.services;
+
+import com.lambdaschool.starthere.exceptions.ResourceNotFoundException;
+import com.lambdaschool.starthere.models.Quote;
+import com.lambdaschool.starthere.models.User;
+import com.lambdaschool.starthere.models.UserRoles;
+import com.lambdaschool.starthere.repository.RoleRepository;
+import com.lambdaschool.starthere.repository.UserRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+@Service(value = "userService")
+public class UserServiceImpl implements UserDetailsService, UserService
+{
+
+ @Autowired
+ private UserRepository userrepos;
+
+ @Autowired
+ private RoleRepository rolerepos;
+
+ @Transactional
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
+ {
+ User user = userrepos.findByUsername(username);
+ if (user == null)
+ {
+ throw new UsernameNotFoundException("Invalid username or password.");
+ }
+ return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), user.getAuthority());
+ }
+
+ public User findUserById(long id) throws ResourceNotFoundException
+ {
+ return userrepos.findById(id).orElseThrow(() -> new ResourceNotFoundException(Long.toString(id)));
+ }
+
+ public List findAll()
+ {
+ List list = new ArrayList<>();
+ userrepos.findAll().iterator().forEachRemaining(list::add);
+ return list;
+ }
+
+ @Override
+ public void delete(long id)
+ {
+ if (userrepos.findById(id).isPresent())
+ {
+ userrepos.deleteById(id);
+ } else
+ {
+ throw new ResourceNotFoundException(Long.toString(id));
+ }
+ }
+
+ @Transactional
+ @Override
+ public User save(User user)
+ {
+ User newUser = new User();
+ newUser.setUsername(user.getUsername());
+ newUser.setPasswordNoEncrypt(user.getPassword());
+
+ ArrayList newRoles = new ArrayList<>();
+ for (UserRoles ur : user.getUserRoles())
+ {
+ newRoles.add(new UserRoles(newUser, ur.getRole()));
+ }
+ newUser.setUserRoles(newRoles);
+
+ for (Quote q : user.getQuotes())
+ {
+ newUser.getQuotes().add(new Quote(q.getQuote(), newUser));
+ }
+
+ return userrepos.save(newUser);
+ }
+
+
+ @Transactional
+ @Override
+ public User update(User user, long id)
+ {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ User currentUser = userrepos.findByUsername(authentication.getName());
+
+ if (currentUser != null)
+ {
+ if (id == currentUser.getUserid())
+ {
+ if (user.getUsername() != null)
+ {
+ currentUser.setUsername(user.getUsername());
+ }
+
+ if (user.getPassword() != null)
+ {
+ currentUser.setPasswordNoEncrypt(user.getPassword());
+ }
+
+ if (user.getUserRoles().size() > 0)
+ {
+ // with so many relationships happening, I decided to go
+ // with old school queries
+ // delete the old ones
+ rolerepos.deleteUserRolesByUserId(currentUser.getUserid());
+
+ // add the new ones
+ for (UserRoles ur : user.getUserRoles())
+ {
+ rolerepos.insertUserRoles(id, ur.getRole().getRoleid());
+ }
+ }
+
+ if (user.getQuotes().size() > 0)
+ {
+ for (Quote q : user.getQuotes())
+ {
+ currentUser.getQuotes().add(new Quote(q.getQuote(), currentUser));
+ }
+ }
+
+ return userrepos.save(currentUser);
+ } else
+ {
+ throw new ResourceNotFoundException(id + " Not current user");
+ }
+ } else
+ {
+ throw new ResourceNotFoundException(authentication.getName());
+ }
+
+ }
+}
diff --git a/StartHere/src/main/resources/application.properties b/StartHere/src/main/resources/application.properties
new file mode 100644
index 00000000..26ae2817
--- /dev/null
+++ b/StartHere/src/main/resources/application.properties
@@ -0,0 +1,67 @@
+server.port=${PORT:2019}
+# server.servlet.context-path=/apis
+
+## Begin h2 configuration
+#spring.h2.console.enabled=true
+#spring.h2.console.path=/h2-console
+#spring.h2.console.settings.web-allow-others=true
+## End h2 configuration
+
+
+# Begin PostgreSQL local configuration
+#spring.datasource.url=jdbc:postgresql://localhost:5432/dbstarthere
+#spring.datasource.username=postgres
+#spring.datasource.password=${MYDBPASSWORD}
+#spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+# End PostgreSQL local configuration
+
+# Begin PostgreSQL heroku configuration
+# heroku config -a jrmmba-starthere
+# postgres://rrwzjxlkniayov:83e8dc9dc5a3c3a30e40dde8fb62941da11030b3953709f5c8f808690e776c71@ec2-54-243-241-62.compute-1.amazonaws.com:5432/d7bl8dlv2l83jj
+# posgress://username :password @url :5432/dbname
+# check environment variables:
+# heroku run echo \$SPRING_DATASOURCE_URL -a jrmmba-starthere
+# heroku run echo \$SPRING_DATASOURCE_USERNAME -a jrmmba-starthere
+# heroku run echo \$SPRING_DATASOURCE_PASSWORD -a jrmmba-starthere
+### If you environment variables get set, just use those!
+#spring.datasource.url=${SPRING_DATASOURCE_URL}
+#spring.datasource.username=${SPRING_DATASOURCE_USERNAME}
+#spring.datasource.password=${SPRING_DATASOURCE_PASSWORD}
+#spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+### If your environment variables do not get set
+#spring.datasource.url=${SPRING_DATASOURCE_URL:jdbc:postgresql://ec2-54-243-241-62.compute-1.amazonaws.com:5432/d7bl8dlv2l83jj?user=rrwzjxlkniayov&password=83e8dc9dc5a3c3a30e40dde8fb62941da11030b3953709f5c8f808690e776c71&sslmode=require}
+#spring.datasource.username=${SPRING_DATASOURCE_USERNAME:rrwzjxlkniayov}
+#spring.datasource.password=${SPRING_DATASOURCE_PASSWORD:83e8dc9dc5a3c3a30e40dde8fb62941da11030b3953709f5c8f808690}
+#spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+# End PostgreSQL heroku configuration
+
+#PostGreSql heroku
+
+spring.datasource.url=${SPRING_DATA_URL:jdbc:postgresql://ec2-107-20-173-2.compute-1.amazonaws.com:5432/d39e2l1k7ubfue?user=uwmtlcoeqpswbk&password=2becc80b9419a03a5d5f702349d30d614eb173e1124ed1123816f24cf70f665c&sslmode=require}
+spring.datasource.username=uwmtlcoeqpswbk
+spring.datasource.password=2becc80b9419a03a5d5f702349d30d614eb173e1124ed1123816f24cf70f665c
+spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
+
+# What do with the schema
+# drop n create table again, good for testing
+spring.jpa.hibernate.ddl-auto=create
+spring.datasource.initialization-mode=always
+
+# Good for production!
+#spring.jpa.hibernate.ddl-auto=update
+#spring.datasource.initialization-mode=never
+
+
+# Feature that determines what happens when no accessors are found for a type
+# (and there are no annotations to indicate it is meant to be serialized).
+spring.jackson.serialization.fail-on-empty-beans=false
+
+
+# Turns off Spring Boot automatic exception handling
+server.error.whitelabel.enabled=false
+
+
+# needed for actuators to work
+management.endpoints.web.exposure.include=*
+management.endpoint.health.show-details=always
+management.endpoint.shutdown.enabled=true
diff --git a/StartHere/src/main/resources/data.sql b/StartHere/src/main/resources/data.sql
new file mode 100644
index 00000000..3bc5b731
--- /dev/null
+++ b/StartHere/src/main/resources/data.sql
@@ -0,0 +1,27 @@
+-- INSERT INTO section (sectionid, name) VALUES (1, 'Fiction');
+-- INSERT INTO section (sectionid, name) VALUES (2, 'Technology');
+-- INSERT INTO section (sectionid, name) VALUES (3, 'Travel');
+-- INSERT INTO section (sectionid, name) VALUES (4, 'Business');
+-- INSERT INTO section (sectionid, name) VALUES (5, 'Religion');
+
+INSERT INTO author (authorid, firstname, lastname) VALUES (1, 'John', 'Mitchell');
+INSERT INTO author (authorid, firstname, lastname) VALUES (2, 'Dan', 'Brown');
+INSERT INTO author (authorid, firstname, lastname) VALUES (3, 'Jerry', 'Poe');
+INSERT INTO author (authorid, firstname, lastname) VALUES (4, 'Wells', 'Teague');
+INSERT INTO author (authorid, firstname, lastname) VALUES (5, 'George', 'Gallinger');
+INSERT INTO author (authorid, firstname, lastname) VALUES (6, 'Ian', 'Stewart');
+
+INSERT INTO book (bookid, booktitle, ISBN, copy) VALUES (1, 'Flatterland', '9780738206752', 2001);
+INSERT INTO book (bookid, booktitle, ISBN, copy) VALUES (2, 'Digital Fortess', '9788489367012', 2007);
+INSERT INTO book (bookid, booktitle, ISBN, copy) VALUES (3, 'The Da Vinci Code', '9780307474278', 2009);
+INSERT INTO book (bookid, booktitle, ISBN, copy) VALUES (4, 'Essentials of Finance', '1314241651234', NULL);
+INSERT INTO book (bookid, booktitle, ISBN, copy) VALUES (5, 'Calling Texas Home', '1885171382134', 2000);
+
+INSERT INTO wrote (bookid, authorid) VALUES (1, 6);
+INSERT INTO wrote (bookid, authorid) VALUES (2, 2);
+INSERT INTO wrote (bookid, authorid) VALUES (3, 2);
+INSERT INTO wrote (bookid, authorid) VALUES (4, 5);
+INSERT INTO wrote (bookid, authorid) VALUES (4, 3);
+INSERT INTO wrote (bookid, authorid) VALUES (5, 4);
+
+alter sequence hibernate_sequence restart with 25;
\ No newline at end of file
diff --git a/StartHere/src/main/resources/info/ChangeLog.txt b/StartHere/src/main/resources/info/ChangeLog.txt
new file mode 100644
index 00000000..b0b52856
--- /dev/null
+++ b/StartHere/src/main/resources/info/ChangeLog.txt
@@ -0,0 +1,13 @@
+Starting June 20, 2019
+
+* Remove generation of refresh token for oauth2
+* Reading Client Id and Secret from environment variables
+* Changed EntityNotFoundException to ResourceNotFoundException
+
+June 23
+
+* Added Access to OpenLibrary API
+
+Todo
+
+Swagger
diff --git a/StartHere/src/main/resources/info/curl.txt b/StartHere/src/main/resources/info/curl.txt
new file mode 100644
index 00000000..094dea7e
--- /dev/null
+++ b/StartHere/src/main/resources/info/curl.txt
@@ -0,0 +1,31 @@
+curl -X POST --user "lambda-client:lambda-secret" -d "grant_type=password&username=admin&password=password" http://localhost:2019/oauth/token
+
+curl -X GET -H "Accept: application/json" -H "Authorization: Bearer d781956f-32c1-46c3-a531-dc8f64466f7b" http://localhost:2019/users/users
+
+curl -X POST --user "lambda-client:lambda-secret" -d 'grant_type=password&username=barnbarn&password=ILuvM4th!' http://localhost:2019/oauth/token
+
+curl -X GET -H "Accept: application/json" -H "Authorization: Bearer acd0586d-fc11-4715-a2ae-9acab553672c" http://localhost:2019/users/users
+
+curl -X GET -H "Accept: application/json" -H "Authorization: Bearer d781956f-32c1-46c3-a531-dc8f64466f7b" http://localhost:2019/users/users
+
+curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer d781956f-32c1-46c3-a531-dc8f64466f7b" -d "{ \"username\":\"snoopy\", \"password\":\"password\", \"roleid\":"1" }" http://localhost:2019/users/user
+
+curl -X GET -H "Accept: application/json" -H "Authorization: Bearer d781956f-32c1-46c3-a531-dc8f64466f7b" http://localhost:2019/users/users
+
+curl -X GET -H "Accept: application/json" -H "Authorization: Bearer d781956f-32c1-46c3-a531-dc8f64466f7b" http://localhost:2019/users/user/14
+
+curl -X DELETE -H "Authorization: Bearer d781956f-32c1-46c3-a531-dc8f64466f7b" http://localhost:2019/users/user/14
+
+curl -X GET -H "Accept: application/json" -H "Authorization: Bearer d781956f-32c1-46c3-a531-dc8f64466f7b" http://localhost:2019/users/user/14
+
+curl -X POST -H "Content-Type: application/json" -d "{\"username\": \"Ginger\", \"password\": \"EATEATEAT\"}" http://localhost:2019/createnewuser
+
+curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer d781956f-32c1-46c3-a531-dc8f64466f7b" -d "{ \"username\": \"Snoopy\", \"password\": \"password\", \"userRoles\": [ { \"role\": { \"roleid\": 1 } } ], \"quotes\": [ { \"quote\": \"The Red Baron\" } ]}" http://localhost:2019/users/user
+
+curl -X GET -H "Accept: application/json" -H "Authorization: Bearer d781956f-32c1-46c3-a531-dc8f64466f7b" http://localhost:2019/users/user/15
+
+curl -X GET -H "Accept: application/json" -H "Authorization: Bearer d781956f-32c1-46c3-a531-dc8f64466f7b" http://localhost:2019/oauth/revoke-token
+
+*** using a different host
+
+curl -X POST --user "lambda-client:lambda-secret" -d "grant_type=password&username=admin&password=password" http://jrmmba-starthere.herokuapp.com/oauth/token
diff --git a/StartHere/src/main/resources/logback-spring.xml b/StartHere/src/main/resources/logback-spring.xml
new file mode 100644
index 00000000..17531612
--- /dev/null
+++ b/StartHere/src/main/resources/logback-spring.xml
@@ -0,0 +1,77 @@
+
+
+
+
+
+ [%d{yyyy-MM-dd' 'HH:mm:ss.SSS}] [%25.25class] [%thread] [%line] [%-5level] %m%n
+
+
+
+
+ /tmp/var/mylog.log
+ true
+
+ [%d{yyyy-MM-dd' 'HH:mm:ss.SSS}] [%C] [%t] [%L] [%-5p] %m%n
+
+
+
+
+
+ /tmp/var/mylog.%d{yyyy-MM-dd HH}.%i.txt
+ 10MB
+
+
+ 30
+ 3GB
+
+
+
+
+ /tmp/var/myTomcatLog.log
+ true
+
+ [%d{yyyy-MM-dd' 'HH:mm:ss.sss}] [%C] [%t] [%L] [%-5p] %m%n
+
+
+
+
+
+ /tmp/var/myTomcatLog.%d{yyyy-MM-dd HH}.%i.txt
+ 10MB
+
+
+ 30
+ 3GB
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data.sql b/data.sql
deleted file mode 100644
index 2316fa71..00000000
--- a/data.sql
+++ /dev/null
@@ -1,27 +0,0 @@
-INSERT INTO section (sectionid, name) VALUES (1, 'Fiction');
-INSERT INTO section (sectionid, name) VALUES (2, 'Technology');
-INSERT INTO section (sectionid, name) VALUES (3, 'Travel');
-INSERT INTO section (sectionid, name) VALUES (4, 'Business');
-INSERT INTO section (sectionid, name) VALUES (5, 'Religion');
-
-INSERT INTO author (authorid, fname, lname) VALUES (1, 'John', 'Mitchell');
-INSERT INTO author (authorid, fname, lname) VALUES (2, 'Dan', 'Brown');
-INSERT INTO author (authorid, fname, lname) VALUES (3, 'Jerry', 'Poe');
-INSERT INTO author (authorid, fname, lname) VALUES (4, 'Wells', 'Teague');
-INSERT INTO author (authorid, fname, lname) VALUES (5, 'George', 'Gallinger');
-INSERT INTO author (authorid, fname, lname) VALUES (6, 'Ian', 'Stewart');
-
-INSERT INTO book (bookid, title, ISBN, copy, sectionid) VALUES (1, 'Flatterland', '9780738206752', 2001, 1);
-INSERT INTO book (bookid, title, ISBN, copy, sectionid) VALUES (2, 'Digital Fortess', '9788489367012', 2007, 1);
-INSERT INTO book (bookid, title, ISBN, copy, sectionid) VALUES (3, 'The Da Vinci Code', '9780307474278', 2009, 1);
-INSERT INTO book (bookid, title, ISBN, copy, sectionid) VALUES (4, 'Essentials of Finance', '1314241651234', NULL, 4);
-INSERT INTO book (bookid, title, ISBN, copy, sectionid) VALUES (5, 'Calling Texas Home', '1885171382134', 2000, 3);
-
-INSERT INTO wrote (bookid, authorid) VALUES (1, 6);
-INSERT INTO wrote (bookid, authorid) VALUES (2, 2);
-INSERT INTO wrote (bookid, authorid) VALUES (3, 2);
-INSERT INTO wrote (bookid, authorid) VALUES (4, 5);
-INSERT INTO wrote (bookid, authorid) VALUES (4, 3);
-INSERT INTO wrote (bookid, authorid) VALUES (5, 4);
-
-alter sequence hibernate_sequence restart with 25;