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

Merge branch 'feat/main' into 'dev'

Feat/main 자잘한 변경 사항들

See merge request !14
parents 6e706c25 9662eda4
No related branches found
No related tags found
2 merge requests!15Feat/certificate,!14Feat/main 자잘한 변경 사항들
Showing
with 284 additions and 137 deletions
......@@ -61,7 +61,7 @@ public class RoutingLogAspect {
+ "ip: " + routing.getInstanceIp() + "\n"
+ "port: " + routing.getInstancePort() + "\n"
+ (routing.getCertificate() != null ? ("certificateId: " + routing.getCertificate().getCertificateId() + "\n") : "")
+ "caching: " + routing.getCaching() + "\n";
+ "caching: " + routing.getCaching();
/* 로그 엔티티 저장 */
logRepository.save(Log.builder()
......@@ -97,7 +97,7 @@ public class RoutingLogAspect {
+ "ip: " + routing.getInstanceIp() + "\n"
+ "port: " + routing.getInstancePort() + "\n"
+ (routing.getCertificate() != null ? ("certificateId: " + routing.getCertificate().getCertificateId() + "\n") : "")
+ "caching: " + routing.getCaching() + "\n";
+ "caching: " + routing.getCaching();
/* 로그 엔티티 저장 */
logRepository.save(Log.builder()
......
......@@ -4,64 +4,73 @@ 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;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@RequiredArgsConstructor
@Component
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {
public class AuthFilter extends OncePerRequestFilter {
private final AuthService authService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (request.getRequestURI().contains("/api/auth")) {
filterChain.doFilter(request, response);
return;
}
String token = request.getHeader("X-Subject-Token");
/* 토큰 헤더 검증 */
// 토큰 헤더 검증
if (token == null || token.isEmpty()) {
throw new CustomException(ErrorCode.INVALID_TOKEN, request.getRequestURI());
}
/* 유효 토큰 검증 */
// 유효 토큰 검증
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());
}
/* 프로젝트 권한 검증 */
// 프로젝트 권한 검증
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());
authService.getBestRoleWithinProject(token, projectId).get("role");
if (!request.getMethod().equals("GET") && !authService.getBestRoleWithinProject(token, projectId).get("role").equals("admin")) {
throw new CustomException(ErrorCode.UNAUTHORIZED_USER, request.getRequestURI());
}
} catch (Exception e) {
throw new CustomException(ErrorCode.UNAUTHORIZED_USER, request.getRequestURI());
}
}
// 프로젝트 리스트 조회
List<String> projects;
if (authService.isAdmin(Map.of("id", userId, "token", token))) {
projects = authService.getAllProjects(token).stream().map(IdAndNameDTO::getId).toList();
} else {
projects = authService.getProjectsWithUser(Map.of("id", userId, "token", token)).stream().map(IdAndNameDTO::getId).toList();
}
/* 프로젝트 리스트 조회 */
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;
filterChain.doFilter(request, response);
}
}
\ No newline at end of file
package com.aolda.itda.config;
import com.aolda.itda.exception.CustomException;
import com.aolda.itda.exception.ErrorCode;
import com.aolda.itda.service.AuthService;
import com.fasterxml.jackson.core.JsonProcessingException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
......@@ -11,11 +16,14 @@ import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import java.io.IOException;
import java.util.Map;
@Component
@RequiredArgsConstructor
public class LoggingFilter extends OncePerRequestFilter {
private static final Logger logger = LoggerFactory.getLogger(LoggingFilter.class);
private final AuthService authService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
......@@ -23,24 +31,22 @@ public class LoggingFilter extends OncePerRequestFilter {
// Request Body를 읽을 수 있도록 래핑
ContentCachingRequestWrapper cachingRequest = new ContentCachingRequestWrapper(request);
System.out.println("필터 적용");
filterChain.doFilter(cachingRequest, response);
// 로그 기록
logRequest(cachingRequest);
System.out.println("왜 안돼ㅐ");
}
private void logRequest(ContentCachingRequestWrapper request) {
System.out.println("되는거 맞아?");
private void logRequest(ContentCachingRequestWrapper request) throws JsonProcessingException {
String ip = request.getRemoteAddr();
String method = request.getMethod();
String uri = request.getRequestURI();
String queryString = request.getQueryString();
String body = getRequestBody(request);
Map<String, String> user = (Map<String, String>) request.getAttribute("user");
logger.info("IP: {}, Method: {}, URI: {}, Query Params: {}, Request Body: {}",
ip, method, uri, (queryString != null ? queryString : "None"),
logger.info("IP: {}, Method: {}, URI: {}, Query Params: {}, User: {}, Request Body: {}",
ip, method, uri, (queryString != null ? queryString : "None"), (user != null ? user.get("id") : "None"),
(!body.isEmpty() ? body : "None"));
}
......
......@@ -3,17 +3,18 @@ package com.aolda.itda.config;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
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;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
private final AuthInterceptor authInterceptor;
private final AuthFilter authFilter;
private final LoggingFilter loggingFilter;
@Override
public void addCorsMappings(CorsRegistry registry) { // 스프링단에서 cors 설정
......@@ -26,13 +27,23 @@ public class WebConfig implements WebMvcConfigurer {
;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
String[] excludeAuth = {"/error", "/api/auth/*" };
registry.addInterceptor(authInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(excludeAuth);
@Bean
public FilterRegistrationBean<AuthFilter> authFilterRegistration() {
FilterRegistrationBean<AuthFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(authFilter);
registrationBean.setOrder(1); // AuthFilter의 순서를 1로 설정
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
@Bean
public FilterRegistrationBean<LoggingFilter> loggingFilterRegistration() {
FilterRegistrationBean<LoggingFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(loggingFilter);
registrationBean.setOrder(2); // LoggingFilter의 순서를 2로 설정
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
@Bean
......
......@@ -30,8 +30,9 @@ public class ForwardingController {
}
@GetMapping("/forwardings")
public ResponseEntity<Object> lists(@RequestParam String projectId) {
return ResponseEntity.ok(forwardingService.getForwardings(projectId));
public ResponseEntity<Object> lists(@RequestParam String projectId,
@RequestParam(required = false) String query) {
return ResponseEntity.ok(forwardingService.getForwardingsWithSearch(projectId, query));
}
@PatchMapping("/forwarding")
......
package com.aolda.itda.controller.main;
import com.aolda.itda.service.main.MainService;
import com.fasterxml.jackson.core.JsonProcessingException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
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 MainController {
private final MainService mainService;
@GetMapping("/projects")
public ResponseEntity<Object> projects(HttpServletRequest request) throws JsonProcessingException {
return ResponseEntity.ok(mainService.getAllProjects((Map<String, String>) request.getSession().getAttribute("user")));
}
@GetMapping("/main")
public ResponseEntity<Object> mainInfo(@RequestParam String projectId, HttpServletRequest request) {
return ResponseEntity.ok(mainService.getMainInfo(projectId, (List<String>) request.getAttribute("projects")));
}
}
......@@ -31,8 +31,9 @@ public class RoutingController {
}
@GetMapping("/routings")
public ResponseEntity<Object> lists(@RequestParam String projectId) {
return ResponseEntity.ok(routingService.getRoutings(projectId));
public ResponseEntity<Object> lists(@RequestParam String projectId,
@RequestParam(required = false) String query) {
return ResponseEntity.ok(routingService.getRoutingsWithSearch(projectId, query));
}
@PatchMapping("/routing")
......
package com.aolda.itda.dto.forwarding;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
......@@ -40,6 +41,10 @@ public class ForwardingDTO {
@NotBlank(message = "name 값이 존재하지 않습니다")
private String name;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime createdAt;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime updatedAt;
}
......@@ -3,6 +3,7 @@ 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.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.querydsl.core.annotations.QueryProjection;
import lombok.AllArgsConstructor;
......@@ -22,7 +23,11 @@ public class LogDTO {
private Action action;
private ObjectType type;
private Long objectId;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private String description;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime createdAt;
@QueryProjection
......
package com.aolda.itda.dto.main;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MainInfoDTO {
private Long routing;
private Long forwarding;
private Long certificate;
}
package com.aolda.itda.dto.routing;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
......@@ -28,8 +29,10 @@ public class RoutingDTO {
@NotNull
private Long certificateId;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime createdAt;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime updatedAt;
@NotNull
......
......@@ -17,12 +17,12 @@ import java.time.LocalDateTime;
public abstract class BaseTimeEntity {
@CreatedDate
@Column(updatable = false)
@Column(updatable = false, columnDefinition = "DATETIME")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime createdAt;
@LastModifiedDate
@Column(name = "updated_at")
@Column(name = "updated_at", columnDefinition = "DATETIME")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime updatedAt;
......
......@@ -27,10 +27,13 @@ public class Certificate extends BaseTimeEntity {
@JoinColumn(nullable = false, name = "user_id")
private User user;
@Column(length = 64)
private String projectId;
@Column(length = 64)
private String domain;
@Column(length = 64)
private String email;
private LocalDateTime expiredAt;
......@@ -40,6 +43,7 @@ public class Certificate extends BaseTimeEntity {
private Boolean isDeleted;
@Column(length = 256)
private String description;
public String formatDomain() {
......
package com.aolda.itda.entity.certificate;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonValue;
@JsonFormat(shape = JsonFormat.Shape.STRING)
public enum Challenge {
HTTP, DNS_CLOUDFLARE
HTTP, DNS_CLOUDFLARE;
@JsonValue
@Override
public String toString() {
return name().toLowerCase();
}
}
......@@ -20,18 +20,24 @@ public class Forwarding extends BaseTimeEntity {
@Column(nullable = false)
private Long forwardingId;
@Column(length = 64)
private String projectId;
@Column(length = 32)
private String serverIp;
@Column(length = 8)
private String serverPort;
@Column(length = 32)
private String instanceIp;
@Column(length = 8)
private String instancePort;
private Boolean isDeleted;
@Column(length = 256)
private String name;
public Forwarding(Forwarding forwarding) {
......
package com.aolda.itda.entity.log;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonValue;
@JsonFormat(shape = JsonFormat.Shape.STRING)
public enum Action {
CREATE, UPDATE, DELETE
CREATE, UPDATE, DELETE;
@JsonValue
@Override
public String toString() {
return name().toLowerCase();
}
}
......@@ -27,16 +27,20 @@ public class Log extends BaseTimeEntity {
@JoinColumn(name = "user_id", nullable = false)
private User user;
@Column(length = 64)
private String projectId;
@Enumerated(EnumType.STRING)
private ObjectType objectType;
@Column(length = 64)
private Long objectId;
@Enumerated(EnumType.STRING)
private Action action;
@Lob
@Column(length = 1024)
private String description;
public LogDTO toLogDTO() {
......
package com.aolda.itda.entity.log;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonValue;
@JsonFormat(shape = JsonFormat.Shape.STRING)
public enum ObjectType {
ROUTING, CERTIFICATE, FORWARDING
ROUTING, CERTIFICATE, FORWARDING;
@JsonValue
@Override
public String toString() {
return name().toLowerCase();
}
}
......@@ -28,18 +28,23 @@ public class Routing extends BaseTimeEntity {
@JoinColumn(name = "certificate_id")
private Certificate certificate;
@Column(length = 64)
private String projectId;
@Column(length = 64)
private String domain;
@Column(length = 32)
private String instanceIp;
@Column(length = 8)
private String instancePort;
private Boolean isDeleted;
private Boolean caching;
@Column(length = 256)
private String name;
public RoutingDTO toRoutingDTO() {
......
......@@ -2,6 +2,7 @@ package com.aolda.itda.repository.forwarding;
import com.aolda.itda.entity.forwarding.Forwarding;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
import java.util.Optional;
......@@ -11,4 +12,7 @@ public interface ForwardingRepository extends JpaRepository<Forwarding, Long> {
Optional<Forwarding> findByForwardingIdAndIsDeleted(Long forwardingId, Boolean isDeleted);
Boolean existsByInstanceIpAndInstancePortAndIsDeleted(String instanceIp, String instancePort, Boolean isDeleted);
Boolean existsByServerPortAndIsDeleted(String serverPort, Boolean isDeleted);
@Query("SELECT f FROM Forwarding f WHERE f.projectId = ?1 AND f.isDeleted = ?3 AND (f.instanceIp LIKE %?2% OR f.serverPort LIKE %?2% OR f.name LIKE %?2%)")
List<Forwarding> findWithSearch(String projectId, String query, Boolean isDeleted);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment