From aaa0bce1d0e011f36d2fbef9246419e76c28653b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=98=84=EC=84=B1=ED=95=84?= Date: Fri, 31 Jan 2025 14:46:06 +0900 Subject: [PATCH] =?UTF-8?q?api=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/MockRouteRestController.java | 98 ++++++++++++++++ .../testmaster/api/dto/MockResponseDTO.java | 10 ++ .../testmaster/api/dto/MockRouteDTO.java | 75 ++++++++++++ .../testmaster/api/entity/MockResponse.java | 4 + .../testmaster/api/entity/MockRoute.java | 2 + .../api/mapper/MockRouteMapper.java | 3 + .../api/service/MockRouteService.java | 6 +- .../controller/ApiRequestMgmtController.java | 2 +- .../client/entity/ApiRequestHistory.java | 4 +- .../testmaster/common/entity/Auditable.java | 6 +- .../CustomGlobalExceptionHandler.java | 10 ++ .../testmaster/config/DateTimeConfig.java | 84 +++++++++++++ .../QueueHandlerMgmtController.java | 14 ++- .../QueueHandlerRestController.java | 100 ++++++++++++++++ .../controller/ServerRestController.java | 43 ++++++- .../server/service/ServerMgmtService.java | 8 +- .../testmaster/socket/NettyServer.java | 6 +- ...java => NettyTCPServerMgmtController.java} | 6 +- .../NettyTCPServerRestController.java | 110 ++++++++++++++++++ ...rSearch.java => NettyTCPServerSearch.java} | 2 +- .../socket/entity/NettyServerEntity.java | 7 +- .../repository/NettyServerRepository.java | 5 +- .../user/controller/AccountApiController.java | 23 ++++ .../user/controller/AccountController.java | 11 -- .../user/controller/UserRestController.java | 96 +++++++++++++++ .../eactive/testmaster/user/entity/User.java | 6 +- .../user/service/StaffUserService.java | 7 +- .../testmaster/user/service/UserService.java | 1 - 28 files changed, 702 insertions(+), 47 deletions(-) create mode 100644 src/main/java/com/eactive/testmaster/api/controller/MockRouteRestController.java create mode 100644 src/main/java/com/eactive/testmaster/api/dto/MockRouteDTO.java create mode 100644 src/main/java/com/eactive/testmaster/config/DateTimeConfig.java create mode 100644 src/main/java/com/eactive/testmaster/queue/controller/QueueHandlerRestController.java rename src/main/java/com/eactive/testmaster/socket/controller/{NettyServerController.java => NettyTCPServerMgmtController.java} (97%) create mode 100644 src/main/java/com/eactive/testmaster/socket/controller/NettyTCPServerRestController.java rename src/main/java/com/eactive/testmaster/socket/controller/{NettyServerSearch.java => NettyTCPServerSearch.java} (92%) create mode 100644 src/main/java/com/eactive/testmaster/user/controller/AccountApiController.java create mode 100644 src/main/java/com/eactive/testmaster/user/controller/UserRestController.java diff --git a/src/main/java/com/eactive/testmaster/api/controller/MockRouteRestController.java b/src/main/java/com/eactive/testmaster/api/controller/MockRouteRestController.java new file mode 100644 index 0000000..ff1f62e --- /dev/null +++ b/src/main/java/com/eactive/testmaster/api/controller/MockRouteRestController.java @@ -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> 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 routes = mockRouteService.findAll(search.buildSpecification(), pageable); + Page dtoPage = routes.map(mockRouteMapper::mapRoute); + + return ResponseEntity.ok(dtoPage); + } + + @GetMapping("/{id}") + public ResponseEntity getMockRoute(@PathVariable Long id) { + MockRoute mockRoute = mockRouteService.findById(id); + return ResponseEntity.ok(mockRoute); + } + + @PostMapping + public ResponseEntity 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 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 deleteMockRoutes(@RequestBody List ids) { + for (Long id : ids) { + MockRoute mockRoute = mockRouteService.findById(id); + mockApiHandlerMapping.unregisterMapping(mockRoute); + mockRouteService.deleteById(id); + } + mockRouteService.initAllRoutes(); + return ResponseEntity.ok().build(); + } + + +} diff --git a/src/main/java/com/eactive/testmaster/api/dto/MockResponseDTO.java b/src/main/java/com/eactive/testmaster/api/dto/MockResponseDTO.java index a4d3109..caa1b4d 100644 --- a/src/main/java/com/eactive/testmaster/api/dto/MockResponseDTO.java +++ b/src/main/java/com/eactive/testmaster/api/dto/MockResponseDTO.java @@ -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; } diff --git a/src/main/java/com/eactive/testmaster/api/dto/MockRouteDTO.java b/src/main/java/com/eactive/testmaster/api/dto/MockRouteDTO.java new file mode 100644 index 0000000..255c8f5 --- /dev/null +++ b/src/main/java/com/eactive/testmaster/api/dto/MockRouteDTO.java @@ -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 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 getResponses() { + return responses; + } + + public void setResponses(List responses) { + this.responses = responses; + } +} diff --git a/src/main/java/com/eactive/testmaster/api/entity/MockResponse.java b/src/main/java/com/eactive/testmaster/api/entity/MockResponse.java index a34257b..38c4c02 100644 --- a/src/main/java/com/eactive/testmaster/api/entity/MockResponse.java +++ b/src/main/java/com/eactive/testmaster/api/entity/MockResponse.java @@ -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; } + + } diff --git a/src/main/java/com/eactive/testmaster/api/entity/MockRoute.java b/src/main/java/com/eactive/testmaster/api/entity/MockRoute.java index c2c640c..d9dd685 100644 --- a/src/main/java/com/eactive/testmaster/api/entity/MockRoute.java +++ b/src/main/java/com/eactive/testmaster/api/entity/MockRoute.java @@ -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 responses = new ArrayList<>(); diff --git a/src/main/java/com/eactive/testmaster/api/mapper/MockRouteMapper.java b/src/main/java/com/eactive/testmaster/api/mapper/MockRouteMapper.java index 8af9cdb..efecd8c 100644 --- a/src/main/java/com/eactive/testmaster/api/mapper/MockRouteMapper.java +++ b/src/main/java/com/eactive/testmaster/api/mapper/MockRouteMapper.java @@ -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") diff --git a/src/main/java/com/eactive/testmaster/api/service/MockRouteService.java b/src/main/java/com/eactive/testmaster/api/service/MockRouteService.java index af723a1..6bf3354 100644 --- a/src/main/java/com/eactive/testmaster/api/service/MockRouteService.java +++ b/src/main/java/com/eactive/testmaster/api/service/MockRouteService.java @@ -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() { diff --git a/src/main/java/com/eactive/testmaster/client/controller/ApiRequestMgmtController.java b/src/main/java/com/eactive/testmaster/client/controller/ApiRequestMgmtController.java index 22ebf4b..da6d2cd 100644 --- a/src/main/java/com/eactive/testmaster/client/controller/ApiRequestMgmtController.java +++ b/src/main/java/com/eactive/testmaster/client/controller/ApiRequestMgmtController.java @@ -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; diff --git a/src/main/java/com/eactive/testmaster/client/entity/ApiRequestHistory.java b/src/main/java/com/eactive/testmaster/client/entity/ApiRequestHistory.java index 9eea350..3604566 100644 --- a/src/main/java/com/eactive/testmaster/client/entity/ApiRequestHistory.java +++ b/src/main/java/com/eactive/testmaster/client/entity/ApiRequestHistory.java @@ -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() { diff --git a/src/main/java/com/eactive/testmaster/common/entity/Auditable.java b/src/main/java/com/eactive/testmaster/common/entity/Auditable.java index 77f9349..8e42675 100644 --- a/src/main/java/com/eactive/testmaster/common/entity/Auditable.java +++ b/src/main/java/com/eactive/testmaster/common/entity/Auditable.java @@ -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; /** diff --git a/src/main/java/com/eactive/testmaster/common/exception/CustomGlobalExceptionHandler.java b/src/main/java/com/eactive/testmaster/common/exception/CustomGlobalExceptionHandler.java index 88d3a5a..db3a294 100644 --- a/src/main/java/com/eactive/testmaster/common/exception/CustomGlobalExceptionHandler.java +++ b/src/main/java/com/eactive/testmaster/common/exception/CustomGlobalExceptionHandler.java @@ -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 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); + } + } diff --git a/src/main/java/com/eactive/testmaster/config/DateTimeConfig.java b/src/main/java/com/eactive/testmaster/config/DateTimeConfig.java new file mode 100644 index 0000000..96579f0 --- /dev/null +++ b/src/main/java/com/eactive/testmaster/config/DateTimeConfig.java @@ -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; + } +} diff --git a/src/main/java/com/eactive/testmaster/queue/controller/QueueHandlerMgmtController.java b/src/main/java/com/eactive/testmaster/queue/controller/QueueHandlerMgmtController.java index 4bed7f9..730b3d8 100644 --- a/src/main/java/com/eactive/testmaster/queue/controller/QueueHandlerMgmtController.java +++ b/src/main/java/com/eactive/testmaster/queue/controller/QueueHandlerMgmtController.java @@ -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") diff --git a/src/main/java/com/eactive/testmaster/queue/controller/QueueHandlerRestController.java b/src/main/java/com/eactive/testmaster/queue/controller/QueueHandlerRestController.java new file mode 100644 index 0000000..4fc2cc5 --- /dev/null +++ b/src/main/java/com/eactive/testmaster/queue/controller/QueueHandlerRestController.java @@ -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> listQueueHandlers( + @ModelAttribute QueueHandlerSearch queueHandlerSearch, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size) { + + Pageable pageable = PageRequest.of(page, size); + Page handlers = queueHandlerService.findAll(queueHandlerSearch.buildSpecification(), pageable); + Page dtoPage = handlers.map(queueHandlerMapper::map); + + return ResponseEntity.ok(dtoPage); + } + + @GetMapping("/{id}") + public ResponseEntity getQueueHandler(@PathVariable String id) { + QueueHandler queueHandler = queueHandlerService.findById(id); + return ResponseEntity.ok(queueHandler); + } + + @PostMapping + public ResponseEntity 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 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 deleteQueueHandlers(@RequestBody List ids) { + for (String id : ids) { + queueHandlerService.deleteById(id); + } + queueHandlerService.initAllQueues(); + return ResponseEntity.ok().build(); + } + + @PostMapping("/{id}/start") + public ResponseEntity startQueue(@PathVariable String id) { + QueueHandler queueHandler = queueHandlerService.findById(id); + dynamicQueueManager.startQueueListener(queueHandler); + return ResponseEntity.ok().build(); + } + + @PostMapping("/{id}/stop") + public ResponseEntity stopQueue(@PathVariable String id) { + QueueHandler queueHandler = queueHandlerService.findById(id); + dynamicQueueManager.stopQueueListener(queueHandler.getQueueName()); + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/com/eactive/testmaster/server/controller/ServerRestController.java b/src/main/java/com/eactive/testmaster/server/controller/ServerRestController.java index c72cc40..5ae0a9f 100644 --- a/src/main/java/com/eactive/testmaster/server/controller/ServerRestController.java +++ b/src/main/java/com/eactive/testmaster/server/controller/ServerRestController.java @@ -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> listServers( + @ModelAttribute ServerSearch serverSearch, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size + ) { + Pageable pageable = PageRequest.of(page, size); + Page servers = serverMgmtService.findAll(serverSearch.buildSpecification(), pageable); + + return ResponseEntity.ok(servers.map(serverMapper::map)); + } + + + @PostMapping + @Secured("ROLE_MANAGE_SERVER") + public ResponseEntity 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 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 deleteServers(@RequestBody List ids) { + for (Long id : ids) { + serverMgmtService.delete(id); + } + return ResponseEntity.ok().build(); + } } diff --git a/src/main/java/com/eactive/testmaster/server/service/ServerMgmtService.java b/src/main/java/com/eactive/testmaster/server/service/ServerMgmtService.java index f6f1867..3f6c61d 100644 --- a/src/main/java/com/eactive/testmaster/server/service/ServerMgmtService.java +++ b/src/main/java/com/eactive/testmaster/server/service/ServerMgmtService.java @@ -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) { diff --git a/src/main/java/com/eactive/testmaster/socket/NettyServer.java b/src/main/java/com/eactive/testmaster/socket/NettyServer.java index 0d75b4c..eb714bf 100644 --- a/src/main/java/com/eactive/testmaster/socket/NettyServer.java +++ b/src/main/java/com/eactive/testmaster/socket/NettyServer.java @@ -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; diff --git a/src/main/java/com/eactive/testmaster/socket/controller/NettyServerController.java b/src/main/java/com/eactive/testmaster/socket/controller/NettyTCPServerMgmtController.java similarity index 97% rename from src/main/java/com/eactive/testmaster/socket/controller/NettyServerController.java rename to src/main/java/com/eactive/testmaster/socket/controller/NettyTCPServerMgmtController.java index 3171518..7786391 100644 --- a/src/main/java/com/eactive/testmaster/socket/controller/NettyServerController.java +++ b/src/main/java/com/eactive/testmaster/socket/controller/NettyTCPServerMgmtController.java @@ -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 page = nettyServerService.findAll(serverSearch.buildSpecification(), pageable); diff --git a/src/main/java/com/eactive/testmaster/socket/controller/NettyTCPServerRestController.java b/src/main/java/com/eactive/testmaster/socket/controller/NettyTCPServerRestController.java new file mode 100644 index 0000000..7a1db5c --- /dev/null +++ b/src/main/java/com/eactive/testmaster/socket/controller/NettyTCPServerRestController.java @@ -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> listNettyServers( + @ModelAttribute("serverSearch") NettyTCPServerSearch serverSearch, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size + ) { + Pageable pageable = PageRequest.of(page, size); + Page servers = nettyServerService.findAll(serverSearch.buildSpecification(), pageable); + return ResponseEntity.ok(servers); + } + + @PostMapping + @Secured("ROLE_MANAGE_NETTY") + public ResponseEntity 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 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 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 deleteTCPServer(@RequestBody List ids) throws InterruptedException { + for (Long id : ids) { + nettyServerService.deleteServer(id); + } + return ResponseEntity.ok().build(); + } + + @PostMapping("/{id}/start") + @Secured("ROLE_MANAGE_NETTY") + public ResponseEntity 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 stopServer(@PathVariable Long id) { + try { + nettyServerService.stopServer(id); + return ResponseEntity.ok().build(); + } catch (Exception e) { + return ResponseEntity.internalServerError().build(); + } + } +} diff --git a/src/main/java/com/eactive/testmaster/socket/controller/NettyServerSearch.java b/src/main/java/com/eactive/testmaster/socket/controller/NettyTCPServerSearch.java similarity index 92% rename from src/main/java/com/eactive/testmaster/socket/controller/NettyServerSearch.java rename to src/main/java/com/eactive/testmaster/socket/controller/NettyTCPServerSearch.java index 48b02d0..f4c9915 100644 --- a/src/main/java/com/eactive/testmaster/socket/controller/NettyServerSearch.java +++ b/src/main/java/com/eactive/testmaster/socket/controller/NettyTCPServerSearch.java @@ -8,7 +8,7 @@ import com.eactive.testmaster.socket.entity.NettyServerEntity; import java.util.ArrayList; import java.util.List; -public class NettyServerSearch implements BaseSearch { +public class NettyTCPServerSearch implements BaseSearch { private String name; private Long port; diff --git a/src/main/java/com/eactive/testmaster/socket/entity/NettyServerEntity.java b/src/main/java/com/eactive/testmaster/socket/entity/NettyServerEntity.java index 890421b..9364945 100644 --- a/src/main/java/com/eactive/testmaster/socket/entity/NettyServerEntity.java +++ b/src/main/java/com/eactive/testmaster/socket/entity/NettyServerEntity.java @@ -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 diff --git a/src/main/java/com/eactive/testmaster/socket/repository/NettyServerRepository.java b/src/main/java/com/eactive/testmaster/socket/repository/NettyServerRepository.java index fff5d21..0e5b24f 100644 --- a/src/main/java/com/eactive/testmaster/socket/repository/NettyServerRepository.java +++ b/src/main/java/com/eactive/testmaster/socket/repository/NettyServerRepository.java @@ -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, JpaSpecificationExecutor { diff --git a/src/main/java/com/eactive/testmaster/user/controller/AccountApiController.java b/src/main/java/com/eactive/testmaster/user/controller/AccountApiController.java new file mode 100644 index 0000000..6db819d --- /dev/null +++ b/src/main/java/com/eactive/testmaster/user/controller/AccountApiController.java @@ -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 account(ModelMap model) { + return ResponseEntity.ok().body(SecurityUtil.getCurrentUser()); + } + +} diff --git a/src/main/java/com/eactive/testmaster/user/controller/AccountController.java b/src/main/java/com/eactive/testmaster/user/controller/AccountController.java index 4fe7d2f..e33419d 100644 --- a/src/main/java/com/eactive/testmaster/user/controller/AccountController.java +++ b/src/main/java/com/eactive/testmaster/user/controller/AccountController.java @@ -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 account(ModelMap model) { - return ResponseEntity.ok().body(SecurityUtil.getCurrentUser()); - } - - @GetMapping("/change_password.do") @Secured("ROLE_API_TESTER") public String changePassword(@ModelAttribute("passwordChangeRequest") PasswordChangeRequestDTO passwordChangeRequestDTO) { diff --git a/src/main/java/com/eactive/testmaster/user/controller/UserRestController.java b/src/main/java/com/eactive/testmaster/user/controller/UserRestController.java new file mode 100644 index 0000000..f726339 --- /dev/null +++ b/src/main/java/com/eactive/testmaster/user/controller/UserRestController.java @@ -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> listUsers( + @ModelAttribute UserSearch userSearch, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size + ) { + Pageable pageable = PageRequest.of(page, size); + Page users = staffUserService.findAll(userSearch.buildSpecification(), pageable); + return ResponseEntity.ok(users); + } + + @GetMapping("/{userId}") + @Secured("ROLE_MANAGE_USER") + public ResponseEntity getUser(@PathVariable String userId) { + StaffUser user = staffUserService.findById(userId); + return ResponseEntity.ok(user); + } + + @PostMapping + @Secured("ROLE_MANAGE_USER") + public ResponseEntity 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 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 deleteUsers(@RequestBody List 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 resetPassword( + @PathVariable String userId, + @RequestBody @Valid StaffPasswordChangeRequestDTO passwordDTO + ) { + staffUserService.updatePassword(userId, passwordDTO.getNewPassword()); + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/com/eactive/testmaster/user/entity/User.java b/src/main/java/com/eactive/testmaster/user/entity/User.java index 75783f2..3c7e67c 100644 --- a/src/main/java/com/eactive/testmaster/user/entity/User.java +++ b/src/main/java/com/eactive/testmaster/user/entity/User.java @@ -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 diff --git a/src/main/java/com/eactive/testmaster/user/service/StaffUserService.java b/src/main/java/com/eactive/testmaster/user/service/StaffUserService.java index be88d0a..1bb7885 100644 --- a/src/main/java/com/eactive/testmaster/user/service/StaffUserService.java +++ b/src/main/java/com/eactive/testmaster/user/service/StaffUserService.java @@ -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) { diff --git a/src/main/java/com/eactive/testmaster/user/service/UserService.java b/src/main/java/com/eactive/testmaster/user/service/UserService.java index 9b092d6..15298c8 100644 --- a/src/main/java/com/eactive/testmaster/user/service/UserService.java +++ b/src/main/java/com/eactive/testmaster/user/service/UserService.java @@ -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;