Skip to content
Snippets Groups Projects
Commit ccc09ba8 authored by nahyun's avatar nahyun
Browse files

Merge branch 'feat/log' into 'dev'

Feat/log

See merge request !12
parents 3925e264 8207b91f
No related branches found
No related tags found
1 merge request!12Feat/log
Showing
with 651 additions and 42 deletions
......@@ -30,12 +30,19 @@ dependencies {
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
runtimeOnly 'com.mysql:mysql-connector-j'
implementation 'org.pacesys:openstack4j:3.1.0'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
}
tasks.named('test') {
useJUnitPlatform()
}
clean {
delete file('src/main/generated')
}
\ No newline at end of file
package com.aolda.itda.aspect;
import com.aolda.itda.dto.forwarding.ForwardingDTO;
import com.aolda.itda.entity.forwarding.Forwarding;
import com.aolda.itda.entity.log.Action;
import com.aolda.itda.entity.log.Log;
import com.aolda.itda.entity.log.ObjectType;
import com.aolda.itda.entity.user.User;
import com.aolda.itda.exception.CustomException;
import com.aolda.itda.exception.ErrorCode;
import com.aolda.itda.repository.certificate.CertificateRepository;
import com.aolda.itda.repository.forwarding.ForwardingRepository;
import com.aolda.itda.repository.log.LogRepository;
import com.aolda.itda.repository.routing.RoutingRepository;
import com.aolda.itda.repository.user.UserRepository;
import com.aolda.itda.service.AuthService;
import jakarta.persistence.EntityManager;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.Map;
import java.util.Objects;
@Aspect
@Component
@RequiredArgsConstructor
public class ForwardingLogAspect {
private final ForwardingRepository forwardingRepository;
private final LogRepository logRepository;
private final EntityManager entityManager;
private final UserRepository userRepository;
/* Create 로깅 */
@AfterReturning(pointcut = "execution(* com.aolda.itda.service.forwarding.*Service.*create*(..))"
, returning = "result")
public void createLogging(JoinPoint joinPoint, ForwardingDTO result) {
/* 사용자 조회 */
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
Map<String, String> tmp = (Map<String, String>) request.getAttribute("user");
User user = userRepository.findByKeystoneId(tmp.get("id")).orElseThrow(
() -> new CustomException(ErrorCode.NOT_FOUND_USER)
);
/* 생성된 엔티티 조회 */
Forwarding forwarding = forwardingRepository.findByForwardingIdAndIsDeleted(result.getId(), false).orElse(null);
/* 로그 메세지 작성 */
String description = "name: " + forwarding.getName() + "\n"
+ "serverPort: " + forwarding.getServerPort() + "\n"
+ "instanceIp: " + forwarding.getInstanceIp() + "\n"
+ "instancePort: " + forwarding.getInstancePort();
/* 로그 엔티티 저장 */
logRepository.save(Log.builder()
.user(user)
.objectType(ObjectType.FORWARDING)
.objectId(forwarding.getForwardingId())
.action(Action.CREATE)
.projectId(forwarding.getProjectId())
.description(description)
.build());
}
/* Delete 로깅 */
@AfterReturning(pointcut = "execution(* com.aolda.itda.service.forwarding.*Service.*delete*(..))")
public void deleteLogging(JoinPoint joinPoint) {
/* 사용자 조회 */
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
Map<String, String> tmp = (Map<String, String>) request.getAttribute("user");
User user = userRepository.findByKeystoneId(tmp.get("id")).orElseThrow(
() -> new CustomException(ErrorCode.NOT_FOUND_USER)
);
/* 삭제된 엔티티 조회 */
Object[] args = joinPoint.getArgs();
Long id = (Long) args[0];
Forwarding forwarding = forwardingRepository.findByForwardingIdAndIsDeleted(id, true).orElse(null);
/* 로그 메세지 작성 */
String description = "name: " + forwarding.getName() + "\n"
+ "serverPort: " + forwarding.getServerPort() + "\n"
+ "instanceIp: " + forwarding.getInstanceIp() + "\n"
+ "instancePort: " + forwarding.getInstancePort();
/* 로그 엔티티 저장 */
logRepository.save(Log.builder()
.user(user)
.objectType(ObjectType.FORWARDING)
.objectId(forwarding.getForwardingId())
.action(Action.DELETE)
.projectId(forwarding.getProjectId())
.description(description)
.build());
}
/* Update(edit) 로깅 */
@Around("execution(* com.aolda.itda.service.forwarding.*Service.*edit*(..))")
public Object editLogging(ProceedingJoinPoint joinPoint) throws Throwable {
/* 사용자 조회 */
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
Map<String, String> tmp = (Map<String, String>) request.getAttribute("user");
User user = userRepository.findByKeystoneId(tmp.get("id")).orElseThrow(
() -> new CustomException(ErrorCode.NOT_FOUND_USER)
);
/* 변경 전 엔티티 조회 */
Object[] args = joinPoint.getArgs();
Long id = (Long) args[0];
Forwarding old = forwardingRepository.findByForwardingIdAndIsDeleted(id, false).orElse(null);
if (old != null) {
entityManager.detach(old);
}
/* 메소드 진행 */
Object result = joinPoint.proceed();
/* 변경 후 엔티티 조회*/
Forwarding newObj = forwardingRepository.findByForwardingIdAndIsDeleted(id, false).orElse(null);
/* 로그 메세지 작성 */
String description = "name: " + old.getName() + (old.getName().equals(newObj.getName()) ? "" : (" -> " + newObj.getName())) + "\n"
+ "serverPort: " + old.getServerPort() + (old.getServerPort().equals(newObj.getServerPort()) ? "" : (" -> " + newObj.getServerPort())) + "\n"
+ "instanceIp: " + old.getInstanceIp() + (old.getInstanceIp().equals(newObj.getInstanceIp()) ? "" : (" -> " + newObj.getInstanceIp())) + "\n"
+ "instancePort: " + old.getInstancePort() + (old.getInstancePort().equals(newObj.getInstancePort()) ? "" : (" -> " + newObj.getInstancePort()));
/* 로그 엔티티 저장 */
logRepository.save(Log.builder()
.user(user)
.objectType(ObjectType.FORWARDING)
.objectId(newObj.getForwardingId())
.action(Action.UPDATE)
.projectId(newObj.getProjectId())
.description(description)
.build());
return result;
}
}
package com.aolda.itda.aspect;
import com.aolda.itda.dto.forwarding.ForwardingDTO;
import com.aolda.itda.dto.routing.RoutingDTO;
import com.aolda.itda.entity.forwarding.Forwarding;
import com.aolda.itda.entity.log.Action;
import com.aolda.itda.entity.log.Log;
import com.aolda.itda.entity.log.ObjectType;
import com.aolda.itda.entity.routing.Routing;
import com.aolda.itda.entity.user.User;
import com.aolda.itda.exception.CustomException;
import com.aolda.itda.exception.ErrorCode;
import com.aolda.itda.repository.forwarding.ForwardingRepository;
import com.aolda.itda.repository.log.LogRepository;
import com.aolda.itda.repository.routing.RoutingRepository;
import com.aolda.itda.repository.user.UserRepository;
import jakarta.persistence.EntityManager;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.Map;
import java.util.Objects;
@Aspect
@Component
@RequiredArgsConstructor
public class RoutingLogAspect {
private final RoutingRepository routingRepository;
private final UserRepository userRepository;
private final LogRepository logRepository;
private final EntityManager entityManager;
/* Create 로깅 */
@AfterReturning(pointcut = "execution(* com.aolda.itda.service.routing.*Service.*create*(..))"
, returning = "result")
public void createLogging(JoinPoint joinPoint, RoutingDTO result) {
/* 사용자 조회 */
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
Map<String, String> tmp = (Map<String, String>) request.getAttribute("user");
User user = userRepository.findByKeystoneId(tmp.get("id")).orElseThrow(
() -> new CustomException(ErrorCode.NOT_FOUND_USER)
);
/* 생성된 엔티티 조회 */
Routing routing = routingRepository.findByRoutingIdAndIsDeleted(result.getId(), false).orElse(null);
/* 로그 메세지 작성 */
String description = "name: " + routing.getName() + "\n"
+ "domain: " + routing.getDomain() + "\n"
+ "ip: " + routing.getInstanceIp() + "\n"
+ "port: " + routing.getInstancePort() + "\n"
+ (routing.getCertificate() != null ? ("certificateId: " + routing.getCertificate().getCertificateId() + "\n") : "")
+ "caching: " + routing.getCaching() + "\n";
/* 로그 엔티티 저장 */
logRepository.save(Log.builder()
.user(user)
.objectType(ObjectType.ROUTING)
.objectId(routing.getRoutingId())
.action(Action.CREATE)
.projectId(routing.getProjectId())
.description(description)
.build());
}
/* Delete 로깅 */
@AfterReturning(pointcut = "execution(* com.aolda.itda.service.routing.*Service.*delete*(..))")
public void deleteLogging(JoinPoint joinPoint) {
/* 사용자 조회 */
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
Map<String, String> tmp = (Map<String, String>) request.getAttribute("user");
User user = userRepository.findByKeystoneId(tmp.get("id")).orElseThrow(
() -> new CustomException(ErrorCode.NOT_FOUND_USER)
);
/* 삭제된 엔티티 조회 */
Object[] args = joinPoint.getArgs();
Long id = (Long) args[0];
Routing routing = routingRepository.findByRoutingIdAndIsDeleted(id, true).orElse(null);
/* 로그 메세지 작성 */
String description = "name: " + routing.getName() + "\n"
+ "domain: " + routing.getDomain() + "\n"
+ "ip: " + routing.getInstanceIp() + "\n"
+ "port: " + routing.getInstancePort() + "\n"
+ (routing.getCertificate() != null ? ("certificateId: " + routing.getCertificate().getCertificateId() + "\n") : "")
+ "caching: " + routing.getCaching() + "\n";
/* 로그 엔티티 저장 */
logRepository.save(Log.builder()
.user(user)
.objectType(ObjectType.ROUTING)
.objectId(routing.getRoutingId())
.action(Action.DELETE)
.projectId(routing.getProjectId())
.description(description)
.build());
}
/* Update(edit) 로깅 */
@Around("execution(* com.aolda.itda.service.routing.*Service.*edit*(..))")
public Object editLogging(ProceedingJoinPoint joinPoint) throws Throwable {
/* 사용자 조회 */
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
Map<String, String> tmp = (Map<String, String>) request.getAttribute("user");
User user = userRepository.findByKeystoneId(tmp.get("id")).orElseThrow(
() -> new CustomException(ErrorCode.NOT_FOUND_USER)
);
/* 변경 전 엔티티 조회 */
Object[] args = joinPoint.getArgs();
Long id = (Long) args[0];
Routing old = routingRepository.findByRoutingIdAndIsDeleted(id, false).orElse(null);
if (old != null) {
entityManager.detach(old);
}
/* 메소드 진행 */
Object result = joinPoint.proceed();
/* 변경 후 엔티티 조회 */
Routing newObj = routingRepository.findByRoutingIdAndIsDeleted(id, false).orElse(null);
/* 로그 메세지 작성 */
String description = "name: " + old.getName() + (old.getName().equals(newObj.getName()) ? "" : " -> " + newObj.getName()) + "\n"
+ "domain: " + old.getDomain() + (old.getDomain().equals(newObj.getDomain()) ? "" : " -> " + newObj.getDomain()) + "\n"
+ "ip: " + old.getInstanceIp() + (old.getInstanceIp().equals(newObj.getInstanceIp()) ? "" : " -> " + newObj.getInstanceIp()) + "\n"
+ "port: " + old.getInstancePort() + (old.getInstancePort().equals(newObj.getInstancePort()) ? "" : " -> " + newObj.getInstancePort()) + "\n";
if (old.getCertificate() == null) {
if (newObj.getCertificate() != null) {
description = description + "certificateId: null -> " + newObj.getCertificate().getCertificateId() + "\n";
}
}
else {
if (newObj.getCertificate() == null) {
description = description + "certificateId: " + old.getCertificate().getCertificateId() + " -> null\n";
}
else {
description = description + "certificateId: " + old.getCertificate().getCertificateId() + " -> " + newObj.getCertificate().getCertificateId() + "\n";
}
}
description = description + "caching: " + (old.getCaching() == newObj.getCaching() ? newObj.getCaching() : (" -> " + newObj.getCaching()));
/* 로그 엔티티 저장 */
logRepository.save(Log.builder()
.user(user)
.objectType(ObjectType.ROUTING)
.objectId(newObj.getRoutingId())
.action(Action.UPDATE)
.projectId(newObj.getProjectId())
.description(description)
.build());
return result;
}
}
package com.aolda.itda.config;
import com.aolda.itda.dto.auth.IdAndNameDTO;
import com.aolda.itda.exception.CustomException;
import com.aolda.itda.exception.ErrorCode;
import com.aolda.itda.service.AuthService;
......@@ -10,6 +11,9 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.List;
import java.util.Map;
@RequiredArgsConstructor
@Component
@Slf4j
......@@ -20,18 +24,44 @@ public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("X-Subject-Token");
/* 토큰 헤더 검증 */
if (token == null || token.isEmpty()) {
throw new CustomException(ErrorCode.INVALID_TOKEN, request.getRequestURI());
}
// 어드민과 일반 유저 구분 필요
try {
if (authService.validateTokenAndGetUserId(token) != null) {
return true;
}
} catch (Exception e) {
log.error("Token validation failed for URI {}: {}", request.getRequestURI(), e.getMessage(), e);
/* 유효 토큰 검증 */
String userId = authService.validateTokenAndGetUserId(token);
if (userId == null) {
log.error("Token validation failed for URI {}: {}", request.getRequestURI(), request.getRemoteAddr());
throw new CustomException(ErrorCode.INVALID_TOKEN, request.getRequestURI());
}
throw new CustomException(ErrorCode.INVALID_TOKEN, request.getRequestURI());
/* 프로젝트 권한 검증 */
String projectId = request.getParameter("projectId");
if (projectId != null) {
try {
String role = authService.getBestRoleWithinProject(token, projectId).get("role");
if (!role.equals("admin")) {
log.error("Unauthorized Token for URI {}: {}", request.getRequestURI(), request.getRemoteAddr());
throw new CustomException(ErrorCode.UNAUTHORIZED_USER, request.getRequestURI());
}
} catch (Exception e) {
throw new CustomException(ErrorCode.UNAUTHORIZED_USER, request.getRequestURI());
}
}
/* 프로젝트 리스트 조회 */
List<String> projects = authService.getProjectsWithUser(Map.of("id", userId, "token", token))
.stream().map(IdAndNameDTO::getId)
.toList();
request.setAttribute("projects", projects);
request.setAttribute("user", Map.of("id", userId, "token", token));
return true;
}
}
package com.aolda.itda.config;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
......@@ -25,10 +28,15 @@ public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
String[] excludeAuth = {"/error", "/api/auth/*", "/api/*" };
String[] excludeAuth = {"/error", "/api/auth/*" };
registry.addInterceptor(authInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(excludeAuth);
}
@Bean
public JPAQueryFactory jpaQueryFactory(EntityManager em) {
return new JPAQueryFactory(em);
}
}
......@@ -2,11 +2,14 @@ package com.aolda.itda.controller.forwarding;
import com.aolda.itda.dto.forwarding.ForwardingDTO;
import com.aolda.itda.service.forwarding.ForwardingService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
......@@ -22,8 +25,8 @@ public class ForwardingController {
}
@GetMapping("/forwarding")
public ResponseEntity<Object> view(@RequestParam Long forwardingId) {
return ResponseEntity.ok(forwardingService.getForwarding(forwardingId));
public ResponseEntity<Object> view(@RequestParam Long forwardingId, HttpServletRequest request) {
return ResponseEntity.ok(forwardingService.getForwarding(forwardingId, (List<String>) request.getAttribute("projects")));
}
@GetMapping("/forwardings")
......@@ -33,14 +36,16 @@ public class ForwardingController {
@PatchMapping("/forwarding")
public ResponseEntity<Object> edit(@RequestParam Long forwardingId,
@RequestBody ForwardingDTO dto) {
forwardingService.editForwarding(forwardingId, dto);
@RequestBody ForwardingDTO dto,
HttpServletRequest request) {
forwardingService.editForwarding(forwardingId, dto, (List<String>) request.getAttribute("projects") );
return ResponseEntity.ok().build();
}
@DeleteMapping("/forwarding")
public ResponseEntity<Object> delete(@RequestParam Long forwardingId) {
forwardingService.deleteForwarding(forwardingId);
public ResponseEntity<Object> delete(@RequestParam Long forwardingId,
HttpServletRequest request) {
forwardingService.deleteForwarding(forwardingId, (List<String>) request.getAttribute("projects"));
return ResponseEntity.ok().build();
}
......
package com.aolda.itda.controller.log;
import com.aolda.itda.service.log.LogService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class LogController {
private final LogService logService;
@GetMapping("/log")
public ResponseEntity<Object> view(@RequestParam Long logId, HttpServletRequest request) {
return ResponseEntity.ok(logService.getLog(logId, (List<String>) request.getAttribute("projects")));
}
@GetMapping("/logs")
public ResponseEntity<Object> lists(@RequestParam(required = false) String projectId
,@RequestParam(required = false) String type
,@RequestParam(required = false) String username
,@RequestParam(required = false) String action
,@RequestParam(defaultValue = "false") boolean isASC
,@PageableDefault(size = 10) Pageable pageable
,HttpServletRequest request) {
return ResponseEntity.ok(logService.getLogs(projectId, type, username, action, isASC, pageable,
(Map<String, String>) request.getAttribute("user")));
}
}
......@@ -3,10 +3,13 @@ package com.aolda.itda.controller.routing;
import com.aolda.itda.dto.forwarding.ForwardingDTO;
import com.aolda.itda.dto.routing.RoutingDTO;
import com.aolda.itda.service.routing.RoutingService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
......@@ -14,7 +17,7 @@ public class RoutingController {
private final RoutingService routingService;
@PostMapping("/forwarding")
@PostMapping("/routing")
public ResponseEntity<Object> create(@RequestParam String projectId,
@RequestBody RoutingDTO dto) {
routingService.createRouting(projectId, dto);
......@@ -22,8 +25,9 @@ public class RoutingController {
}
@GetMapping("/routing")
public ResponseEntity<Object> view(@RequestParam Long routingId) {
return ResponseEntity.ok(routingService.getRouting(routingId));
public ResponseEntity<Object> view(@RequestParam Long routingId,
HttpServletRequest request) {
return ResponseEntity.ok(routingService.getRouting(routingId, (List<String>) request.getAttribute("projects")));
}
@GetMapping("/routings")
......@@ -33,14 +37,16 @@ public class RoutingController {
@PatchMapping("/routing")
public ResponseEntity<Object> edit(@RequestParam Long routingId,
@RequestBody RoutingDTO dto) {
routingService.editRouting(routingId, dto);
@RequestBody RoutingDTO dto,
HttpServletRequest request) {
routingService.editRouting(routingId, dto, (List<String>) request.getAttribute("projects"));
return ResponseEntity.ok().build();
}
@DeleteMapping("/routing")
public ResponseEntity<Object> delete(@RequestParam Long routingId) {
routingService.deleteRouting(routingId);
public ResponseEntity<Object> delete(@RequestParam Long routingId,
HttpServletRequest request) {
routingService.deleteRouting(routingId, (List<String>) request.getAttribute("projects"));
return ResponseEntity.ok().build();
}
......
......@@ -15,7 +15,7 @@ import java.util.List;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PageResp<T> {
private Integer totalPages;
private Integer totalElements;
private Long totalElements;
private Integer size;
private List<T> contents;
private Boolean first;
......
package com.aolda.itda.dto.auth;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.querydsl.core.annotations.QueryProjection;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
......@@ -7,10 +9,16 @@ import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ProjectIdAndNameDTO {
@JsonInclude(JsonInclude.Include.NON_NULL)
public class IdAndNameDTO {
private String id;
private String name;
@QueryProjection
public IdAndNameDTO(String id, String name) {
this.id = id;
this.name = name;
}
}
......@@ -13,5 +13,5 @@ import java.util.List;
@Builder
public class LoginResponseDTO {
private Boolean isAdmin;
private List<ProjectIdAndNameDTO> projects;
private List<IdAndNameDTO> projects;
}
package com.aolda.itda.dto.log;
import com.aolda.itda.dto.auth.IdAndNameDTO;
import com.aolda.itda.entity.log.Action;
import com.aolda.itda.entity.log.ObjectType;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.querydsl.core.annotations.QueryProjection;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public class LogDTO {
private Long id;
private IdAndNameDTO user;
private Action action;
private ObjectType type;
private Long objectId;
private String description;
private LocalDateTime createdAt;
@QueryProjection
public LogDTO(Long id, IdAndNameDTO user, Action action, ObjectType type, Long objectId, String description, LocalDateTime createdAt) {
this.id = id;
this.user = user;
this.action = action;
this.type = type;
this.objectId = objectId;
this.description = description;
this.createdAt = createdAt;
}
}
......@@ -25,7 +25,7 @@ public class RoutingDTO {
@NotBlank
private String port;
private Long id;
@NotBlank
@NotNull
private Long certificateId;
private LocalDateTime createdAt;
......
package com.aolda.itda.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
......@@ -17,10 +18,12 @@ public abstract class BaseTimeEntity {
@CreatedDate
@Column(updatable = false)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime createdAt;
@LastModifiedDate
@Column(name = "updated_at")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime updatedAt;
}
......@@ -23,7 +23,7 @@ public class Certificate extends BaseTimeEntity {
@Column(nullable = false)
private Long certificateId;
@OneToOne
@ManyToOne
@JoinColumn(nullable = false, name = "user_id")
private User user;
......
......@@ -4,10 +4,7 @@ import com.aolda.itda.dto.forwarding.ForwardingDTO;
import com.aolda.itda.entity.BaseTimeEntity;
import com.aolda.itda.entity.user.User;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.*;
@Entity
@Table(name = "forwarding")
......@@ -15,6 +12,7 @@ import lombok.NoArgsConstructor;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Forwarding extends BaseTimeEntity {
@Id
......@@ -22,10 +20,6 @@ public class Forwarding extends BaseTimeEntity {
@Column(nullable = false)
private Long forwardingId;
@OneToOne
@JoinColumn(name = "user_id")
private User user;
private String projectId;
private String serverIp;
......@@ -40,6 +34,17 @@ public class Forwarding extends BaseTimeEntity {
private String name;
public Forwarding(Forwarding forwarding) {
this.forwardingId = forwarding.getForwardingId();
this.projectId = forwarding.getProjectId();
this.serverIp = forwarding.getServerIp();
this.serverPort = forwarding.getServerPort();
this.instanceIp = forwarding.getInstanceIp();
this.instancePort = forwarding.getInstancePort();
this.isDeleted = forwarding.getIsDeleted();
this.name = forwarding.getName();
}
public ForwardingDTO toForwardingDTO() {
return ForwardingDTO.builder()
.id(forwardingId)
......
package com.aolda.itda.entity.log;
import com.aolda.itda.dto.auth.IdAndNameDTO;
import com.aolda.itda.dto.log.LogDTO;
import com.aolda.itda.entity.BaseTimeEntity;
import com.aolda.itda.entity.user.User;
import jakarta.persistence.*;
......@@ -21,7 +23,7 @@ public class Log extends BaseTimeEntity {
@Column(nullable = false)
private Long logId;
@OneToOne
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
......@@ -37,4 +39,16 @@ public class Log extends BaseTimeEntity {
private String description;
public LogDTO toLogDTO() {
return LogDTO.builder()
.id(logId)
.user(IdAndNameDTO.builder().id(user.getKeystoneId()).name(user.getKeystoneUsername()).build())
.action(action)
.type(objectType)
.objectId(objectId)
.description(description)
.createdAt(getCreatedAt())
.build();
}
}
......@@ -24,12 +24,8 @@ public class Routing extends BaseTimeEntity {
@Column(nullable = false)
private Long routingId;
@OneToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
@OneToOne
@JoinColumn(name = "certificate_id", nullable = false)
@ManyToOne
@JoinColumn(name = "certificate_id")
private Certificate certificate;
private String projectId;
......
......@@ -10,6 +10,8 @@ public enum ErrorCode {
// User
INVALID_USER_INFO(HttpStatus.BAD_REQUEST, "잘못된 회원 정보입니다"),
NOT_FOUND_USER(HttpStatus.BAD_REQUEST, "존재하지 않는 사용자입니다"),
UNAUTHORIZED_USER(HttpStatus.BAD_REQUEST, "권한이 없는 사용자입니다"),
// Token
INVALID_TOKEN(HttpStatus.BAD_REQUEST, "잘못된 토큰입니다"),
......@@ -19,6 +21,9 @@ public enum ErrorCode {
// Routing
NOT_FOUND_ROUTING(HttpStatus.BAD_REQUEST, "라우팅 파일이 존재하지 않습니다"),
// Routing
NOT_FOUND_LOG(HttpStatus.BAD_REQUEST, "로그가 존재하지 않습니다"),
// Certificate
NOT_FOUND_CERTIFICATE(HttpStatus.BAD_REQUEST, "SSL 인증서가 존재하지 않습니다"),
......
package com.aolda.itda.repository.log;
import com.aolda.itda.dto.PageResp;
import com.aolda.itda.dto.auth.QIdAndNameDTO;
import com.aolda.itda.dto.log.LogDTO;
import com.aolda.itda.dto.log.QLogDTO;
import com.aolda.itda.entity.log.Action;
import com.aolda.itda.entity.log.ObjectType;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.stereotype.Repository;
import java.util.List;
import static com.aolda.itda.entity.log.QLog.*;
import static com.aolda.itda.entity.user.QUser.*;
@Repository
@RequiredArgsConstructor
public class LogQueryDSL {
private final JPAQueryFactory jpaQueryFactory;
/* log 목록 반환 */
public PageResp<LogDTO> getLogs(String projectId, String type,
String username, String action, Boolean isASC, Pageable pageable) {
List<LogDTO> content = jpaQueryFactory
.select(new QLogDTO(
log.logId,
new QIdAndNameDTO(user.keystoneId, user.keystoneUsername),
log.action,
log.objectType,
log.objectId,
log.description,
log.createdAt
)).from(log)
.join(log.user, user).on(log.user.eq(user))
.where(getFilter(projectId, type, username, action))
.orderBy(isASC ? log.logId.asc() : log.logId.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
JPAQuery<Long> cnt = jpaQueryFactory
.select(log.count())
.from(log)
.where(getFilter(projectId, type, username, action));
Page<LogDTO> page = PageableExecutionUtils.getPage(content, pageable, cnt::fetchOne);
return PageResp.<LogDTO>builder()
.contents(page.getContent())
.first(page.isFirst())
.last(page.isLast())
.size(page.getSize())
.totalPages(page.getTotalPages())
.totalElements(page.getTotalElements())
.build();
}
/* Where 필터 */
private BooleanBuilder getFilter(String projectId, String type,
String username, String action) {
BooleanBuilder builder = new BooleanBuilder();
/* 프로젝트 조건 */
if (projectId != null) {
builder.and(log.projectId.eq(projectId));
}
/* 오브젝트 타입 조건 */
if (type != null) {
switch (type) {
case "certificate" -> builder.and(log.objectType.eq(ObjectType.CERTIFICATE));
case "forwarding" -> builder.and(log.objectType.eq(ObjectType.FORWARDING));
case "routing" -> builder.and(log.objectType.eq(ObjectType.ROUTING));
}
}
/* 사용자 ID 조건 */
if (username != null) {
builder.and(log.user.keystoneUsername.eq(username));
}
/* CUD 조건 */
if (action != null) {
switch (action) {
case "create" -> builder.and(log.action.eq(Action.CREATE));
case "update" -> builder.and(log.action.eq(Action.UPDATE));
case "delete" -> builder.and(log.action.eq(Action.DELETE));
}
}
return builder;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment