Init project.
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
**/*.class
|
||||
**/target
|
||||
**/static
|
||||
**/.idea
|
||||
**/*.iml
|
||||
84
pom.xml
Normal file
84
pom.xml
Normal file
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.cerberus</groupId>
|
||||
<artifactId>cerberus</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.1.6.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>11</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.mindrot</groupId>
|
||||
<artifactId>jbcrypt</artifactId>
|
||||
<version>0.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.2.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<executable>true</executable>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
13
src/main/java/org/cerberus/CerberusApplication.java
Normal file
13
src/main/java/org/cerberus/CerberusApplication.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package org.cerberus;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableAutoConfiguration
|
||||
public class CerberusApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(CerberusApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.cerberus.controllers;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@RestController
|
||||
public class RobotsTxtController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(RobotsTxtController.class);
|
||||
|
||||
@RequestMapping(value = "/robots.txt")
|
||||
public void robots(HttpServletResponse response) {
|
||||
try {
|
||||
response.getWriter().write("User-agent: *\nDisallow: /\n");
|
||||
} catch (IOException ex) {
|
||||
LOG.info("Error during robots.txt serving.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
41
src/main/java/org/cerberus/controllers/UserController.java
Normal file
41
src/main/java/org/cerberus/controllers/UserController.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package org.cerberus.controllers;
|
||||
|
||||
import org.cerberus.core.config.security.CustomAuthenticationProvider;
|
||||
import org.cerberus.entities.persistence.User;
|
||||
import org.cerberus.repositories.UserRepository;
|
||||
import org.cerberus.services.UserService;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Collections;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/users")
|
||||
public class UserController {
|
||||
private UserService userService;
|
||||
|
||||
public UserController(UserService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public void login(@RequestBody User user, HttpServletResponse response) {
|
||||
userService.authenticate(user);
|
||||
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
|
||||
}
|
||||
|
||||
@GetMapping("/disconnection")
|
||||
public void disconnection(final HttpServletRequest request, final HttpServletResponse response) {
|
||||
final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
if(auth != null) {
|
||||
new SecurityContextLogoutHandler().logout(request, response, auth);
|
||||
}
|
||||
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.cerberus.core.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.web.servlet.error.ErrorAttributes;
|
||||
import org.springframework.boot.web.servlet.error.ErrorController;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Controller that catch errors from spring rest or spring security and others, and transform them to JSON response.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/error")
|
||||
public class CustomErrorController implements ErrorController {
|
||||
|
||||
private final ErrorAttributes errorAttributes;
|
||||
|
||||
@Autowired
|
||||
public CustomErrorController(ErrorAttributes errorAttributes) {
|
||||
Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
|
||||
this.errorAttributes = errorAttributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorPath() {
|
||||
return "/error";
|
||||
}
|
||||
|
||||
@RequestMapping
|
||||
public Map<String, Object> error(HttpServletRequest request) {
|
||||
Map<String, Object> body = getErrorAttributes(request, getTraceParameter(request));
|
||||
String trace = (String) body.get("trace");
|
||||
if (trace != null) {
|
||||
String[] lines = trace.split("\n\t");
|
||||
body.put("trace", lines);
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
private boolean getTraceParameter(HttpServletRequest request) {
|
||||
String parameter = request.getParameter("trace");
|
||||
if (parameter == null) {
|
||||
return false;
|
||||
}
|
||||
return !"false".equals(parameter.toLowerCase());
|
||||
}
|
||||
|
||||
private Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) {
|
||||
return errorAttributes.getErrorAttributes(new ServletWebRequest(request), includeStackTrace);
|
||||
}
|
||||
}
|
||||
41
src/main/java/org/cerberus/core/config/JpaConfiguration.java
Normal file
41
src/main/java/org/cerberus/core/config/JpaConfiguration.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package org.cerberus.core.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@Configuration
|
||||
@EntityScan("org.cerberus.entities.persistence")
|
||||
@EnableTransactionManagement
|
||||
@EnableJpaRepositories("org.cerberus.repositories")
|
||||
@PropertySource("classpath:application.yml")
|
||||
public class JpaConfiguration {
|
||||
@Value("${spring.jpa.datasource.driverClassName}")
|
||||
private String driverClassName;
|
||||
|
||||
@Value("${spring.jpa.datasource.url}")
|
||||
private String url;
|
||||
|
||||
@Value("${spring.jpa.datasource.username}")
|
||||
private String username;
|
||||
|
||||
@Value("${spring.jpa.datasource.password}")
|
||||
private String password;
|
||||
|
||||
@Bean(name = "dataSource")
|
||||
public DataSource getDataSource() {
|
||||
return DataSourceBuilder.create()
|
||||
.username(username)
|
||||
.password(password)
|
||||
.url(url)
|
||||
.driverClassName(driverClassName)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
34
src/main/java/org/cerberus/core/config/WebConfiguration.java
Normal file
34
src/main/java/org/cerberus/core/config/WebConfiguration.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package org.cerberus.core.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.resource.PathResourceResolver;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This configuration class serves Angular app if the url isn't available in sprint REST module.
|
||||
*
|
||||
* @author florian
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class WebConfiguration implements WebMvcConfigurer {
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/**/*")
|
||||
.addResourceLocations("classpath:/static/")
|
||||
.resourceChain(true)
|
||||
.addResolver(new PathResourceResolver() {
|
||||
@Override
|
||||
protected Resource getResource(String resourcePath, Resource location) throws IOException {
|
||||
Resource requestedResource = location.createRelative(resourcePath);
|
||||
return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
|
||||
: new ClassPathResource("/static/index.html");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
38
src/main/java/org/cerberus/core/config/security/CorsFilter.java
Executable file
38
src/main/java/org/cerberus/core/config/security/CorsFilter.java
Executable file
@@ -0,0 +1,38 @@
|
||||
package org.cerberus.core.config.security;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class CorsFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||
httpResponse.addHeader("Access-Control-Allow-Origin", "*");
|
||||
httpResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH, HEAD");
|
||||
httpResponse.addHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
|
||||
httpResponse.addHeader("Access-Control-Expose-Headers", "Access-Control-Allow-Origin, Access-Control-Allow-Credentials");
|
||||
httpResponse.addHeader("Access-Control-Allow-Credentials", "true");
|
||||
httpResponse.addIntHeader("Access-Control-Max-Age", 10);
|
||||
chain.doFilter(request, httpResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.cerberus.core.config.security;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@Component
|
||||
public class CustomAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
// Creation of the authentication bean with its roles
|
||||
Authentication auth = new UsernamePasswordAuthenticationToken(authentication.getName(),
|
||||
authentication.getCredentials(), new ArrayList<>());
|
||||
|
||||
// Set the auth bean in spring security context
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> authentication) {
|
||||
return authentication.equals(UsernamePasswordAuthenticationToken.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.cerberus.core.config.security;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Authentication entry point configured in
|
||||
* {@link SecurityConfiguration#configure(org.springframework.security.config.annotation.web.builders.HttpSecurity)}
|
||||
* to avoid yo get a login form at authentication failure from Angular app.
|
||||
*
|
||||
* @author takiguchi
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException {
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
72
src/main/java/org/cerberus/core/config/security/SecurityConfiguration.java
Executable file
72
src/main/java/org/cerberus/core/config/security/SecurityConfiguration.java
Executable file
@@ -0,0 +1,72 @@
|
||||
package org.cerberus.core.config.security;
|
||||
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpMethod;
|
||||
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.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.csrf.CsrfFilter;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
|
||||
|
||||
import static org.springframework.http.HttpMethod.GET;
|
||||
import static org.springframework.http.HttpMethod.POST;
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
@Order(SecurityProperties.BASIC_AUTH_ORDER)
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private static final String XSRF_REPOSITORY_HEADER_NAME = "X-XSRF-TOKEN";
|
||||
|
||||
private CustomAuthenticationProvider authenticationProvider;
|
||||
private RestAuthenticationEntryPoint authenticationEntryPoint;
|
||||
|
||||
public SecurityConfiguration(CustomAuthenticationProvider authenticationProvider,
|
||||
RestAuthenticationEntryPoint authenticationEntryPoint) {
|
||||
this.authenticationProvider = authenticationProvider;
|
||||
this.authenticationEntryPoint = authenticationEntryPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) {
|
||||
auth.authenticationProvider(authenticationProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests()
|
||||
// Permits all
|
||||
.antMatchers(
|
||||
"/robots.txt"
|
||||
).permitAll()
|
||||
.antMatchers(GET,
|
||||
"/api/users/disconnection"
|
||||
).permitAll()
|
||||
.antMatchers(POST,
|
||||
"/api/users/login"
|
||||
).permitAll()
|
||||
.anyRequest().permitAll()
|
||||
.and()
|
||||
// Allow to avoid login form at authentication failure from Angular app
|
||||
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
|
||||
.and()
|
||||
.addFilterAfter(new XSRFTokenFilter(), CsrfFilter.class)
|
||||
.csrf()
|
||||
.csrfTokenRepository(xsrfTokenRepository());
|
||||
http.httpBasic();
|
||||
http.csrf().disable();
|
||||
}
|
||||
|
||||
private CsrfTokenRepository xsrfTokenRepository() {
|
||||
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
|
||||
repository.setHeaderName(XSRF_REPOSITORY_HEADER_NAME);
|
||||
return repository;
|
||||
}
|
||||
}
|
||||
33
src/main/java/org/cerberus/core/config/security/XSRFTokenFilter.java
Executable file
33
src/main/java/org/cerberus/core/config/security/XSRFTokenFilter.java
Executable file
@@ -0,0 +1,33 @@
|
||||
package org.cerberus.core.config.security;
|
||||
|
||||
import org.springframework.security.web.csrf.CsrfToken;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class XSRFTokenFilter extends OncePerRequestFilter {
|
||||
private static final String XSRF_TOKEN_PATH = "/";
|
||||
private static final String XSRF_TOKEN = "XSRF-TOKEN";
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
|
||||
if(csrf != null) {
|
||||
Cookie cookie = WebUtils.getCookie(request, XSRF_TOKEN);
|
||||
String token = csrf.getToken();
|
||||
if(cookie == null || token != null && !token.equals(cookie.getValue())) {
|
||||
cookie = new Cookie(XSRF_TOKEN, token);
|
||||
cookie.setPath(XSRF_TOKEN_PATH);
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.cerberus.core.exceptions;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
|
||||
public class BadRequestException extends BusinessException {
|
||||
public BadRequestException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public BadRequestException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.cerberus.core.exceptions;
|
||||
|
||||
/**
|
||||
* Abstract class for all business exception that could be thrown at any time.
|
||||
*/
|
||||
abstract class BusinessException extends RuntimeException {
|
||||
BusinessException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
BusinessException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package org.cerberus.entities.persistence;
|
||||
|
||||
import org.hibernate.annotations.Generated;
|
||||
import org.hibernate.annotations.GenerationTime;
|
||||
import org.hibernate.annotations.Proxy;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name="application")
|
||||
@Proxy(lazy = false)
|
||||
public class Application {
|
||||
@Id
|
||||
@Generated(GenerationTime.ALWAYS)
|
||||
private String id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String serviceName;
|
||||
|
||||
@OneToMany(mappedBy = "application")
|
||||
private List<ConfigurationFile> configurationFileList;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
name = "administrator",
|
||||
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "application_id", referencedColumnName = "id")
|
||||
)
|
||||
private List<User> administratorList;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getServiceName() {
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
public void setServiceName(String serviceName) {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
public List<ConfigurationFile> getConfigurationFileList() {
|
||||
return configurationFileList;
|
||||
}
|
||||
|
||||
public void setConfigurationFileList(List<ConfigurationFile> configurationFileList) {
|
||||
this.configurationFileList = configurationFileList;
|
||||
}
|
||||
|
||||
public List<User> getAdministratorList() {
|
||||
return administratorList;
|
||||
}
|
||||
|
||||
public void setAdministratorList(List<User> administratorList) {
|
||||
this.administratorList = administratorList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.cerberus.entities.persistence;
|
||||
|
||||
import org.hibernate.annotations.Generated;
|
||||
import org.hibernate.annotations.GenerationTime;
|
||||
import org.hibernate.annotations.Proxy;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity
|
||||
@Table(name="configuration_file")
|
||||
@Proxy(lazy = false)
|
||||
public class ConfigurationFile {
|
||||
@Id
|
||||
@Generated(GenerationTime.ALWAYS)
|
||||
private String id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String path;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "application_id")
|
||||
private Application application;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public Application getApplication() {
|
||||
return application;
|
||||
}
|
||||
|
||||
public void setApplication(Application application) {
|
||||
this.application = application;
|
||||
}
|
||||
}
|
||||
87
src/main/java/org/cerberus/entities/persistence/User.java
Normal file
87
src/main/java/org/cerberus/entities/persistence/User.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package org.cerberus.entities.persistence;
|
||||
|
||||
import org.hibernate.annotations.Generated;
|
||||
import org.hibernate.annotations.GenerationTime;
|
||||
import org.hibernate.annotations.Proxy;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name="`user`")
|
||||
@Proxy(lazy = false)
|
||||
public class User {
|
||||
@Id
|
||||
@Generated(GenerationTime.ALWAYS)
|
||||
private String id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String email;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String password;
|
||||
|
||||
@Column(name = "inscription_date", nullable = false)
|
||||
@Generated(GenerationTime.ALWAYS)
|
||||
private LocalDate inscriptionDate;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
name = "administrator",
|
||||
joinColumns = @JoinColumn(name = "application_id", referencedColumnName = "id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id")
|
||||
)
|
||||
private List<Application> applicationList;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public LocalDate getInscriptionDate() {
|
||||
return inscriptionDate;
|
||||
}
|
||||
|
||||
public void setInscriptionDate(LocalDate inscriptionDate) {
|
||||
this.inscriptionDate = inscriptionDate;
|
||||
}
|
||||
|
||||
public List<Application> getApplicationList() {
|
||||
return applicationList;
|
||||
}
|
||||
|
||||
public void setApplicationList(List<Application> applicationList) {
|
||||
this.applicationList = applicationList;
|
||||
}
|
||||
}
|
||||
13
src/main/java/org/cerberus/repositories/UserRepository.java
Normal file
13
src/main/java/org/cerberus/repositories/UserRepository.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package org.cerberus.repositories;
|
||||
|
||||
import org.cerberus.entities.persistence.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface UserRepository extends JpaRepository<User, String> {
|
||||
@Query("SELECT u FROM User u WHERE u.email = :email")
|
||||
Optional<User> findByEmail(@Param("email") String email);
|
||||
}
|
||||
42
src/main/java/org/cerberus/services/UserService.java
Normal file
42
src/main/java/org/cerberus/services/UserService.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package org.cerberus.services;
|
||||
|
||||
import org.cerberus.core.config.security.CustomAuthenticationProvider;
|
||||
import org.cerberus.core.exceptions.BadRequestException;
|
||||
import org.cerberus.entities.persistence.User;
|
||||
import org.cerberus.repositories.UserRepository;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.swing.text.html.Option;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class UserService {
|
||||
private CustomAuthenticationProvider authenticationProvider;
|
||||
private UserRepository userRepository;
|
||||
|
||||
public UserService(CustomAuthenticationProvider authenticationProvider, UserRepository userRepository) {
|
||||
this.authenticationProvider = authenticationProvider;
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
public void authenticate(User user) {
|
||||
checkCredentials(user.getEmail(), user.getPassword());
|
||||
|
||||
authenticationProvider.authenticate(new UsernamePasswordAuthenticationToken(
|
||||
user.getEmail(),
|
||||
user.getPassword(),
|
||||
Collections.singleton(new SimpleGrantedAuthority("APPLICATION_ADMIN"))
|
||||
));
|
||||
}
|
||||
|
||||
void checkCredentials(String email, String password) {
|
||||
Optional<User> optUser = userRepository.findByEmail(email);
|
||||
|
||||
if(optUser.isEmpty() || !optUser.get().getPassword().equals(password)) {
|
||||
throw new BadRequestException("Credentials are incorrect.");
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/main/resources/application.yml
Normal file
26
src/main/resources/application.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
logging:
|
||||
level:
|
||||
org:
|
||||
hibernate:
|
||||
SQL: DEBUG
|
||||
|
||||
server:
|
||||
# use-forward-headers=true
|
||||
error:
|
||||
whitelabel:
|
||||
enabled: false # Disable html error responses.
|
||||
port: 8080
|
||||
|
||||
spring:
|
||||
jpa:
|
||||
datasource:
|
||||
driverClassName: org.postgresql.Driver
|
||||
url: jdbc:postgresql://localhost:5432/db_cerberus
|
||||
username: cerberus
|
||||
password: P@ssword
|
||||
open-in-view: false
|
||||
# Because detection is disabled you have to set correct dialect by hand.
|
||||
database-platform: org.hibernate.dialect.PostgreSQL9Dialect
|
||||
# Disable feature detection by this undocumented parameter.
|
||||
# Check the org.hibernate.engine.jdbc.internal.JdbcServiceImpl.configure method for more details.
|
||||
properties.hibernate.temp.use_jdbc_metadata_defaults: false
|
||||
15
src/main/resources/banner.txt
Normal file
15
src/main/resources/banner.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
***********
|
||||
*******************
|
||||
***********************
|
||||
*********##*****##*********
|
||||
*****#***###########***#***** ( )
|
||||
*****#######*#####*#######***** )\ ( ( ( /( ( (
|
||||
****#######################**** (((_) ))\ )( )\()) ))\ )( ( (
|
||||
****#*########***########*#**** )\___ /((_|()\((_)\ /((_|()\ )\ )\
|
||||
****#*#########*#########*#**** ((/ __(_)) ((_) |(_)(_)) ((_)((_|(_)
|
||||
******##*#####***#####*##****** | (__/ -_)| '_| '_ \/ -_)| '_| | (_-<
|
||||
******########***########****** \___\___||_| |_.__/\___||_| \___/__/
|
||||
******#######***#######******
|
||||
******######***######******
|
||||
*******###***###*******
|
||||
*******************
|
||||
34
src/main/sql/1.0.0-SNAPSHOT
Normal file
34
src/main/sql/1.0.0-SNAPSHOT
Normal file
@@ -0,0 +1,34 @@
|
||||
CREATE TABLE "user" (
|
||||
id uuid DEFAULT uuid_generate_v4(),
|
||||
name VARCHAR NOT NULL,
|
||||
email VARCHAR NOT NULL UNIQUE,
|
||||
password VARCHAR NOT NULL,
|
||||
inscription_date DATE DEFAULT current_date,
|
||||
CONSTRAINT user_pk PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE application (
|
||||
id uuid DEFAULT uuid_generate_v4(),
|
||||
name VARCHAR NOT NULL,
|
||||
service_name VARCHAR NOT NULL,
|
||||
CONSTRAINT application_pk PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE configuration_file (
|
||||
id uuid DEFAULT uuid_generate_v4(),
|
||||
path VARCHAR NOT NULL,
|
||||
application_id uuid NOT NULL,
|
||||
CONSTRAINT configuration_file_pk PRIMARY KEY (id),
|
||||
CONSTRAINT configuration_file_application_id_fk FOREIGN KEY (application_id) REFERENCES application (id)
|
||||
);
|
||||
CREATE INDEX configuration_file_application_id_idx ON configuration_file(application_id);
|
||||
|
||||
CREATE TABLE administrator (
|
||||
user_id uuid NOT NULL,
|
||||
application_id uuid NOT NULL,
|
||||
CONSTRAINT administrator_pk PRIMARY KEY (user_id, application_id),
|
||||
CONSTRAINT administrator_user_id FOREIGN KEY (user_id) REFERENCES "user" (id),
|
||||
CONSTRAINT administrator_application_id FOREIGN KEY (application_id) REFERENCES application (id)
|
||||
);
|
||||
CREATE INDEX administrator_user_id_idx ON administrator(user_id);
|
||||
CREATE INDEX administrator_application_id_idx ON administrator(application_id);
|
||||
Reference in New Issue
Block a user