Compare commits
No commits in common. "Lab6_Vue" and "master" have entirely different histories.
28
build.gradle
28
build.gradle
@ -1,44 +1,20 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'org.springframework.boot' version '3.0.4'
|
id 'org.springframework.boot' version '3.0.2'
|
||||||
id 'io.spring.dependency-management' version '1.1.0'
|
id 'io.spring.dependency-management' version '1.1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'com.example'
|
group = 'com.example'
|
||||||
version = '0.0.1-SNAPSHOT'
|
version = '0.0.1-SNAPSHOT'
|
||||||
sourceCompatibility = '19'
|
sourceCompatibility = '17'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
|
||||||
enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
|
||||||
implementation 'org.springframework.boot:spring-boot-devtools'
|
|
||||||
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
|
|
||||||
|
|
||||||
implementation 'org.webjars.npm:bootstrap:5.3.0-alpha2'
|
|
||||||
implementation 'org.webjars:jquery:3.6.0'
|
|
||||||
implementation 'org.webjars:font-awesome:6.1.0'
|
|
||||||
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
|
||||||
implementation 'com.auth0:java-jwt:4.4.0'
|
|
||||||
implementation 'com.h2database:h2:2.1.210'
|
|
||||||
|
|
||||||
implementation 'org.hibernate.validator:hibernate-validator'
|
|
||||||
|
|
||||||
implementation 'org.springdoc:springdoc-openapi-ui:1.6.5'
|
|
||||||
implementation 'org.projectlombok:lombok:1.18.22'
|
|
||||||
|
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named('test') {
|
tasks.named('test') {
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@ -1,2 +1 @@
|
|||||||
rootProject.name = 'demo'
|
rootProject.name = 'demo1'
|
||||||
include 'front'
|
|
||||||
|
18
src/main/java/com/example/demo/Demo1Application.java
Normal file
18
src/main/java/com/example/demo/Demo1Application.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package com.example.demo;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@RestController
|
||||||
|
public class Demo1Application {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Demo1Application.class, args);
|
||||||
|
}
|
||||||
|
@GetMapping("/")
|
||||||
|
public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {
|
||||||
|
return String.format("Hello %s!", name);
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
package com.example.demo;
|
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@SpringBootApplication
|
|
||||||
@RestController
|
|
||||||
public class DemoApplication {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
SpringApplication.run(DemoApplication.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
package com.example.demo.configuration;
|
|
||||||
|
|
||||||
|
|
||||||
import com.example.demo.configuration.jwt.JwtFilter;
|
|
||||||
import io.swagger.v3.oas.models.Components;
|
|
||||||
import io.swagger.v3.oas.models.OpenAPI;
|
|
||||||
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
|
||||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class OpenAPI30Configuration {
|
|
||||||
public static final String API_PREFIX = "/api/1.0";
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public OpenAPI customizeOpenAPI() {
|
|
||||||
final String securitySchemeName = JwtFilter.TOKEN_BEGIN_STR;
|
|
||||||
return new OpenAPI()
|
|
||||||
.addSecurityItem(new SecurityRequirement()
|
|
||||||
.addList(securitySchemeName))
|
|
||||||
.components(new Components()
|
|
||||||
.addSecuritySchemes(securitySchemeName, new SecurityScheme()
|
|
||||||
.name(securitySchemeName)
|
|
||||||
.type(SecurityScheme.Type.HTTP)
|
|
||||||
.scheme("bearer")
|
|
||||||
.bearerFormat("JWT")));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package com.example.demo.configuration;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class PasswordEncoderConfiguration {
|
|
||||||
@Bean
|
|
||||||
public PasswordEncoder passwordEncoder() {
|
|
||||||
return new BCryptPasswordEncoder();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
package com.example.demo.configuration;
|
|
||||||
|
|
||||||
|
|
||||||
import com.example.demo.configuration.jwt.JwtFilter;
|
|
||||||
import com.example.demo.master.MasterController;
|
|
||||||
import com.example.demo.master.MasterRole;
|
|
||||||
import com.example.demo.master.MasterService;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
|
||||||
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.WebSecurityCustomizer;
|
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSecurity
|
|
||||||
@EnableMethodSecurity(
|
|
||||||
securedEnabled = true
|
|
||||||
)
|
|
||||||
public class SecurityConfiguration {
|
|
||||||
private final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class);
|
|
||||||
public static final String SPA_URL_MASK = "/{path:[^\\.]*}";
|
|
||||||
private final MasterService masterService;
|
|
||||||
private final JwtFilter jwtFilter;
|
|
||||||
|
|
||||||
public SecurityConfiguration(MasterService masterService) {
|
|
||||||
this.masterService = masterService;
|
|
||||||
this.jwtFilter = new JwtFilter(masterService);
|
|
||||||
createAdminOnStartup();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createAdminOnStartup() {
|
|
||||||
final String admin = "admin";
|
|
||||||
if (masterService.findMaster(admin) == null) {
|
|
||||||
log.info("Admin user successfully created");
|
|
||||||
masterService.addMaster(admin, admin, admin, admin, MasterRole.ADMIN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
|
||||||
http.cors()
|
|
||||||
.and()
|
|
||||||
.csrf().disable()
|
|
||||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
|
||||||
.and()
|
|
||||||
.authorizeHttpRequests()
|
|
||||||
.requestMatchers("/", SPA_URL_MASK).permitAll()
|
|
||||||
.requestMatchers(HttpMethod.GET, OpenAPI30Configuration.API_PREFIX + "/product/").permitAll()
|
|
||||||
.requestMatchers(HttpMethod.POST, MasterController.URL_LOGIN).permitAll()
|
|
||||||
.requestMatchers(HttpMethod.POST, MasterController.URL_SING_UP).permitAll()
|
|
||||||
.requestMatchers(HttpMethod.POST, MasterController.URL_WHO_AM_I).permitAll()
|
|
||||||
.anyRequest()
|
|
||||||
.authenticated()
|
|
||||||
.and()
|
|
||||||
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
|
|
||||||
.anonymous();
|
|
||||||
return http.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public AuthenticationManager authenticationManagerBean(HttpSecurity http) throws Exception {
|
|
||||||
AuthenticationManagerBuilder authenticationManagerBuilder = http
|
|
||||||
.getSharedObject(AuthenticationManagerBuilder.class);
|
|
||||||
authenticationManagerBuilder.userDetailsService(masterService);
|
|
||||||
return authenticationManagerBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public WebSecurityCustomizer webSecurityCustomizer() {
|
|
||||||
return (web) -> web.ignoring()
|
|
||||||
.requestMatchers(HttpMethod.OPTIONS, "/**")
|
|
||||||
.requestMatchers("/*.js")
|
|
||||||
.requestMatchers("/*.html")
|
|
||||||
.requestMatchers("/*.css")
|
|
||||||
.requestMatchers("/assets/**")
|
|
||||||
.requestMatchers("/favicon.ico")
|
|
||||||
.requestMatchers("/.js", "/.css")
|
|
||||||
.requestMatchers("/swagger-ui/index.html")
|
|
||||||
.requestMatchers("/webjars/**")
|
|
||||||
.requestMatchers("/swagger-resources/**")
|
|
||||||
.requestMatchers("/v3/api-docs/**")
|
|
||||||
.requestMatchers("/h2-console");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
package com.example.demo.configuration;
|
|
||||||
|
|
||||||
import org.springframework.boot.web.server.ErrorPage;
|
|
||||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
|
||||||
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistration;
|
|
||||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|
||||||
@Configuration
|
|
||||||
public class WebConfiguration implements WebMvcConfigurer {
|
|
||||||
@Override
|
|
||||||
public void addViewControllers(ViewControllerRegistry registry) {
|
|
||||||
registry.addViewController(SecurityConfiguration.SPA_URL_MASK).setViewName("forward:/");
|
|
||||||
registry.addViewController("/notFound").setViewName("forward:/");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> containerCustomizer() {
|
|
||||||
return container -> container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notFound"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addCorsMappings(CorsRegistry registry) {
|
|
||||||
registry.addMapping("/**").allowedMethods("*");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package com.example.demo.configuration.jwt;
|
|
||||||
|
|
||||||
public class JwtException extends RuntimeException {
|
|
||||||
public JwtException(Throwable throwable) {
|
|
||||||
super(throwable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JwtException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
package com.example.demo.configuration.jwt;
|
|
||||||
|
|
||||||
import com.example.demo.master.MasterService;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import jakarta.servlet.FilterChain;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.ServletRequest;
|
|
||||||
import jakarta.servlet.ServletResponse;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.web.filter.GenericFilterBean;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class JwtFilter extends GenericFilterBean {
|
|
||||||
private static final String AUTHORIZATION = "Authorization";
|
|
||||||
public static final String TOKEN_BEGIN_STR = "Bearer ";
|
|
||||||
|
|
||||||
private final MasterService masterService;
|
|
||||||
|
|
||||||
public JwtFilter(MasterService masterService) {
|
|
||||||
this.masterService = masterService;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTokenFromRequest(HttpServletRequest request) {
|
|
||||||
String bearer = request.getHeader(AUTHORIZATION);
|
|
||||||
if (StringUtils.hasText(bearer) && bearer.startsWith(TOKEN_BEGIN_STR)) {
|
|
||||||
return bearer.substring(TOKEN_BEGIN_STR.length());
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void raiseException(ServletResponse response, int status, String message) throws IOException {
|
|
||||||
if (response instanceof final HttpServletResponse httpResponse) {
|
|
||||||
httpResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
|
||||||
httpResponse.setStatus(status);
|
|
||||||
final byte[] body = new ObjectMapper().writeValueAsBytes(message);
|
|
||||||
response.getOutputStream().write(body);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doFilter(ServletRequest request,
|
|
||||||
ServletResponse response,
|
|
||||||
FilterChain chain) throws IOException, ServletException {
|
|
||||||
if (request instanceof final HttpServletRequest httpRequest) {
|
|
||||||
final String token = getTokenFromRequest(httpRequest);
|
|
||||||
if (StringUtils.hasText(token)) {
|
|
||||||
try {
|
|
||||||
final UserDetails user = masterService.loadUserByToken(token);
|
|
||||||
final UsernamePasswordAuthenticationToken auth =
|
|
||||||
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
|
||||||
} catch (JwtException e) {
|
|
||||||
raiseException(response, HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
|
|
||||||
return;
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
raiseException(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
|
||||||
String.format("Internal error: %s", e.getMessage()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chain.doFilter(request, response);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
package com.example.demo.configuration.jwt;
|
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@ConfigurationProperties(prefix = "jwt", ignoreInvalidFields = true)
|
|
||||||
public class JwtProperties {
|
|
||||||
private String devToken = "";
|
|
||||||
private Boolean isDev = true;
|
|
||||||
|
|
||||||
public String getDevToken() {
|
|
||||||
return devToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDevToken(String devToken) {
|
|
||||||
this.devToken = devToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean isDev() {
|
|
||||||
return isDev;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDev(Boolean dev) {
|
|
||||||
isDev = dev;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,107 +0,0 @@
|
|||||||
package com.example.demo.configuration.jwt;
|
|
||||||
|
|
||||||
import com.auth0.jwt.JWT;
|
|
||||||
import com.auth0.jwt.algorithms.Algorithm;
|
|
||||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
|
||||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
|
||||||
import com.auth0.jwt.interfaces.JWTVerifier;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class JwtProvider {
|
|
||||||
private final static Logger LOG = LoggerFactory.getLogger(JwtProvider.class);
|
|
||||||
|
|
||||||
private final static byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
|
|
||||||
private final static String ISSUER = "auth0";
|
|
||||||
|
|
||||||
private final Algorithm algorithm;
|
|
||||||
private final JWTVerifier verifier;
|
|
||||||
|
|
||||||
public JwtProvider(JwtProperties jwtProperties) {
|
|
||||||
if (!jwtProperties.isDev()) {
|
|
||||||
LOG.info("Generate new JWT key for prod");
|
|
||||||
try {
|
|
||||||
final MessageDigest salt = MessageDigest.getInstance("SHA-256");
|
|
||||||
salt.update(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8));
|
|
||||||
LOG.info("Use generated JWT key for prod \n{}", bytesToHex(salt.digest()));
|
|
||||||
algorithm = Algorithm.HMAC256(bytesToHex(salt.digest()));
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new JwtException(e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG.info("Use default JWT key for dev \n{}", jwtProperties.getDevToken());
|
|
||||||
algorithm = Algorithm.HMAC256(jwtProperties.getDevToken());
|
|
||||||
}
|
|
||||||
verifier = JWT.require(algorithm)
|
|
||||||
.withIssuer(ISSUER)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String bytesToHex(byte[] bytes) {
|
|
||||||
byte[] hexChars = new byte[bytes.length * 2];
|
|
||||||
for (int j = 0; j < bytes.length; j++) {
|
|
||||||
int v = bytes[j] & 0xFF;
|
|
||||||
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
|
|
||||||
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
|
|
||||||
}
|
|
||||||
return new String(hexChars, StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String generateToken(String login) {
|
|
||||||
final Date issueDate = Date.from(LocalDate.now()
|
|
||||||
.atStartOfDay(ZoneId.systemDefault())
|
|
||||||
.toInstant());
|
|
||||||
final Date expireDate = Date.from(LocalDate.now()
|
|
||||||
.plusDays(15)
|
|
||||||
.atStartOfDay(ZoneId.systemDefault())
|
|
||||||
.toInstant());
|
|
||||||
return JWT.create()
|
|
||||||
.withIssuer(ISSUER)
|
|
||||||
.withIssuedAt(issueDate)
|
|
||||||
.withExpiresAt(expireDate)
|
|
||||||
.withSubject(login)
|
|
||||||
.sign(algorithm);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DecodedJWT validateToken(String token) {
|
|
||||||
try {
|
|
||||||
return verifier.verify(token);
|
|
||||||
} catch (JWTVerificationException e) {
|
|
||||||
throw new JwtException(String.format("Token verification error: %s", e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isTokenValid(String token) {
|
|
||||||
if (!StringUtils.hasText(token)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
validateToken(token);
|
|
||||||
return true;
|
|
||||||
} catch (JwtException e) {
|
|
||||||
LOG.error(e.getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<String> getLoginFromToken(String token) {
|
|
||||||
try {
|
|
||||||
return Optional.ofNullable(validateToken(token).getSubject());
|
|
||||||
} catch (JwtException e) {
|
|
||||||
LOG.error(e.getMessage());
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,100 +0,0 @@
|
|||||||
package com.example.demo.master;
|
|
||||||
|
|
||||||
import com.example.demo.master.MasterRole;
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
|
|
||||||
public class Master {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
|
||||||
@Column(name="_id")
|
|
||||||
private Long id;
|
|
||||||
@Column()
|
|
||||||
private String firstName;
|
|
||||||
private String lastName;
|
|
||||||
private String email;
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
private MasterRole role;
|
|
||||||
|
|
||||||
public Master() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Master(String firstName, String lastName, String email, String password, MasterRole role) {
|
|
||||||
this.firstName = firstName;
|
|
||||||
this.lastName = lastName;
|
|
||||||
this.email = email;
|
|
||||||
this.password = password;
|
|
||||||
this.role = role;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFirstName() {
|
|
||||||
return firstName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLastName() {
|
|
||||||
return lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmail() {return email; }
|
|
||||||
|
|
||||||
public String getPassword() { return password; }
|
|
||||||
|
|
||||||
public MasterRole getRole() {
|
|
||||||
return role;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFirstName(String firstName) {
|
|
||||||
this.firstName = firstName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLastName(String lastName) {
|
|
||||||
this.lastName = lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmail(String email) {
|
|
||||||
this.email = email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassword(String password) {
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRole(MasterRole role) {
|
|
||||||
this.role = role;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
Master master = (Master) o;
|
|
||||||
return Objects.equals(id, master.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "{" +
|
|
||||||
"\"id\":" + id +
|
|
||||||
", \"firstName\":\"" + firstName + '\"' +
|
|
||||||
", \"lastName\":\"" + lastName + '\"' +
|
|
||||||
", \"email\":\"" + email + '\"' +
|
|
||||||
", \"password\":\"" + password + '\"' +
|
|
||||||
", \"role\":\"" + role + "\"" +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
package com.example.demo.master;
|
|
||||||
|
|
||||||
import com.example.demo.configuration.OpenAPI30Configuration;
|
|
||||||
import com.example.demo.order.Order;
|
|
||||||
import com.example.demo.order.OrderService;
|
|
||||||
import com.example.demo.util.validation.ValidationException;
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.io.Console;
|
|
||||||
import java.security.Principal;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
public class MasterController {
|
|
||||||
private final MasterService masterService;
|
|
||||||
private final OrderService orderService;
|
|
||||||
|
|
||||||
public static final String URL_LOGIN = "/jwt/login";
|
|
||||||
public static final String URL_SING_UP = "/sing_up";
|
|
||||||
public static final String URL_WHO_AM_I = "/who_am_i";
|
|
||||||
|
|
||||||
public MasterController(MasterService masterService, OrderService orderService) {
|
|
||||||
this.masterService = masterService;
|
|
||||||
this.orderService = orderService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping(URL_LOGIN)
|
|
||||||
public String login(@RequestBody @Valid MasterLoginDto userDto) {
|
|
||||||
return masterService.loginAndGetToken(userDto);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping(URL_SING_UP)
|
|
||||||
public String singUp(@RequestBody MasterSignupDto masterSignupDto) {
|
|
||||||
try {
|
|
||||||
final Master master = masterService.addMaster(masterSignupDto.getFirstName(), masterSignupDto.getLastName(),
|
|
||||||
masterSignupDto.getEmail(), masterSignupDto.getPassword(), MasterRole.USER);
|
|
||||||
orderService.addOrder(master.getId());
|
|
||||||
return "created " + master.getEmail();
|
|
||||||
} catch (ValidationException e) {
|
|
||||||
return e.getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping(URL_WHO_AM_I)
|
|
||||||
public String whoAmI(@RequestParam("token") String token) {
|
|
||||||
UserDetails userDetails = masterService.loadUserByToken(token);
|
|
||||||
Master master = masterService.findMaster(userDetails.getUsername());
|
|
||||||
return master.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@PatchMapping(OpenAPI30Configuration.API_PREFIX + "/master")
|
|
||||||
public MasterDto updateMaster(@RequestParam("firstName") String firstName,
|
|
||||||
@RequestParam("lastName") String lastName,
|
|
||||||
@RequestParam("email") String email,
|
|
||||||
@RequestParam("password") String password,
|
|
||||||
@RequestParam("token") String token) {
|
|
||||||
UserDetails userDetails = masterService.loadUserByToken(token);
|
|
||||||
Master master = masterService.findMaster(userDetails.getUsername());
|
|
||||||
return new MasterDto(masterService.updateMaster(master.getId(),
|
|
||||||
firstName, lastName, email, password));
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping("/")
|
|
||||||
public MasterDto deleteMaster(@PathVariable Long id) {
|
|
||||||
return new MasterDto(masterService.deleteMaster(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping(OpenAPI30Configuration.API_PREFIX + "/master/all")
|
|
||||||
public List<MasterDto> GetMasters(){
|
|
||||||
return masterService.findAllMasters().stream().map(MasterDto::new).toList();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
package com.example.demo.master;
|
|
||||||
|
|
||||||
import com.example.demo.order.Order;
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class MasterDto {
|
|
||||||
private final Long id;
|
|
||||||
|
|
||||||
private final String firstName;
|
|
||||||
|
|
||||||
private final String lastName;
|
|
||||||
|
|
||||||
@NotBlank
|
|
||||||
private final String email;
|
|
||||||
|
|
||||||
@NotBlank
|
|
||||||
private final String password;
|
|
||||||
|
|
||||||
public MasterDto(Master master) {
|
|
||||||
id = master.getId();
|
|
||||||
firstName = master.getFirstName();
|
|
||||||
lastName = master.getLastName();
|
|
||||||
email = master.getEmail();
|
|
||||||
password = master.getPassword();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFirstName() {
|
|
||||||
return firstName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLastName() {
|
|
||||||
return lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmail() {return email; }
|
|
||||||
|
|
||||||
public String getPassword() { return password; }
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
package com.example.demo.master;
|
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
|
|
||||||
public class MasterLoginDto {
|
|
||||||
@NotBlank
|
|
||||||
private String email;
|
|
||||||
@NotBlank
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
|
|
||||||
public String getEmail() {return email; }
|
|
||||||
|
|
||||||
public String getPassword() { return password; }
|
|
||||||
|
|
||||||
public void setEmail(String email) {
|
|
||||||
this.email = email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassword(String password) {
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package com.example.demo.master;
|
|
||||||
|
|
||||||
public class MasterNotFoundException extends RuntimeException {
|
|
||||||
public MasterNotFoundException(Long id) {
|
|
||||||
super(String.format("Master with id [%s] is not found", id));
|
|
||||||
}
|
|
||||||
public MasterNotFoundException(String email) {
|
|
||||||
super(String.format("Master with email [%s] is not found", email));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
package com.example.demo.master;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public interface MasterRepository extends JpaRepository<Master, Long> {
|
|
||||||
Optional<Master> findByEmail(String email);
|
|
||||||
|
|
||||||
Master findOneByEmailIgnoreCase(String login);
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
package com.example.demo.master;
|
|
||||||
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
|
|
||||||
public enum MasterRole implements GrantedAuthority {
|
|
||||||
ADMIN,
|
|
||||||
USER;
|
|
||||||
|
|
||||||
private static final String PREFIX = "ROLE_";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAuthority() {
|
|
||||||
return PREFIX + this.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class AsString {
|
|
||||||
public static final String ADMIN = PREFIX + "ADMIN";
|
|
||||||
public static final String USER = PREFIX + "USER";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,133 +0,0 @@
|
|||||||
package com.example.demo.master;
|
|
||||||
|
|
||||||
import com.example.demo.configuration.jwt.JwtException;
|
|
||||||
import com.example.demo.configuration.jwt.JwtProvider;
|
|
||||||
import com.example.demo.order.Order;
|
|
||||||
import com.example.demo.order.OrderController;
|
|
||||||
import com.example.demo.order.OrderService;
|
|
||||||
import com.example.demo.util.validation.ValidationException;
|
|
||||||
import com.example.demo.util.validation.ValidatorUtil;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class MasterService implements UserDetailsService {
|
|
||||||
private final MasterRepository masterRepository;
|
|
||||||
|
|
||||||
private final ValidatorUtil validatorUtil;
|
|
||||||
private final PasswordEncoder passwordEncoder;
|
|
||||||
|
|
||||||
private final JwtProvider jwtProvider;
|
|
||||||
public MasterService(MasterRepository masterRepository, ValidatorUtil validatorUtil,
|
|
||||||
PasswordEncoder passwordEncoder, JwtProvider jwtProvider) {
|
|
||||||
this.masterRepository = masterRepository;
|
|
||||||
this.validatorUtil = validatorUtil;
|
|
||||||
this.passwordEncoder = passwordEncoder;
|
|
||||||
this.jwtProvider = jwtProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public Master addMaster(String firstName, String lastName, String email, String password, MasterRole role) {
|
|
||||||
final Master master = new Master(firstName, lastName, email, passwordEncoder.encode(password), role);
|
|
||||||
validatorUtil.validate(master);
|
|
||||||
|
|
||||||
return masterRepository.save(master);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public Master addMaster(String firstName, String lastName, String email, String password) {
|
|
||||||
final Master master = new Master(firstName, lastName, email, passwordEncoder.encode(password), MasterRole.USER);
|
|
||||||
validatorUtil.validate(master);
|
|
||||||
return masterRepository.save(master);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
public Master findMaster(Long id) {
|
|
||||||
final Optional<Master> mater = masterRepository.findById(id);
|
|
||||||
return mater.orElseThrow(() -> new MasterNotFoundException(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
public Master findMaster(String email, String password) {
|
|
||||||
final Optional<Master> master = masterRepository.findByEmail(email);
|
|
||||||
Master realMaster = master.orElseThrow(() -> new MasterNotFoundException(email));
|
|
||||||
if (!Objects.equals(realMaster.getPassword(), password)) {
|
|
||||||
throw new MasterNotFoundException(email);
|
|
||||||
}
|
|
||||||
return realMaster;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
public Master findMaster(String email) {
|
|
||||||
return masterRepository.findOneByEmailIgnoreCase(email);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
public List<Master> findAllMasters() {
|
|
||||||
return masterRepository.findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public Master updateMaster(Long id, String firstName, String lastName, String email, String password) {
|
|
||||||
final Master master = findMaster(id);
|
|
||||||
master.setFirstName(firstName);
|
|
||||||
master.setLastName(lastName);
|
|
||||||
master.setEmail(email);
|
|
||||||
master.setPassword(password);
|
|
||||||
validatorUtil.validate(master);
|
|
||||||
return masterRepository.save(master);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public Master deleteMaster(Long id) {
|
|
||||||
final Master master = findMaster(id);
|
|
||||||
masterRepository.delete(master);
|
|
||||||
return master;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void deleteAllMasters() {
|
|
||||||
masterRepository.deleteAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String loginAndGetToken(MasterLoginDto userDto) {
|
|
||||||
final Master master = findMaster(userDto.getEmail());
|
|
||||||
if (master == null) {
|
|
||||||
throw new MasterNotFoundException(userDto.getEmail());
|
|
||||||
}
|
|
||||||
if (!passwordEncoder.matches(userDto.getPassword(), master.getPassword())) {
|
|
||||||
throw new ValidationException("Incorrect password");
|
|
||||||
}
|
|
||||||
return jwtProvider.generateToken(master.getEmail());
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserDetails loadUserByToken(String token) throws UsernameNotFoundException {
|
|
||||||
if (!jwtProvider.isTokenValid(token)) {
|
|
||||||
throw new JwtException("Bad token");
|
|
||||||
}
|
|
||||||
final String userLogin = jwtProvider.getLoginFromToken(token)
|
|
||||||
.orElseThrow(() -> new JwtException("Token is not contain Login"));
|
|
||||||
return loadUserByUsername(userLogin);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
|
||||||
final Master userEntity = findMaster(username);
|
|
||||||
if (userEntity == null) {
|
|
||||||
throw new UsernameNotFoundException(username);
|
|
||||||
}
|
|
||||||
return new org.springframework.security.core.userdetails.User(
|
|
||||||
userEntity.getEmail(), userEntity.getPassword(), Collections.singleton(userEntity.getRole()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package com.example.demo.master;
|
|
||||||
|
|
||||||
public class MasterSignupDto {
|
|
||||||
private String firstName;
|
|
||||||
private String lastName;
|
|
||||||
private String email;
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
|
|
||||||
public String getFirstName() {
|
|
||||||
return firstName;
|
|
||||||
}
|
|
||||||
public String getLastName() {
|
|
||||||
return lastName;
|
|
||||||
}
|
|
||||||
public String getEmail() {return email; }
|
|
||||||
|
|
||||||
public String getPassword() { return password; }
|
|
||||||
|
|
||||||
public void setFirstName(String firstName) {
|
|
||||||
this.firstName = firstName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLastName(String lastName) {
|
|
||||||
this.lastName = lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmail(String email) {
|
|
||||||
this.email = email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassword(String password) {
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,97 +0,0 @@
|
|||||||
package com.example.demo.order;
|
|
||||||
|
|
||||||
import com.example.demo.master.Master;
|
|
||||||
import com.example.demo.product.Product;
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "Master_order")
|
|
||||||
public class Order {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
|
||||||
@Column(name="_id")
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.EAGER)
|
|
||||||
private Master master;
|
|
||||||
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
|
|
||||||
@JoinTable(name = "order_products", joinColumns = {@JoinColumn(name = "order_id")}, inverseJoinColumns = {@JoinColumn(name = "product_id")})
|
|
||||||
private List<Product> products;
|
|
||||||
|
|
||||||
private OrderStatus status;
|
|
||||||
|
|
||||||
public Order() {
|
|
||||||
status = OrderStatus.Open;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void buyProducts() {
|
|
||||||
for (var item: products) {
|
|
||||||
removeProduct(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addProduct(Product product) {
|
|
||||||
if (products == null)
|
|
||||||
products = new ArrayList<>();
|
|
||||||
products.add(product);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeProduct(Product product) {
|
|
||||||
if (products == null)
|
|
||||||
products = new ArrayList<>();
|
|
||||||
products.remove(product);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Master getMaster() {
|
|
||||||
return master;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMaster(Master master) {
|
|
||||||
this.master = master;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Product> getProducts() {
|
|
||||||
return products;
|
|
||||||
}
|
|
||||||
public OrderStatus getStatus() {return status;}
|
|
||||||
|
|
||||||
public void setStatus(OrderStatus status) {
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProducts(List<Product> products) {
|
|
||||||
this.products = products;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
Order order = (Order) o;
|
|
||||||
return Objects.equals(id, order.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Order {" +
|
|
||||||
"id=" + id +
|
|
||||||
", master='" + master.toString() + '\'' +
|
|
||||||
", products='" + products.toString() + '\'';
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
package com.example.demo.order;
|
|
||||||
|
|
||||||
import com.example.demo.configuration.OpenAPI30Configuration;
|
|
||||||
import com.example.demo.configuration.WebConfiguration;
|
|
||||||
import com.example.demo.master.Master;
|
|
||||||
import com.example.demo.master.MasterRole;
|
|
||||||
import com.example.demo.master.MasterService;
|
|
||||||
import org.springframework.security.access.annotation.Secured;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.net.http.HttpHeaders;
|
|
||||||
import java.security.Principal;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping(OpenAPI30Configuration.API_PREFIX + "/order")
|
|
||||||
public class OrderController {
|
|
||||||
private final OrderService orderService;
|
|
||||||
private final MasterService masterService;
|
|
||||||
|
|
||||||
public OrderController(OrderService orderService, MasterService masterService) {
|
|
||||||
this.orderService = orderService;
|
|
||||||
this.masterService = masterService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/")
|
|
||||||
public OrderDto getOrder(@RequestHeader("Authorization") String token) {
|
|
||||||
UserDetails userDetails = masterService.loadUserByToken(token.substring(7));
|
|
||||||
Master master = masterService.findMaster(userDetails.getUsername());
|
|
||||||
return new OrderDto(orderService.findOrder(master.getId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping("/")
|
|
||||||
public void buyProducts(@RequestHeader("Authorization") String token) {
|
|
||||||
UserDetails userDetails = masterService.loadUserByToken(token.substring(7));
|
|
||||||
Master master = masterService.findMaster(userDetails.getUsername());
|
|
||||||
orderService.buyProducts(master.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/all")
|
|
||||||
public List<OrderDto> getOrder() {
|
|
||||||
return orderService.findAllOrders().stream().map(OrderDto::new).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/{product}")
|
|
||||||
public void addProduct(@PathVariable("product") Long productId, @RequestHeader("Authorization") String token) {
|
|
||||||
UserDetails userDetails = masterService.loadUserByToken(token.substring(7));
|
|
||||||
Master master = masterService.findMaster(userDetails.getUsername());
|
|
||||||
orderService.addProduct(master.getId(), productId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping("/{product}")
|
|
||||||
public void deleteProduct(@PathVariable("product") Long productId, @RequestHeader("Authorization") String token) {
|
|
||||||
UserDetails userDetails = masterService.loadUserByToken(token.substring(7));
|
|
||||||
Master master = masterService.findMaster(userDetails.getUsername());
|
|
||||||
orderService.deleteProduct(master.getId(), productId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/findOrders/{id}")
|
|
||||||
@Secured(MasterRole.AsString.ADMIN)
|
|
||||||
public List<OrderDto> findOrders(@PathVariable("id") Long id) {
|
|
||||||
return orderService.findMastersOrders(id).stream().map(OrderDto::new).toList();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
package com.example.demo.order;
|
|
||||||
|
|
||||||
import com.example.demo.master.Master;
|
|
||||||
import com.example.demo.product.Product;
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class OrderDto {
|
|
||||||
private final Long id;
|
|
||||||
@NotBlank
|
|
||||||
private final Master master;
|
|
||||||
private final List<Product> products;
|
|
||||||
|
|
||||||
private final OrderStatus status;
|
|
||||||
|
|
||||||
private final int cost;
|
|
||||||
|
|
||||||
public OrderDto(Order order) {
|
|
||||||
id = order.getId();
|
|
||||||
master = order.getMaster();
|
|
||||||
products = order.getProducts();
|
|
||||||
status = order.getStatus();
|
|
||||||
int cost1 = 0;
|
|
||||||
for (var item : products) {
|
|
||||||
cost1 += item.getCost();
|
|
||||||
}
|
|
||||||
cost = cost1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Master getMaster() {
|
|
||||||
return master;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Product> getProducts() {
|
|
||||||
return products;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OrderStatus getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
public int getCost() {
|
|
||||||
return cost;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package com.example.demo.order;
|
|
||||||
|
|
||||||
public class OrderNotFoundException extends RuntimeException {
|
|
||||||
public OrderNotFoundException(Long id) {
|
|
||||||
super(String.format("Order with id [%s] is not found", id));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package com.example.demo.order;
|
|
||||||
|
|
||||||
import com.example.demo.master.Master;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public interface OrderRepository extends JpaRepository<Order, Long> {
|
|
||||||
Optional<Order> findByMasterAndStatus(Master master, OrderStatus status);
|
|
||||||
|
|
||||||
List<Order> findByMaster(Master master);
|
|
||||||
}
|
|
@ -1,95 +0,0 @@
|
|||||||
package com.example.demo.order;
|
|
||||||
|
|
||||||
import com.example.demo.master.MasterService;
|
|
||||||
import com.example.demo.product.*;
|
|
||||||
import com.example.demo.util.validation.ValidatorUtil;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class OrderService {
|
|
||||||
private final OrderRepository orderRepository;
|
|
||||||
private final ProductService productService;
|
|
||||||
private final MasterService masterService;
|
|
||||||
private final ValidatorUtil validatorUtil;
|
|
||||||
|
|
||||||
public OrderService(OrderRepository orderRepository, ProductService productService,
|
|
||||||
MasterService masterService, ValidatorUtil validatorUtil) {
|
|
||||||
this.orderRepository = orderRepository;
|
|
||||||
this.productService = productService;
|
|
||||||
this.masterService = masterService;
|
|
||||||
this.validatorUtil = validatorUtil;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public Order addOrder(Long masterId) {
|
|
||||||
final Order order = new Order();
|
|
||||||
order.setMaster(masterService.findMaster(masterId));
|
|
||||||
validatorUtil.validate(order);
|
|
||||||
return orderRepository.save(order);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void addProduct(Long masterId, Long productId) {
|
|
||||||
final Order order = findOrder(masterId);
|
|
||||||
final Product product = productService.findProduct(productId);
|
|
||||||
order.addProduct(product); var products = new ArrayList<Product>();
|
|
||||||
product.setOrder(order);
|
|
||||||
product.setAvailable(Status.Ordered);
|
|
||||||
orderRepository.save(order);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void buyProducts(Long masterId) {
|
|
||||||
final Order order = findOrder(masterId);
|
|
||||||
for (var item: order.getProducts()) {
|
|
||||||
item.setAvailable(Status.Bought);
|
|
||||||
}
|
|
||||||
order.setStatus(OrderStatus.Closed);
|
|
||||||
orderRepository.save(order);
|
|
||||||
addOrder(masterId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void deleteProduct(Long masterId, Long productId) {
|
|
||||||
final Order order = findOrder(masterId);
|
|
||||||
final Product product = productService.findProduct(productId);
|
|
||||||
order.removeProduct(product);
|
|
||||||
product.removeOrder(order);
|
|
||||||
product.setAvailable(Status.Availible);
|
|
||||||
orderRepository.save(order);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional()
|
|
||||||
public Order findOrder(Long masterId) {
|
|
||||||
return orderRepository.findByMasterAndStatus(masterService.findMaster(masterId), OrderStatus.Open).orElseThrow(
|
|
||||||
() -> new OrderNotFoundException(masterId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
public List<Order> findAllOrders() {
|
|
||||||
return orderRepository.findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public Order deleteOrder(Long id) {
|
|
||||||
final Order order = findOrder(id);
|
|
||||||
order.setStatus(OrderStatus.Closed);
|
|
||||||
orderRepository.save(order);
|
|
||||||
return addOrder(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void deleteAllOrders() {
|
|
||||||
orderRepository.deleteAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public List<Order> findMastersOrders(Long masterId) {
|
|
||||||
return orderRepository.findByMaster(masterService.findMaster(masterId));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
package com.example.demo.order;
|
|
||||||
|
|
||||||
public enum OrderStatus {
|
|
||||||
Open,
|
|
||||||
Closed
|
|
||||||
}
|
|
@ -1,111 +0,0 @@
|
|||||||
package com.example.demo.product;
|
|
||||||
|
|
||||||
import com.example.demo.master.Master;
|
|
||||||
import com.example.demo.order.Order;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
public class Product {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
|
||||||
@Column(name="_id")
|
|
||||||
private Long id;
|
|
||||||
@Column()
|
|
||||||
private String name;
|
|
||||||
private Integer cost;
|
|
||||||
|
|
||||||
@ManyToMany(fetch = FetchType.LAZY)
|
|
||||||
@JsonIgnore
|
|
||||||
private List<Order> mastersOrders;
|
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.EAGER)
|
|
||||||
private Master master;
|
|
||||||
|
|
||||||
private Status status;
|
|
||||||
|
|
||||||
public Product() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Product(String name, Integer cost) {
|
|
||||||
this.name = name;
|
|
||||||
this.cost = cost;
|
|
||||||
this.status = Status.Availible;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String _name) {
|
|
||||||
this.name = _name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getCost() {
|
|
||||||
return cost;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCost(Integer cost) {
|
|
||||||
this.cost = cost;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
Product product = (Product) o;
|
|
||||||
return Objects.equals(id, product.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Product {" +
|
|
||||||
"id=" + id +
|
|
||||||
", name='" + name + '\'' +
|
|
||||||
", cost='" + cost.toString() + '\'' +
|
|
||||||
", master='" + master.toString() + '\'' +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Master getMaster() {
|
|
||||||
return master;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMaster(Master master) {
|
|
||||||
this.master = master;
|
|
||||||
}
|
|
||||||
public List<Order> getOrders() {
|
|
||||||
return mastersOrders;
|
|
||||||
}
|
|
||||||
public void setOrder(Order order) {
|
|
||||||
if (!order.getProducts().contains(this)) {
|
|
||||||
order.getProducts().add(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeOrder(Order order) {
|
|
||||||
order.getProducts().remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Status getAvailable() {
|
|
||||||
return this.status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAvailable(Status status) {
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
package com.example.demo.product;
|
|
||||||
|
|
||||||
import com.example.demo.configuration.OpenAPI30Configuration;
|
|
||||||
import com.example.demo.configuration.WebConfiguration;
|
|
||||||
import com.example.demo.master.Master;
|
|
||||||
import com.example.demo.master.MasterService;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
@RestController
|
|
||||||
@RequestMapping(OpenAPI30Configuration.API_PREFIX + "/product")
|
|
||||||
public class ProductController {
|
|
||||||
private final ProductService productService;
|
|
||||||
private final MasterService masterService;
|
|
||||||
|
|
||||||
public ProductController(ProductService productService, MasterService masterService) {
|
|
||||||
this.productService = productService;
|
|
||||||
this.masterService = masterService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
|
||||||
public ProductDto getProduct(@PathVariable Long id) {
|
|
||||||
return new ProductDto(productService.findProduct(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/")
|
|
||||||
public List<ProductDto> getProduct() {
|
|
||||||
return productService.findAllProducts().stream().map(ProductDto::new).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/master")
|
|
||||||
public List<ProductDto> getMasterProduct(@RequestHeader("Authorization") String token) {
|
|
||||||
UserDetails userDetails = masterService.loadUserByToken(token.substring(7));
|
|
||||||
Master master = masterService.findMaster(userDetails.getUsername());
|
|
||||||
return productService.findProducts(master.getId()).stream().map(ProductDto::new).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/{name}/{cost}")
|
|
||||||
public ProductDto createProduct(@PathVariable("name") String name,
|
|
||||||
@PathVariable("cost") Integer cost,
|
|
||||||
@RequestHeader("Authorization") String token) {
|
|
||||||
UserDetails userDetails = masterService.loadUserByToken(token.substring(7));
|
|
||||||
Master master = masterService.findMaster(userDetails.getUsername());
|
|
||||||
return new ProductDto(productService.addProduct(name, cost, master.getId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@PatchMapping("/{id}")
|
|
||||||
public ProductDto updateProduct(@PathVariable Long id,
|
|
||||||
@RequestParam("name") String name,
|
|
||||||
@RequestParam("cost") Integer cost) {
|
|
||||||
return new ProductDto(productService.updateProduct(id, name, cost));
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
|
||||||
public ProductDto deleteProduct(@PathVariable Long id) {
|
|
||||||
return new ProductDto(productService.deleteProduct(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
package com.example.demo.product;
|
|
||||||
|
|
||||||
import com.example.demo.master.Master;
|
|
||||||
import com.example.demo.order.Order;
|
|
||||||
import jakarta.validation.constraints.Min;
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ProductDto {
|
|
||||||
private final long id;
|
|
||||||
@NotBlank
|
|
||||||
private final String name;
|
|
||||||
@Min(1)
|
|
||||||
private final int cost;
|
|
||||||
private final List<Order> orders;
|
|
||||||
@NotBlank
|
|
||||||
private final Master master;
|
|
||||||
@NotBlank
|
|
||||||
private final Status status;
|
|
||||||
|
|
||||||
public ProductDto(Product product) {
|
|
||||||
id = product.getId();
|
|
||||||
name = product.getName();
|
|
||||||
cost = product.getCost();
|
|
||||||
orders = product.getOrders();
|
|
||||||
master = product.getMaster();
|
|
||||||
status = product.getAvailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getCost() {
|
|
||||||
return cost;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Order> getOrders() {
|
|
||||||
return orders;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Master getMaster() {
|
|
||||||
return master;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Status getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package com.example.demo.product;
|
|
||||||
|
|
||||||
public class ProductNotFoundException extends RuntimeException {
|
|
||||||
public ProductNotFoundException(Long id) {
|
|
||||||
super(String.format("Product with id [%s] is not found", id));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package com.example.demo.product;
|
|
||||||
|
|
||||||
import com.example.demo.master.Master;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public interface ProductRepository extends JpaRepository<Product, Long> {
|
|
||||||
List<Product> findByMaster(Master master);
|
|
||||||
|
|
||||||
List<Product> findByStatus(Status status);
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
package com.example.demo.product;
|
|
||||||
|
|
||||||
import com.example.demo.master.*;
|
|
||||||
import com.example.demo.util.validation.ValidatorUtil;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class ProductService {
|
|
||||||
private final ProductRepository productRepository;
|
|
||||||
private final ValidatorUtil validatorUtil;
|
|
||||||
private final MasterService masterService;
|
|
||||||
|
|
||||||
public ProductService(ProductRepository productRepository, MasterService masterService, ValidatorUtil validatorUtil) {
|
|
||||||
this.productRepository = productRepository;
|
|
||||||
this.validatorUtil = validatorUtil;
|
|
||||||
this.masterService = masterService;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public Product addProduct(String name, Integer cost, Long masterId) {
|
|
||||||
final Product product = new Product(name, cost);
|
|
||||||
validatorUtil.validate(product);
|
|
||||||
product.setMaster(masterService.findMaster(masterId));
|
|
||||||
return productRepository.save(product);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
public Product findProduct(Long id) {
|
|
||||||
final Optional<Product> product = productRepository.findById(id);
|
|
||||||
return product.orElseThrow(() -> new ProductNotFoundException(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
public List<Product> findProducts(Long masterId) {
|
|
||||||
List<Product> products = productRepository.findByMaster(masterService.findMaster(masterId));
|
|
||||||
return products.stream().filter((item) -> item.getAvailable() != Status.Bought).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
|
||||||
public List<Product> findAllProducts() {
|
|
||||||
return productRepository.findByStatus(Status.Availible);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public Product updateProduct(Long id, String name, Integer cost) {
|
|
||||||
final Product product = findProduct(id);
|
|
||||||
product.setName(name);
|
|
||||||
product.setCost(cost);
|
|
||||||
validatorUtil.validate(product);
|
|
||||||
return productRepository.save(product);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public Product deleteProduct(Long id) {
|
|
||||||
final Product product = findProduct(id);
|
|
||||||
productRepository.delete(product);
|
|
||||||
return product;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void deleteAllProducts() {
|
|
||||||
productRepository.deleteAll();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package com.example.demo.product;
|
|
||||||
|
|
||||||
public enum Status {
|
|
||||||
Availible,
|
|
||||||
Ordered,
|
|
||||||
Bought
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
package com.example.demo.util.error;
|
|
||||||
|
|
||||||
import com.example.demo.master.MasterNotFoundException;
|
|
||||||
import com.example.demo.order.Order;
|
|
||||||
import com.example.demo.order.OrderNotFoundException;
|
|
||||||
import com.example.demo.product.ProductNotFoundException;
|
|
||||||
import com.example.demo.util.validation.ValidationException;
|
|
||||||
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
|
||||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@ControllerAdvice
|
|
||||||
public class AdviceController {
|
|
||||||
@ExceptionHandler({
|
|
||||||
MasterNotFoundException.class,
|
|
||||||
ProductNotFoundException.class,
|
|
||||||
OrderNotFoundException.class,
|
|
||||||
ValidationException.class,
|
|
||||||
})
|
|
||||||
public ResponseEntity<Object> handleException(Throwable e) {
|
|
||||||
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
|
||||||
public ResponseEntity<Object> handleBindException(MethodArgumentNotValidException e) {
|
|
||||||
final ValidationException validationException = new ValidationException(
|
|
||||||
e.getBindingResult().getAllErrors().stream()
|
|
||||||
.map(DefaultMessageSourceResolvable::getDefaultMessage)
|
|
||||||
.collect(Collectors.toSet()));
|
|
||||||
return handleException(validationException);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(Exception.class)
|
|
||||||
public ResponseEntity<Object> handleUnknownException(Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package com.example.demo.util.validation;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class ValidationException extends RuntimeException {
|
|
||||||
public ValidationException(Set<String> errors) {
|
|
||||||
super(String.join("\n", errors));
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> ValidationException(String error) {
|
|
||||||
super(error);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package com.example.demo.util.validation;
|
|
||||||
|
|
||||||
import jakarta.validation.ConstraintViolation;
|
|
||||||
import jakarta.validation.Validation;
|
|
||||||
import jakarta.validation.Validator;
|
|
||||||
import jakarta.validation.ValidatorFactory;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class ValidatorUtil {
|
|
||||||
private final Validator validator;
|
|
||||||
|
|
||||||
public ValidatorUtil() {
|
|
||||||
try (ValidatorFactory factory = Validation.buildDefaultValidatorFactory()) {
|
|
||||||
this.validator = factory.getValidator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> void validate(T object) {
|
|
||||||
final Set<ConstraintViolation<T>> errors = validator.validate(object);
|
|
||||||
if (!errors.isEmpty()) {
|
|
||||||
throw new ValidationException(errors.stream()
|
|
||||||
.map(ConstraintViolation::getMessage)
|
|
||||||
.collect(Collectors.toSet()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +1 @@
|
|||||||
|
|
||||||
server.port=8080
|
|
||||||
spring.datasource.url=jdbc:h2:file:./data
|
|
||||||
spring.datasource.driverClassName=org.h2.Driver
|
|
||||||
spring.datasource.username=sa
|
|
||||||
spring.datasource.password=password
|
|
||||||
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
|
||||||
spring.jpa.hibernate.ddl-auto=update
|
|
||||||
spring.h2.console.enabled=true
|
|
||||||
spring.h2.console.settings.trace=false
|
|
||||||
spring.h2.console.settings.web-allow-others=false
|
|
||||||
jwt.dev-token=my-secret-jwt
|
|
||||||
jwt.dev=true
|
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
body {
|
|
||||||
background: #f54d9a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
background: #FF9CCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
padding: 2%;
|
|
||||||
margin: 10% 5%;
|
|
||||||
}
|
|
||||||
|
|
||||||
main img {
|
|
||||||
width: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
form {
|
|
||||||
padding: 1%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.product-div {
|
|
||||||
background: #e874ac;
|
|
||||||
}
|
|
13
src/test/java/com/example/demo/Demo1ApplicationTests.java
Normal file
13
src/test/java/com/example/demo/Demo1ApplicationTests.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package com.example.demo;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class Demo1ApplicationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void contextLoads() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,133 +0,0 @@
|
|||||||
//package com.example.demo;
|
|
||||||
//
|
|
||||||
//import jakarta.persistence.EntityNotFoundException;
|
|
||||||
//import org.junit.jupiter.api.Assertions;
|
|
||||||
//import org.junit.jupiter.api.Test;
|
|
||||||
//import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
//import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
//import com.example.demo.order.*;
|
|
||||||
//import com.example.demo.master.*;
|
|
||||||
//import com.example.demo.product.*;
|
|
||||||
//
|
|
||||||
//import java.util.List;
|
|
||||||
//
|
|
||||||
//@SpringBootTest
|
|
||||||
//class DemoApplicationTests {
|
|
||||||
//
|
|
||||||
// @Autowired
|
|
||||||
// private MasterService masterService;
|
|
||||||
// @Autowired
|
|
||||||
// private ProductService productService;
|
|
||||||
// @Autowired
|
|
||||||
// private OrderService orderService;
|
|
||||||
//
|
|
||||||
// @Test
|
|
||||||
// void testOrder() {
|
|
||||||
// productService.deleteAllProducts();
|
|
||||||
// orderService.deleteAllOrders();
|
|
||||||
// masterService.deleteAllMasters();
|
|
||||||
//
|
|
||||||
// final Product product1 = productService.addProduct("Машинка", 300);
|
|
||||||
// final Product product2 = productService.addProduct("Ключ", 200);
|
|
||||||
//
|
|
||||||
// final Master master1 = masterService.addMaster("Кирилл", "Петрович");
|
|
||||||
//
|
|
||||||
// final Order order0 = orderService.addOrder(masterService.findMaster(master1.getId()));
|
|
||||||
// final Order order1 = orderService.findOrder(order0.getId());
|
|
||||||
// Assertions.assertEquals(order0, order1);
|
|
||||||
//
|
|
||||||
// Assertions.assertEquals(masterService
|
|
||||||
// .findMaster(master1.getId()).getOrders().size(), 1);
|
|
||||||
// orderService.deleteAllOrders();
|
|
||||||
// Assertions.assertThrows(EntityNotFoundException.class, () -> orderService.findOrder(-1L));
|
|
||||||
// final Master customer2 = masterService.addMaster("Александр", "Игоревич");
|
|
||||||
// final Order order2 = orderService
|
|
||||||
// .addOrder(masterService.findMaster(customer2.getId()));
|
|
||||||
// orderService.addProduct(order2.getId(), product1);
|
|
||||||
// orderService.addProduct(order2.getId(), product1);
|
|
||||||
// orderService.deleteProductsInOrder(order2.getId(), product1);
|
|
||||||
//
|
|
||||||
// Assertions.assertEquals(orderService
|
|
||||||
// .findOrder(order2.getId()).getProducts().size(), 1);
|
|
||||||
// masterService.deleteMaster(customer2.getId());
|
|
||||||
// Assertions.assertThrows(EntityNotFoundException.class, () -> masterService.findMaster(customer2.getId()));
|
|
||||||
// Assertions.assertThrows(EntityNotFoundException.class, () -> orderService.findOrder(order2.getId()));
|
|
||||||
// Assertions.assertEquals(orderService.findAllOrders().size(), 0);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Test()
|
|
||||||
// void testMaster() {
|
|
||||||
// masterService.deleteAllMasters();
|
|
||||||
// final Master customer = masterService.addMaster("Иван", "Иванов");
|
|
||||||
// Assertions.assertNotNull(customer.getId());
|
|
||||||
//
|
|
||||||
// masterService.deleteAllMasters();
|
|
||||||
// final Master customer1 = masterService.addMaster("Иван", "Иванов");
|
|
||||||
// final Master findMaster = masterService.findMaster(customer1.getId());
|
|
||||||
// Assertions.assertEquals(customer1, findMaster);
|
|
||||||
//
|
|
||||||
// masterService.deleteAllMasters();
|
|
||||||
// Assertions.assertThrows(EntityNotFoundException.class, () -> masterService.findMaster(-1L));
|
|
||||||
//
|
|
||||||
// masterService.deleteAllMasters();
|
|
||||||
// masterService.addMaster("Иван", "Иванов");
|
|
||||||
// masterService.addMaster("Петр", "Петров");
|
|
||||||
// final List<Master> customers1 = masterService.findAllMasters();
|
|
||||||
// Assertions.assertEquals(customers1.size(), 2);
|
|
||||||
//
|
|
||||||
// masterService.deleteAllMasters();
|
|
||||||
// final List<Master> customers2 = masterService.findAllMasters();
|
|
||||||
//
|
|
||||||
// Assertions.assertEquals(customers2.size(), 0);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Test
|
|
||||||
// void testProduct() {
|
|
||||||
// productService.deleteAllProducts();
|
|
||||||
// final Product ticket1 = productService.addProduct("Руно", 100);
|
|
||||||
// Assertions.assertNotNull(ticket1.getId());
|
|
||||||
//
|
|
||||||
// productService.deleteAllProducts();
|
|
||||||
// final Product ticket2 = productService.addProduct("Шоколад", 100);
|
|
||||||
// final Product findProduct = productService.findProduct(ticket2.getId());
|
|
||||||
// Assertions.assertEquals(ticket2, findProduct);
|
|
||||||
//
|
|
||||||
// productService.deleteAllProducts();
|
|
||||||
// Assertions.assertThrows(EntityNotFoundException.class, () -> productService.findProduct(-1L));
|
|
||||||
//
|
|
||||||
// productService.deleteAllProducts();
|
|
||||||
// productService.addProduct("Автомобиль", 100);
|
|
||||||
// productService.addProduct("Мячик", 100);
|
|
||||||
// final List<Product> tickets1 = productService.findAllProducts();
|
|
||||||
// Assertions.assertEquals(tickets1.size(), 2);
|
|
||||||
//
|
|
||||||
// productService.deleteAllProducts();
|
|
||||||
// final List<Product> tickets2 = productService.findAllProducts();
|
|
||||||
// Assertions.assertEquals(tickets2.size(), 0);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Test
|
|
||||||
// void testCommand() {
|
|
||||||
// productService.deleteAllProducts();
|
|
||||||
// orderService.deleteAllOrders();
|
|
||||||
// masterService.deleteAllMasters();
|
|
||||||
//
|
|
||||||
// final Product product1 = productService.addProduct("Машинка", 300);
|
|
||||||
// final Product product2 = productService.addProduct("Ключ", 200);
|
|
||||||
//
|
|
||||||
// final Master master1 = masterService.addMaster("Кирилл", "Петрович");
|
|
||||||
// final Master master2 = masterService.addMaster("Александр", "Камугович");
|
|
||||||
//
|
|
||||||
// final Order order0 = orderService.addOrder(masterService.findMaster(master1.getId()));
|
|
||||||
// final Order order1 = orderService.addOrder(masterService.findMaster(master2.getId()));
|
|
||||||
// final Order order2 = orderService.addOrder(masterService.findMaster(master2.getId()));
|
|
||||||
// orderService.addProduct(order0.getId(), product1);
|
|
||||||
// orderService.addProduct(order1.getId(), product1);
|
|
||||||
// orderService.addProduct(order2.getId(), product1);
|
|
||||||
//
|
|
||||||
// Assertions.assertTrue(orderService.findOrdersWithProduct(master1.getId(), product1).contains(order0));
|
|
||||||
// Assertions.assertTrue(orderService.findOrdersWithProduct(master1.getId(), product2).isEmpty());
|
|
||||||
// Assertions.assertTrue(orderService.findOrdersWithProduct(master2.getId(), product1).contains(order1)
|
|
||||||
// && orderService.findOrdersWithProduct(master2.getId(), product1).contains(order2));
|
|
||||||
// }
|
|
||||||
//}
|
|
@ -1,6 +0,0 @@
|
|||||||
spring.datasource.url=jdbc:h2:mem:testdb
|
|
||||||
spring.datasource.driverClassName=org.h2.Driver
|
|
||||||
spring.datasource.username=sa
|
|
||||||
spring.datasource.password=password
|
|
||||||
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
|
||||||
spring.jpa.hibernate.ddl-auto=create-drop
|
|
Loading…
Reference in New Issue
Block a user