Commit 32abbb6b authored by Denis's avatar Denis Committed by Denis Ligin

Security issue fix

parent 9506b3c3
Pipeline #374 canceled with stage
package kz.project.printedFormsService.config;
import kz.project.printedFormsService.exception.AccessDeniedException;
import kz.project.printedFormsService.exception.ValidationException;
import lombok.experimental.UtilityClass;
import org.springframework.security.core.GrantedAuthority;
......@@ -26,6 +27,13 @@ public class SecurityContextUtils {
}
public static String getUsername() {
return SecurityContextHolder
.getContext()
.getAuthentication()
.getName();
}
public static Map<String, List<String>> getProjectRoleMap() {
return SecurityContextHolder
......@@ -59,6 +67,6 @@ public class SecurityContextUtils {
.filter(role -> role.contains("gitlab"))
.map(role -> role.replace("ROLE_gitlab_", ""))
.findFirst()
.orElseThrow(() -> new ValidationException("Не указана роль для доступа к gitlab"));
.orElseThrow(() -> new AccessDeniedException("Не указана роль для доступа к gitlab"));
}
}
package kz.project.printedFormsService.controller;
;
import kz.project.printedFormsService.exception.ValidationException;
import kz.project.printedFormsService.data.dto.ResponseErrorDto;
import kz.project.printedFormsService.exception.AccessDeniedException;
import kz.project.printedFormsService.exception.ValidationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
;
@ControllerAdvice
@Slf4j
public class RestErrorController extends ResponseEntityExceptionHandler {
@ExceptionHandler(ValidationException.class)
//@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "Remote service response")
protected ResponseEntity<ResponseErrorDto> handleThereIsNoSuchUserException(ValidationException err) {
protected ResponseEntity<ResponseErrorDto> handleThereIsNoSuchUserException(ValidationException err) {
err.printStackTrace();
return new ResponseEntity<>(new ResponseErrorDto(err.getMessage(),err.getCode()),HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(new ResponseErrorDto(err.getMessage(), err.getCode()), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(AccessDeniedException.class)
protected ResponseEntity<ResponseErrorDto> handleAccessDeniedException(AccessDeniedException err) {
log.warn("Access denied", err);
return new ResponseEntity<>(new ResponseErrorDto(err.getMessage(), HttpStatus.FORBIDDEN.value()), HttpStatus.FORBIDDEN);
}
}
......@@ -9,14 +9,13 @@ import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import kz.project.printedFormsService.config.SecurityContextUtils;
import kz.project.printedFormsService.data.dto.TemplateDto;
import kz.project.printedFormsService.data.dto.TemplateResponseDto;
import kz.project.printedFormsService.data.dto.TemplateShortDto;
import kz.project.printedFormsService.exception.AccessDeniedException;
import kz.project.printedFormsService.exception.ValidationException;
import kz.project.printedFormsService.logging.ProcessLogger;
import kz.project.printedFormsService.service.TemplateService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -30,6 +29,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
@RestController
@RequestMapping(TemplateController.BASE_PATH)
......@@ -85,7 +85,7 @@ public class TemplateController {
processLogger.start(this.getClass(), new Throwable().getStackTrace()[0].getMethodName(), "Получение шаблона по идентификатору");
Map<String, byte[]> templateMap = service.getTemplate(id);
return ResponseEntity.ok(templateMap);
} catch (Exception e){
} catch (Exception e) {
processLogger.error(this.getClass(), new Throwable().getStackTrace()[0].getMethodName(), "Получение шаблона по идентификатору");
LOGGER.error(e.getMessage(), e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
......@@ -123,7 +123,7 @@ public class TemplateController {
TemplateDto templateData = service.getTemplateData(id);
processLogger.finish(this.getClass(), new Throwable().getStackTrace()[0].getMethodName(), "Получение данных шаблона по идентификатору");
return ResponseEntity.ok(templateData);
} catch (Exception e){
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
processLogger.finish(this.getClass(), new Throwable().getStackTrace()[0].getMethodName(), "Получение данных шаблона по идентификатору");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
......@@ -153,8 +153,8 @@ public class TemplateController {
})
})
public ResponseEntity saveTemplate(@Parameter(name = "data") @RequestParam(name = "data", required = false) MultipartFile data,
@Parameter(name = "header") @RequestParam(name = "header", required = false) MultipartFile header,
@RequestParam TemplateDto dto
@Parameter(name = "header") @RequestParam(name = "header", required = false) MultipartFile header,
@RequestParam TemplateDto dto
) throws IOException, ValidationException {
......@@ -162,12 +162,15 @@ public class TemplateController {
if (data == null) {
throw new ValidationException("Не переданы обязательные поля: data", 13);
}
checkUserRights(dto);
if (header != null) {
return ResponseEntity.ok(service.save(dto, List.of(data, header)));
} else {
return ResponseEntity.ok(service.save(dto, List.of(data)));
}
} catch (Exception e){
} catch (AccessDeniedException e) {
throw e;
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
processLogger.start(this.getClass(), new Throwable().getStackTrace()[0].getMethodName(), "Сохранение шаблона");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
......@@ -201,12 +204,15 @@ public class TemplateController {
})
public ResponseEntity editTemplate(@Parameter(name = "data") @RequestParam(name = "data", required = false) MultipartFile data,
@Parameter(name = "header") @RequestParam(name = "header", required = false) MultipartFile header,
@RequestParam TemplateDto dto) throws IOException, ValidationException {
@Parameter(name = "header") @RequestParam(name = "header", required = false) MultipartFile header,
@RequestParam TemplateDto dto) throws IOException, ValidationException {
try {
// if (data == null) {
// throw new ValidationException("Не переданы обязательные поля: data", 13);
// }
if (data != null) {
checkUserRights(dto);
}
if (header != null) {
return ResponseEntity.ok(service.edit(dto, List.of(data, header)));
} else if (data != null) {
......@@ -214,7 +220,9 @@ public class TemplateController {
} else {
return ResponseEntity.ok(service.edit(dto, null));
}
} catch (Exception e){
} catch (AccessDeniedException e) {
throw e;
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
processLogger.start(this.getClass(), new Throwable().getStackTrace()[0].getMethodName(), "Редактирование шаблона");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
......@@ -228,7 +236,7 @@ public class TemplateController {
processLogger.start(this.getClass(), new Throwable().getStackTrace()[0].getMethodName(), "Удаление шаблона");
service.delete(code);
return ResponseEntity.ok("delete is success");
} catch (Exception e){
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
processLogger.start(this.getClass(), new Throwable().getStackTrace()[0].getMethodName(), "Удаление шаблона");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
......@@ -259,15 +267,15 @@ public class TemplateController {
@Operation(description = "Метод для получения всех шаблонов")
public ResponseEntity getAll(@Parameter(name = "isActive") @RequestParam(value = "isActive", required = false) Boolean isActive,
@Parameter(name = "page") @RequestParam(value = "page", defaultValue = "0") Integer page,
@Parameter(name = "size") @RequestParam(value = "size", defaultValue = "50") Integer size) {
@Parameter(name = "page") @RequestParam(value = "page", defaultValue = "0") Integer page,
@Parameter(name = "size") @RequestParam(value = "size", defaultValue = "50") Integer size) {
try {
processLogger.start(TemplateController.class, new Throwable().getStackTrace()[0].getMethodName(), "Получение списка шаблонов");
Page<TemplateShortDto> allTemplates = service.getAllTemplate(isActive, PageRequest.of(page, size));
processLogger.finish(TemplateController.class, new Throwable().getStackTrace()[0].getMethodName(), "Получение списка шаблонов");
return ResponseEntity.ok(allTemplates);
} catch (Exception e){
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
processLogger.error(TemplateController.class, new Throwable().getStackTrace()[0].getMethodName(), "Получение списка шаблонов");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
......@@ -297,16 +305,23 @@ public class TemplateController {
})
})
public ResponseEntity getAllByCode(@Parameter(name = "code") @PathVariable(value = "code") String code,
@Parameter(name = "page") @RequestParam(value = "page", defaultValue = "0") Integer page,
@Parameter(name = "size") @RequestParam(value = "size", defaultValue = "50") Integer size) throws ValidationException {
@Parameter(name = "page") @RequestParam(value = "page", defaultValue = "0") Integer page,
@Parameter(name = "size") @RequestParam(value = "size", defaultValue = "50") Integer size) throws ValidationException {
try {
Page<TemplateDto> pageDTO = service.getAllTemplateByCode(code, PageRequest.of(page, size));
return ResponseEntity.ok(pageDTO);
} catch (Exception e){
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
processLogger.start(TemplateController.class, new Throwable().getStackTrace()[0].getMethodName(), "Получение всех шаблонов по коду");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
}
}
private static void checkUserRights(TemplateDto dto) {
Set<String> projects = SecurityContextUtils.getProjectRoleMap().keySet();
if (!projects.contains(dto.getProject())) {
throw new AccessDeniedException(String.format("User %s does not have access to the project %s", SecurityContextUtils.getUsername(), dto.getProject()));
}
}
}
package kz.project.printedFormsService.exception;
import lombok.Data;
@Data
public class AccessDeniedException extends RuntimeException {
public AccessDeniedException(String message) {
super(message);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment