-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TEMPLATE-5: Реализован импорт шаблонов
- Loading branch information
Showing
34 changed files
with
1,275 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -95,7 +95,6 @@ fabric.properties | |
*.war | ||
*.nar | ||
*.ear | ||
*.zip | ||
*.tar.gz | ||
*.rar | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
src/main/java/com/archipio/templateservice/config/LocaleConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.archipio.templateservice.config; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.context.support.ResourceBundleMessageSource; | ||
import org.springframework.web.servlet.LocaleResolver; | ||
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver; | ||
|
||
@Configuration | ||
public class LocaleConfig { | ||
|
||
@Bean | ||
public LocaleResolver localeResolver() { | ||
return new AcceptHeaderLocaleResolver(); | ||
} | ||
|
||
@Bean | ||
public ResourceBundleMessageSource messageSource() { | ||
final ResourceBundleMessageSource source = new ResourceBundleMessageSource(); | ||
source.setDefaultEncoding("UTF-8"); | ||
source.setBasename("lang/messages"); | ||
return source; | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
src/main/java/com/archipio/templateservice/config/SecurityConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package com.archipio.templateservice.config; | ||
|
||
import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS; | ||
|
||
import com.archipio.commonauth.JwtTokenProvider; | ||
import com.archipio.commonauth.JwtVerifierFilter; | ||
import java.util.List; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
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.configurers.AbstractHttpConfigurer; | ||
import org.springframework.security.core.userdetails.UserDetailsService; | ||
import org.springframework.security.provisioning.InMemoryUserDetailsManager; | ||
import org.springframework.security.web.SecurityFilterChain; | ||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||
import org.springframework.web.cors.CorsConfiguration; | ||
import org.springframework.web.cors.CorsConfigurationSource; | ||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | ||
|
||
@Configuration | ||
@EnableMethodSecurity | ||
@EnableWebSecurity | ||
public class SecurityConfig { | ||
|
||
@Bean | ||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { | ||
return http.csrf(AbstractHttpConfigurer::disable) | ||
.httpBasic(AbstractHttpConfigurer::disable) | ||
.sessionManagement((session) -> session.sessionCreationPolicy(STATELESS)) | ||
.cors((cors) -> cors.configurationSource(corsConfigurationSource())) | ||
.authorizeHttpRequests(request -> request.anyRequest().permitAll()) | ||
.addFilterBefore( | ||
new JwtVerifierFilter(new JwtTokenProvider()), | ||
UsernamePasswordAuthenticationFilter.class) | ||
.build(); | ||
} | ||
|
||
@Bean | ||
public CorsConfigurationSource corsConfigurationSource() { | ||
CorsConfiguration configuration = new CorsConfiguration(); | ||
configuration.setAllowedOrigins(List.of("*")); | ||
configuration.setAllowedHeaders(List.of("*")); | ||
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE")); | ||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); | ||
source.registerCorsConfiguration("/**", configuration); | ||
return source; | ||
} | ||
|
||
@Bean | ||
public UserDetailsService userDetailsService() { | ||
return new InMemoryUserDetailsManager(); | ||
} | ||
} |
206 changes: 206 additions & 0 deletions
206
src/main/java/com/archipio/templateservice/controller/ExceptionCatcher.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
package com.archipio.templateservice.controller; | ||
|
||
import static org.springframework.http.HttpStatus.BAD_REQUEST; | ||
import static org.springframework.http.HttpStatus.CONFLICT; | ||
import static org.springframework.http.HttpStatus.FORBIDDEN; | ||
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; | ||
import static org.springframework.http.HttpStatus.METHOD_NOT_ALLOWED; | ||
import static org.springframework.http.HttpStatus.NOT_FOUND; | ||
import static org.springframework.http.HttpStatus.UNSUPPORTED_MEDIA_TYPE; | ||
|
||
import com.archipio.templateservice.dto.ErrorDto; | ||
import com.archipio.templateservice.exception.InvalidTemplateConfigurationFormatException; | ||
import com.archipio.templateservice.exception.InvalidZipFormatException; | ||
import com.archipio.templateservice.exception.TemplateCodeAlreadyExistsException; | ||
import com.archipio.templateservice.exception.TemplateNameAlreadyExistsException; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.validation.ConstraintViolationException; | ||
import java.time.Instant; | ||
import java.util.StringJoiner; | ||
import java.util.stream.Collectors; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.context.MessageSource; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.http.converter.HttpMessageNotReadableException; | ||
import org.springframework.security.access.AccessDeniedException; | ||
import org.springframework.validation.FieldError; | ||
import org.springframework.web.HttpMediaTypeNotSupportedException; | ||
import org.springframework.web.HttpRequestMethodNotSupportedException; | ||
import org.springframework.web.bind.MethodArgumentNotValidException; | ||
import org.springframework.web.bind.MissingServletRequestParameterException; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
import org.springframework.web.bind.annotation.RestControllerAdvice; | ||
import org.springframework.web.servlet.NoHandlerFoundException; | ||
import org.springframework.web.servlet.support.RequestContextUtils; | ||
|
||
@RestControllerAdvice | ||
@RequiredArgsConstructor | ||
public class ExceptionCatcher { | ||
|
||
private final MessageSource messageSource; | ||
|
||
@ExceptionHandler(MethodArgumentNotValidException.class) | ||
public ResponseEntity<ErrorDto> handleMethodArgumentNotValidException( | ||
HttpServletRequest request, MethodArgumentNotValidException e) { | ||
var errors = | ||
e.getBindingResult().getFieldErrors().stream() | ||
.collect( | ||
Collectors.groupingBy( | ||
FieldError::getField, | ||
Collectors.mapping(FieldError::getDefaultMessage, Collectors.joining(" ")))); | ||
|
||
return ResponseEntity.status(BAD_REQUEST) | ||
.body( | ||
ErrorDto.builder() | ||
.createdAt(Instant.now()) | ||
.message(getMessage("exception.validation-error", request)) | ||
.errors(errors) | ||
.build()); | ||
} | ||
|
||
@ExceptionHandler(ConstraintViolationException.class) | ||
public ResponseEntity<ErrorDto> handleConstraintViolationException( | ||
HttpServletRequest request, ConstraintViolationException e) { | ||
var errors = | ||
e.getConstraintViolations().stream() | ||
.map( | ||
constraintViolation -> | ||
new FieldError( | ||
constraintViolation.getRootBeanClass().getName(), | ||
constraintViolation.getPropertyPath().toString(), | ||
constraintViolation.getMessage())) | ||
.collect( | ||
Collectors.groupingBy( | ||
FieldError::getField, | ||
Collectors.mapping(FieldError::getDefaultMessage, Collectors.joining(" ")))); | ||
|
||
return ResponseEntity.status(BAD_REQUEST) | ||
.body( | ||
ErrorDto.builder() | ||
.createdAt(Instant.now()) | ||
.message(getMessage("exception.validation-error", request)) | ||
.errors(errors) | ||
.build()); | ||
} | ||
|
||
@ExceptionHandler(NoHandlerFoundException.class) | ||
public ResponseEntity<ErrorDto> handleNoHandlerFoundException(HttpServletRequest request) { | ||
return ResponseEntity.status(NOT_FOUND) | ||
.body( | ||
ErrorDto.builder() | ||
.createdAt(Instant.now()) | ||
.message(getMessage("exception.endpoint-not-found", request)) | ||
.build()); | ||
} | ||
|
||
@ExceptionHandler(HttpRequestMethodNotSupportedException.class) | ||
public ResponseEntity<ErrorDto> handleHttpRequestMethodNotSupportedException( | ||
HttpServletRequest request) { | ||
return ResponseEntity.status(METHOD_NOT_ALLOWED) | ||
.body( | ||
ErrorDto.builder() | ||
.createdAt(Instant.now()) | ||
.message(getMessage("exception.method-not-supported", request)) | ||
.build()); | ||
} | ||
|
||
@ExceptionHandler(HttpMessageNotReadableException.class) | ||
public ResponseEntity<ErrorDto> handleHttpMessageNotReadableException( | ||
HttpServletRequest request) { | ||
return ResponseEntity.status(BAD_REQUEST) | ||
.body( | ||
ErrorDto.builder() | ||
.createdAt(Instant.now()) | ||
.message(getMessage("exception.invalid-json-format", request)) | ||
.build()); | ||
} | ||
|
||
@ExceptionHandler(MissingServletRequestParameterException.class) | ||
public ResponseEntity<ErrorDto> handleMissingServletRequestParameterException( | ||
HttpServletRequest request) { | ||
return ResponseEntity.status(BAD_REQUEST) | ||
.body( | ||
ErrorDto.builder() | ||
.createdAt(Instant.now()) | ||
.message(getMessage("exception.missing-request-parameter", request)) | ||
.build()); | ||
} | ||
|
||
@ExceptionHandler(HttpMediaTypeNotSupportedException.class) | ||
public ResponseEntity<ErrorDto> handleHttpMediaTypeNotSupportedException( | ||
HttpServletRequest request) { | ||
return ResponseEntity.status(UNSUPPORTED_MEDIA_TYPE) | ||
.body( | ||
ErrorDto.builder() | ||
.createdAt(Instant.now()) | ||
.message(getMessage("exception.unsupported-media-type", request)) | ||
.build()); | ||
} | ||
|
||
@ExceptionHandler(InvalidZipFormatException.class) | ||
public ResponseEntity<ErrorDto> handleUnsupportedZipFormatException( | ||
HttpServletRequest request, InvalidZipFormatException e) { | ||
var joiner = new StringJoiner(" "); | ||
joiner.add(getMessage("exception.invalid-zip-format", request)); | ||
joiner.add(e.getMessage()); | ||
|
||
return ResponseEntity.status(BAD_REQUEST) | ||
.body(ErrorDto.builder().createdAt(Instant.now()).message(joiner.toString()).build()); | ||
} | ||
|
||
@ExceptionHandler(InvalidTemplateConfigurationFormatException.class) | ||
public ResponseEntity<ErrorDto> handleInvalidTemplateConfigurationFormatException( | ||
HttpServletRequest request) { | ||
return ResponseEntity.status(BAD_REQUEST) | ||
.body( | ||
ErrorDto.builder() | ||
.createdAt(Instant.now()) | ||
.message(getMessage("exception.invalid-template-config-format", request)) | ||
.build()); | ||
} | ||
|
||
@ExceptionHandler(TemplateCodeAlreadyExistsException.class) | ||
public ResponseEntity<ErrorDto> handleEmailAlreadyExistsException(HttpServletRequest request) { | ||
return ResponseEntity.status(CONFLICT) | ||
.body( | ||
ErrorDto.builder() | ||
.createdAt(Instant.now()) | ||
.message(getMessage("exception.template-code-already-exists", request)) | ||
.build()); | ||
} | ||
|
||
@ExceptionHandler(TemplateNameAlreadyExistsException.class) | ||
public ResponseEntity<ErrorDto> handleTemplateNameAlreadyExistsException( | ||
HttpServletRequest request) { | ||
return ResponseEntity.status(CONFLICT) | ||
.body( | ||
ErrorDto.builder() | ||
.createdAt(Instant.now()) | ||
.message(getMessage("exception.template-name-already-exists", request)) | ||
.build()); | ||
} | ||
|
||
@ExceptionHandler(AccessDeniedException.class) | ||
public ResponseEntity<ErrorDto> handleAccessDeniedException(HttpServletRequest request) { | ||
return ResponseEntity.status(FORBIDDEN) | ||
.body( | ||
ErrorDto.builder() | ||
.createdAt(Instant.now()) | ||
.message(getMessage("exception.access-denied", request)) | ||
.build()); | ||
} | ||
|
||
@ExceptionHandler(Exception.class) | ||
public ResponseEntity<ErrorDto> handleException(HttpServletRequest request) { | ||
return ResponseEntity.status(INTERNAL_SERVER_ERROR) | ||
.body( | ||
ErrorDto.builder() | ||
.createdAt(Instant.now()) | ||
.message(getMessage("exception.internal-server-error", request)) | ||
.build()); | ||
} | ||
|
||
private String getMessage(String code, HttpServletRequest request) { | ||
return messageSource.getMessage(code, null, RequestContextUtils.getLocale(request)); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
src/main/java/com/archipio/templateservice/controller/api/v0/TemplateController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.archipio.templateservice.controller.api.v0; | ||
|
||
import static com.archipio.templateservice.util.ApiUtils.API_V0_PREFIX; | ||
import static com.archipio.templateservice.util.ApiUtils.IMPORT_SUFFIX; | ||
import static org.springframework.http.HttpStatus.OK; | ||
|
||
import com.archipio.templateservice.service.TemplateService; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestPart; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping(API_V0_PREFIX) | ||
public class TemplateController { | ||
|
||
private final TemplateService templateService; | ||
|
||
@PostMapping(value = IMPORT_SUFFIX, consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | ||
public ResponseEntity<Void> importTemplate(@RequestPart("data") MultipartFile data) { | ||
templateService.importTemplate(data); | ||
return ResponseEntity.status(OK).build(); | ||
} | ||
} |
Oops, something went wrong.