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

Merge branch 'feat/forwarding' into 'dev'

Feat/forwarding 포트포워딩 CRUD

See merge request !7
parents 02fbd7f6 e6f1aafb
No related branches found
No related tags found
2 merge requests!15Feat/certificate,!7Feat/forwarding 포트포워딩 CRUD
Showing
with 652 additions and 10 deletions
...@@ -26,6 +26,7 @@ repositories { ...@@ -26,6 +26,7 @@ repositories {
dependencies { dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
compileOnly 'org.projectlombok:lombok' compileOnly 'org.projectlombok:lombok'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
runtimeOnly 'com.mysql:mysql-connector-j' runtimeOnly 'com.mysql:mysql-connector-j'
......
...@@ -2,8 +2,10 @@ package com.aolda.itda; ...@@ -2,8 +2,10 @@ package com.aolda.itda;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@SpringBootApplication @SpringBootApplication
@EnableJpaAuditing
public class ItdaApplication { public class ItdaApplication {
public static void main(String[] args) { public static void main(String[] args) {
......
package com.aolda.itda.config;
import com.aolda.itda.exception.CustomException;
import com.aolda.itda.exception.ErrorCode;
import com.aolda.itda.service.AuthService;
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;
@RequiredArgsConstructor
@Component
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {
private final AuthService authService;
@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);
throw new CustomException(ErrorCode.INVALID_TOKEN, request.getRequestURI());
}
throw new CustomException(ErrorCode.INVALID_TOKEN, request.getRequestURI());
}
}
package com.aolda.itda.config; package com.aolda.itda.config;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration @Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer { public class WebConfig implements WebMvcConfigurer {
private final AuthInterceptor authInterceptor;
@Override @Override
public void addCorsMappings(CorsRegistry registry) { // 스프링단에서 cors 설정 public void addCorsMappings(CorsRegistry registry) { // 스프링단에서 cors 설정
registry.addMapping("/**") registry.addMapping("/**")
...@@ -16,4 +22,13 @@ public class WebConfig implements WebMvcConfigurer { ...@@ -16,4 +22,13 @@ public class WebConfig implements WebMvcConfigurer {
.exposedHeaders("Authorization", "X-Refresh-Token", "Access-Control-Allow-Origin") .exposedHeaders("Authorization", "X-Refresh-Token", "Access-Control-Allow-Origin")
; ;
} }
@Override
public void addInterceptors(InterceptorRegistry registry) {
String[] excludeAuth = {"/error", "/api/auth/*" };
registry.addInterceptor(authInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(excludeAuth);
}
} }
package com.aolda.itda.controller.forwarding;
import com.aolda.itda.dto.forwarding.ForwardingDTO;
import com.aolda.itda.service.forwarding.ForwardingService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class ForwardingController {
private final ForwardingService forwardingService;
@PostMapping("/forwarding")
public ResponseEntity<Object> create(@RequestParam String projectId,
@RequestBody ForwardingDTO dto) {
forwardingService.createForwarding(projectId, dto);
return ResponseEntity.ok().build();
}
@GetMapping("/forwarding")
public ResponseEntity<Object> view(@RequestParam Long forwardingId) {
return ResponseEntity.ok(forwardingService.getForwarding(forwardingId));
}
@GetMapping("/forwardings")
public ResponseEntity<Object> lists(@RequestParam String projectId) {
return ResponseEntity.ok(forwardingService.getForwardings(projectId));
}
@PatchMapping("/forwarding")
public ResponseEntity<Object> edit(@RequestParam Long forwardingId,
@RequestBody ForwardingDTO dto) {
forwardingService.editForwarding(forwardingId, dto);
return ResponseEntity.ok().build();
}
@DeleteMapping("/forwarding")
public ResponseEntity<Object> delete(@RequestParam Long forwardingId) {
forwardingService.deleteForwarding(forwardingId);
return ResponseEntity.ok().build();
}
}
package com.aolda.itda.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.List;
@Builder
@Getter
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PageResp<T> {
private Integer totalPages;
private Integer totalElements;
private Integer size;
private List<T> contents;
private Boolean first;
private Boolean last;
public static <T> PageRespBuilder<T> builderFor(Class<T> clazz) {
return (PageRespBuilder<T>) new PageRespBuilder<>();
}
}
package com.aolda.itda.dto.forwarding;
import com.fasterxml.jackson.annotation.JsonInclude;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ForwardingDTO {
private Long id;
@Pattern(regexp = "^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$",
message = "잘못된 IP 형식 (server)")
private String serverIp;
@NotBlank(message = "serverPort 값이 존재하지 않습니다")
@Pattern(regexp = "^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$",
message = "잘못된 포트 형식 (server)")
private String serverPort;
@NotBlank(message = "instanceIp 값이 존재하지 않습니다")
@Pattern(regexp = "^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$",
message = "잘못된 IP 형식 (instance)")
private String instanceIp;
@NotBlank(message = "instancePort 값이 존재하지 않습니다")
@Pattern(regexp = "^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$",
message = "잘못된 포트 형식 (instance)")
private String instancePort;
@NotBlank(message = "name 값이 존재하지 않습니다")
private String name;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
package com.aolda.itda.entity;
import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.time.LocalDateTime;
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseTimeEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
@Column(name = "updated_at")
private LocalDateTime updatedAt;
}
package com.aolda.itda.entity.certificate;
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 java.time.LocalDateTime;
@Entity
@Table(name = "certificate")
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Certificate extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false)
private Long certificateId;
@OneToOne
@JoinColumn(nullable = false, name = "user_id")
private User user;
private String projectId;
private String domain;
private String email;
private LocalDateTime expiredAt;
@Enumerated(EnumType.STRING)
private Challenge challenge;
private Boolean isDeleted;
private String description;
}
package com.aolda.itda.entity.certificate;
public enum Challenge {
HTTP, DNS_CLOUDFLARE
}
package com.aolda.itda.entity.forwarding;
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;
@Entity
@Table(name = "forwarding")
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Forwarding extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false)
private Long forwardingId;
@OneToOne
@JoinColumn(name = "user_id")
private User user;
private String projectId;
private String serverIp;
private String serverPort;
private String instanceIp;
private String instancePort;
private Boolean isDeleted;
private String name;
public ForwardingDTO toForwardingDTO() {
return ForwardingDTO.builder()
.id(forwardingId)
.name(name)
.serverPort(serverPort)
.instanceIp(instanceIp)
.instancePort(instancePort)
.createdAt(getCreatedAt())
.updatedAt(getUpdatedAt())
.build();
}
public void edit(ForwardingDTO dto) {
this.name = dto.getName() != null ? dto.getName() : this.name;
this.serverPort = dto.getServerPort() != null &&
dto.getServerPort().matches("^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$")
? dto.getServerPort() : this.serverPort;
this.instanceIp = dto.getInstanceIp() != null &&
dto.getInstanceIp().matches("^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$")
? dto.getInstanceIp() : this.instanceIp;
this.instancePort = dto.getInstancePort() != null &&
dto.getInstancePort().matches("^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$")
? dto.getInstancePort() : this.instancePort;
}
public void delete() {
this.isDeleted = true;
}
}
package com.aolda.itda.entity.log;
public enum Action {
CREATE, UPDATE, DELETE
}
package com.aolda.itda.entity.log;
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;
@Entity
@Table(name = "log")
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Log extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false)
private Long logId;
@OneToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
private String projectId;
@Enumerated(EnumType.STRING)
private ObjectType objectType;
private Long objectId;
@Enumerated(EnumType.STRING)
private Action action;
private String metadata;
}
package com.aolda.itda.entity.log;
public enum ObjectType {
ROUTING, CERTIFICATE, FORWARDING
}
package com.aolda.itda.entity.routing;
import com.aolda.itda.entity.BaseTimeEntity;
import com.aolda.itda.entity.certificate.Certificate;
import com.aolda.itda.entity.user.User;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "routing")
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Routing extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false)
private Long routingId;
@OneToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
@OneToOne
@JoinColumn(name = "certificate_id", nullable = false)
private Certificate certificate;
private String projectId;
private String domain;
private String instanceIp;
private Boolean isDeleted;
private String description;
}
package com.aolda.itda.entity.user;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "user")
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false)
private Long userId;
private String keystoneUsername;
private String keystoneId;
}
...@@ -12,7 +12,15 @@ public enum ErrorCode { ...@@ -12,7 +12,15 @@ public enum ErrorCode {
INVALID_USER_INFO(HttpStatus.BAD_REQUEST, "잘못된 회원 정보입니다"), INVALID_USER_INFO(HttpStatus.BAD_REQUEST, "잘못된 회원 정보입니다"),
// Token // Token
INVALID_TOKEN(HttpStatus.BAD_REQUEST, "잘못된 토큰입니다"); INVALID_TOKEN(HttpStatus.BAD_REQUEST, "잘못된 토큰입니다"),
//Forwarding
FAIL_CREATE_CONF(HttpStatus.BAD_REQUEST, "Conf 파일을 생성하지 못했습니다"),
FAIL_UPDATE_CONF(HttpStatus.BAD_REQUEST, "Conf 파일을 수정하지 못했습니다"),
NOT_FOUND_FORWARDING(HttpStatus.BAD_REQUEST, "포트포워딩 파일이 존재하지 않습니다"),
INVALID_CONF_INPUT(HttpStatus.BAD_REQUEST, "잘못된 입력이 존재합니다"),
DUPLICATED_INSTANCE_INFO(HttpStatus.BAD_REQUEST, "중복된 인스턴스 IP와 포트입니다"),
DUPLICATED_SERVER_PORT(HttpStatus.BAD_REQUEST, "중복된 서버 포트입니다");
private final HttpStatus status; private final HttpStatus status;
private final String message; private final String message;
......
package com.aolda.itda.repository.forwarding;
import com.aolda.itda.entity.forwarding.Forwarding;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Optional;
public interface ForwardingRepository extends JpaRepository<Forwarding, Long> {
List<Forwarding> findByProjectIdAndIsDeleted(String projectId, Boolean isDeleted);
Optional<Forwarding> findByForwardingIdAndIsDeleted(Long forwardingId, Boolean isDeleted);
Boolean existsByInstanceIpAndInstancePortAndIsDeleted(String instanceIp, String instancePort, Boolean isDeleted);
Boolean existsByServerPortAndIsDeleted(String serverPort, Boolean isDeleted);
}
...@@ -15,7 +15,6 @@ import org.springframework.beans.factory.annotation.Value; ...@@ -15,7 +15,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*; import org.springframework.http.*;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.util.*; import java.util.*;
...@@ -79,8 +78,13 @@ public class AuthService { ...@@ -79,8 +78,13 @@ public class AuthService {
"}"; "}";
HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers); HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);
ResponseEntity<Map> res = restTemplate.postForEntity(url, requestEntity, Map.class); ResponseEntity<Map> res;
try {
res = restTemplate.postForEntity(url, requestEntity, Map.class);
} catch (Exception e) {
e.printStackTrace();
throw new CustomException(ErrorCode.INVALID_USER_INFO);
}
Map<String, Object> resToken = (Map<String, Object>) res.getBody().get("token"); Map<String, Object> resToken = (Map<String, Object>) res.getBody().get("token");
Map<String, Object> resUser = (Map<String, Object>) resToken.get("user"); Map<String, Object> resUser = (Map<String, Object>) resToken.get("user");
String userId = (String) resUser.get("id"); String userId = (String) resUser.get("id");
...@@ -263,7 +267,7 @@ public class AuthService { ...@@ -263,7 +267,7 @@ public class AuthService {
return lists; return lists;
} }
private String validateTokenAndGetUserId(String token) throws JsonProcessingException { public String validateTokenAndGetUserId(String token) throws JsonProcessingException {
String url = keystone + "/auth/tokens"; String url = keystone + "/auth/tokens";
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.set("X-Auth-Token", token); headers.set("X-Auth-Token", token);
...@@ -273,7 +277,6 @@ public class AuthService { ...@@ -273,7 +277,6 @@ public class AuthService {
try { try {
res = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class); res = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
} catch (HttpClientErrorException.NotFound e) { } catch (HttpClientErrorException.NotFound e) {
System.out.println("validate");
throw new CustomException(ErrorCode.INVALID_TOKEN); throw new CustomException(ErrorCode.INVALID_TOKEN);
} }
return objectMapper.readTree(res.getBody()).path("token").path("user").path("id").asText(); return objectMapper.readTree(res.getBody()).path("token").path("user").path("id").asText();
...@@ -290,18 +293,14 @@ public class AuthService { ...@@ -290,18 +293,14 @@ public class AuthService {
res = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class); res = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
} catch (RuntimeException e) { } catch (RuntimeException e) {
e.printStackTrace(); e.printStackTrace();
System.out.println("runtime");
return false; return false;
} }
JsonNode node = objectMapper.readTree(res.getBody()).path("role_assignments"); JsonNode node = objectMapper.readTree(res.getBody()).path("role_assignments");
String system_all = node.path("scope").path("system").path("all").asText(); String system_all = node.path("scope").path("system").path("all").asText();
String role = node.path("role").path("name").asText(); String role = node.path("role").path("name").asText();
System.out.println("role: " + role);
if (system_all.equals("true") && role.equals("admin")) { if (system_all.equals("true") && role.equals("admin")) {
System.out.println(system_all);
return true; return true;
} }
System.out.println("hi");
return false; return false;
} }
......
package com.aolda.itda.service.forwarding;
import com.aolda.itda.dto.PageResp;
import com.aolda.itda.dto.forwarding.ForwardingDTO;
import com.aolda.itda.entity.forwarding.Forwarding;
import com.aolda.itda.exception.CustomException;
import com.aolda.itda.exception.ErrorCode;
import com.aolda.itda.repository.forwarding.ForwardingRepository;
import com.aolda.itda.template.ForwardingTemplate;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@Service
@Transactional
@RequiredArgsConstructor
public class ForwardingService {
@Value("${spring.server.base-ip}")
private String serverBaseIp;
private final ForwardingTemplate forwardingTemplate;
private final ForwardingRepository forwardingRepository;
/* 포트포워딩 정보 조회 */
public ForwardingDTO getForwarding(Long forwardingId) {
Forwarding forwarding = forwardingRepository.findByForwardingIdAndIsDeleted(forwardingId, false)
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_FORWARDING));
return forwarding.toForwardingDTO();
}
/* 포트포워딩 목록 조회 */
public PageResp<ForwardingDTO> getForwardings(String projectId) {
return PageResp.<ForwardingDTO>builder()
.contents(forwardingRepository.findByProjectIdAndIsDeleted(projectId, false)
.stream()
.map(Forwarding::toForwardingDTO)
.toList()).build();
}
/* 포트포워딩 생성 */
public void createForwarding(String projectId, ForwardingDTO dto) {
/* 입력 DTO 검증 */
validateDTO(dto);
/* 중복 검증 */
if (forwardingRepository.existsByInstanceIpAndInstancePortAndIsDeleted(dto.getInstanceIp(), dto.getInstancePort(), false)) {
throw new CustomException(ErrorCode.DUPLICATED_INSTANCE_INFO);
}
if (forwardingRepository.existsByServerPortAndIsDeleted(dto.getServerPort(), false)) {
throw new CustomException(ErrorCode.DUPLICATED_SERVER_PORT);
}
/* 포트포워딩 엔티티 생성 */
Forwarding forwarding = Forwarding.builder()
.isDeleted(false)
.projectId(projectId)
.name(dto.getName())
.serverIp(dto.getServerIp() == null ? serverBaseIp : dto.getServerIp())
.serverPort(dto.getServerPort())
.instanceIp(dto.getInstanceIp())
.instancePort(dto.getInstancePort())
.build();
forwardingRepository.save(forwarding);
/* nginx conf 파일 생성 및 예외 처리 */
String content = forwardingTemplate.getPortForwardingWithTCP(dto.getServerPort(), dto.getInstanceIp(), dto.getInstancePort(), dto.getName());
String confPath = "/data/nginx/stream/" + forwarding.getForwardingId() + ".conf";
File file = new File(confPath);
try {
Path path = Paths.get(confPath);
Files.createDirectories(path.getParent());
if (!file.createNewFile()) {
throw new CustomException(ErrorCode.FAIL_CREATE_CONF, "중복된 포트포워딩 Conf 파일이 존재합니다");
}
} catch (IOException e) {
e.printStackTrace();
throw new CustomException(ErrorCode.FAIL_CREATE_CONF);
}
/* conf 파일 작성 및 예외 처리 */
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(file, true)); // 예외처리 필요
bw.write(content);
bw.flush();
bw.close();
} catch (Exception e) {
e.printStackTrace();
if (file.exists()) {
file.delete();
}
throw new CustomException(ErrorCode.FAIL_CREATE_CONF, "포트포워딩 Conf 파일을 작성하지 못했습니다");
}
}
/* 포트포워딩 정보 수정 */
public void editForwarding(Long forwardingId, ForwardingDTO dto) {
Forwarding forwarding = forwardingRepository.findByForwardingIdAndIsDeleted(forwardingId, false)
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_FORWARDING));
forwarding.edit(dto);
/* 중복 검증 */
if (!(dto.getInstanceIp() == null && dto.getInstancePort() == null) &&
forwardingRepository.existsByInstanceIpAndInstancePortAndIsDeleted(forwarding.getInstanceIp()
, forwarding.getInstancePort()
, false)) {
throw new CustomException(ErrorCode.DUPLICATED_INSTANCE_INFO);
}
if (dto.getServerPort() != null && forwardingRepository.existsByServerPortAndIsDeleted(dto.getServerPort(), false)) {
throw new CustomException(ErrorCode.DUPLICATED_SERVER_PORT);
}
/* 파일 수정 */
String content = forwardingTemplate.getPortForwardingWithTCP(forwarding.getServerPort(),
forwarding.getInstanceIp(),
forwarding.getInstancePort(),
forwarding.getName());
String confPath = "/data/nginx/stream/" + forwarding.getForwardingId() + ".conf";
File file = new File(confPath);
if (!file.exists()) {
throw new CustomException(ErrorCode.NOT_FOUND_FORWARDING, "Conf 파일이 존재하지 않아 수정할 수 없습니다");
}
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(file, true)); // 예외처리 필요
bw.write(content);
bw.flush();
bw.close();
} catch (Exception e) {
e.printStackTrace();
throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "포트포워딩 Conf 파일을 수정하지 못했습니다");
}
/* DB 정보 수정 */
forwardingRepository.save(forwarding);
}
/* 포트포워딩 삭제 (소프트) */
public void deleteForwarding(Long forwardingId) {
Forwarding forwarding = forwardingRepository.findByForwardingIdAndIsDeleted(forwardingId, false)
.orElseThrow(() -> new CustomException(ErrorCode.NOT_FOUND_FORWARDING));
/* 파일 삭제 */
String confPath = "/data/nginx/stream/" + forwarding.getForwardingId() + ".conf";
File file = new File(confPath);
if (!file.delete()) {
throw new CustomException(ErrorCode.NOT_FOUND_FORWARDING, "Conf 파일이 존재하지 않아 삭제할 수 없습니다");
}
/* DB */
forwarding.delete();
forwardingRepository.save(forwarding);
}
/* 입력 DTO 검증 */
private void validateDTO(ForwardingDTO dto) {
for (ConstraintViolation<ForwardingDTO> violation : Validation.buildDefaultValidatorFactory().getValidator().validate(dto)) {
throw new CustomException(ErrorCode.INVALID_CONF_INPUT, violation.getMessage());
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment