api 수정

This commit is contained in:
현성필
2025-01-31 14:46:06 +09:00
parent 2dc222c29b
commit aaa0bce1d0
28 changed files with 702 additions and 47 deletions
@@ -0,0 +1,98 @@
package com.eactive.testmaster.api.controller;
import com.eactive.testmaster.api.dto.MockRouteDTO;
import com.eactive.testmaster.api.dto.MockRouteRegisterDTO;
import com.eactive.testmaster.api.dto.MockRouteSearch;
import com.eactive.testmaster.api.dto.MockRouteUpdateDTO;
import com.eactive.testmaster.api.entity.MockRoute;
import com.eactive.testmaster.api.mapper.MockRouteMapper;
import com.eactive.testmaster.api.service.MockRouteService;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/mock-routes")
public class MockRouteRestController {
private final MockRouteService mockRouteService;
private final MockRouteMapper mockRouteMapper;
private final MockApiHandlerMapping mockApiHandlerMapping;
public MockRouteRestController(MockRouteService mockRouteService,
MockRouteMapper mockRouteMapper,
MockApiHandlerMapping mockApiHandlerMapping) {
this.mockRouteService = mockRouteService;
this.mockRouteMapper = mockRouteMapper;
this.mockApiHandlerMapping = mockApiHandlerMapping;
}
@GetMapping
public ResponseEntity<Page<MockRouteDTO>> listMockRoutes(
@RequestParam(required = false) String name,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
MockRouteSearch search = new MockRouteSearch();
search.setName(name);
Pageable pageable = PageRequest.of(page, size);
Page<MockRoute> routes = mockRouteService.findAll(search.buildSpecification(), pageable);
Page<MockRouteDTO> dtoPage = routes.map(mockRouteMapper::mapRoute);
return ResponseEntity.ok(dtoPage);
}
@GetMapping("/{id}")
public ResponseEntity<MockRoute> getMockRoute(@PathVariable Long id) {
MockRoute mockRoute = mockRouteService.findById(id);
return ResponseEntity.ok(mockRoute);
}
@PostMapping
public ResponseEntity<MockRoute> createMockRoute(@RequestBody MockRouteRegisterDTO dto) {
MockRoute mockRoute = mockRouteMapper.map(dto);
MockRoute created = mockRouteService.create(mockRoute);
mockRouteService.initAllRoutes();
mockApiHandlerMapping.registerMapping(created);
return ResponseEntity.ok(created);
}
@PostMapping("/update/{id}")
public ResponseEntity<MockRoute> updateMockRoute(
@PathVariable Long id,
@RequestBody MockRouteUpdateDTO dto) {
MockRoute prev = mockRouteService.findById(id);
mockApiHandlerMapping.unregisterMapping(prev);
MockRoute mockRoute = mockRouteMapper.map(dto);
MockRoute updated = mockRouteService.update(id, mockRoute);
mockRouteService.initAllRoutes();
mockApiHandlerMapping.registerMapping(updated);
return ResponseEntity.ok(updated);
}
@PostMapping("/delete")
public ResponseEntity<Void> deleteMockRoutes(@RequestBody List<Long> ids) {
for (Long id : ids) {
MockRoute mockRoute = mockRouteService.findById(id);
mockApiHandlerMapping.unregisterMapping(mockRoute);
mockRouteService.deleteById(id);
}
mockRouteService.initAllRoutes();
return ResponseEntity.ok().build();
}
}
@@ -6,6 +6,8 @@ import javax.validation.constraints.Min;
public class MockResponseDTO {
private Long id;
@Min(100)
private int statusCode = 200;
@@ -21,6 +23,14 @@ public class MockResponseDTO {
private String encodingCharset;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public int getStatusCode() {
return statusCode;
}
@@ -0,0 +1,75 @@
package com.eactive.testmaster.api.dto;
import java.util.ArrayList;
import java.util.List;
public class MockRouteDTO {
private Long id;
private String name;
private String method;
private String pathPattern;
private String requestScript;
private List<MockResponseDTO> responses = new ArrayList<>();
// Add constructor for entity conversion
// public static MockRouteDTO from(MockRoute route) {
// MockRouteDTO dto = new MockRouteDTO();
// dto.setId(route.getId());
// dto.setName(route.getName());
// dto.setMethod(route.getMethod());
// dto.setPathPattern(route.getPathPattern());
// dto.setRequestScript(route.getRequestScript());
// dto.setResponses(route.getResponses().stream()
// .map(MockResponseDTO::from)
// .collect(Collectors.toList()));
// return dto;
// }
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getPathPattern() {
return pathPattern;
}
public void setPathPattern(String pathPattern) {
this.pathPattern = pathPattern;
}
public String getRequestScript() {
return requestScript;
}
public void setRequestScript(String requestScript) {
this.requestScript = requestScript;
}
public List<MockResponseDTO> getResponses() {
return responses;
}
public void setResponses(List<MockResponseDTO> responses) {
this.responses = responses;
}
}
@@ -1,5 +1,6 @@
package com.eactive.testmaster.api.entity;
import com.fasterxml.jackson.annotation.JsonBackReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -43,6 +44,7 @@ public class MockResponse {
@Column(name = "DEFAULT_RESPONSE", nullable = false, columnDefinition = "boolean default false")
private boolean defaultResponse = false;
@JsonBackReference
@ManyToOne
@JoinColumn(name = "ROUTE_ID", nullable = false)
private MockRoute route;
@@ -134,4 +136,6 @@ public class MockResponse {
public void setResponseScript(String responseScript) {
this.responseScript = responseScript;
}
}
@@ -1,5 +1,6 @@
package com.eactive.testmaster.api.entity;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
@@ -32,6 +33,7 @@ public class MockRoute {
@Lob
private String requestScript;
@JsonManagedReference
@OneToMany(mappedBy = "route", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private List<MockResponse> responses = new ArrayList<>();
@@ -2,6 +2,7 @@ package com.eactive.testmaster.api.mapper;
import com.eactive.testmaster.api.dto.MockHeaderDTO;
import com.eactive.testmaster.api.dto.MockResponseDTO;
import com.eactive.testmaster.api.dto.MockRouteDTO;
import com.eactive.testmaster.api.dto.MockRouteRegisterDTO;
import com.eactive.testmaster.api.dto.MockRouteUpdateDTO;
import com.eactive.testmaster.api.entity.MockResponse;
@@ -40,6 +41,8 @@ public abstract class MockRouteMapper {
public abstract MockRouteRegisterDTO map(MockRoute entity);
public abstract MockRouteDTO mapRoute(MockRoute entity);
@Mapping(target = "headers", source = "headers", qualifiedByName = "mapHeadersToMap")
@Mapping(target = "defaultResponse", source = "defaultResponse", qualifiedByName = "mapEntityDefaultResponse")
@Mapping(target = "body", source="body" , qualifiedByName = "unescapeBody")
@@ -44,7 +44,7 @@ public class MockRouteService {
return mockRouteRepository.findById(id).orElseThrow(() -> new NotFoundException(NOT_FOUND_MESSAGE));
}
public void create(MockRoute mockRoute) {
public MockRoute create(MockRoute mockRoute) {
if (!mockRoute.getPathPattern().startsWith("/")) {
mockRoute.setPathPattern("/" + mockRoute.getPathPattern());
@@ -60,13 +60,14 @@ public class MockRouteService {
}
}
mockRouteRepository.save(mockRoute);
return mockRoute;
}
public void deleteById(long id) {
mockRouteRepository.deleteById(id);
}
public void update(Long id, MockRoute updated) {
public MockRoute update(Long id, MockRoute updated) {
MockRoute route = mockRouteRepository.findById(id).orElseThrow(() -> new NotFoundException(NOT_FOUND_MESSAGE));
route.getResponses().clear();
@@ -91,6 +92,7 @@ public class MockRouteService {
}
mockRouteRepository.save(route);
return route;
}
public void initAllRoutes() {
@@ -12,8 +12,8 @@ import com.eactive.testmaster.client.service.ApiRequestMgmtService;
import com.eactive.testmaster.common.util.SecurityUtil;
import com.eactive.testmaster.user.entity.StaffUser;
import com.eactive.testmaster.user.service.UserService;
import java.util.List;
import java.util.Collections;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
@@ -2,13 +2,13 @@ package com.eactive.testmaster.client.entity;
import com.eactive.testmaster.server.entity.Server;
import com.eactive.testmaster.user.entity.StaffUser;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import org.hibernate.annotations.Type;
public class ApiRequestHistory {
@Id
@@ -35,7 +35,7 @@ public class ApiRequestHistory {
private String responseHeaders;
@Type(type = "org.hibernate.type.LocalDateTimeType")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime requestTime;
public Long getId() {
@@ -1,10 +1,10 @@
package com.eactive.testmaster.common.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import org.hibernate.annotations.Type;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
@@ -19,8 +19,8 @@ public abstract class Auditable {
* 최초등록시점
*/
@Column(name = "REGISTERED_ON")
@Type(type = "org.hibernate.type.LocalDateTimeType")
@CreatedDate
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime createdAt;
/**
@@ -34,8 +34,8 @@ public abstract class Auditable {
* 최종수정시점
*/
@Column(name = "LAST_MODIFIED_ON")
@Type(type = "org.hibernate.type.LocalDateTimeType")
@LastModifiedDate
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime updatedAt;
/**
@@ -4,6 +4,7 @@ import java.time.LocalDateTime;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@@ -44,4 +45,13 @@ public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler
return new ResponseEntity<>(errors, HttpStatus.UNAUTHORIZED);
}
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<CustomErrorResponse> handleAccessDeniedException(Exception ex, WebRequest request) {
CustomErrorResponse errors = new CustomErrorResponse();
errors.setTimestamp(LocalDateTime.now());
errors.setError(ex.getMessage());
errors.setStatus(HttpStatus.UNAUTHORIZED.value());
return new ResponseEntity<>(errors, HttpStatus.UNAUTHORIZED);
}
}
@@ -0,0 +1,84 @@
package com.eactive.testmaster.config;
/**
* Compatible with Java 8+
* Required dependencies:
* - com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.0+ (for Java 8)
* - com.fasterxml.jackson.core:jackson-databind:2.9.0+
*/
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.util.StdDateFormat;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
//@Configuration
//public class DateTimeConfig {
//
// private static final String ISO_DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
//
// @Bean
// public ObjectMapper objectMapper() {
// JavaTimeModule module = new JavaTimeModule();
// LocalDateTimeSerializer localDateTimeSerializer = new LocalDateTimeSerializer(
// DateTimeFormatter.ofPattern(ISO_DATE_TIME_PATTERN)
// );
// LocalDateTimeDeserializer localDateTimeDeserializer = new LocalDateTimeDeserializer(
// DateTimeFormatter.ofPattern(ISO_DATE_TIME_PATTERN)
// );
//
// module.addSerializer(LocalDateTime.class, localDateTimeSerializer);
// module.addDeserializer(LocalDateTime.class, localDateTimeDeserializer);
//
// return Jackson2ObjectMapperBuilder.json()
// .modules(module)
// .build();
// }
//}
//@Configuration
//public class DateTimeConfig {
// private static final String ISO_DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
//
// @Bean
// public ObjectMapper objectMapper() {
// ObjectMapper mapper = Jackson2ObjectMapperBuilder.json()
// .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) // This is key!
// .modules(new JavaTimeModule())
// .build();
//
// // Configure specific DateTime format if needed
// mapper.setDateFormat(new SimpleDateFormat(ISO_DATE_TIME_PATTERN));
//
// return mapper;
// }
//}
@Configuration
public class DateTimeConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = Jackson2ObjectMapperBuilder.json()
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.modules(new JavaTimeModule())
.serializationInclusion(JsonInclude.Include.NON_NULL)
.dateFormat(new StdDateFormat())
.build();
// Configure LocalDateTime serialization
SimpleModule module = new SimpleModule();
module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(
DateTimeFormatter.ISO_DATE_TIME));
mapper.registerModule(module);
return mapper;
}
}
@@ -1,11 +1,13 @@
package com.eactive.testmaster.queue.controller;
import com.eactive.testmaster.queue.dto.QueueHandlerDTO;
import com.eactive.testmaster.queue.dto.QueueHandlerSearch;
import com.eactive.testmaster.queue.entity.QueueHandler;
import com.eactive.testmaster.queue.mapper.QueueHandlerMapper;
import com.eactive.testmaster.queue.service.DynamicQueueManager;
import com.eactive.testmaster.queue.service.QueueHandlerService;
import com.eactive.testmaster.queue.dto.QueueHandlerDTO;
import com.eactive.testmaster.queue.dto.QueueHandlerSearch;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.annotation.Secured;
@@ -13,10 +15,12 @@ import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.PostConstruct;
import java.util.List;
@Controller
@RequestMapping("/mgmt/queues")
@@ -0,0 +1,100 @@
package com.eactive.testmaster.queue.controller;
import com.eactive.testmaster.queue.dto.QueueHandlerDTO;
import com.eactive.testmaster.queue.dto.QueueHandlerSearch;
import com.eactive.testmaster.queue.entity.QueueHandler;
import com.eactive.testmaster.queue.mapper.QueueHandlerMapper;
import com.eactive.testmaster.queue.service.DynamicQueueManager;
import com.eactive.testmaster.queue.service.QueueHandlerService;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/queue-handlers")
public class QueueHandlerRestController {
private final QueueHandlerService queueHandlerService;
private final QueueHandlerMapper queueHandlerMapper;
private final DynamicQueueManager dynamicQueueManager;
public QueueHandlerRestController(
QueueHandlerService queueHandlerService,
QueueHandlerMapper queueHandlerMapper,
DynamicQueueManager dynamicQueueManager) {
this.queueHandlerService = queueHandlerService;
this.queueHandlerMapper = queueHandlerMapper;
this.dynamicQueueManager = dynamicQueueManager;
}
@GetMapping
public ResponseEntity<Page<QueueHandlerDTO>> listQueueHandlers(
@ModelAttribute QueueHandlerSearch queueHandlerSearch,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Pageable pageable = PageRequest.of(page, size);
Page<QueueHandler> handlers = queueHandlerService.findAll(queueHandlerSearch.buildSpecification(), pageable);
Page<QueueHandlerDTO> dtoPage = handlers.map(queueHandlerMapper::map);
return ResponseEntity.ok(dtoPage);
}
@GetMapping("/{id}")
public ResponseEntity<QueueHandler> getQueueHandler(@PathVariable String id) {
QueueHandler queueHandler = queueHandlerService.findById(id);
return ResponseEntity.ok(queueHandler);
}
@PostMapping
public ResponseEntity<QueueHandler> createQueueHandler(@RequestBody QueueHandlerDTO dto) {
QueueHandler queueHandler = queueHandlerMapper.map(dto);
QueueHandler created = queueHandlerService.create(queueHandler);
queueHandlerService.initAllQueues();
return ResponseEntity.ok(created);
}
@PostMapping("/update/{id}")
public ResponseEntity<QueueHandler> updateQueueHandler(
@PathVariable String id,
@RequestBody QueueHandlerDTO dto) {
QueueHandler queueHandler = queueHandlerMapper.map(dto);
QueueHandler updated = queueHandlerService.update(id, queueHandler);
queueHandlerService.initAllQueues();
return ResponseEntity.ok(updated);
}
@PostMapping("/delete")
public ResponseEntity<Void> deleteQueueHandlers(@RequestBody List<String> ids) {
for (String id : ids) {
queueHandlerService.deleteById(id);
}
queueHandlerService.initAllQueues();
return ResponseEntity.ok().build();
}
@PostMapping("/{id}/start")
public ResponseEntity<Void> startQueue(@PathVariable String id) {
QueueHandler queueHandler = queueHandlerService.findById(id);
dynamicQueueManager.startQueueListener(queueHandler);
return ResponseEntity.ok().build();
}
@PostMapping("/{id}/stop")
public ResponseEntity<Void> stopQueue(@PathVariable String id) {
QueueHandler queueHandler = queueHandlerService.findById(id);
dynamicQueueManager.stopQueueListener(queueHandler.getQueueName());
return ResponseEntity.ok().build();
}
}
@@ -6,6 +6,7 @@ import com.eactive.testmaster.server.entity.Server;
import com.eactive.testmaster.server.mapper.ServerMapper;
import com.eactive.testmaster.server.service.ServerMgmtService;
import java.util.List;
import javax.validation.Valid;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
@@ -13,10 +14,13 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@@ -45,4 +49,41 @@ public class ServerRestController {
headers.add("X-Page-Size", String.valueOf(page.getSize()));
return new ResponseEntity<>(serverMapper.map(page.getContent()), headers, HttpStatus.OK);
}
@GetMapping
@Secured({"ROLE_MANAGE_SERVER", "ROLE_API_TESTER"})
public ResponseEntity<Page<ServerDTO>> listServers(
@ModelAttribute ServerSearch serverSearch,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size
) {
Pageable pageable = PageRequest.of(page, size);
Page<Server> servers = serverMgmtService.findAll(serverSearch.buildSpecification(), pageable);
return ResponseEntity.ok(servers.map(serverMapper::map));
}
@PostMapping
@Secured("ROLE_MANAGE_SERVER")
public ResponseEntity<ServerDTO> createServer(@RequestBody @Valid ServerDTO server) {
Server created = serverMgmtService.create(serverMapper.map(server));
return ResponseEntity.ok(serverMapper.map(created));
}
@PostMapping("/update/{id}")
@Secured("ROLE_MANAGE_SERVER")
public ResponseEntity<ServerDTO> updateServer(@PathVariable Long id, @RequestBody @Valid ServerDTO server) {
Server updated = serverMgmtService.update(id, serverMapper.map(server));
return ResponseEntity.ok(serverMapper.map(updated));
}
@PostMapping("/delete")
@Secured("ROLE_MANAGE_SERVER")
public ResponseEntity<Void> deleteServers(@RequestBody List<Long> ids) {
for (Long id : ids) {
serverMgmtService.delete(id);
}
return ResponseEntity.ok().build();
}
}
@@ -25,7 +25,7 @@ public class ServerMgmtService {
return serverRepository.findById(id).orElseThrow(() -> new NotFoundException("Server Not Found"));
}
public void create(Server server) {
public Server create(Server server) {
if (server.getServerOptions()!=null){
server.getServerOptions().forEach(serverOption -> {
serverOption.setEnabled(true);
@@ -33,9 +33,10 @@ public class ServerMgmtService {
});
}
serverRepository.save(server);
return server;
}
public void update(Long id, Server updated) {
public Server update(Long id, Server updated) {
Server server = serverRepository.findById(id).orElseThrow(() -> new NotFoundException("Server Not Found"));
server.setName(updated.getName());
@@ -55,8 +56,7 @@ public class ServerMgmtService {
}
serverRepository.save(server);
return server;
}
public void delete(Long id) {
@@ -1,7 +1,11 @@
package com.eactive.testmaster.socket;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.DefaultThreadFactory;
@@ -21,7 +21,7 @@ import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/mgmt/socket")
public class NettyServerController {
public class NettyTCPServerMgmtController {
private static final String NETTY_SERVER = "nettyServer";
private static final String NETTY_SERVER_LIST_VIEW = "page/socket/serverList";
@@ -30,13 +30,13 @@ public class NettyServerController {
private final NettyServerService nettyServerService;
public NettyServerController(NettyServerService nettyServerService) {
public NettyTCPServerMgmtController(NettyServerService nettyServerService) {
this.nettyServerService = nettyServerService;
}
@GetMapping("/list_view.do")
@Secured("ROLE_MANAGE_NETTY")
public ModelAndView listView(@ModelAttribute("serverSearch") NettyServerSearch serverSearch,
public ModelAndView listView(@ModelAttribute("serverSearch") NettyTCPServerSearch serverSearch,
Pageable pageable) {
ModelAndView mav = new ModelAndView(NETTY_SERVER_LIST_VIEW);
Page<NettyServerEntity> page = nettyServerService.findAll(serverSearch.buildSpecification(), pageable);
@@ -0,0 +1,110 @@
package com.eactive.testmaster.socket.controller;
import com.eactive.testmaster.socket.entity.NettyServerEntity;
import com.eactive.testmaster.socket.service.NettyServerService;
import java.util.List;
import javax.validation.Valid;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/socket")
public class NettyTCPServerRestController {
private final NettyServerService nettyServerService;
public NettyTCPServerRestController(NettyServerService nettyServerService) {
this.nettyServerService = nettyServerService;
}
@GetMapping
@Secured("ROLE_MANAGE_NETTY")
public ResponseEntity<Page<NettyServerEntity>> listNettyServers(
@ModelAttribute("serverSearch") NettyTCPServerSearch serverSearch,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size
) {
Pageable pageable = PageRequest.of(page, size);
Page<NettyServerEntity> servers = nettyServerService.findAll(serverSearch.buildSpecification(), pageable);
return ResponseEntity.ok(servers);
}
@PostMapping
@Secured("ROLE_MANAGE_NETTY")
public ResponseEntity<NettyServerEntity> createNettyServer(@RequestBody @Valid NettyServerEntity server) {
try {
NettyServerEntity created = nettyServerService.createServer(server);
return ResponseEntity.ok(created);
} catch (Exception e) {
return ResponseEntity.internalServerError().build();
}
}
@PostMapping("/update/{id}")
@Secured("ROLE_MANAGE_NETTY")
public ResponseEntity<NettyServerEntity> updateNettyServer(
@PathVariable Long id,
@RequestBody @Valid NettyServerEntity server
) {
try {
NettyServerEntity updated = nettyServerService.updateServer(id, server);
return ResponseEntity.ok(updated);
} catch (Exception e) {
return ResponseEntity.internalServerError().build();
}
}
@GetMapping("/{id}")
@Secured("ROLE_MANAGE_NETTY")
public ResponseEntity<NettyServerEntity> getNettyServer(@PathVariable Long id) {
try {
NettyServerEntity server = nettyServerService.findById(id);
return ResponseEntity.ok(server);
} catch (Exception e) {
return ResponseEntity.notFound().build();
}
}
@PostMapping("/delete")
public ResponseEntity<Void> deleteTCPServer(@RequestBody List<Long> ids) throws InterruptedException {
for (Long id : ids) {
nettyServerService.deleteServer(id);
}
return ResponseEntity.ok().build();
}
@PostMapping("/{id}/start")
@Secured("ROLE_MANAGE_NETTY")
public ResponseEntity<Void> startServer(@PathVariable Long id) {
try {
nettyServerService.startServer(id);
return ResponseEntity.ok().build();
} catch (Exception e) {
return ResponseEntity.internalServerError().build();
}
}
@PostMapping("/{id}/stop")
@Secured("ROLE_MANAGE_NETTY")
public ResponseEntity<Void> stopServer(@PathVariable Long id) {
try {
nettyServerService.stopServer(id);
return ResponseEntity.ok().build();
} catch (Exception e) {
return ResponseEntity.internalServerError().build();
}
}
}
@@ -8,7 +8,7 @@ import com.eactive.testmaster.socket.entity.NettyServerEntity;
import java.util.ArrayList;
import java.util.List;
public class NettyServerSearch implements BaseSearch<NettyServerEntity> {
public class NettyTCPServerSearch implements BaseSearch<NettyServerEntity> {
private String name;
private Long port;
@@ -1,5 +1,6 @@
package com.eactive.testmaster.socket.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;
import javax.persistence.Column;
import javax.persistence.Entity;
@@ -9,7 +10,6 @@ import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import org.hibernate.annotations.Type;
@Entity
@Table(name = "netty_servers")
@@ -30,11 +30,10 @@ public class NettyServerEntity {
@Lob
private String script;
@Type(type = "org.hibernate.type.LocalDateTimeType")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime createdAt = LocalDateTime.now();
@Type(type = "org.hibernate.type.LocalDateTimeType")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime lastModified = LocalDateTime.now();
// Standard getters and setters
@@ -2,13 +2,12 @@ package com.eactive.testmaster.socket.repository;
import com.eactive.testmaster.socket.entity.NettyServerEntity;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface NettyServerRepository extends JpaRepository<NettyServerEntity, Long>, JpaSpecificationExecutor<NettyServerEntity> {
@@ -0,0 +1,23 @@
package com.eactive.testmaster.user.controller;
import com.eactive.testmaster.common.util.SecurityUtil;
import com.eactive.testmaster.user.entity.User;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AccountApiController {
public AccountApiController() {
}
@GetMapping("/api/account")
@Secured("ROLE_API_TESTER")
public ResponseEntity<User> account(ModelMap model) {
return ResponseEntity.ok().body(SecurityUtil.getCurrentUser());
}
}
@@ -2,9 +2,7 @@ package com.eactive.testmaster.user.controller;
import com.eactive.testmaster.common.util.SecurityUtil;
import com.eactive.testmaster.user.dto.PasswordChangeRequestDTO;
import com.eactive.testmaster.user.entity.User;
import com.eactive.testmaster.user.service.UserService;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
@@ -14,7 +12,6 @@ import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class AccountController {
@@ -29,14 +26,6 @@ public class AccountController {
this.userService = userService;
}
@GetMapping("/api/account")
@ResponseBody
@Secured("ROLE_API_TESTER")
public ResponseEntity<User> account(ModelMap model) {
return ResponseEntity.ok().body(SecurityUtil.getCurrentUser());
}
@GetMapping("/change_password.do")
@Secured("ROLE_API_TESTER")
public String changePassword(@ModelAttribute("passwordChangeRequest") PasswordChangeRequestDTO passwordChangeRequestDTO) {
@@ -0,0 +1,96 @@
package com.eactive.testmaster.user.controller;
import com.eactive.testmaster.common.util.SecurityUtil;
import com.eactive.testmaster.user.dto.StaffPasswordChangeRequestDTO;
import com.eactive.testmaster.user.dto.UserRegisterDTO;
import com.eactive.testmaster.user.dto.UserSearch;
import com.eactive.testmaster.user.dto.UserUpdateDTO;
import com.eactive.testmaster.user.entity.StaffUser;
import com.eactive.testmaster.user.mapper.StaffUserMapper;
import com.eactive.testmaster.user.service.StaffUserService;
import java.util.List;
import javax.validation.Valid;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/users")
public class UserRestController {
private final StaffUserService staffUserService;
private final StaffUserMapper staffUserMapper;
public UserRestController(StaffUserService staffUserService, StaffUserMapper staffUserMapper) {
this.staffUserService = staffUserService;
this.staffUserMapper = staffUserMapper;
}
@GetMapping
@Secured("ROLE_MANAGE_USER")
public ResponseEntity<Page<StaffUser>> listUsers(
@ModelAttribute UserSearch userSearch,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size
) {
Pageable pageable = PageRequest.of(page, size);
Page<StaffUser> users = staffUserService.findAll(userSearch.buildSpecification(), pageable);
return ResponseEntity.ok(users);
}
@GetMapping("/{userId}")
@Secured("ROLE_MANAGE_USER")
public ResponseEntity<StaffUser> getUser(@PathVariable String userId) {
StaffUser user = staffUserService.findById(userId);
return ResponseEntity.ok(user);
}
@PostMapping
@Secured("ROLE_MANAGE_USER")
public ResponseEntity<StaffUser> createUser(@RequestBody @Valid UserRegisterDTO userDTO) {
StaffUser newUser = staffUserMapper.map(userDTO);
StaffUser created = staffUserService.create(newUser);
return ResponseEntity.ok(created);
}
@PostMapping("/update/{userId}")
@Secured("ROLE_MANAGE_USER")
public ResponseEntity<StaffUser> updateUser(
@PathVariable String userId,
@RequestBody @Valid UserUpdateDTO userDTO
) {
StaffUser updatedUser = staffUserMapper.map(userDTO);
StaffUser result = staffUserService.update(userId, updatedUser);
return ResponseEntity.ok(result);
}
@PostMapping("/delete")
@Secured("ROLE_MANAGE_USER")
public ResponseEntity<Void> deleteUsers(@RequestBody List<String> userIds) {
String currentUserId = SecurityUtil.getCurrentUserEsntlId();
userIds.stream()
.filter(id -> !currentUserId.equals(id)) // Exclude current user from deletion
.forEach(staffUserService::deleteById);
return ResponseEntity.ok().build();
}
@PostMapping("/reset-password/{userId}/")
@Secured("ROLE_MANAGE_USER")
public ResponseEntity<Void> resetPassword(
@PathVariable String userId,
@RequestBody @Valid StaffPasswordChangeRequestDTO passwordDTO
) {
staffUserService.updatePassword(userId, passwordDTO.getNewPassword());
return ResponseEntity.ok().build();
}
}
@@ -2,6 +2,7 @@ package com.eactive.testmaster.user.entity;
import com.eactive.testmaster.common.entity.Auditable;
import com.eactive.testmaster.common.entity.EnabledStatus;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
@@ -13,7 +14,6 @@ import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import org.hibernate.annotations.Type;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
@@ -47,11 +47,11 @@ public abstract class User extends Auditable implements Serializable, UserDetail
* 잠금최종시점
*/
@Column(name = "LAST_LOCK_DATE")
@Type(type = "org.hibernate.type.LocalDateTimeType")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime lastLockDate;
@Column(name = "LAST_CHANGE_PASSWORD_DATE")
@Type(type = "org.hibernate.type.LocalDateTimeType")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
private LocalDateTime lastPasswordChangeDate;
@Transient
@@ -30,7 +30,7 @@ public class StaffUserService {
return staffUserRepository.findById(id).orElseThrow(() -> new UserNotFoundException(USER_NOT_FOUND_MESSAGE));
}
public void update(String esntlId, StaffUser user) {
public StaffUser update(String esntlId, StaffUser user) {
StaffUser original = staffUserRepository.findById(esntlId).orElseThrow(() -> new UserNotFoundException(USER_NOT_FOUND_MESSAGE));
original.setUserId(user.getUserId());
original.setMobilePhone(user.getMobilePhone());
@@ -43,6 +43,7 @@ public class StaffUserService {
original.setUserSecurity(user.getUserSecurity());
staffUserRepository.save(original);
return original;
}
public void deleteById(String esntlId) {
@@ -54,7 +55,7 @@ public class StaffUserService {
staffUserRepository.save(user);
}
public void create(StaffUser user) {
public StaffUser create(StaffUser user) {
user.setEsntlId(UUID.randomUUID().toString());
user.setStatus(UserStatus.ACTIVE);
user.setLockAt(EnabledStatus.N);
@@ -62,6 +63,8 @@ public class StaffUserService {
staffUserRepository.save(user);
return user;
}
public void updatePassword(String id, String newPassword) {
@@ -14,7 +14,6 @@ import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;