This commit is contained in:
2025-07-02 21:55:07 +09:00
commit fa63330e69
855 changed files with 432271 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
package com.kospo.talk;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.servers.Server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
@OpenAPIDefinition(servers = {
@Server(url = "http://localhost:8010", description = "로컬 api"),
})
@EnableScheduling
@SpringBootApplication
@EnableWebSocket
public class ChatApplication {
public static void main(String[] args) {
SpringApplication.run(ChatApplication.class, args);
}
}

View File

@@ -0,0 +1,21 @@
package com.kospo.talk.config.exception;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
@Schema(name="errorResponse", description = "오류")
public class CustomErrorResponse {
@Schema(name="code", description = "오류 코드", example = "30000")
private String code;
@Schema(name="message", description = "오류 메시지", example = "오류 발생")
private String message;
@Schema(name="errTime", description = "오류 시간", example = "1761000247")
private long errTime;
}

View File

@@ -0,0 +1,98 @@
package com.kospo.talk.config.exception;
import com.kospo.talk.exception.CustomException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import java.util.Date;
@Slf4j
@ControllerAdvice
@Controller
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
public static final String ANSI_RESET = "\u001B[0m";
public static final String ANSI_YELLOW_COLOR = "\u001B[33m";
@ExceptionHandler(CustomException.class)
@ResponseBody
public ResponseEntity customException(CustomException e, HandlerMethod method, HttpServletRequest request, WebRequest webRequest) {
Date errorDate = new Date();
String exceptionName = e.getClass().getSimpleName();
String controllerName = method.getMethod().getDeclaringClass().getSimpleName();
String methodName = method.getMethod().getName();
int lineNumber = e.getStackTrace()[0].getLineNumber();
String detail = e.getMessage();
String requestURI = request.getRequestURI();
log.error(ANSI_YELLOW_COLOR + "[EVENT_TIME: {} | CONTROLLER_NAME : {} | METHOD_NAME : {} | EXCEPTION_LINE : {} | EXCEPTION_NAME : {} | DETAIL : {} | REQUEST_URI : {}]" + ANSI_RESET
, errorDate
, controllerName
, methodName
, lineNumber
, exceptionName
, detail
, requestURI);
HttpHeaders resHeaders = new HttpHeaders();
resHeaders.add("Content-Type", "application/json;charset=UTF-8");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(resHeaders).body(
CustomErrorResponse.builder()
.code(e.getErrorCode().getCode())
.message(e.getErrorCode().getMessage())
.errTime(System.currentTimeMillis()).build()
);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<?> handleException(Exception e, HandlerMethod method, HttpServletRequest request, WebRequest webRequest) {
// Date errorDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime());
Date errorDate = new Date();
String exceptionName = e.getClass().getSimpleName();
String controllerName = method.getMethod().getDeclaringClass().getSimpleName();
String methodName = method.getMethod().getName();
int lineNumber = e.getStackTrace()[0].getLineNumber();
String detail = e.getMessage();
String requestURI = request.getRequestURI();
log.error(ANSI_YELLOW_COLOR + "[EVENT_TIME: {} | CONTROLLER_NAME : {} | METHOD_NAME : {} | EXCEPTION_LINE : {} | EXCEPTION_NAME : {} | DETAIL : {} | REQUEST_URI : {}]" + ANSI_RESET
, errorDate
, controllerName
, methodName
, lineNumber
, exceptionName
, detail
, requestURI);
HttpHeaders resHeaders = new HttpHeaders();
resHeaders.add("Content-Type", "application/json;charset=UTF-8");
return ResponseEntity.status(500).headers(resHeaders).body(
CustomErrorResponse.builder()
.code(ErrorCode.INTERNAL_SERVER_ERROR.getCode())
.message(ErrorCode.INTERNAL_SERVER_ERROR.getMessage())
.errTime(System.currentTimeMillis()).build()
);
}
}

View File

@@ -0,0 +1,35 @@
package com.kospo.talk.config.exception;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum ErrorCode {
/*토큰 관련*/
EXPIRE_TOKEN("30000", "토큰이 만료 되었습니다."),
MALFORMED_JWT("30001", "JWT 문자열은 정확히 2개의 마침표 문자를 포함해야 합니다."),
/*bad request*/
BIND_ERROR("40001", "파라미터를 다시 확인해주세요."),
/*존재 하지 않음*/
NO_RESULT("44001", "존재하지 않는 데이터 입니다."),
NO_ACCOUNT("44011", "아이디 또는 비밀번호를 다시 확인해주세요."),
NO_MATCH_ACCOUNT("44012", "일치하는 사용자가 없습니다."),
NO_TOKEN("44021", "헤더에 토큰이 없습니다."),
NO_MATCH_TOKEN("44022", "일치 하지 않는 토큰입니다."),
NO_SAME_IP("44030", "등록된 아이피와 일치 하지 않습니다. 다시 로그인 해주세요"),
NO_SAME_DATA("44031", "사용자가 소유한 데이터가 아닙니다."),
/*권한 관련*/
AUTHENTICATION("43000", "사용자가 정보가 일치하지 않습니다."),
AUTHENTICATION_NOT_SUPPORT("43001", "허용되지 않은 사용자입니다."),
//500 INTERNAL SERVER ERROR
INTERNAL_SERVER_ERROR("50000", "서버 에러입니다. 유지보수관리자에게 연락주세요!"),
EXCEL_UPLOAD_ERROR("50001", "엑셀파일이 정상적이지 않습니다. 확인해주세요"),
NO_SIGNAL("90000", "응답 코드가 없습니다."),
NO_EXIST_TALK_START("10000", "톡 멤버에 존재 하지 않는 사용자는 톡방을 시작할수 없어요."),
NO_EXIST_TALK_CLOSE("10001", "톡 멤버에 존재 하지 않는 사용자는 톡방을 종료할수 없어요."),
/*파일오류*/
INVALID_FILE("10000", "허용되지 않는 파일");
private final String code;
private final String message;
}

View File

@@ -0,0 +1,34 @@
package com.kospo.talk.config.filter;
import com.kospo.talk.service.UserService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
@Configuration
@RequiredArgsConstructor
public class AuthenticationFilter extends OncePerRequestFilter {
private final UserService userService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
/*sso 로그인 추가*/
filterChain.doFilter(request, response);
}
private static String decodeCredentials(String credentials) {
return new String(java.util.Base64.getDecoder().decode(credentials.getBytes()));
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,407 @@
package com.kospo.talk.config.filter;
import com.initech.eam.api.NXContext;
import com.initech.eam.api.NXUserAPI;
import com.initech.eam.nls.CookieManager;
import com.initech.eam.smartenforcer.SECode;
import com.kospo.talk.config.utils.CryptoUtil;
import com.kospo.talk.model.User;
import com.kospo.talk.repository.UserRepository;
import jakarta.servlet.FilterChain;
//import jakarta.servlet.ServletException;
//import jakarta.servlet.http.HttpServletRequest;
//import jakarta.servlet.http.HttpServletResponse;
//import jakarta.servlet.http.HttpSession;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import javax.security.sasl.AuthenticationException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
@Slf4j
public class CustomBasicAuthenticationFilter extends BasicAuthenticationFilter {
private UserRepository userRepository;
private static final String SERVICE_NAME = "kdems";
/**
* ep url : 남부발전 POTAL SITE
*/
private static final String EP_URL = "http://ep.kospo.co.kr/irj/portal";
/**
* domain_name : 남부발전
*/
private static final String DOMAIN_NAME = SERVICE_NAME + ".kospo.co.kr";
/**
* domain_port : 남부발전 포트
*/
private static final String DOMAIN_PORT = "80";
/**
* server url : 해당 Application의 URL --> 업무시스템에 맞게 URL 수정!
*/
private static final String SERVER_URL = "http://" + DOMAIN_NAME;
/**
* ASCP(로그인후 리다이렉트 페이지) --> 설치한 경로에 맞게 수정!
*/
private static final String ASCP_URL = SERVER_URL + ":" + DOMAIN_PORT + "/";
private static final String custom_url = "";
/**
* nls url
*/
private static final String NLS_URL = "http://sso.kospo.co.kr";
/**
* nls port
*/
private static final String NLS_PORT = "8011";
/**
* 로그인을 위해서 NLS로 redirect할 URL (fail-over는 L4)
*/
private static final String NLS_LOGIN_URL = NLS_URL + ":" + NLS_PORT + "/nls3/clientLogin.jsp";
private String NLS_LOGOUT_URL = NLS_URL + ":" + NLS_PORT + "/nls3/NCLogout.jsp";
/**
* 에러 페이지 URL
*/
private static final String NLS_ERROR_URL = NLS_URL + ":" + NLS_PORT + "/nls3/error.jsp";
/**
* Nexess API가 사용할 Nexess Daemon의 주소
*/
private static final String ND_URL = "http://sso.kospo.co.kr:5480";
private static final String ND_URL1 = "http://sso.kospo.co.kr:5480";
private static Vector PROVIDER_LIST = new Vector();
private static final int COOKIE_SESSTION_TIME_OUT = 3000000;
/**
* 인증 타입 (ID/PW 방식 : 1, 인증서 방식 : 3)
*/
private static final String TOA = "1";
/**
* domain (.mento.com) --> 해당 Domain 맞게 수정!
*/
private static final String SSO_DOMAIN = ".kospo.co.kr";
private static final int timeout = 15000;
private static NXContext context = null;
public CustomBasicAuthenticationFilter(AuthenticationManager authenticationManager, UserRepository userRepository) {
super(authenticationManager);
this.userRepository = userRepository;
}
static {
//PropertyConfigurator.configureAndWatch("D:/INISafeNexess/site/4.1.0/src/Web/WebContent/WEB-INF/logger.properties");
List<String> serverurlList = new ArrayList<>();
serverurlList.add(ND_URL1);
//serverurlList.add(ND_URL2);
context = new NXContext(serverurlList, timeout);
CookieManager.setEncStatus(true);
// CookieManager.setSameSiteStatus(false);
//7-1. 테스트 시 sso로 테스트 할 경우
// PROVIDER_LIST.add("sso.kospo.co.kr");
//7-2. 운영에 배포할 때
PROVIDER_LIST.add("sso1.kospo.co.kr");
PROVIDER_LIST.add("sso2.kospo.co.kr");
//NLS3 web.xml의 CookiePadding 값과 같아야 한다. 안그럼 검증 페일남
//InitechEamUID +"_V42" .... 형태로 쿠명 생성됨
SECode.setCookiePadding("_V42");
}
public NXContext getContext() {
NXContext context = null;
try {
List serverurlList = new ArrayList();
serverurlList.add(ND_URL1);
context = new NXContext(serverurlList);
} catch (Exception e) {
log.error(e.getMessage());
}
return context;
}
public String getSsoId(jakarta.servlet.http.HttpServletRequest request) {
String sso_id = getCookieValue(SECode.USER_ID, request);
return sso_id;
}
public static String getCookieValue(String cookieName, jakarta.servlet.http.HttpServletRequest request) {
try {
Cookie[] cookies = request.getCookies();
if (cookies == null) {
return null;
} else {
String cookieValue = null;
for(int i = 0; i < cookies.length; ++i) {
Cookie cookieInfo = cookies[i];
if (cookieInfo.getName().equals(cookieName)) {
if (!CookieManager.getEncStatus() || !cookieName.equals(SECode.USER_ID) && !cookieName.equals(SECode.USER_IP) && !cookieName.equals(SECode.USER_PID)) {
cookieValue = cookieInfo.getValue();
if (cookieValue != null) {
cookieValue = URLDecoder.decode(cookieValue);
}
} else {
cookieValue = CookieManager.decryptWithSEED(URLDecoder.decode(cookieInfo.getValue()));
}
return cookieValue;
}
}
return cookieValue;
}
} catch (Exception e) {
log.error("", e);
return "";
}
}
public boolean AppAduditLog(HttpServletRequest request, String retCode) throws Exception {
boolean ret = false;
String sso_id = getSsoId(request);
String sso_ip = null;
String sso_mac = null;
String sso_toa = null;
String retValue = null;
NXContext context = null;
NXUserAPI nx_userapi = null;
try {
if (context == null)
context = getContext();
nx_userapi = new NXUserAPI(context);
sso_id = CookieManager.encryptWithSEED(sso_id);
sso_ip = CookieManager.getCookieValue("InitechEamClientip", request);
sso_toa = CookieManager.getCookieValue(SECode.USER_TOA, request);
sso_mac = CookieManager.getCookieValue("InitechEamClientmac", request);
System.out.println("MAC" + sso_mac);
System.out.println(sso_ip);
if (!retCode.equals("0"))
retValue = "1";
else
retValue = "0";
ret = nx_userapi.setAccessHistory(SERVICE_NAME, sso_mac, sso_ip, sso_id, sso_toa, retValue, retCode);
if (ret)
ret = true;
} catch (Exception e) {
log.error(e.getMessage());
return ret;
}
return ret;
}
// 통합인증 세션을 체크 하기 위하여 사용되는 API
public String getEamSessionCheck(HttpServletRequest request, HttpServletResponse response) {
String retCode = "";
try {
retCode = CookieManager.verifyNexessCookie(request, response, 10, COOKIE_SESSTION_TIME_OUT, PROVIDER_LIST);
} catch (Exception npe) {
log.error(npe.getMessage());
}
return retCode;
}
private Boolean getEamSessionCheckIP(HttpServletRequest request) throws Exception {
String clientIP = request.getHeader("X-Forwarded-For");
if (clientIP == null || clientIP.length() < 1 || "unknown".equalsIgnoreCase(clientIP)) {
clientIP = request.getRemoteAddr();
}
String sso_uip = CookieManager.getCookieValue(SECode.USER_IP, request);
log.debug("*================== clientIP: " + clientIP + ", ssoUIP: " + sso_uip);
if (!(clientIP.equals(sso_uip))) {
return false;
}
return true;
}
public String getEamSessionCheckAndAgentValid(HttpServletRequest request, HttpServletResponse response) {
String retCode = "";
try {
Boolean result = getEamSessionCheckIP(request);
if (result == true) {
retCode = CookieManager.verifyNexessCookieAndAgentVaild(request, response, 10,
COOKIE_SESSTION_TIME_OUT, PROVIDER_LIST, SERVER_URL, context);
} else {
//쿠키값 전체를 탈취해 로그인 시도한 경우
retCode = "1004";
}
} catch (Exception npe) {
log.error(npe.getMessage());
return "5451";
}
return retCode;
}
public void goErrorPage(HttpServletResponse response, int error_code) throws Exception {
CookieManager.removeNexessCookie(SSO_DOMAIN, response);
CookieManager.addCookie(SECode.USER_URL, ASCP_URL, SSO_DOMAIN, response);
response.sendRedirect(NLS_ERROR_URL + "?errorCode=" + error_code);
}
public void goLoginPage(HttpServletResponse response) throws Exception {
CookieManager.addCookie(SECode.USER_URL, ASCP_URL, SSO_DOMAIN, response);
CookieManager.addCookie(SECode.R_TOA, TOA, SSO_DOMAIN, response);
//자체 로그인을 할경우 로그인 페이지 Setting
if (custom_url.equals("")) {
CookieManager.addCookie("CLP", "", SSO_DOMAIN, response);
} else {
CookieManager.addCookie("CLP", custom_url, SSO_DOMAIN, response);
}
// response.sendRedirect(NLS_LOGIN_URL);
}
@Override
protected void doFilterInternal(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
// log.info("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★" + request.getRequestURI());
// System.out.println("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★" + request.getRequestURI());
jakarta.servlet.http.HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
String sso_sabun = "";
boolean isSso = true;
try {
if (sso_sabun == null || sso_sabun.isEmpty()) {
sso_sabun = request.getHeader("Authentication");
if(sso_sabun != null) sso_sabun = CryptoUtil.decrypt(sso_sabun);
// System.out.println("header : " + sso_sabun);
}
} catch(Exception e) {
new RuntimeException(e);
}
try {
if (sso_sabun == null || sso_sabun.isEmpty()) {
sso_sabun = request.getParameter("Authentication");
if(sso_sabun != null) sso_sabun = CryptoUtil.decrypt(sso_sabun);
// System.out.println("request : " + sso_sabun);
}
} catch(Exception e) {
new RuntimeException(e);
}
isSso = sso_sabun == null || sso_sabun.equals("");
if(!isSso) user = null;
/* SSO 인증 부분 */
if (user == null) {
/*sso 인증 개발시 header 정보에 사번 추가 하여 테스트*/
if(isSso) {
sso_sabun = getSsoId(request);
// System.out.println("sso : " + sso_sabun);
}
user = userRepository.findBySabun(sso_sabun);
if(user != null) {
Authentication authentication = null;
try {
if (user.getAuthorities() == null) {
authentication = new UsernamePasswordAuthenticationToken(user, null, Arrays.asList(new SimpleGrantedAuthority("ROLE_DEFAULT")));
} else {
authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
}
} catch(Exception e) {
authentication = new UsernamePasswordAuthenticationToken(user, null, Arrays.asList(new SimpleGrantedAuthority("ROLE_DEFAULT")));
}
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
securityContext.setAuthentication(authentication);
SecurityContextHolder.setContext(securityContext);
SecurityContextHolder.getContext().getAuthentication();
session.setAttribute("user", user);
}
} else {
Authentication getAuth = SecurityContextHolder.getContext().getAuthentication();
if (getAuth == null) {
Authentication authentication = null;
try {
if (user.getAuthorities() == null) {
authentication = new UsernamePasswordAuthenticationToken(user, null, Arrays.asList(new SimpleGrantedAuthority("ROLE_DEFAULT")));
} else {
authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
}
} catch(Exception e) {
authentication = new UsernamePasswordAuthenticationToken(user, null, Arrays.asList(new SimpleGrantedAuthority("ROLE_DEFAULT")));
}
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
securityContext.setAuthentication(authentication);
SecurityContextHolder.setContext(securityContext);
SecurityContextHolder.getContext().getAuthentication();
}
}
chain.doFilter(request, response);
/*추후 적용 필요 할수도 잇음*/
// SecurityContextHolder.clearContext();
}
public CustomBasicAuthenticationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
public CustomBasicAuthenticationFilter(AuthenticationManager authenticationManager, AuthenticationEntryPoint authenticationEntryPoint) {
super(authenticationManager, authenticationEntryPoint);
}
}

View File

@@ -0,0 +1,18 @@
package com.kospo.talk.config.filter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;
public class LoggingFilter extends Filter<ILoggingEvent> {
@Override
public FilterReply decide(ILoggingEvent iLoggingEvent) {
if(iLoggingEvent.getMessage().contains("locale")) {
return FilterReply.DENY;
} else {
return FilterReply.ACCEPT;
}
}
}

View File

@@ -0,0 +1,104 @@
package com.kospo.talk.config.filter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.config.exception.ErrorCode;
import com.kospo.talk.exception.*;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
public class SecurityExceptionFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException {
ObjectMapper om = new ObjectMapper();
try {
filterChain.doFilter(request, response);
} catch (CustomExpireTokenException e) {
response.setStatus(500);
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(
om.writeValueAsString(CustomErrorResponse.builder()
.code(ErrorCode.EXPIRE_TOKEN.getCode())
.message(ErrorCode.EXPIRE_TOKEN.getMessage())
.errTime(System.currentTimeMillis()).build())
);
} catch (CustomNoAccountException e) {
response.setStatus(500);
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(
om.writeValueAsString(CustomErrorResponse.builder()
.code(ErrorCode.NO_ACCOUNT.getCode())
.message(ErrorCode.NO_ACCOUNT.getMessage())
.errTime(System.currentTimeMillis()).build())
);
} catch (CustomNoMatchTokenException e) {
response.setStatus(500);
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(
om.writeValueAsString(CustomErrorResponse.builder()
.code(ErrorCode.NO_MATCH_TOKEN.getCode())
.message(ErrorCode.NO_MATCH_TOKEN.getMessage())
.errTime(System.currentTimeMillis()).build())
);
} catch (CustomNoResultException e) {
response.setStatus(500);
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(
om.writeValueAsString(CustomErrorResponse.builder()
.code(ErrorCode.NO_RESULT.getCode())
.message(ErrorCode.NO_RESULT.getMessage())
.errTime(System.currentTimeMillis()).build())
);
} catch (CustomNoTokenException e) {
response.setStatus(500);
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(
om.writeValueAsString(CustomErrorResponse.builder()
.code(ErrorCode.NO_TOKEN.getCode())
.message(ErrorCode.NO_TOKEN.getMessage())
.errTime(System.currentTimeMillis()).build())
);
} catch (ServletException e) {
response.setStatus(500);
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(
om.writeValueAsString(CustomErrorResponse.builder()
.code(ErrorCode.INTERNAL_SERVER_ERROR.getCode())
.message(ErrorCode.INTERNAL_SERVER_ERROR.getMessage())
.errTime(System.currentTimeMillis()).build())
);
} catch (IOException e) {
response.setStatus(500);
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(
om.writeValueAsString(CustomErrorResponse.builder()
.code(ErrorCode.INTERNAL_SERVER_ERROR.getCode())
.message(ErrorCode.INTERNAL_SERVER_ERROR.getMessage())
.errTime(System.currentTimeMillis()).build())
);
} catch (CustomMalformedJwtException e) {
response.setStatus(500);
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(
om.writeValueAsString(CustomErrorResponse.builder()
.code(ErrorCode.MALFORMED_JWT.getCode())
.message(ErrorCode.MALFORMED_JWT.getMessage())
.errTime(System.currentTimeMillis()).build())
);
} catch (CustomNoSameIpException e) {
response.setStatus(500);
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(
om.writeValueAsString(CustomErrorResponse.builder()
.code(ErrorCode.NO_SAME_IP.getCode())
.message(ErrorCode.NO_SAME_IP.getMessage())
.errTime(System.currentTimeMillis()).build())
);
}
}
}

View File

@@ -0,0 +1,31 @@
package com.kospo.talk.config.flux;
import com.kospo.talk.payload.PushDto;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.util.List;
import java.util.Map;
@Component
public class FluxClient {
private final WebClient webClient;
@Value("${server.push.url}")
private String pushUrl;
public FluxClient(WebClient.Builder builder) {
this.webClient = builder.baseUrl(pushUrl).build();
}
public void sendPush(List<PushDto> pushDto) {
String result = webClient.post().uri(pushUrl+"/api/push").accept(MediaType.APPLICATION_JSON)
.bodyValue(pushDto)
.retrieve()
.bodyToMono(String.class)
.block();
// System.out.println(result);
}
}

View File

@@ -0,0 +1,199 @@
package com.kospo.talk.config.interceptor;
import com.kospo.talk.config.utils.CommonUtils;
import com.kospo.talk.model.AutoReply;
import com.kospo.talk.model.SmUser;
import com.kospo.talk.model.User;
import com.kospo.talk.payload.*;
import com.kospo.talk.service.SmUserService;
import com.kospo.talk.service.TalkMemberService;
import com.kospo.talk.service.TalkService;
import com.kospo.talk.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.session.SessionRegistry;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
@Configuration
@RequiredArgsConstructor
public class ChatInfoInterceptor implements ChannelInterceptor {
@Value("${rabbitmq.user.exchange}")
private String userExchange;
@Value("${rabbitmq.user.route}")
private String userRoute;
@Value("${rabbitmq.work.exchange}")
private String workExchange;
@Value("${rabbitmq.work.route}")
private String workRoute;
private final UserService userService;
private final TalkService talkService;
private final TalkMemberService talkMemberService;
private final RabbitTemplate workTemplate;
private final RabbitTemplate userTemplate;
private final SessionRegistry sessionRegistry;
private final SmUserService smUserService;
private Map<String, List<String>> connectList = new HashMap<>();
/* 온라인 오프라인 처리 헤더 정보 추가 해서 서비스워커에 있는 소켓만 허용*/
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.wrap(message);
String destination = headerAccessor.getDestination();
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
String location = headerAccessor.getNativeHeader("location").get(0);
if (location.equals("SW")) {
String sessionId = headerAccessor.getSessionId();
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) headerAccessor.getHeader("simpUser");
User user = (User) token.getPrincipal();
AtomicBoolean online = new AtomicBoolean(false);
class OnlineThread extends Thread {
public void run() {
List<SmUser> smUserList = smUserService.findBySabun(user.getSabun());
smUserList.stream().forEach((sm) -> {
workTemplate.convertAndSend(workExchange, workRoute + sm.getWork().getWorkId(), TalkNotStartDto.builder()
.type("WORK_COUNT")
.notStart((int) talkService.nonStartTalk(sm.getWork().getWorkId()))
.workId(sm.getWork().getWorkId())
.build()
);
long onlineUserCnt = smUserService.countByOnlineYnAndWorkId(sm.getWork().getWorkId());
// long onlineUserCnt = smUserService.countByOnlineYnAndWorkIdExceptSabun(sm.getWork().getWorkId(), user.getSabun());
if (onlineUserCnt > 0) online.set(true);
if (online.get()) {
workTemplate.convertAndSend(workExchange, workRoute + sm.getId().getWorkId(), OnlineDto.builder()
.sabun(user.getSabun())
.type("WORK_ONLINE")
.onlineYn(online.get())
.build()
);
}
});
talkMemberService.findBySabunGroupBySabun(user.getSabun()).stream().forEach((sabun) -> {
if (!sabun.equals(user.getSabun())) {
userTemplate.convertAndSend(userExchange, userRoute + sabun, OnlineDto.builder()
.sabun(user.getSabun())
.type("ONLINE")
.onlineYn(true)
.works(smUserList.stream().map(SmUserDto::to).toList())
.build());
}
});
}
}
if (user != null) {
if (!user.isOnlineYn()) {
user.setOnlineYn(true);
userService.save(user);
OnlineThread onlineThread = new OnlineThread();
onlineThread.setDaemon(true);
onlineThread.start();
onlineThread = null;
}
}
try {
List<String> currentUserList = connectList.get(user.getSabun());
if(currentUserList == null) {
currentUserList = new ArrayList<>();
}
currentUserList.add(sessionId);
connectList.put(user.getSabun(), currentUserList);
} catch (Exception e) {
new RuntimeException(e);
}
}
}
return message;
}
@Override
public void afterSendCompletion(Message<?> message, MessageChannel channel, boolean sent, Exception ex) {
SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.wrap(message);
String destination = headerAccessor.getDestination();
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.DISCONNECT.equals(accessor.getCommand())) {
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) headerAccessor.getHeader("simpUser");
User user = (User) token.getPrincipal();
String sessionId = headerAccessor.getSessionId();
List<String> currentUserList = connectList.get(user.getSabun());
if(currentUserList == null) {
currentUserList = new ArrayList<>();
} else {
currentUserList.remove(sessionId);
}
AtomicBoolean online = new AtomicBoolean(true);
if (currentUserList.size() == 0) {
connectList.remove(user.getSabun());
user.setOnlineYn(false);
userService.save(user);
List<SmUser> smUserList = smUserService.findBySabun(user.getSabun());
smUserList.stream().forEach((sm) -> {
workTemplate.convertAndSend(workExchange, workRoute + sm.getId().getWorkId(), TalkNotStartDto.builder()
.type("WORK_COUNT")
.notStart((int) talkService.nonStartTalk(sm.getId().getWorkId()))
.workId(sm.getId().getWorkId())
.build()
);
long onlineUserCnt = smUserService.countByOnlineYnAndWorkId(sm.getWork().getWorkId());
if (onlineUserCnt == 0) online.set(false);
if (!online.get()) {
workTemplate.convertAndSend(workExchange, workRoute + sm.getId().getWorkId(), OnlineDto.builder()
.sabun(user.getSabun())
.type("WORK_OFFLINE")
.onlineYn(online.get())
.build()
);
}
});
List<ITalkMemberDto> talkList = talkMemberService.findTalkOnlineYnInSabun(user.getSabun());
talkMemberService.findBySabunGroupBySabun(user.getSabun()).stream().forEach((sabun) -> {
if (!sabun.equals(user.getSabun())) {
userTemplate.convertAndSend(userExchange, userRoute + sabun, OnlineDto.builder()
.sabun(user.getSabun())
.type("OFFLINE")
.onlineYn(true)
.works(smUserList.stream().map(SmUserDto::to).toList())
.talks(talkList.stream().map(TalkMemberDto::from).toList())
.build());
}
});
}
sessionRegistry.removeSessionInformation(sessionId);
}
}
}

View File

@@ -0,0 +1,33 @@
package com.kospo.talk.config.jasypt;
import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableEncryptableProperties
public class JasyptConfigAES {
@Value("${jasypt.encryptor.key}")
private String key;
@Bean("jasyptEncryptorAES")
public StringEncryptor stringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(key); // 암호화키
config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256"); // 알고리즘
config.setKeyObtentionIterations("1000"); // 반복할 해싱 회수
config.setPoolSize("1"); // 인스턴스 pool
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator"); // salt 생성 클래스
config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
config.setStringOutputType("base64"); //인코딩 방식
encryptor.setConfig(config);
return encryptor;
}
}

View File

@@ -0,0 +1,36 @@
package com.kospo.talk.config.listener;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.simp.broker.SubscriptionRegistry;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.messaging.SessionConnectedEvent;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Configuration
@RequiredArgsConstructor
public class CustomMessageListener {
private final SubscriptionRegistry subscriptionRegistry;
private final SessionRegistry sessionRegistry;
// private final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
// @EventListener
// public void onSessionConnected(SessionConnectedEvent event) {
// String sabun = event.getUser().getName();
// sessions.put(sabun = event.)
// }
@EventListener
public void handleDisconnect(SessionDisconnectEvent event) {
System.out.println("handleDisconnect : " + event.getSessionId());
subscriptionRegistry.unregisterAllSubscriptions(event.getSessionId());
sessionRegistry.removeSessionInformation(event.getSessionId());
}
}

View File

@@ -0,0 +1,369 @@
package com.kospo.talk.config.listener;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.kospo.talk.config.utils.CommonUtils;
import com.kospo.talk.model.*;
import com.kospo.talk.payload.MessageDto;
import com.kospo.talk.payload.TalkDto;
import com.kospo.talk.payload.TalkMemberDto;
import com.kospo.talk.service.*;
import jakarta.annotation.PreDestroy;
import jakarta.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpRejectAndDontRequeueException;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.io.*;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
@Slf4j
@Component
public class RabbitMqMessageListener {
@Value("${server.attach}")
private String attachPath;
@Value("${rabbitmq.user.exchange}")
private String userExchange;
@Value("${rabbitmq.user.route}")
private String userRoute;
@Autowired
private TalkMessageService talkMessageService;
@Autowired
private TalkService talkService;
@Autowired
private TalkMemberService talkMemberService;
@Autowired
private TalkAttachService talkAttachService;
@Autowired
private TalkReadService talkReadService;
@Autowired
private RabbitTemplate userTemplate;
ArrayList<TalkMessage> talkMessages = new ArrayList<>();
ArrayList<TalkRead> talkReads = new ArrayList<>();
private final ExecutorService executorService = Executors.newFixedThreadPool(10);
@Scheduled(fixedRate = 300)
public void CollectSave() {
if (talkMessages.isEmpty()) {
return;
}
if (!talkMessages.isEmpty()) {
// System.out.println("in");
ArrayList<TalkMessage> tempMessages = (ArrayList<TalkMessage>) talkMessages.clone();
ArrayList<TalkRead> tempReads = (ArrayList<TalkRead>) talkReads.clone();
talkMessageService.saveAll(tempMessages);
talkReadService.saveAll(tempReads);
talkMessages.removeAll(tempMessages);
talkReads.removeAll(tempReads);
}
}
@Transactional
@RabbitListener(queues = "${rabbitmq.talk.queue}")
public void receive(Message message) throws IOException {
try {
SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.wrap(message);
String sessionId = headerAccessor.getSessionId();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
TalkDto talkDto = objectMapper.readValue((byte[]) message.getPayload(), TalkDto.class);
// System.out.println("**************************************** type : " + talkDto.getType() + " insSabun : " + talkDto.getInsSabun() + " ****************************************");
List<String> ignores = Arrays.asList("[사진]", "[파일]", "[매뉴얼]");
if (talkDto.getType().equals("MESSAGE")) {
Talk dto = talkService.findByOne(talkDto.getTalkId());
if (dto != null) {
AtomicBoolean searchYn = new AtomicBoolean(true);
ignores.stream().forEach((ignore) -> {
if (talkDto.getMessage().indexOf(ignore) > -1) searchYn.set(false);
if (talkDto.getInsSabun().equals("info")) searchYn.set(false);
});
talkMessages.add(TalkMessage.builder()
.id(TalkMessageId.builder().talkId(talkDto.getTalkId()).sabun(talkDto.getInsSabun()).insDate(talkDto.getInsDate()).build())
.message(talkDto.getMessage())
.searchYn(searchYn.get())
.insName(talkDto.getInsName()).build());
List<TalkMember> members = talkMemberService.findAllByTalkId(talkDto.getTalkId());
members.stream().forEach((mem) -> {
if (!mem.getId().getSabun().equals("info")) {
talkReads.add(TalkRead.builder()
.readYn(talkDto.getInsSabun().equals(mem.getId().getSabun()) ? true : false)
.id(TalkReadId.builder()
.talkId(talkDto.getTalkId())
.sabun(mem.getId().getSabun())
.insDate(talkDto.getInsDate()).build()).build());
}
});
if (!talkDto.getMessage().isEmpty() || !talkDto.getMessage().isBlank()) {
if (talkDto.getMessage().contains("[매뉴얼]")) {
dto.setLastMessage("[매뉴얼]");
} else {
dto.setLastMessage(talkDto.getMessage());
}
dto.setLastMessageDate(talkDto.getInsDate());
if (talkDto.getStartYn() != null) dto.setStartYn(talkDto.getStartYn());
talkService.createTalk(dto);
}
}
} else if (talkDto.getType().equals("QUESTION")) {
Talk dto = talkService.findByOne(talkDto.getTalkId());
if (dto != null) {
talkMessages.add(TalkMessage.builder()
.id(TalkMessageId.builder().talkId(talkDto.getTalkId()).sabun(talkDto.getInsSabun()).insDate(talkDto.getInsDate()).build())
.message(talkDto.getMessage())
.searchYn(false)
.insName(talkDto.getInsName()).build());
List<TalkMember> members = talkMemberService.findAllByTalkId(talkDto.getTalkId());
members.stream().forEach((mem) -> {
if (!mem.getId().getSabun().equals("info")) {
talkReads.add(TalkRead.builder()
.readYn(talkDto.getInsSabun().equals(mem.getId().getSabun()) ? true : false)
.id(TalkReadId.builder()
.talkId(talkDto.getTalkId())
.sabun(mem.getId().getSabun())
.insDate(talkDto.getInsDate()).build()).build());
}
});
}
} else if (talkDto.getType().equals("CLOSE")) {
Talk talk = talkService.findByOne(talkDto.getTalkId());
talk.setCloseYn(true);
talk.setRatingYn(false);
if (talkDto.getForce()) {
talk.setRatingYn(true);
talk.setCompYn(true);
}
talkService.createTalk(talk);
} else if (talkDto.getType().equals("READ")) {
talkMessageService.read(talkDto.getTalkId(), talkDto.getInsSabun());
} else if (talkDto.getType().equals("ATTACH_INIT")) {
// System.out.println("listener ATTACH_INIT");
Talk dto = talkService.findByOne(talkDto.getTalkId());
talkMessageService.save(TalkMessage.builder()
.id(
TalkMessageId.builder().talkId(talkDto.getTalkId()).sabun(talkDto.getInsSabun()).insDate(talkDto.getInsDate()).build()
)
.message(talkDto.getMessage())
.searchYn(false)
.insName(talkDto.getInsName()).build());
dto.setLastMessage(talkDto.getMessage());
dto.setLastMessageDate(talkDto.getInsDate());
talkService.createTalk(dto);
}
} catch (Exception e) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
TalkDto talkDto = objectMapper.readValue((byte[]) message.getPayload(), TalkDto.class);
log.error(talkDto.toString());
throw new AmqpRejectAndDontRequeueException(e);
}
}
@RabbitListener(queues = "${rabbitmq.file.queue}")
public void receiveFile(Message message) throws IOException {
try {
SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.wrap(message);
String sessionId = headerAccessor.getSessionId();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
MessageDto messageDto = objectMapper.readValue((byte[]) message.getPayload(), MessageDto.class);
// System.out.println("**************************************** file type : " + messageDto.getType() + " insSabun : " + messageDto.getInsSabun() + " ****************************************");
if (messageDto.getType().equals("ATTACH_START")) {
// System.out.println("listener ATTACH_START");
String vnm = messageDto.getAttach().getVnm();
// System.out.println(vnm);
TalkAttach attach = TalkAttach.builder()
.id(TalkAttachId.builder()
.talkId(messageDto.getTalkId())
.sort(messageDto.getAttach().getSort())
.sabun(messageDto.getInsSabun())
.insDate(messageDto.getInsDate())
.build()
)
.onm(messageDto.getAttach().getOnm())
.vnm(vnm)
.path(attachPath)
.type(messageDto.getAttach().getType())
.size(messageDto.getAttach().getSize())
.uploading(true)
.build();
talkAttachService.save(attach);
} else if (messageDto.getType().equals("ATTACH_PROGRESS")) {
// System.out.println("listener ATTACH_PROGRESS");
uploadAndResume(messageDto.getAttach().getVnm(), messageDto.getAttach().getData());
} else if (messageDto.getType().equals("ATTACH_END")) {
// System.out.println("listener ATTACH_end");
talkAttachService.getTalkAttachList(messageDto.getTalkId(), messageDto.getInsSabun(), messageDto.getInsDate()).stream().forEach((attach) -> {
attach.setUploading(false);
talkAttachService.save(attach);
});
}
} catch(Exception e) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
MessageDto messageDto = objectMapper.readValue((byte[]) message.getPayload(), MessageDto.class);
log.error(messageDto.toString());
throw new AmqpRejectAndDontRequeueException(e);
}
}
public synchronized void uploadAndResume(String vnm, byte[] data) {
File file = new File(attachPath, vnm);
BufferedOutputStream bos = null;
try {
if (file.exists()) {
bos = new BufferedOutputStream(new FileOutputStream(file, true));
} else {
bos = new BufferedOutputStream(new FileOutputStream(file));
}
bos.write(data);
bos.flush();
bos.close();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
}
// public synchronized void uploadAndResume(String vnm, byte[] data) {
// File file = new File(attachPath, vnm);
// System.out.println(file.getAbsoluteFile());
// BufferedOutputStream bos = null;
// long skip = 0;
//
// try {
// if (file.exists()) {
// bos = new BufferedOutputStream(new FileOutputStream(file, true));
//
// } else {
// bos = new BufferedOutputStream(new FileOutputStream(file));
//
// }
// bos.write(data);
// bos.flush();
// } catch (FileNotFoundException e) {
// throw new RuntimeException(e);
// } catch (IOException e) {
// throw new RuntimeException(e);
// } finally {
// if(bos != null) {
// try {
// bos.close();
// } catch (IOException ex) {
// throw new RuntimeException(ex);
// }
// }
// }
// }
@RabbitListener(queues = "${rabbitmq.user.queue}")
public void adminReceive(Message message) throws IOException {
try {
SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.wrap(message);
String sessionId = headerAccessor.getSessionId();
String sabun = (String) headerAccessor.getHeader("sabun");
String name = (String) headerAccessor.getHeader("name");
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
TalkDto talkDto = objectMapper.readValue((byte[]) message.getPayload(), TalkDto.class);
if (talkDto.getType().equals("JOIN")) {
TalkDto dto = talkService.findByTalkId(talkDto.getTalkId());
if (dto == null) {
talkService.createTalk(Talk.builder()
.talkId(talkDto.getTalkId())
.closeYn(false)
.startYn(false)
.compYn(false)
.workId(talkDto.getWorkId())
.insSabun(talkDto.getInsSabun())
.insDate(LocalDateTime.now())
.insName(talkDto.getInsName())
.build()
);
}
talkMemberService.save(
TalkMemberDto.builder()
.talkId(talkDto.getTalkId())
.sabun(sabun)
.name(name)
.markYn(false)
.deleteYn(false)
.dummyYn(false).build()
);
}
// System.out.println("user received");
} catch (Exception e) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
MessageDto messageDto = objectMapper.readValue((byte[]) message.getPayload(), MessageDto.class);
log.error(messageDto.toString());
throw new AmqpRejectAndDontRequeueException(e);
}
}
@Transactional
@RabbitListener(queues = "${rabbitmq.hub.queue}")
public void hubChannel(Message message) throws IOException {
}
@Transactional
@RabbitListener(queues = "${rabbitmq.work.queue}")
public void workChannel(Message message) throws IOException {
}
@RabbitListener(queues = "${rabbitmq.dead.queue}")
public void dadChannel(Message message) throws IOException {
SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.wrap(message);
String sessionId = headerAccessor.getSessionId();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
MessageDto messageDto = objectMapper.readValue((byte[]) message.getPayload(), MessageDto.class);
if(messageDto.getType().equals("MESSAGE") || messageDto.getType().contains("ATTACH")) {
messageDto.setType("DEAD_MESSAGE");
userTemplate.convertAndSend(userExchange, userRoute + messageDto.getInsSabun(), messageDto);
}
}
}

View File

@@ -0,0 +1,341 @@
package com.kospo.talk.config.rabbit;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.kospo.talk.payload.TalkDto;
import lombok.RequiredArgsConstructor;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.Connection;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Configuration
@EnableRabbit
@RequiredArgsConstructor
public class RabbitConfig {
@Value("${rabbitmq.connection.host}")
private String host;
@Value("${rabbitmq.connection.username}")
private String username;
@Value("${rabbitmq.connection.password}")
private String password;
@Value("${rabbitmq.talk.exchange}")
private String talkExchange;
@Value("${rabbitmq.talk.routing}")
private String talkRouting;
@Value("${rabbitmq.talk.queue}")
private String talkQueue;
@Value("${rabbitmq.user.exchange}")
private String userExchange;
@Value("${rabbitmq.user.routing}")
private String userRouting;
@Value("${rabbitmq.user.queue}")
private String userQueue;
@Value("${rabbitmq.file.exchange}")
private String fileExchange;
@Value("${rabbitmq.file.routing}")
private String fileRouting;
@Value("${rabbitmq.file.queue}")
private String fileQueue;
@Value("${rabbitmq.hub.exchange}")
private String hubExchange;
@Value("${rabbitmq.hub.routing}")
private String hubRouting;
@Value("${rabbitmq.hub.queue}")
private String hubQueue;
@Value("${rabbitmq.work.exchange}")
private String workExchange;
@Value("${rabbitmq.work.routing}")
private String workRouting;
@Value("${rabbitmq.work.queue}")
private String workQueue;
@Value("${rabbitmq.dead.exchange}")
private String deadExchange;
@Value("${rabbitmq.dead.queue}")
private String deadQueue;
private GenericObjectPool<Connection> connectionPool;
@Bean
public TopicExchange talkExchange() {
return new TopicExchange(talkExchange);
}
@Bean
public TopicExchange userExchange() {
return new TopicExchange(userExchange);
}
@Bean
public TopicExchange hubExchange() {
return new TopicExchange(hubExchange);
}
@Bean
public TopicExchange fileExchange() {
return new TopicExchange(fileExchange);
}
@Bean
public TopicExchange workExchange() {
return new TopicExchange(workExchange);
}
@Bean
public FanoutExchange deadExchange() {
return new FanoutExchange(deadExchange);
}
private Map<String, Object> dlSetting() {
Map<String, Object> setting = new HashMap();
setting.put("x-dead-letter-exchange", deadExchange);
setting.put("x-message-ttl", 30000);
return setting;
}
@Bean
public Queue deadQueue() {
return new Queue(deadQueue, true, false, false);
}
@Bean
public Queue talkQueue() {
return new Queue(talkQueue, true, false, false, dlSetting());
}
@Bean
public Queue userQueue() {
return new Queue(userQueue, true, false, false, dlSetting());
}
@Bean
public Queue fileQueue() {
return new Queue(fileQueue, true, false, false, dlSetting());
}
@Bean
public Queue hubQueue() {
return new Queue(hubQueue, true, false, false, dlSetting());
}
@Bean
public Queue workQueue() {
return new Queue(workQueue, true, false, false, dlSetting());
}
@Bean
public Binding talkBinding(TopicExchange talkExchange) {
return BindingBuilder.bind(talkQueue()).to(talkExchange).with(talkRouting);
}
@Bean
public Binding userBinding(TopicExchange userExchange) {
return BindingBuilder.bind(userQueue()).to(userExchange).with(userRouting);
}
@Bean
public Binding fileBinding(TopicExchange fileExchange) {
return BindingBuilder.bind(fileQueue()).to(fileExchange).with(fileRouting);
}
@Bean
public Binding hubBinding(TopicExchange hubExchange) {
return BindingBuilder.bind(hubQueue()).to(hubExchange).with(hubRouting);
}
@Bean
public Binding workBinding(TopicExchange workExchange) {
return BindingBuilder.bind(workQueue()).to(workExchange).with(workRouting);
}
@Bean
public Binding deadBinding(FanoutExchange deadExchange) {
return BindingBuilder.bind(deadQueue()).to(deadExchange);
}
@Bean
public RabbitTemplate talkTemplate() {
RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory());
rabbitTemplate.setMessageConverter(jsonMessageConverter());
rabbitTemplate.setRoutingKey(talkRouting);
return rabbitTemplate;
}
@Bean
public RabbitTemplate userTemplate() {
RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory());
rabbitTemplate.setMessageConverter(jsonMessageConverter());
rabbitTemplate.setRoutingKey(userRouting);
return rabbitTemplate;
}
@Bean
public RabbitTemplate fileTemplate() {
RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory());
rabbitTemplate.setMessageConverter(jsonMessageConverter());
rabbitTemplate.setRoutingKey(fileRouting);
return rabbitTemplate;
}
@Bean
public RabbitTemplate hubTemplate() {
RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory());
rabbitTemplate.setMessageConverter(jsonMessageConverter());
rabbitTemplate.setRoutingKey(hubRouting);
return rabbitTemplate;
}
@Bean
public RabbitTemplate workTemplate() {
RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory());
rabbitTemplate.setMessageConverter(jsonMessageConverter());
rabbitTemplate.setRoutingKey(workRouting);
return rabbitTemplate;
}
@Bean
public CachingConnectionFactory cachingConnectionFactory() {
CachingConnectionFactory factory = new CachingConnectionFactory();
factory.setHost(host);
factory.setPort(5672);
factory.setUsername(username);
factory.setPassword(password);
factory.setConnectionTimeout(10000);
factory.setChannelCacheSize(70);
factory.setChannelCheckoutTimeout(15000);
factory.setRequestedHeartBeat(15);
factory.setCacheMode(CachingConnectionFactory.CacheMode.CHANNEL);
factory.setCloseTimeout(15000);
// factory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
return factory;
}
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(cachingConnectionFactory());
factory.setRetryTemplate(retryTemplate());
factory.setIdleEventInterval(60000L);
factory.setConcurrentConsumers(10); // 초기 소비자 수 설정
factory.setMaxConcurrentConsumers(400); // 최대 동시 소비자 수 설정
factory.setBatchSize(20);
factory.setPrefetchCount(100);
return factory;
}
private RetryTemplate retryTemplate() {
RetryTemplate retryTemplate = new RetryTemplate();
// 재시도 정책 설정
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(3); // 최대 재시도 횟수
retryTemplate.setRetryPolicy(retryPolicy);
// 백오프 정책 설정 (지수 백오프)
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(1000); // 초기 간격 (밀리초)
backOffPolicy.setMultiplier(2.0); // 간격 증가 배수
backOffPolicy.setMaxInterval(10000); // 최대 간격 (밀리초)
retryTemplate.setBackOffPolicy(backOffPolicy);
return retryTemplate;
}
// 메시지 리스너 대리자
public static class Delegate {
public void handleMessage(TalkDto talkDto) {
if(talkDto != null) {
System.out.println("delegate : " +talkDto.getMessage());
}
}
}
@Bean
public Delegate delegate() {
return new Delegate();
}
@Bean
public MessageListener messageListener() {
return new MessageListenerAdapter(delegate(), jsonMessageConverter());
}
// @Bean
// public SimpleMessageListenerContainer container() {
// SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
// container.setConnectionFactory(connectionFactory());
// container.setQueueNames(CHAT_QUEUE_NAME);
// container.setMessageListener(new CustomMessageListener());
// return container;
// }
// @Bean
// public ConnectionFactory connectionFactory() {
// CachingConnectionFactory factory = new CachingConnectionFactory();
// factory.setHost("10.130.7.61");
// factory.setPort(5672);
// factory.setUsername(username);
// factory.setPassword(password);
// factory.setConnectionTimeout(2000);
//
// return factory;
// }
@Bean
public Jackson2JsonMessageConverter jsonMessageConverter(){
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true);
objectMapper.registerModule(dateTimeModule());
Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter(objectMapper);
return converter;
}
@Bean
public Module dateTimeModule() {
return new JavaTimeModule();
}
// @Scheduled(fixedDelay = 30000L)
// public void IdleThreadRemove() {
// int count = 0;
//
// Map<Thread, StackTraceElement[]> threads = Thread.getAllStackTraces();
//
// for(Map.Entry<Thread, StackTraceElement[]> entry : threads.entrySet()) {
// Thread thread = entry.getKey();
// StackTraceElement[] stackTraceElements = entry.getValue();
// if(thread.getName().contains("RabbitListenerEndpointContainer")) {
// if(thread.getState() == Thread.State.WAITING || thread.getState() == Thread.State.TIMED_WAITING) {
// thread.interrupt();
// count++;
// }
//
// }
// }
// System.out.println("Interrupted " + count + " waiting RabbitMq Threads");
// }
}

View File

@@ -0,0 +1,110 @@
package com.kospo.talk.config.security;
import com.kospo.talk.config.filter.AuthenticationFilter;
import com.kospo.talk.config.filter.CustomBasicAuthenticationFilter;
import com.kospo.talk.config.filter.SecurityExceptionFilter;
import com.kospo.talk.repository.UserRepository;
import com.kospo.talk.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.ExceptionTranslationFilter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import java.util.Arrays;
@Configuration
@RequiredArgsConstructor
public class SecurityConfig {
private final UserService userService;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http,
UserRepository userRepository) throws Exception {
http
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry
.requestMatchers("/admin*").hasRole("ADMIN")
.anyRequest().authenticated()
)
.csrf(AbstractHttpConfigurer::disable)
.formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.disable())
.addFilterBefore(new CustomBasicAuthenticationFilter(authenticationManager(), userRepository), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new SecurityExceptionFilter(), CustomBasicAuthenticationFilter.class)
.sessionManagement(httpSecuritySessionManagementConfigurer ->
httpSecuritySessionManagementConfigurer
.maximumSessions(1)
.sessionRegistry(sessionRegistry())
)
.cors(httpSecurityCorsConfigurer -> httpSecurityCorsConfigurer.configurationSource(new CorsConfigurationSource() {
@Override
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
CorsConfiguration config = new CorsConfiguration();
String origin = request.getHeader("Origin");
config.setAllowCredentials(true);
config.setAllowedOrigins(Arrays.asList("http://kisp.kospo.co.kr:8010", "http://localhost:8010"));
config.setAllowedMethods(Arrays.asList("POST","GET","DELETE","PUT","OPTIONS"));
config.setAllowedHeaders(Arrays.asList("*"));
return config;
}
}));
return http.build();
}
private String getEncoding (String str) {
BCryptPasswordEncoder b = new BCryptPasswordEncoder();
return b.encode(str);
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public AuthenticationManager authenticationManager() {
AuthenticationManager manager = new AuthenticationManager() {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
return authentication;
}
};
return manager;
}
/*특정 url 필터 제외 처리*/
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().requestMatchers(
"/manifest.json", "/css/**", "/images/**", "/js/**", "/pages/**"
// -- Swagger UI v2
, "/v2/api-docs/**", "/swagger-resources/**", "/v3/api-docs/**"
, "/swagger-ui/**", "/webjars/**", "/swagger/**", "/api-docs/**"
);
}
@Bean
public SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(sessionRegistry());
}
}

View File

@@ -0,0 +1,6 @@
package com.kospo.talk.config.security;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityWebInitializer extends AbstractSecurityWebApplicationInitializer {
}

View File

@@ -0,0 +1,34 @@
package com.kospo.talk.config.spring;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.reactive.function.client.WebClient;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executor;
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("Async-");
executor.initialize();
return executor;
}
}

View File

@@ -0,0 +1,33 @@
package com.kospo.talk.config.spring;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.reactive.function.client.WebClient;
import java.util.concurrent.Executor;
@Configuration
@EnableAsync
public class WebClientConfig {
@Value("${server.itsm}")
private String itsmUrl;
@Value("${server.scm}")
private String scmUrl;
@Bean
public WebClient itsmWebClient() {
return WebClient.builder()
.baseUrl(itsmUrl)
.build();
}
@Bean
public WebClient scmWebClient() {
return WebClient.builder()
.baseUrl(scmUrl)
.build();
}
}

View File

@@ -0,0 +1,13 @@
package com.kospo.talk.config.spring;
import com.kospo.talk.config.filter.BadWordFiltering;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WebMvcConfig {
@Bean
public BadWordFiltering badWordFiltering() {
return new BadWordFiltering();
}
}

View File

@@ -0,0 +1,40 @@
package com.kospo.talk.config.swagger;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
// return new OpenAPI()
// .info(apiInfo())
// .components(new Components().addSecuritySchemes("basicScheme", new SecurityScheme()
// .type(SecurityScheme.Type.HTTP).scheme("basic")));
// }
return new OpenAPI()
.info(apiInfo())
.components(new Components()
.addSecuritySchemes("custom-header", new SecurityScheme()
.type(SecurityScheme.Type.APIKEY)
.in(SecurityScheme.In.HEADER)
.name("Authentication")))
.addSecurityItem(new SecurityRequirement().addList("custom-header"));
}
private Info apiInfo() {
return new Info()
.title("헬프톡")
.description("헬프톡 api")
.version("1.0.0");
}
}

View File

@@ -0,0 +1,164 @@
package com.kospo.talk.config.utils;
import com.kospo.talk.payload.ListeningDto;
import com.kospo.talk.payload.MasterDto;
import org.springframework.data.domain.Sort;
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
public class CommonUtils {
private static HashMap<String, Set<HashMap<String, Integer>>> listenings;
public CommonUtils() {
}
public static void setListening(ListeningDto listeningDto) {
if(listenings == null) listenings = new HashMap<>();
Set<HashMap<String, Integer>> getList = listenings.get(listeningDto.getSabun());
HashMap<String, Integer> map = new HashMap<>();
if(getList == null) {
getList = new HashSet<>();
map.put(listeningDto.getTalkId(), listeningDto.getStatus());
} else {
getList = getList.stream().filter((li) -> !li.containsKey(listeningDto.getTalkId())).collect(Collectors.toSet());
map.put(listeningDto.getTalkId(), listeningDto.getStatus());
}
getList.add(map);
listenings.put(listeningDto.getSabun(), getList);
}
public static Integer getListening(ListeningDto listeningDto) {
AtomicInteger result = new AtomicInteger();
if(listenings == null) {
listenings = new HashMap<>();
return 0;
} else {
Set<HashMap<String, Integer>> getList = listenings.get(listeningDto.getSabun());
if(getList == null) {
return 0;
} else {
getList.stream().forEach((li) -> {
if (li.containsKey(listeningDto.getTalkId())) {
result.set(li.get(listeningDto.getTalkId()));
}
});
return result.get();
}
}
}
public static Sort convertSort(String field) {
String[] propertyAndDirection = field.split(",");
if(propertyAndDirection.length == 1) propertyAndDirection = field.split(" ");
String property = propertyAndDirection[0];
Sort.Direction direction = Sort.DEFAULT_DIRECTION;
if(propertyAndDirection.length > 1) {
String directionString = propertyAndDirection[1];
direction = Sort.Direction.fromOptionalString(directionString)
.orElse(Sort.DEFAULT_DIRECTION);
}
Sort.Order order = new Sort.Order(direction, property);
return Sort.by(order);
}
public static String dateFormat(Date setDate, String pattern) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
return sdf.format(setDate);
}
public static String dateFormat(String pattern) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
return sdf.format(new Date());
}
public static Date stringToDate(String dateString) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS");
// sdf.setTimeZone(TimeZone.getTimeZone("Asia/Seoul"));
Date date = null;
try {
date = sdf.parse(dateString);
} catch (ParseException e) {
throw new RuntimeException(e);
}
return date;
}
public static LocalDateTime stringToDate(String dateString, String pattern) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
// sdf.setTimeZone(TimeZone.getTimeZone("Asia/Seoul"));
LocalDateTime date = null;
date = LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(pattern));
return date;
}
public static String generateFileName() {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSSSSSS");
String datePart = now.format(formatter);
String uniquePart = UUID.randomUUID().toString().substring(0, 8);
return datePart + "_" + uniquePart;
}
public static boolean checkAllowExt(String fileNm) {
String fileExtNm = "";
List<String> allowList = Arrays.asList(
"7z", "ai", "art", "asd", "avi", "bak", "bin", "c", "cell", "cfg", "cls", "css", "csv", "der", "drt", "dsd", "dwg", "dxf", "emf", "eps", "gz", "html", "hwpx", "inf", "info", "ini", "java", "is", "key", "lic", "log", "m", "mov", "mp3", "mp4", "mpeg", "msg", "ods", "odt", "otf", "p12", "pdf", "png", "ppsx", "pptm", "pptx", "psd", "svg", "tar", "tgz", "tif", "tiff", "tmp", "ttf", "twb", "twbx", "ui", "url", "vsd", "wav", "webp", "whl", "wmf", "wmv", "woff", "xl", "xla", "xlm", "xlsb", "xlsm", "xml", "xsd", "bmp", "doc", "docx", "eml", "gif", "hwp", "jpe", "jpeg", "jpg", "pfx", "ppt", "txt", "xls", "xlsx", "zip"
);
fileExtNm = fileNm.toLowerCase().substring(fileNm.toLowerCase().lastIndexOf(".") + 1);
fileExtNm = fileExtNm.toLowerCase();
String allows = allowList.stream().map((str) -> str).collect(Collectors.joining(","));
return allows.contains(fileExtNm);
}
public static synchronized void uploadAndResume(String path, String vnm, byte[] data) {
File file = new File(path, vnm);
BufferedOutputStream bos = null;
try {
if (file.exists()) {
bos = new BufferedOutputStream(new FileOutputStream(file, true));
} else {
bos = new BufferedOutputStream(new FileOutputStream(file));
}
bos.write(data);
bos.flush();
bos.close();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
}
}

View File

@@ -0,0 +1,89 @@
package com.kospo.talk.config.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.FileCopyUtils;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAKeyGenParameterSpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class CryptoUtil {
public static String encrypt(String plainText) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, loadPublicKey());
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
return Base64.getEncoder().encodeToString(encryptedBytes);
}
public static String decrypt(String encryptText) throws Exception {
encryptText = encryptText.replaceAll(" ", "+");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, loadPrivateKey());
byte[] decryptBytes = cipher.doFinal(Base64.getDecoder().decode(encryptText));
return new String(decryptBytes);
}
private static PublicKey loadPublicKey() throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
ClassPathResource resource = new ClassPathResource("public.key");
byte[] keyBytes = FileCopyUtils.copyToByteArray(resource.getInputStream());
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(spec);
}
private static PrivateKey loadPrivateKey() throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
ClassPathResource resource = new ClassPathResource("private.key");
byte[] keyBytes = FileCopyUtils.copyToByteArray(resource.getInputStream());
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(spec);
}
private static byte[] readKeyFromFile(String fileName) {
File file = new File(fileName);
byte[] keyBytes = new byte[(int) file.length()];
try(FileInputStream fis = new FileInputStream(file)) {
fis.read(keyBytes);
} catch (IOException e) {
throw new RuntimeException(e);
}
return keyBytes;
}
private static void saveKeyToFile(String fileName, byte[] keyBytes) {
File file = new File(fileName);
try(FileOutputStream fos = new FileOutputStream(file)) {
fos.write(keyBytes);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
// System.out.println(encrypt("psn14020"));
// KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
// keygen.initialize(new RSAKeyGenParameterSpec(2048, RSAKeyGenParameterSpec.F4));
// KeyPair pair = keygen.generateKeyPair();
//
// saveKeyToFile("C:\\Users\\psn14020\\IdeaProjects\\talk\\src\\main\\resources\\private.key", pair.getPrivate().getEncoded());
// saveKeyToFile("C:\\Users\\psn14020\\IdeaProjects\\talk\\src\\main\\resources\\public.key", pair.getPublic().getEncoded());
}
}

View File

@@ -0,0 +1,15 @@
package com.kospo.talk.config.utils;
import lombok.Getter;
import java.io.FileNotFoundException;
public class FileState {
@Getter
private String vnm;
public FileState(String vnm) throws FileNotFoundException {
this.vnm = vnm;
}
}

View File

@@ -0,0 +1,40 @@
package com.kospo.talk.config.utils;
import lombok.Getter;
import java.io.FileNotFoundException;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
public class MultipleUpload {
@Getter
private long fileSize;
@Getter
private long bytesReceived;
@Getter
private LocalDateTime insDate;
private HashMap<Integer, FileState> uploadStates = new HashMap<>();
public MultipleUpload(long fileSize, LocalDateTime insDate) {
this.fileSize = fileSize;
this.insDate = insDate;
}
public void setBytesReceived(int fileSize) {
bytesReceived += fileSize;
};
public void setUploadState(Integer sort, String vnm) {
try {
FileState state = new FileState(vnm);
uploadStates.put(sort, state);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
public FileState getUploadState(int sort) {
return uploadStates.get(sort);
}
}

View File

@@ -0,0 +1,13 @@
package com.kospo.talk.config.utils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class UploadObject {
public static Map<String, MultipleUpload> uploadStates = new HashMap<>();
}

View File

@@ -0,0 +1,44 @@
//package com.kospo.talk.config.ws;
//
//import org.springframework.context.annotation.Configuration;
//import org.springframework.web.socket.CloseStatus;
//import org.springframework.web.socket.WebSocketHandler;
//import org.springframework.web.socket.WebSocketSession;
//import org.springframework.web.socket.handler.TextWebSocketHandler;
//import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
//import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;
//
//import java.io.IOException;
//import java.util.Map;
//import java.util.concurrent.ConcurrentHashMap;
//@Configuration
//public class CustomWebSocketHandler implements WebSocketHandlerDecoratorFactory {
// private final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
//
// @Override
// public WebSocketHandler decorate(WebSocketHandler handler) {
// return new WebSocketHandlerDecorator(handler) {
// @Override
// public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// String sessionId = session.getId();
// sessions.put(sessionId, session);
//
// super.afterConnectionEstablished(session);
// }
//
// @Override
// public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
// String sessionId = session.getId();
// try {
// session.close(status);
// } catch(IOException e) {
//
// } finally {
// sessions.remove(sessionId);
// }
// super.afterConnectionClosed(session, status);
// }
// };
// }
//
//}

View File

@@ -0,0 +1,111 @@
package com.kospo.talk.config.ws;
import com.kospo.talk.config.interceptor.ChatInfoInterceptor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry;
import org.springframework.messaging.simp.broker.SubscriptionRegistry;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
@Configuration
@EnableWebSocketMessageBroker // 문자 채팅용
@RequiredArgsConstructor
@Slf4j
public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer {
private final ChatInfoInterceptor chatInfoInterceptor;
// private final CustomWebSocketHandler customWebSocketHandler;
@Value("${rabbitmq.connection.host}")
private String host;
@Value("${rabbitmq.connection.username}")
private String username;
@Value("${rabbitmq.connection.password}")
private String password;
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/stomp/talk", "/stomp/file")
.setAllowedOriginPatterns("*")
.withSockJS()
.setHeartbeatTime(20000)
.setStreamBytesLimit(512 * 1024) // 5MB
.setHttpMessageCacheSize(1000)
.setWebSocketEnabled(true)
.setSessionCookieNeeded(true)
.setDisconnectDelay(15000); // 연결 해지시 체크 시간
registry.addEndpoint("/stomp/ws")
.setAllowedOriginPatterns("*");
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
log.debug("websocketbrokerConfigurer");
config.setPathMatcher((new AntPathMatcher(".")));
config.setApplicationDestinationPrefixes("/pub");
config.enableStompBrokerRelay("/queue", "/topic", "/exchange", "/amq/queue")
.setRelayHost(host)
.setRelayPort(61613)
.setSystemLogin(username)
.setSystemPasscode(password)
.setClientLogin(username)
.setClientPasscode(password)
.setSystemHeartbeatSendInterval(20000)
.setSystemHeartbeatReceiveInterval(20000);
}
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setMessageSizeLimit(1024 * 1024); // 1mb
registration.setSendBufferSizeLimit(1024 * 1024); // 1mb
registration.setSendTimeLimit(20 * 1000); // 20 seconds
// registration.setDecoratorFactories(customWebSocketHandler);
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(chatInfoInterceptor);
registration.taskExecutor().corePoolSize(16)
.maxPoolSize(32)
.keepAliveSeconds(360);
}
@Override
public void configureClientOutboundChannel(ChannelRegistration registration) {
registration.interceptors(chatInfoInterceptor);
registration.taskExecutor().corePoolSize(16)
.maxPoolSize(32);
}
@Bean
public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(1024 * 1024);
container.setMaxBinaryMessageBufferSize(1024 * 1024);
container.setMaxSessionIdleTimeout(60000L);
return container;
}
@Bean
public SubscriptionRegistry subscriptionRegistry() {
return new DefaultSubscriptionRegistry();
}
}

View File

@@ -0,0 +1,141 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.model.User;
import com.kospo.talk.payload.AutoReplyDto;
import com.kospo.talk.payload.ManualDto;
import com.kospo.talk.service.AutoReplyService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
import java.time.LocalDateTime;
@RestController
@Tag(name = "AutoReply Api", description = "자동응답 관리")
@RequestMapping("/api")
@RequiredArgsConstructor
public class AutoReplyController {
private final AutoReplyService autoReplyService;
@Operation(summary = "자동응답 조회", description = "본인의 work id 로 해당 자동응답 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{AutoReplyDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/autoReply")
public ResponseEntity findAll(
@Parameter(description = "검색") @RequestParam(name="workId", required = false) String workId,
@Parameter(description = "타입: (0010 : 방생성 메시지(온라인), 0020 : 방생성 메시지 (오프라인), 0300: 시작하기 메시지)") @RequestParam(name="type", required = false) String type,
Principal principal
) {
return ResponseEntity.ok(autoReplyService.findByWorkIdAndType(workId, type));
}
@Operation(summary = "개인 자동응답 조회", description = "본인의 사번으로 해당 자동응답 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{AutoReplyDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/autoReply/person")
public ResponseEntity findBySabun(
@Parameter(description = "검색") @RequestParam(name="workId", required = false) String workId,
@Parameter(description = "타입: (0010 : 방생성 메시지(온라인), 0020 : 방생성 메시지 (오프라인), 0300: 시작하기 메시지)") @RequestParam(name="type", required = false) String type,
Principal principal
) {
return ResponseEntity.ok(autoReplyService.findBySabun(principal.getName()));
}
@Operation(summary = "자동응답 저장", description = "자동응답 저장")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PostMapping("/autoReply")
public ResponseEntity save(@RequestBody AutoReplyDto autoReplyDto, Principal principal) {
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
autoReplyDto.setInsSabun(user.getSabun());
autoReplyDto.setInsName(user.getName());
autoReplyDto.setInsDate(LocalDateTime.now());
autoReplyService.save(autoReplyDto);
return ResponseEntity.ok("success");
}
@Operation(summary = "자동응답 수정", description = "자동응답 수정")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PutMapping("/autoReply")
public ResponseEntity update(@RequestBody AutoReplyDto autoReplyDto, Principal principal) {
autoReplyService.update(autoReplyDto, principal.getName());
return ResponseEntity.ok("success");
}
@Operation(summary = "자동응답 삭제", description = "자동응답 삭제")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@DeleteMapping("/autoReply/{workId}/{type}")
public ResponseEntity delete(
@Parameter(description = "업무아이디") @PathVariable String workId,
@Parameter(description = "타입") @PathVariable String type,
Principal principal) {
autoReplyService.delete(AutoReplyDto.builder()
.workId(workId).type(type).build(), principal.getName());
return ResponseEntity.ok("success");
}
}

View File

@@ -0,0 +1,87 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.payload.FavoriteDto;
import com.kospo.talk.payload.ManualDto;
import com.kospo.talk.service.FavoriteService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
@RestController
@Tag(name = "Favorite Api", description = "즐겨찾기 관리")
@RequestMapping("/api")
@RequiredArgsConstructor
public class FavoriteController {
private final FavoriteService favoriteService;
@Operation(summary = "즐겨찾기 조회", description = "본인 사번의 즐겨찾기 항목 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{FavoriteDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/favorite")
public ResponseEntity findFavorite(Principal principal) {
return ResponseEntity.ok(favoriteService.findBySabun(principal.getName()));
}
@Operation(summary = "즐겨찾기 저장", description = "즐겨찾기 업무 저장")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PostMapping("/favorite")
public ResponseEntity saveFavorite(@RequestBody FavoriteDto favoriteDto, Principal principal) {
favoriteDto.setSabun(principal.getName());
favoriteService.save(favoriteDto);
return ResponseEntity.ok("success");
}
@Operation(summary = "즐겨찾기 삭제", description = "즐겨찾기 업무 삭제")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@DeleteMapping("/favorite/{workId}")
public ResponseEntity deleteFavorite(
@Parameter(description = "업무아이디") @PathVariable String workId,
Principal principal) {
favoriteService.delete(FavoriteDto.builder()
.sabun(principal.getName())
.workId(workId)
.build());
return ResponseEntity.ok("success");
}
}

View File

@@ -0,0 +1,150 @@
package com.kospo.talk.controller;
import com.kospo.talk.model.User;
import com.kospo.talk.payload.*;
import io.swagger.v3.oas.annotations.Hidden;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.net.SocketException;
import java.security.Principal;
import java.util.*;
@Controller
@Hidden
@RequiredArgsConstructor
@Slf4j
public class HubController {
@Value("${rabbitmq.hub.exchange}")
private String hubExchange;
@Value("${rabbitmq.hub.route}")
private String hubRoute;
private final RabbitTemplate hubTemplate;
private Map<String, List<String>> connectList = new HashMap<>();
@MessageMapping("hub.start.{tabId}")
public void start(TalkDto talkDto, @DestinationVariable String tabId) throws IOException {
try {
List<String> connect = connectList.get(talkDto.getInsSabun());
if(connect == null) {
connect = new ArrayList<>();
} else {
connect = new ArrayList<>(connect);
}
if(!connect.contains(tabId)) {
connect.add(tabId);
connectList.put(talkDto.getInsSabun(), connect);
}
} catch(Exception e) {}
}
@MessageMapping("hub.close.{tabId}")
public void close(TalkDto talkDto) throws IOException {
// System.out.println("hub.close start : " + connectList);
// System.out.println("hub.close start : " + talkDto.toString());
try {
if(!CollectionUtils.isEmpty(connectList)) {
List<String> connect = connectList.get(talkDto.getChannelSabun());
connect = new ArrayList<>(connect);
connect.remove(talkDto.getTabId());
connectList.put(talkDto.getChannelSabun(), connect);
// System.out.println("hub.close end : " + connectList);
}
} catch(Exception e) {}
}
@MessageMapping("hub.kill")
public void kill(TalkDto talkDto) throws IOException {
// System.out.println("hub.close start : " + connectList);
// System.out.println("hub.close start : " + talkDto.toString());
try {
connectList.put(talkDto.getChannelSabun(), new LinkedList<>());
} catch(Exception e) {}
}
@MessageMapping("hub.send.otherInit")
public void channelOtherInit(TalkDto talkDto) {
try {
if(!CollectionUtils.isEmpty(connectList)) {
connectList.get(talkDto.getInsSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, talkDto));
}
} catch(Exception e) {}
}
@MessageMapping("hub.send.setMaster")
public void channelSetMaster(TalkDto talkDto) throws IOException {
try {
talkDto.setType("SEND_SET_MASTER");
if(!CollectionUtils.isEmpty(connectList)) {
connectList.get(talkDto.getInsSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, talkDto));
}
} catch(Exception e) {}
}
@MessageMapping("hub.otherInit")
public void otherInit(OtherDto otherDto) throws IOException {
try {
if(!CollectionUtils.isEmpty(connectList)) {
connectList.get(otherDto.getInsSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, otherDto));
}
} catch(Exception e) {}
}
@MessageMapping("hub.talk.message")
public void userMessage(TalkDto talkDto) throws IOException {
try {
if(!CollectionUtils.isEmpty(connectList)) {
connectList.get(talkDto.getChannelSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, talkDto));
}
} catch(Exception e) {}
}
@MessageMapping("hub.file.message")
public void fileMessage(MessageDto messageDto) throws IOException {
try {
if(!CollectionUtils.isEmpty(connectList)) {
connectList.get(messageDto.getChannelSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, messageDto));
}
} catch(Exception e) {}
}
@MessageMapping("hub.work")
public void work(TalkNotStartDto talkNotStartDto) {
try {
if(!CollectionUtils.isEmpty(connectList)) {
connectList.get(talkNotStartDto.getChannelSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, talkNotStartDto));
}
} catch(Exception e) {}
}
@MessageMapping("hub.online")
public void online(OnlineDto onlineDto) throws IOException {
try {
// System.out.println(onlineDto.getType());
if(!CollectionUtils.isEmpty(connectList)) {
connectList.get(onlineDto.getChannelSabun()).stream().forEach((conn) -> hubTemplate.convertAndSend(hubExchange, hubRoute + conn, onlineDto));
}
} catch(Exception e) {}
}
@MessageMapping("hub.checker.{tabId}")
public void alive(@DestinationVariable String tabId, Principal principal) {
MessageDto messageDto = new MessageDto();
messageDto.setType("CHECKER");
hubTemplate.convertAndSend(hubExchange, hubRoute + tabId, messageDto);
}
}

View File

@@ -0,0 +1,192 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.config.utils.CommonUtils;
import com.kospo.talk.model.*;
import com.kospo.talk.payload.HappyDto;
import com.kospo.talk.payload.MessageDto;
import com.kospo.talk.payload.ReqDto;
import com.kospo.talk.payload.SatisDto;
import com.kospo.talk.service.TalkMemberService;
import com.kospo.talk.service.TalkMessageService;
import com.kospo.talk.service.TalkService;
import com.kospo.talk.service.WorkService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.client.WebClient;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@RestController
@Tag(name = "ITSM API", description = "ICT 요청 관리")
@RequestMapping("/api/ict")
@RequiredArgsConstructor
@Slf4j
public class ItsmController {
@Value("${rabbitmq.user.exchange}")
private String userExchange;
@Value("${rabbitmq.user.route}")
private String userRoute;
@Value("${rabbitmq.talk.exchange}")
private String talkExchange;
@Value("${rabbitmq.talk.route}")
private String talkRoute;
private final WebClient itsmWebClient;
private final TalkService talkService;
private final WorkService workService;
private final TalkMessageService talkMessageService;
private final TalkMemberService talkMemberService;
private final RabbitTemplate userTemplate;
private final RabbitTemplate talkTemplate;
@Operation(summary = "외부 ITSM 요청 하기", description = "itsm 요청 정보 저장 결과값으로 req_id 리턴")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PostMapping("/save")
public ResponseEntity save(
@RequestBody ReqDto reqDto,
HttpServletRequest request,
Principal principal
) {
reqDto.setProc_sabun(principal.getName());
reqDto.setReq_dt(CommonUtils.dateFormat("yyyyMMddHHmmss"));
MultiValueMap cookieMap = new LinkedMultiValueMap();
Arrays.stream(request.getCookies()).forEach((cookie) -> {
cookieMap.add(cookie.getName(), cookie.getValue());
});
MultiValueMap headerMap = new LinkedMultiValueMap();
headerMap.add("X-Forwarded-For", request.getHeader("X-Forwarded-For"));
log.debug("itsm Save satart");
System.out.println("itsm Save satart");
log.debug(reqDto.getTalk_id());
System.out.println(reqDto.getTalk_id());
log.debug(reqDto.toString());
System.out.println(reqDto.toString());
try {
Map<String, String> resultMap = itsmWebClient.post()
.uri("/api/saveTalk")
.headers(h -> h.addAll(headerMap))
.cookies(c -> c.addAll(cookieMap))
.bodyValue(reqDto)
.retrieve().bodyToMono(Map.class).block();
String req_id = resultMap.get("req_id");
log.debug("itsm Save end req_id : " + req_id);
System.out.println("itsm Save end req_id : " + req_id);
Talk talk = talkService.findByOne(reqDto.getTalk_id());
talk.setReqId(req_id);
talkService.createTalk(talk);
MessageDto messageDto = MessageDto.builder().type("EXTERNAL_SAVE")
.reqId(req_id)
.talkId(talk.getTalkId()).build();
talkTemplate.convertAndSend(talkExchange, talkRoute + talk.getTalkId(), messageDto);
return ResponseEntity.ok(req_id);
} catch(Exception e) {
log.debug("itsm Save error : " + e);
System.out.println("itsm Save error : " + e);
return ResponseEntity.ok("");
}
}
@Operation(summary = "외부 ITSM 만족도 조사", description = "itsm 만족도 조사 등록")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PostMapping("/satis")
public ResponseEntity satisSave(
@RequestBody SatisDto satisDto,
HttpServletRequest request,
Principal principal
) {
MultiValueMap cookieMap = new LinkedMultiValueMap();
Arrays.stream(request.getCookies()).forEach((cookie) -> {
cookieMap.add(cookie.getName(), cookie.getValue());
});
MultiValueMap headerMap = new LinkedMultiValueMap();
Talk currentTalk = talkService.findByOne(satisDto.getTalk_id());
Map<String, String> resultMap = new HashMap<>();
headerMap.add("X-Forwarded-For", request.getHeader("X-Forwarded-For"));
resultMap = itsmWebClient.post()
.uri("/api/savePoint")
.headers(h -> h.addAll(headerMap))
.cookies(c -> c.addAll(cookieMap))
.bodyValue(HappyDto.builder()
.req_id(currentTalk.getReqId())
.h_point(satisDto.getH_point())
.opinion(satisDto.getOpinion()).build()
)
.retrieve().bodyToMono(Map.class).block();
String result = resultMap.get("result");
if(result.equals("s")) {
talkService.ratingUpdate(currentTalk.getReqId());
Work work = workService.findByTalkId(currentTalk.getTalkId());
MessageDto messageDto = MessageDto.builder()
.type("STATUS")
.message("만족도 조사에 참여해 주셔서 감사해요.\n앞으로도 많은 참여 부탁드려요.")
.talkId(currentTalk.getTalkId())
.workId(work.getWorkId())
.workNm(work.getWorkNm())
.insSabun("info")
.insName("시스템")
.insDate(LocalDateTime.now())
.build();
talkMessageService.save(TalkMessage.builder()
.id(TalkMessageId.builder().talkId(messageDto.getTalkId()).sabun(messageDto.getInsSabun()).insDate(messageDto.getInsDate()).build())
.message(messageDto.getMessage())
.searchYn(false)
.insName(messageDto.getInsName()).build()
);
talkMemberService.findAllByTalkId(messageDto.getTalkId()).stream().forEach(talkMember -> {
userTemplate.convertAndSend(userExchange, userRoute + talkMember.getId().getSabun(), messageDto);
});
}
return ResponseEntity.ok(resultMap.get("result"));
}
}

View File

@@ -0,0 +1,384 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.model.ManualId;
import com.kospo.talk.payload.ManualDto;
import com.kospo.talk.payload.VManualDto;
import com.kospo.talk.service.ManualService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourceRegion;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.MalformedURLException;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.security.Principal;
import java.time.Duration;
import java.util.HashMap;
import java.util.List;
@RestController
@Tag(name = "Manual Api", description = "업무 매뉴얼 관리")
@RequestMapping("/api")
@RequiredArgsConstructor
public class ManualController {
private final ManualService manualService;
@Operation(summary = "매뉴얼 조회(문서)", description = "본인의 work id 로 해당 매뉴얼 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{ManualDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/manual")
public ResponseEntity docSearch(
@Parameter(description = "검색") @RequestParam(name="search", defaultValue = "", required = false) String search,
@Parameter(description = "업무아이디") @RequestParam(name="workId", defaultValue = "", required = false) String workId,
@Parameter(description = "매뉴얼 타입: 0000(문서) 0100(사진) 0200(동영상)") @RequestParam(name="type", required = false) String type,
Principal principal
) {
return ResponseEntity.ok(manualService.findDocSearch(search, workId, type));
}
@Operation(summary = "매뉴얼 조회(문서) 개인용", description = "본인의 사번으로 해당 매뉴얼 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{ManualDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/manual/person")
public ResponseEntity docSearch(
@Parameter(description = "매뉴얼 타입: 0000(문서) 0100(사진) 0200(동영상)") @RequestParam(name="type", required = true) String type,
Principal principal
) {
return ResponseEntity.ok(manualService.findDocSearchPerson(principal.getName(), type));
}
@Operation(summary = "매뉴얼 조회(이미지, 동영상)", description = "본인의 work id 로 해당 매뉴얼 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{ManualDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/manual/intro")
public ResponseEntity introList(
@Parameter(description = "업무 아이디") @RequestParam(name="workId") String workId,
Principal principal
) {
return ResponseEntity.ok(manualService.introList(workId));
}
@Operation(summary = "매뉴얼 조회(문서)", description = "본인의 work id 로 문서 매뉴얼 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{ManualDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/manual/doc")
public ResponseEntity docList(
@Parameter(description = "업무 아이디") @RequestParam(name="workId") String workId,
Principal principal
) {
return ResponseEntity.ok(manualService.findDoc(workId));
}
@Operation(summary = "매뉴얼 조회(동영상)", description = "본인의 work id 로 동영상 매뉴얼 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{ManualDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/manual/video")
public ResponseEntity videoList(
@Parameter(description = "검색") @RequestParam(name="search", defaultValue = "", required = false) String search,
@Parameter(description = "업무 아이디") @RequestParam(name="workId", defaultValue = "", required = false) String workId,
Principal principal
) {
return ResponseEntity.ok(manualService.findVideo(search, workId));
}
@Operation(summary = "매뉴얼 조회(동영상)", description = "본인이 등록한 work id 로 동영상 매뉴얼 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{ManualDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/manual/video/sm")
public ResponseEntity videoListSm(
@Parameter(description = "업무 아이디") @RequestParam(name="workId", required = false) String workId,
Principal principal
) {
return ResponseEntity.ok(manualService.findVideoSm(workId, principal.getName()));
}
@Operation(summary = "매뉴얼(이미지) 스트리밍", description = "workId, vnm 으로 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{Byte[].class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/manual/view/image")
public ResponseEntity<byte[]> contentImageView(
@Parameter(description = "업무 아이디") @RequestParam("workId") String workId,
@Parameter(description = "파일 물리명") @RequestParam("vnm") String vnm,
Principal principal) {
byte[] bytes = manualService.loadImage(
ManualId.builder()
.workId(workId)
.vnm(vnm).build()
);
CacheControl cacheControl = CacheControl.maxAge(Duration.ofDays(7)).cachePublic().staleWhileRevalidate(Duration.ofDays(7));
// HTTP 헤더 설정
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
headers.setContentLength(bytes.length);
return ResponseEntity.ok()
.headers(headers)
.cacheControl(cacheControl)
.body(bytes);
// return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
}
@Operation(summary = "매뉴얼(비디오) 스트리밍", description = "workId, vnm 으로 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{Byte[].class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/manual/view/video")
public ResponseEntity<List<ResourceRegion>> contentMovieView(
@Parameter(description = "동영상 아이디") @RequestParam("id") int id,
@Parameter(description = "숏츠 : S 원본 : O") @RequestParam("id") String type,
@RequestHeader HttpHeaders headers,
Principal principal) {
try {
Resource video = manualService.loadVideo(id, type);
List<ResourceRegion> regions = HttpRange.toResourceRegions(headers.getRange(), video);
return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT)
.contentType(MediaType.parseMediaType("video/mp4"))
.body(regions);
} catch (IOException e) {
// 클라이언트가 연결을 끊었을 때 발생하는 예외 처리
// 로그를 남기고 스트리밍을 중단
System.err.println("IOException occurred during streaming: " + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
@Operation(summary = "매뉴얼(문서) 다운로드", description = "workId, vnm 으로 다운로드")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{Byte[].class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/manual/download/doc")
public ResponseEntity<byte[]> docDownload(
@Parameter(description = "업무 아이디") @RequestParam("workId") String workId,
@Parameter(description = "파일 물리명") @RequestParam("vnm") String vnm,
Principal principal) {
HashMap<String, Object> map = manualService.loadOoc(
ManualId.builder()
.workId(workId)
.vnm(vnm).build()
);
// HTTP 헤더 설정
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + URLEncoder.encode((String) map.get("onm")) + "\"");
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentLength(((byte[])map.get("data")).length);
return new ResponseEntity<>((byte[])map.get("data"), headers, HttpStatus.OK);
}
@Operation(summary = "매뉴얼 저장", description = "메뉴얼 저장 (required : workId, version, type, onm,. data) 0000 문서매뉴얼, 0100 이미지")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PostMapping("/manual")
public ResponseEntity save(@RequestBody ManualDto manualDto) {
manualService.save(manualDto);
return ResponseEntity.ok("success");
}
@Operation(summary = "동영상 매뉴얼 저장", description = "동영상 메뉴얼 저장 (required : workId, sonm, onm)")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PostMapping("/manual/video")
public ResponseEntity videoSave(@RequestBody VManualDto vmanualDto) {
manualService.videoSave(vmanualDto);
return ResponseEntity.ok("success");
}
@Operation(summary = "동영상 매뉴얼 삭제", description = "동영상 메뉴얼 삭제 (delete_yn = true)")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@DeleteMapping("/manual/video/{id}")
public ResponseEntity videoDelete(
@Parameter(description = "동영상 매뉴얼 아이디") @PathVariable("id") int id,
Principal principal
) {
return ResponseEntity.ok(manualService.videoDelete(principal.getName(), id));
}
@Operation(summary = "매뉴얼 수정", description = "메뉴얼 수정 (required : workId, version, type, onm, data) 동영상 이미지 메뉴얼 지원 안함")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PutMapping("/manual")
public ResponseEntity update(@RequestBody ManualDto manualDto) {
manualService.update(manualDto);
return ResponseEntity.ok("success");
}
@Operation(summary = "매뉴얼 삭제", description = "메뉴얼 삭제")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@DeleteMapping("/manual/{workId}/{vnm}")
public ResponseEntity delete(
@Parameter(description = "업무 아이디") @PathVariable("workId") String workId,
@Parameter(description = "물리파일명") @PathVariable("vnm") String vnm
) {
manualService.delete(workId, vnm);
return ResponseEntity.ok("success");
}
}

View File

@@ -0,0 +1,116 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.model.User;
import com.kospo.talk.payload.AutoReplyDto;
import com.kospo.talk.payload.PersonAutoReplyDto;
import com.kospo.talk.service.AutoReplyService;
import com.kospo.talk.service.PersonAutoReplyService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
import java.time.LocalDateTime;
@RestController
@Tag(name = "PersonAutoReply Api", description = "개인 자동응답 관리")
@RequestMapping("/api")
@RequiredArgsConstructor
public class PersonAutoReplyController {
private final PersonAutoReplyService personAutoReplyService;
@Operation(summary = "자동응답 조회", description = "본인의 work id 와 사번 으로 자동응답 내용 검색")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{PersonAutoReplyDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/person/autoReply")
public ResponseEntity findAll(
@Parameter(description = "내용") @RequestParam(name="content", required = false) String content,
Principal principal
) {
return ResponseEntity.ok(personAutoReplyService.findByWorkAndSabunAndLikeContent(PersonAutoReplyDto.builder()
.sabun(principal.getName())
.content(content == null ? "" : "%"+content+"%")
.build()));
}
@Operation(summary = "자동응답 저장", description = "자동응답 저장")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PostMapping("/person/autoReply")
public ResponseEntity save(@RequestBody PersonAutoReplyDto personAutoReplyDto, Principal principal) {
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
personAutoReplyDto.setSabun(user.getSabun());
personAutoReplyService.save(personAutoReplyDto);
return ResponseEntity.ok("success");
}
@Operation(summary = "자동응답 삭제", description = "자동응답 삭제")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@DeleteMapping("/person/autoReply/{id}")
public ResponseEntity delete(
@Parameter(description = "아이디") @PathVariable("id") int id,
Principal principal) {
personAutoReplyService.delete(id);
return ResponseEntity.ok("success");
}
@Operation(summary = "자동응답 수정", description = "자동응답 수정")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PutMapping("/person/autoReply")
public ResponseEntity update(@RequestBody PersonAutoReplyDto personAutoReplyDto, Principal principal) {
personAutoReplyService.update(personAutoReplyDto);
return ResponseEntity.ok("success");
}
}

View File

@@ -0,0 +1,150 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.model.Question;
import com.kospo.talk.model.QuestionId;
import com.kospo.talk.model.User;
import com.kospo.talk.payload.QuestionDto;
import com.kospo.talk.service.QuestionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
import java.time.LocalDateTime;
@RestController
@Tag(name = "Question Api", description = "질문 관리")
@RequestMapping("/api")
@RequiredArgsConstructor
public class QuestionController {
private final QuestionService questionService;
@Operation(summary = "질문 조회", description = "본인 업무 시스템 질문 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{Question.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/question")
public ResponseEntity questionList(
Principal principal
) {
return ResponseEntity.ok(questionService.findBySabun(principal.getName()));
}
@Operation(summary = "질문 조회", description = "업무별 질문 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{Question.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/question/{workId}")
public ResponseEntity chatList(
@Parameter(description = "업무아이디") @PathVariable("workId") String workId,
Principal principal
) {
return ResponseEntity.ok(questionService.findByWorkId(workId));
}
@Operation(summary = "질문 저장", description = "유지보수 담당자 질문 데이터 저장")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json",
schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PostMapping("/question")
public ResponseEntity save(
@RequestBody QuestionDto questionDto
) {
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
questionDto.setInsSabun(user.getSabun());
questionDto.setInsName(user.getName());
questionDto.setInsDate(LocalDateTime.now());
questionService.save(questionDto);
return ResponseEntity.ok("success");
}
@Operation(summary = "질문 수정", description = "유지보수 담당자 질문 데이터 수정")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json",
schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PutMapping("/question")
public ResponseEntity update(
@RequestBody QuestionDto questionDto,
Principal principal
) {
questionService.update(questionDto);
return ResponseEntity.ok("success");
}
@Operation(summary = "질문 삭제", description = "유지보수 담당자 질문 데이터 삭제")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json",
schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@DeleteMapping("/question/{workId}/{sort}")
public ResponseEntity delete(
@Parameter(description = "업무아이디") @PathVariable("workId") String workId,
@Parameter(description = "순차") @PathVariable("sort") Integer sort,
Principal principal
) {
questionService.delete(QuestionId.builder()
.workId(workId)
.sort(sort)
.build());
return ResponseEntity.ok("success");
}
}

View File

@@ -0,0 +1,13 @@
package com.kospo.talk.controller;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Tag(name = "Role Api", description = " 관리")
@RequestMapping("/api/role")
@RequiredArgsConstructor
public class RoleController {
}

View File

@@ -0,0 +1,274 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.config.utils.CommonUtils;
import com.kospo.talk.model.Talk;
import com.kospo.talk.model.TalkMessage;
import com.kospo.talk.model.TalkMessageId;
import com.kospo.talk.model.Work;
import com.kospo.talk.payload.*;
import com.kospo.talk.service.TalkMemberService;
import com.kospo.talk.service.TalkMessageService;
import com.kospo.talk.service.TalkService;
import com.kospo.talk.service.WorkService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.client.WebClient;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@Tag(name = "SCM API", description = "SCM 작업 관리")
@RequestMapping("/api/scm")
@RequiredArgsConstructor
@Slf4j
public class ScmController {
@Value("${rabbitmq.user.exchange}")
private String userExchange;
@Value("${rabbitmq.user.route}")
private String userRoute;
@Value("${rabbitmq.talk.exchange}")
private String talkExchange;
@Value("${rabbitmq.talk.route}")
private String talkRoute;
private final WebClient scmWebClient;
private final TalkService talkService;
private final WorkService workService;
private final TalkMessageService talkMessageService;
private final TalkMemberService talkMemberService;
private final RabbitTemplate userTemplate;
private final RabbitTemplate talkTemplate;
@Operation(summary = "SCM 업무 카테고리 그룹 조회", description = "SCM 업무 카테고리 그룹 조회 후 map 으로 리턴")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{HashMap.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/group")
public ResponseEntity getGroup(
HttpServletRequest request,
Principal principal
) {
MultiValueMap cookieMap = new LinkedMultiValueMap();
Arrays.stream(request.getCookies()).forEach((cookie) -> {
cookieMap.add(cookie.getName(), cookie.getValue());
});
MultiValueMap headerMap = new LinkedMultiValueMap();
headerMap.add("X-Forwarded-For", request.getHeader("X-Forwarded-For"));
List<HashMap<String,String>> resultList = scmWebClient.post()
.uri("/api/reqScmCodeGroup.do")
.headers(h -> h.addAll(headerMap))
.cookies(c -> c.addAll(cookieMap))
.retrieve().bodyToMono(List.class).block();
return ResponseEntity.ok(resultList);
}
@Operation(summary = "SCM 업무 코드 조회", description = "SCM 업무 코드 조회 후 map 으로 리턴")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{HashMap.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/code")
public ResponseEntity getCode(
@Parameter(description = "구분코드") @RequestParam("gubun") String gubun,
HttpServletRequest request,
Principal principal
) {
MultiValueMap cookieMap = new LinkedMultiValueMap();
Arrays.stream(request.getCookies()).forEach((cookie) -> {
cookieMap.add(cookie.getName(), cookie.getValue());
});
MultiValueMap headerMap = new LinkedMultiValueMap();
headerMap.add("X-Forwarded-For", request.getHeader("X-Forwarded-For"));
HashMap<String, String> body =new HashMap();
body.put("SEARCH_SYS_GUBUN", gubun);
List<HashMap<String,String>> resultList = scmWebClient.post()
.uri("/api/reqScmCodeList.do")
.headers(h -> h.addAll(headerMap))
.cookies(c -> c.addAll(cookieMap))
.bodyValue(body)
.retrieve().bodyToMono(List.class).block();
return ResponseEntity.ok(resultList);
}
@Operation(summary = "SCM 작업 요청 하기", description = "itsm 요청 정보 저장 결과값으로 req_id 리턴")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PostMapping("/save")
public ResponseEntity save(
@RequestBody ScmDto scmDto,
HttpServletRequest request,
Principal principal
) {
MultiValueMap cookieMap = new LinkedMultiValueMap();
Arrays.stream(request.getCookies()).forEach((cookie) -> {
cookieMap.add(cookie.getName(), cookie.getValue());
});
MultiValueMap headerMap = new LinkedMultiValueMap();
headerMap.add("X-Forwarded-For", request.getHeader("X-Forwarded-For"));
try {
String req_id = scmWebClient.post()
.uri("/api/reqHelpTalkIns.do")
.headers(h -> h.addAll(headerMap))
.cookies(c -> c.addAll(cookieMap))
.bodyValue(scmDto)
.retrieve().bodyToMono(String.class).block();
Talk talk = talkService.findByOne(scmDto.getTalk_id());
talk.setReqId(req_id);
talkService.createTalk(talk);
MessageDto messageDto = MessageDto.builder().type("EXTERNAL_SAVE")
.reqId(req_id)
.talkId(talk.getTalkId()).build();
talkTemplate.convertAndSend(talkExchange, talkRoute + talk.getTalkId(), messageDto);
return ResponseEntity.ok(req_id);
} catch(Exception e) {
return ResponseEntity.ok("");
}
}
@Operation(summary = "외부 ITSM 만족도 조사", description = "itsm 만족도 조사 등록")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PostMapping("/satis")
public ResponseEntity satisSave(
@RequestBody SatisDto satisDto,
HttpServletRequest request,
Principal principal
) {
MultiValueMap cookieMap = new LinkedMultiValueMap();
Arrays.stream(request.getCookies()).forEach((cookie) -> {
cookieMap.add(cookie.getName(), cookie.getValue());
});
MultiValueMap headerMap = new LinkedMultiValueMap();
Talk currentTalk = talkService.findByOne(satisDto.getTalk_id());
Map<String, String> resultMap = new HashMap<>();
headerMap.add("X-Forwarded-For", request.getHeader("X-Forwarded-For"));
resultMap = scmWebClient.post()
.uri("/api/reqHelpTalkManIns.do")
.headers(h -> h.addAll(headerMap))
.cookies(c -> c.addAll(cookieMap))
.bodyValue(HappyDto.builder()
.req_id(currentTalk.getReqId())
.h_point(satisDto.getH_point())
.opinion(satisDto.getOpinion()).build()
)
.retrieve().bodyToMono(Map.class).block();
String result = resultMap.get("result");
if(result.equals("s")) {
talkService.ratingUpdate(currentTalk.getReqId());
Work work = workService.findByTalkId(currentTalk.getTalkId());
MessageDto messageDto = MessageDto.builder()
.type("STATUS")
.message("만족도 조사에 참여해 주셔서 감사해요.\n앞으로도 많은 참여 부탁드려요.")
.talkId(currentTalk.getTalkId())
.workId(work.getWorkId())
.workNm(work.getWorkNm())
.insSabun("info")
.insName("시스템")
.insDate(LocalDateTime.now())
.build();
talkMessageService.save(TalkMessage.builder()
.id(TalkMessageId.builder().talkId(messageDto.getTalkId()).sabun(messageDto.getInsSabun()).insDate(messageDto.getInsDate()).build())
.message(messageDto.getMessage())
.searchYn(false)
.insName(messageDto.getInsName()).build()
);
talkMemberService.findAllByTalkId(messageDto.getTalkId()).stream().forEach(talkMember -> {
talkMember.getId().getSabun();
userTemplate.convertAndSend(userExchange, userRoute + talkMember.getId().getSabun(), messageDto);
});
}
return ResponseEntity.ok(resultMap.get("result"));
}
}

View File

@@ -0,0 +1,71 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.payload.AutoReplyDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.Principal;
import java.util.HashMap;
@RestController
@Tag(name = "Service Api", description = "서비스 관리")
@RequestMapping("/api")
@RequiredArgsConstructor
public class SerivceController {
@Operation(summary = "현재 접속 ap 조회", description = "현재 접속 서비스 확인")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/getApInfo")
public ResponseEntity findAll(
HttpServletRequest request,
Principal principal
) {
HashMap<String, String> map = new HashMap<>();
try {
String ip = InetAddress.getLocalHost().getHostAddress();
if(ip.equals("10.130.7.62")) {
map.put("server", "ap1");
} else if(ip.equals("10.130.7.63")) {
map.put("server", "ap2");
} else if(ip.equals("10.130.7.64")) {
map.put("server", "ap3");
} else if(ip.equals("10.130.7.65")) {
map.put("server", "ap4");
} else if(ip.equals("10.130.7.61")) {
map.put("server", "ma");
} else {
map.put("server", "local");
}
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
return ResponseEntity.ok(map);
}
}

View File

@@ -0,0 +1,53 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.model.SmUserId;
import com.kospo.talk.payload.SmUserDto;
import com.kospo.talk.payload.WorkDto;
import com.kospo.talk.service.SmUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
import java.util.Date;
@RestController
@Tag(name = "SmUser Api", description = "유지보수 관리")
@RequestMapping("/api")
@RequiredArgsConstructor
public class SmUserController {
private final SmUserService smUserService;
@Operation(summary = "유지보수 요원 조회", description = "업무 아이디로 유지보수 요원 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{SmUserDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/smUser")
@Transactional(readOnly = true)
public ResponseEntity findByWorkId(
@Parameter(description = "업무코드") @RequestParam(value="workId", defaultValue = "") String workId,
Principal principal
) {
return ResponseEntity.ok(smUserService.findByWorkId(workId));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.service.StressService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.security.Principal;
@RestController
@Tag(name = "Stress Api", description = "정신건강 관리")
@RequestMapping("/api")
@RequiredArgsConstructor
public class StressController {
private final StressService stressService;
@Operation(summary = "마크 설정", description = "마크 활성화시 최상단 고정")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{Boolean.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PutMapping("/stress/{sabun}/{stress}")
public ResponseEntity stress(
@Parameter(description = "사번") @PathVariable("sabun") String sabun,
@Parameter(description = "멘탈지수") @PathVariable("stress") String stress
) {
stressService.stress(sabun, stress);
return ResponseEntity.ok(null);
}
}

View File

@@ -0,0 +1,137 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.model.Talk;
import com.kospo.talk.service.TalkMemberService;
import com.kospo.talk.service.TalkService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
@RestController
@Tag(name = "Talk Api", description = "채팅 관리")
@RequestMapping("/api")
@RequiredArgsConstructor
public class TalkController {
private final TalkService talkService;
private final TalkMemberService talkMemberService;
@Operation(summary = "룸 조회", description = "현재 사용자의 룸 목록을 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{Talk.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/talk")
public ResponseEntity talkList(
Principal principal
) {
return ResponseEntity.ok(talkService.findByMemberSabun(principal.getName()));
}
@Operation(summary = "룸 그룹 조회", description = "톡멤버의 룸 목록을 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{Talk.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/talk/group")
public ResponseEntity talkGroupList(
@Parameter(description = "시작 라인") @RequestParam(name = "start") Integer start,
@Parameter(description = "가져올 데이터수") @RequestParam(name = "row") Integer row,
Principal principal
) {
return ResponseEntity.ok(talkService.findTalkGroup(principal.getName(), start, row));
}
@Operation(summary = "그룹톡 정보 조회", description = "talkId 해당되는 정보 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{Talk.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/talk/group/{talkId}")
public ResponseEntity talkGroupList(
@Parameter(description = "톡아이디") @PathVariable String talkId,
Principal principal
) {
return ResponseEntity.ok(talkService.findTalkGroupByTalkId(principal.getName(), talkId));
}
@Operation(summary = "마크 설정", description = "마크 활성화시 최상단 고정")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{Boolean.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PutMapping("/talk/mark/{talkId}")
public ResponseEntity markYn(
@Parameter(description = "채팅 아이디") @PathVariable("talkId") String talkId,
Principal principal) {
boolean flag = talkMemberService.updateMark(talkId, principal.getName());
return ResponseEntity.ok(flag);
}
@Operation(summary = "삭제 설정", description = "채팅방이 종료된 경우에만 본인의 채팅방 삭제(실제 삭제 아님 상태제어)")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{Boolean.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PutMapping("/talk/delete/{talkId}")
public ResponseEntity deleteYn(
@Parameter(description = "채팅 아이디") @PathVariable("talkId") String talkId,
Principal principal) {
boolean flag = talkMemberService.updateDelete(talkId, principal.getName());
return ResponseEntity.ok(flag);
}
}

View File

@@ -0,0 +1,355 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.config.exception.ErrorCode;
import com.kospo.talk.config.utils.CommonUtils;
import com.kospo.talk.exception.CustomException;
import com.kospo.talk.model.*;
import com.kospo.talk.payload.ExternalMessageDto;
import com.kospo.talk.payload.MessageDto;
import com.kospo.talk.payload.TalkDto;
import com.kospo.talk.payload.TalkReadDto;
import com.kospo.talk.service.TalkAttachService;
import com.kospo.talk.service.TalkMessageService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.InputStreamResource;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import org.yaml.snakeyaml.util.UriEncoder;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@Tag(name = "Talk Message Api", description = "톡 대화내용 관리")
@RequestMapping("/api")
@RequiredArgsConstructor
public class TalkMessageController {
private final TalkMessageService talkMessageService;
private final TalkAttachService talkAttachService;
@Operation(summary = "대화 내용 조회", description = "채팅 아이디로 대화 내용을 조회(날짜별 조회) 한다.")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{TalkDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class})))
})
@GetMapping("/message")
public ResponseEntity contentList(
@Parameter(description = "룸아이디") @RequestParam(name = "talkId") String talkId,
@Parameter(description = "날짜") @RequestParam(name = "insDate") String insDate,
Principal principal) {
return ResponseEntity.ok(
talkMessageService.getMessage(talkId, insDate)
);
}
@Operation(summary = "대화 내용 조회(30건)", description = "사번으로 본인이 참여된 톡방 데이터 호출")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{TalkDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class})))
})
@GetMapping("/message/all")
public ResponseEntity getMessageAll(
Principal principal) {
return ResponseEntity.ok(
talkMessageService.getMessageAll(principal.getName())
);
}
@Operation(summary = "(소켓 재연결)추가된 대화 내용 조회", description = "마지막 등록시간(last_message_date) 보다 최신 데이터 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{TalkDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class})))
})
@GetMapping("/message/more/all")
public ResponseEntity getMessageAllByInsDate(
@Parameter(description = "마지막 메시지 시간") @RequestParam(name = "insDate") String insDate,
Principal principal) {
return ResponseEntity.ok(
talkMessageService.getMessageAllMore(principal.getName(), UriEncoder.decode(insDate))
);
}
@Operation(summary = "대화 내용 조회", description = "채팅 아이디로 대화 내용을 조회(라인 조회) 한다.")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{TalkDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class})))
})
@GetMapping("/message/line")
public ResponseEntity contentLine(
@Parameter(description = "룸아이디") @RequestParam(name = "talkId") String talkId,
@Parameter(description = "시작 라인") @RequestParam(name = "start") Integer start,
@Parameter(description = "가져올 데이터수") @RequestParam(name = "row") Integer row,
@Parameter(description = "마지막 메시지 일자") @RequestParam(name = "insDate", required = false, defaultValue = "") String insDate,
Principal principal) {
return ResponseEntity.ok(
talkMessageService.getMessageLine(talkId, start, row, insDate)
);
}
@Operation(summary = "대화 내용 조회", description = "채팅 아이디로 대화 내용을 조회(검색 조회) 한다.")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{TalkDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class})))
})
@GetMapping("/message/search")
public ResponseEntity contentSearchList(
@Parameter(description = "룸아이디") @RequestParam(name = "talkId") String talkId,
@Parameter(description = "검색") @RequestParam(name = "search") String search,
Principal principal) {
return ResponseEntity.ok(
talkMessageService.getSearchMessage(talkId, search)
);
}
@Operation(summary = "전체 검색", description = "특정 업무의 모든 채팅방의 내용을 검색한다.")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{TalkDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class})))
})
@GetMapping("/message/search/all")
public ResponseEntity talkListSearchContent(
@Parameter(description = "검색") @RequestParam(name = "search") String search,
Principal principal) {
return ResponseEntity.ok(
talkMessageService.getAllSearchContent(search, principal.getName())
);
}
@Operation(summary = "대화 읽음 처리", description = "채팅 아이디로 대화 내용을 (상대방 메시지) 전체 읽음 처리 한다.")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{Integer.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class})))
})
@PostMapping("/message/read")
public ResponseEntity contentRead(
@RequestBody TalkReadDto talkReadDto,
Principal principal) {
return ResponseEntity.ok(
talkMessageService.read(talkReadDto.getTalkId(), principal.getName())
);
}
@Operation(summary = "첨부파일 썸네일", description = "첨부파일 썸네일 이이지 사이즈 조절 및 crop 기능")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{Byte[].class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class})))
})
@GetMapping("/message/thumb")
public ResponseEntity<byte[]> contentThumbRead(
@Parameter(description = "채팅 아이디") @RequestParam("talkId") String talkId,
@Parameter(description = "사번") @RequestParam("sabun") String sabun,
@Parameter(description = "등록일자") @RequestParam("insDate") String insDate,
@Parameter(description = "정렬") @RequestParam("sort") Integer sort,
@Parameter(description = "size") @RequestParam("size") Integer size,
Principal principal) {
byte[] thumbnailBytes = talkAttachService.readThumb(
TalkAttachId.builder()
.talkId(talkId)
.sabun(sabun)
.insDate(CommonUtils.stringToDate(insDate, "yyyy-MM-dd HH:mm:ss.SSSSSS"))
.sort(sort).build(), size
);
// HTTP 헤더 설정
HttpHeaders headers = new HttpHeaders();
headers.set("Cache-Control", "max-age=31536000, public");
headers.setContentType(MediaType.IMAGE_PNG);
headers.setContentLength(thumbnailBytes.length);
return new ResponseEntity<>(thumbnailBytes, headers, HttpStatus.OK);
}
@Operation(summary = "첨부파일 썸네일", description = "첨부파일 썸네일 이이지 사이즈 조절 및 crop 기능")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{Byte[].class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class})))
})
@GetMapping("/message/image")
public ResponseEntity<byte[]> contentImageRead(
@Parameter(description = "채팅 아이디") @RequestParam("talkId") String talkId,
@Parameter(description = "사번") @RequestParam("sabun") String sabun,
@Parameter(description = "등록일자") @RequestParam("insDate") String insDate,
@Parameter(description = "정렬") @RequestParam("sort") Integer sort,
Principal principal) {
byte[] thumbnailBytes = talkAttachService.readFile(
TalkAttachId.builder()
.talkId(talkId)
.sabun(sabun)
.insDate(CommonUtils.stringToDate(insDate, "yyyy-MM-dd HH:mm:ss.SSSSSS"))
.sort(sort).build()
);
// HTTP 헤더 설정
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
headers.set("Cache-Control", "max-age=31536000, public");
headers.setContentLength(thumbnailBytes.length);
return new ResponseEntity<>(thumbnailBytes, headers, HttpStatus.OK);
}
@Operation(summary = "첨부파일 다운로드", description = "이미지 다운로드")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{Byte[].class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class})))
})
@GetMapping("/message/download")
public ResponseEntity<InputStreamResource> contentFileDownload(
@Parameter(description = "채팅 아이디") @RequestParam("talkId") String talkId,
@Parameter(description = "사번") @RequestParam("sabun") String sabun,
@Parameter(description = "등록일자") @RequestParam("insDate") String insDate,
Principal principal) throws IOException {
ByteArrayInputStream bais = null;
List<TalkAttach> lists = talkAttachService.getTalkAttachList(talkId, sabun, insDate);
HttpHeaders headers = new HttpHeaders();
if (lists.size() == 1) {
// HTTP 헤더 설정
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + UriEncoder.encode(lists.get(0).getOnm()));
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
bais = talkAttachService.getTalkAttachByte(lists.get(0));
} else if (lists.isEmpty()) {
throw new CustomException(ErrorCode.NO_RESULT);
} else {
// HTTP 헤더 설정
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + UriEncoder.encode(lists.get(0).getOnm() + "" + (lists.size() - 1) + ".zip"));
headers.setContentType(MediaType.parseMediaType("application/zip"));
bais = talkAttachService.getTalkAttachCompression(lists);
}
return new ResponseEntity<>(new InputStreamResource(bais), headers, HttpStatus.OK);
}
@Operation(summary = "외부 메시지 저장", description = "외부 메시지 저장")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{String.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class})))
})
@PostMapping("/message")
public ResponseEntity externalSave(@RequestBody ExternalMessageDto externalMessageDto) {
talkMessageService.externalSave(externalMessageDto);
return ResponseEntity.ok("s");
}
}

View File

@@ -0,0 +1,181 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.config.utils.CommonUtils;
import com.kospo.talk.config.utils.CryptoUtil;
import com.kospo.talk.model.User;
import com.kospo.talk.payload.ListeningDto;
import com.kospo.talk.payload.MasterDto;
import com.kospo.talk.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
@RestController
@Tag(name = "User Api", description = "사용자 관리")
@RequestMapping("/api/user")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@Operation(summary = "현재 사용자 정보 조회", description = "현재 사용자의 인사정보를 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{User.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/info")
public ResponseEntity userInfo(
// @Parameter(description = "사번") @Htt(value="sabun", required = false) String sabun,
Principal principal) {
// System.out.println(principal.getName());
return ResponseEntity.ok(userService.findByUserid(principal.getName()));
}
@Operation(summary = "사용자 정보 조회", description = "사번으로 인사정보를 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{User.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/info/{sabun}")
public ResponseEntity userInfo(
@Parameter(description = "사번") @PathVariable(value="sabun", required = false) String sabun,
Principal principal) {
return ResponseEntity.ok(userService.findByUserid(sabun));
}
@Operation(summary = "현재 사용자 정보 조회(유지보수)", description = "현재 사용자가 유지보수자 인지 확인")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{User.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/info/sm")
public ResponseEntity smUserInfo(
Principal principal) {
return ResponseEntity.ok(userService.findSmByUserid(principal.getName()));
}
@Operation(summary = "현재 사용자 정보 조회(고객사)", description = "현재 사용자가 고객사 인지 확인")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{User.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/info/client")
public ResponseEntity clientUserInfo(
Principal principal) {
return ResponseEntity.ok(userService.findClientByUserid(principal.getName()));
}
@Operation(summary = "사번 암호화", description = "사번 암호화된 값 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/info/enc")
public ResponseEntity encryptSabun(
@RequestParam("sabun") String sabun,
Principal principal) throws Exception {
String encSabun = CryptoUtil.encrypt(sabun);
return ResponseEntity.ok(encSabun);
}
@Operation(summary = "메시지 공통 상태 조회", description = "메시지 공통 상태 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{Integer.class}))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping(value = "/listening")
public ResponseEntity getListening(
@RequestParam("talkId") String talkId,
Principal principal
) {
return ResponseEntity.ok(CommonUtils.getListening(
ListeningDto.builder()
.sabun(principal.getName())
.talkId(talkId).build()
));
}
@Operation(summary = "메시지 공통 상태 갱신", description = "메시지 공통 상태 갱신")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PostMapping(value = "/listening")
public ResponseEntity setListening(
@RequestBody ListeningDto listeningDto,
Principal principal
) {
listeningDto.setSabun(principal.getName());
CommonUtils.setListening(listeningDto);
return ResponseEntity.ok("success");
}
}

View File

@@ -0,0 +1,209 @@
package com.kospo.talk.controller;
import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.payload.WorkDto;
import com.kospo.talk.payload.WorkLogoDto;
import com.kospo.talk.service.WorkService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.security.Principal;
import java.util.Date;
@RestController
@Tag(name = "Work Api", description = "업무 관리")
@RequestMapping("/api")
@RequiredArgsConstructor
public class WorkController {
private final WorkService workService;
@Operation(summary = "업무 조회", description = "사이트 URL 로 담당자 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{WorkDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/work")
@Transactional(readOnly = true)
public ResponseEntity findByWorkURl(
@Parameter(description = "사이트url") @RequestParam(value="url", defaultValue = "") String url,
@Parameter(description = "업무코드") @RequestParam(value="workId", defaultValue = "") String workId,
Principal principal
) {
return ResponseEntity.ok(workService.findByWorkUrl(url, workId, principal.getName()));
}
@Operation(summary = "업무 카테고리 조회", description = "업무 카테고리 조회 (상위 코드)")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{WorkDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/work/dept")
@Transactional(readOnly = true)
public ResponseEntity findByWorkCategory(
@Parameter(description = "상위코드") @RequestParam(value="pWorkId", defaultValue = "") String pWorkId,
Principal principal
) {
return ResponseEntity.ok(workService.findByWorkDepth(pWorkId));
}
@Operation(summary = "업무 조회", description = "업무 카테고리 조회 (업무명 & 담당자명)")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{WorkDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/work/search")
@Transactional(readOnly = true)
public ResponseEntity findByWorkSearch(
@Parameter(description = "업무명&담당자명") @RequestParam(value="name", defaultValue = "") String name,
Principal principal
) {
return ResponseEntity.ok(workService.findByWorkSearech(name));
}
@Operation(summary = "업무 카테고리 상위 전체 조회", description = "업무 카테고리 조회 (업무 코드)")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{WorkDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/work/dept/all")
@Transactional(readOnly = true)
public ResponseEntity findByAlLDepth(
@Parameter(description = "업무코드") @RequestParam(value="workId", defaultValue = "") String workId,
Principal principal
) {
return ResponseEntity.ok(workService.findByAlLDepth(workId));
}
@Operation(summary = "업무 전체 조회", description = "업무 전체 목록 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{WorkDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/work/all")
@Transactional(readOnly = true)
public ResponseEntity findAll(
Principal principal
) {
return ResponseEntity.ok(workService.findAll());
}
@Operation(summary = "본인 업무 조회", description = "본인 업무 목록 조회")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
schema = @Schema(oneOf =
{WorkDto.class})
))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@GetMapping("/work/me")
@Transactional(readOnly = true)
public ResponseEntity findBySabun(
Principal principal
) {
return ResponseEntity.ok(workService.findSabun(principal.getName()));
}
@Operation(summary = "시스템 로고 저장", description = "시스템 로고 등록")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json",
schema = @Schema(oneOf =
{WorkLogoDto.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PostMapping("/work/logo")
public ResponseEntity logoSave(
@RequestBody WorkLogoDto workLogoDto,
Principal principal
) {
return ResponseEntity.ok(workService.logoSave(workLogoDto));
}
@Operation(summary = "시스템 로고 수정", description = "시스템 로고 수정")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json",
schema = @Schema(oneOf =
{WorkLogoDto.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PutMapping("/work/logo")
public ResponseEntity logoUpdate(
@RequestBody WorkLogoDto workLogoDto,
Principal principal
) {
return ResponseEntity.ok(workService.logoSave(workLogoDto));
}
}

View File

@@ -0,0 +1,14 @@
package com.kospo.talk.exception;
import com.kospo.talk.config.exception.ErrorCode;
import lombok.Getter;
@Getter
public class CustomException extends RuntimeException{
private ErrorCode errorCode;
public CustomException(ErrorCode errorCode) {
this.errorCode = errorCode;
}
}

View File

@@ -0,0 +1,7 @@
package com.kospo.talk.exception;
public class CustomExpireTokenException extends RuntimeException{
public CustomExpireTokenException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,7 @@
package com.kospo.talk.exception;
public class CustomMalformedJwtException extends RuntimeException{
public CustomMalformedJwtException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,7 @@
package com.kospo.talk.exception;
public class CustomNoAccountException extends RuntimeException{
public CustomNoAccountException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,7 @@
package com.kospo.talk.exception;
public class CustomNoMatchTokenException extends RuntimeException{
public CustomNoMatchTokenException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,7 @@
package com.kospo.talk.exception;
public class CustomNoResultException extends RuntimeException{
public CustomNoResultException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,7 @@
package com.kospo.talk.exception;
public class CustomNoSameIpException extends RuntimeException{
public CustomNoSameIpException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,7 @@
package com.kospo.talk.exception;
public class CustomNoTokenException extends RuntimeException{
public CustomNoTokenException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,49 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import org.hibernate.annotations.ColumnDefault;
import java.time.LocalDateTime;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "auto_reply")
public class AutoReply {
@EmbeddedId
private AutoReplyId id;
@Size(max = 200)
@Column(name = "content", length = 200)
private String content;
@Size(max = 10)
@Column(name = "ins_sabun", length = 10)
private String insSabun;
@Size(max = 20)
@Column(name = "ins_name", length = 20)
private String insName;
@ColumnDefault("CURRENT_TIMESTAMP")
@Column(name = "ins_date")
private LocalDateTime insDate;
/*
TODO [리버스 엔지니어링] 필드를 생성하여 'work_id' 열에 매핑
사용 가능한 액션: 현재 상태대로 주석 해제 | 열 매핑 제거
@MapsId
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "work_id", nullable = false)
private Work work;
*/
}

View File

@@ -0,0 +1,45 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import org.hibernate.Hibernate;
import java.io.Serializable;
import java.util.Objects;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Embeddable
public class AutoReplyId implements Serializable {
private static final long serialVersionUID = 8574100646242609185L;
@Size(max = 4)
@NotNull
@Column(name = "work_id", nullable = false, length = 4)
private String workId;
@Size(max = 4)
@NotNull
@Column(name = "type", nullable = false, length = 4)
private String type;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
AutoReplyId entity = (AutoReplyId) o;
return Objects.equals(this.type, entity.type) &&
Objects.equals(this.workId, entity.workId);
}
@Override
public int hashCode() {
return Objects.hash(type, workId);
}
}

View File

@@ -0,0 +1,31 @@
package com.kospo.talk.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
@Table(name = "code")
public class Code {
@EmbeddedId
private CodeId id;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "id", nullable = false, updatable = false, insertable = false)
private PCode id1;
@Size(max = 20)
@Column(name = "nm", length = 20)
private String nm;
@Size(max = 200)
@Column(name = "description", length = 200)
private String description;
@Column(name = "use_yn")
private Boolean useYn;
}

View File

@@ -0,0 +1,41 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.Hibernate;
import java.util.Objects;
@Getter
@Setter
@Embeddable
public class CodeId implements java.io.Serializable {
private static final long serialVersionUID = -9144701466423603292L;
@NotNull
@Column(name = "id", nullable = false)
private Integer id;
@Size(max = 4)
@NotNull
@Column(name = "code", nullable = false, length = 4)
private String code;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
CodeId entity = (CodeId) o;
return Objects.equals(this.code, entity.code) &&
Objects.equals(this.id, entity.id);
}
@Override
public int hashCode() {
return Objects.hash(code, id);
}
}

View File

@@ -0,0 +1,43 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
@Table(name = "dept")
public class Dept {
@Id
@Size(max = 10)
@Column(name = "dept_cd", nullable = false, length = 10)
private String deptCd;
@Size(max = 200)
@Column(name = "dept_nm", length = 200)
private String deptNm;
@Column(name = "use_yn")
private Boolean useYn;
@Size(max = 50)
@Column(name = "p_dept_cd", length = 50)
private String pDeptCd;
@Size(max = 200)
@Column(name = "formal_name", length = 200)
private String formalName;
@Size(max = 10)
@Column(name = "chief", length = 10)
private String chief;
@Column(name = "bonsa_yn")
private Boolean bonsaYn;
}

View File

@@ -0,0 +1,27 @@
package com.kospo.talk.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.kospo.talk.payload.FavoriteDto;
import jakarta.persistence.*;
import lombok.*;
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@JsonIgnoreProperties(ignoreUnknown = true)
@Table(name = "favorites")
public class Favorite {
@EmbeddedId
private FavoriteId id;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "work_id", nullable = false, updatable = false, insertable = false)
private Work work;
public static Favorite to(FavoriteDto favoriteDto) {
return Favorite.builder().id(FavoriteId.builder().sabun(favoriteDto.getSabun()).workId(favoriteDto.getWorkId()).build()).build();
}
}

View File

@@ -0,0 +1,45 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import org.hibernate.Hibernate;
import java.io.Serializable;
import java.util.Objects;
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class FavoriteId implements Serializable {
private static final long serialVersionUID = 3746070278156087030L;
@Size(max = 10)
@NotNull
@Column(name = "sabun", nullable = false, length = 10)
private String sabun;
@Size(max = 20)
@NotNull
@Column(name = "work_id", nullable = false, length = 20)
private String workId;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
FavoriteId entity = (FavoriteId) o;
return Objects.equals(this.workId, entity.workId) &&
Objects.equals(this.sabun, entity.sabun);
}
@Override
public int hashCode() {
return Objects.hash(workId, sabun);
}
}

View File

@@ -0,0 +1,63 @@
package com.kospo.talk.model;
import com.kospo.talk.payload.ManualDto;
import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import lombok.*;
import java.time.LocalDateTime;
import java.util.Date;
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "manual")
public class Manual {
@EmbeddedId
private ManualId id;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "work_id", nullable = false, updatable = false, insertable = false)
private Work work;
@Column(name = "version")
private String version;
@Size(max = 4)
@Column(name = "type", length = 4)
private String type;
@Size(max = 100)
@Column(name = "onm", length = 100)
private String onm;
@Size(max = 200)
@Column(name = "path", length = 200)
private String path;
@Column(name = "size")
private Integer size;
@Column(name = "ins_date")
private LocalDateTime insDate;
@Column(name = "delete_yn")
private Boolean deleteYn;
public static Manual to(ManualDto manualDto) {
return Manual.builder()
.id(ManualId.builder()
.workId(manualDto.getWorkId())
.vnm(manualDto.getVnm()).build()
)
.version(manualDto.getVersion())
.type(manualDto.getType())
.onm(manualDto.getOnm())
.path(manualDto.getPath())
.deleteYn(manualDto.getDeleteYn())
.insDate(manualDto.getInsDate()).build();
}
}

View File

@@ -0,0 +1,43 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import org.hibernate.Hibernate;
import java.util.Objects;
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class ManualId implements java.io.Serializable {
private static final long serialVersionUID = -8746197877419636430L;
@Size(max = 20)
@NotNull
@Column(name = "work_id", nullable = false, length = 20)
private String workId;
@NotNull
@Column(name = "vnm", nullable = false)
private String vnm;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
ManualId entity = (ManualId) o;
return Objects.equals(this.vnm, entity.vnm) &&
Objects.equals(this.workId, entity.workId);
}
@Override
public int hashCode() {
return Objects.hash(vnm, workId);
}
}

View File

@@ -0,0 +1,26 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "mental")
public class Mental {
@Id
@Column(name = "no", nullable = false, insertable = false, updatable = false)
private String no;
@Column(name = "keyword", insertable = false, updatable = false)
private String keyword;
}

View File

@@ -0,0 +1,31 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
@Table(name = "p_code")
public class PCode {
@Id
@Column(name = "id", nullable = false)
private Integer id;
@Size(max = 20)
@Column(name = "nm", length = 20)
private String nm;
@Size(max = 200)
@Column(name = "description", length = 200)
private String description;
@Column(name = "use_yn")
private Boolean useYn;
}

View File

@@ -0,0 +1,51 @@
package com.kospo.talk.model;
import com.kospo.talk.payload.PersonAutoReplyDto;
import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import lombok.*;
import java.time.Instant;
import java.time.LocalDateTime;
@TableGenerator(
name = "person_auto_reply_seq",
table = "sequence",
pkColumnName = "sequence_name",
valueColumnName = "next_val",
allocationSize = 1
)
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "person_auto_reply")
public class PersonAutoReply {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,generator = "person_auto_reply_seq")
private Integer id;
@Column(name = "sabun", length = 10)
private String sabun;
@Column(name = "work_id", length = 20)
private String workId;
@Column(name = "content", length = 200)
private String content;
@Column(name = "ins_date")
private LocalDateTime insDate;
public static PersonAutoReply to(PersonAutoReplyDto personAutoReplyDto) {
return PersonAutoReply.builder()
.sabun(personAutoReplyDto.getSabun())
.workId(personAutoReplyDto.getWorkId())
.content(personAutoReplyDto.getContent())
.insDate(personAutoReplyDto.getInsDate()).build();
}
}

View File

@@ -0,0 +1,43 @@
package com.kospo.talk.model;
import com.kospo.talk.payload.PIUserDto;
import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import lombok.*;
@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Table(name = "pi_user")
public class PiUser {
@EmbeddedId
private PiUserId id;
@MapsId("workId")
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "work_id", nullable = false)
private Work work;
@Size(max = 50)
@Column(name = "work_nm", length = 50)
private String workNm;
@Size(max = 10)
@Column(name = "name", length = 10)
private String name;
public static PiUser to(PIUserDto piUserDto) {
return PiUser.builder()
.id(PiUserId.builder()
.workId(piUserDto.getWorkId())
.sabun(piUserDto.getSabun()).build()
)
.workNm(piUserDto.getWorkNm())
.name(piUserDto.getName()).build();
}
}

View File

@@ -0,0 +1,45 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import org.hibernate.Hibernate;
import java.io.Serializable;
import java.util.Objects;
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class PiUserId implements Serializable {
private static final long serialVersionUID = -8603174846425880017L;
@Size(max = 10)
@NotNull
@Column(name = "sabun", nullable = false, length = 10)
private String sabun;
@Size(max = 4)
@NotNull
@Column(name = "work_id", nullable = false, length = 4)
private String workId;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
PiUserId entity = (PiUserId) o;
return Objects.equals(this.workId, entity.workId) &&
Objects.equals(this.sabun, entity.sabun);
}
@Override
public int hashCode() {
return Objects.hash(workId, sabun);
}
}

View File

@@ -0,0 +1,54 @@
package com.kospo.talk.model;
import com.kospo.talk.payload.QuestionDto;
import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import lombok.*;
import org.hibernate.annotations.ColumnDefault;
import java.time.LocalDateTime;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "question")
public class Question {
@EmbeddedId
private QuestionId id;
@Size(max = 200)
@Column(name = "content", length = 200)
private String content;
@Column(name = "ask", length = Integer.MAX_VALUE)
private String ask;
@Size(max = 10)
@Column(name = "ins_sabun", length = 10)
private String insSabun;
@Size(max = 20)
@Column(name = "ins_name", length = 20)
private String insName;
@ColumnDefault("CURRENT_TIMESTAMP")
@Column(name = "ins_date")
private LocalDateTime insDate;
public static Question to(QuestionDto questionDto) {
return Question.builder()
.content(questionDto.getContent())
.ask(questionDto.getAsk())
.insSabun(questionDto.getInsSabun())
.insDate(questionDto.getInsDate())
.insName(questionDto.getInsName())
.id(
QuestionId.builder()
.workId(questionDto.getWorkId())
.sort(questionDto.getSort()).build()
).build();
}
}

View File

@@ -0,0 +1,39 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import java.util.Objects;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Embeddable
public class QuestionId implements java.io.Serializable {
private static final long serialVersionUID = -8855211954636978484L;
@Size(max = 20)
@NotNull
@Column(name = "work_id", nullable = false, length = 20)
private String workId;
@NotNull
@Column(name = "sort", nullable = false)
private Integer sort;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof QuestionId that)) return false;
return Objects.equals(workId, that.workId) && Objects.equals(sort, that.sort);
}
@Override
public int hashCode() {
return Objects.hash(workId, sort);
}
}

View File

@@ -0,0 +1,20 @@
package com.kospo.talk.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
@Table(name = "role")
public class Role {
@EmbeddedId
private RoleId id;
@Size(max = 20)
@Column(name = "role_nm", length = 20)
private String roleNm;
}

View File

@@ -0,0 +1,42 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.Hibernate;
import java.util.Objects;
@Getter
@Setter
@Embeddable
public class RoleId implements java.io.Serializable {
private static final long serialVersionUID = -8824456448256682460L;
@Size(max = 4)
@NotNull
@Column(name = "role_id", nullable = false, length = 4)
private String roleId;
@Size(max = 10)
@NotNull
@Column(name = "sabun", nullable = false, length = 10)
private String sabun;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
RoleId entity = (RoleId) o;
return Objects.equals(this.roleId, entity.roleId) &&
Objects.equals(this.sabun, entity.sabun);
}
@Override
public int hashCode() {
return Objects.hash(roleId, sabun);
}
}

View File

@@ -0,0 +1,22 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
@Table(name = "sequence")
public class Sequence {
@Id
@Column(name = "sequence_name", nullable = false, length = Integer.MAX_VALUE)
private String sequenceName;
@Column(name = "next_val")
private Long nextVal;
}

View File

@@ -0,0 +1,43 @@
package com.kospo.talk.model;
import com.kospo.talk.payload.SmUserDto;
import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import lombok.*;
@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Table(name = "sm_user")
public class SmUser {
@EmbeddedId
private SmUserId id;
@MapsId("workId")
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "work_id", nullable = false)
private Work work;
@Size(max = 50)
@Column(name = "work_nm", length = 50)
private String workNm;
@Size(max = 10)
@Column(name = "name", length = 10)
private String name;
public static SmUser to(SmUserDto smUserDto) {
return SmUser.builder()
.id(SmUserId.builder()
.workId(smUserDto.getWorkId())
.sabun(smUserDto.getSabun()).build()
)
.workNm(smUserDto.getWorkNm())
.name(smUserDto.getName()).build();
}
}

View File

@@ -0,0 +1,45 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import org.hibernate.Hibernate;
import java.io.Serializable;
import java.util.Objects;
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class SmUserId implements Serializable {
private static final long serialVersionUID = -8603174846425880017L;
@Size(max = 10)
@NotNull
@Column(name = "sabun", nullable = false, length = 10)
private String sabun;
@Size(max = 20)
@NotNull
@Column(name = "work_id", nullable = false, length = 20)
private String workId;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
SmUserId entity = (SmUserId) o;
return Objects.equals(this.workId, entity.workId) &&
Objects.equals(this.sabun, entity.sabun);
}
@Override
public int hashCode() {
return Objects.hash(workId, sabun);
}
}

View File

@@ -0,0 +1,72 @@
package com.kospo.talk.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import lombok.*;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.Fetch;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "talk")
public class Talk {
@Id
@Size(max = 10)
@Column(name = "talk_id", nullable = false, length = 100)
private String talkId;
@Size(max = 10)
@Column(name = "ins_sabun", length = 10)
private String insSabun;
@Size(max = 20)
@Column(name = "work_id", length = 20)
private String workId;
@ColumnDefault("CURRENT_TIMESTAMP")
@Column(name = "ins_date")
private LocalDateTime insDate;
@Size(max = 20)
@Column(name = "ins_name", length = 20)
private String insName;
@Size(max = 10)
@Column(name = "upd_sabun", length = 10)
private String updSabun;
@Column(name = "close_yn")
private Boolean closeYn;
@Column(name = "start_yn")
private Boolean startYn;
@Column(name = "rating_yn")
private Boolean ratingYn;
@Column(name = "comp_yn")
private Boolean compYn;
@Column(name = "last_message")
private String lastMessage;
@Column(name = "last_message_date")
private LocalDateTime lastMessageDate;
@Column(name = "req_id")
private String reqId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="work_id", nullable = false, insertable = false, updatable = false)
private Work work;
}

View File

@@ -0,0 +1,47 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import jakarta.validation.constraints.Size;
import lombok.*;
import java.util.Date;
@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Table(name = "talk_attach")
public class TalkAttach {
@EmbeddedId
private TalkAttachId id;
@Size(max = 100)
@Column(name = "onm", length = 100)
private String onm;
@Size(max = 100)
@Column(name = "vnm", length = 100)
private String vnm;
@Size(max = 100)
@Column(name = "path", length = 100)
private String path;
@Size(max = 20)
@Column(name = "type", length = 100)
private String type;
@Column(name = "size")
private Long size;
@Column(name = "uploading")
private Boolean uploading;
@Column(name = "del_yn")
private Boolean delYn;
}

View File

@@ -0,0 +1,57 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import org.hibernate.Hibernate;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Objects;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Embeddable
public class TalkAttachId implements Serializable {
private static final long serialVersionUID = 3772990622177570065L;
@Size(max = 100)
@NotNull
@Column(name = "talk_id", nullable = false, length = 100)
private String talkId;
@Size(max = 10)
@NotNull
@Column(name = "sabun", nullable = false, length = 10)
private String sabun;
@NotNull
@Column(name = "ins_date", nullable = false)
private LocalDateTime insDate;
@NotNull
@Column(name = "sort", nullable = false)
private Integer sort;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
TalkAttachId entity = (TalkAttachId) o;
return Objects.equals(this.talkId, entity.talkId) &&
Objects.equals(this.insDate, entity.insDate) &&
Objects.equals(this.sort, entity.sort) &&
Objects.equals(this.sabun, entity.sabun);
}
@Override
public int hashCode() {
return Objects.hash(talkId, insDate, sort, sabun);
}
}

View File

@@ -0,0 +1,41 @@
package com.kospo.talk.model;
import com.kospo.talk.payload.TalkMemberDto;
import jakarta.persistence.Column;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.*;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "talk_member")
public class TalkMember {
@EmbeddedId
private TalkMemberId id;
@Column(name="name")
private String name;
@Column(name="mark_yn")
private Boolean markYn;
@Column(name="delete_yn")
private Boolean deleteYn;
@Column(name="dummy_yn")
private Boolean dummyYn;
public static TalkMember to(TalkMemberDto talkMemberDto) {
return TalkMember.builder()
.id(TalkMemberId.builder().talkId(talkMemberDto.getTalkId()).sabun(talkMemberDto.getSabun()).build())
.name(talkMemberDto.getName())
.markYn(talkMemberDto.getMarkYn())
.dummyYn(talkMemberDto.getDummyYn())
.deleteYn(talkMemberDto.getDeleteYn()).build();
}
}

View File

@@ -0,0 +1,44 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import org.hibernate.Hibernate;
import java.util.Objects;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Embeddable
public class TalkMemberId implements java.io.Serializable {
private static final long serialVersionUID = 7914414333816584579L;
@Size(max = 10)
@NotNull
@Column(name = "talk_id", nullable = false, length = 100)
private String talkId;
@Size(max = 10)
@NotNull
@Column(name = "sabun", nullable = false, length = 10)
private String sabun;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
TalkMemberId entity = (TalkMemberId) o;
return Objects.equals(this.talkId, entity.talkId) &&
Objects.equals(this.sabun, entity.sabun);
}
@Override
public int hashCode() {
return Objects.hash(talkId, sabun);
}
}

View File

@@ -0,0 +1,29 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.*;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "talk_message")
public class TalkMessage {
@EmbeddedId
private TalkMessageId id;
@Column(name = "message", length = Integer.MAX_VALUE)
private String message;
@Column(name = "ins_name", length = 20)
private String insName;
@Column(name = "search_yn")
private Boolean searchYn;
}

View File

@@ -0,0 +1,51 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import org.hibernate.Hibernate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Objects;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Embeddable
public class TalkMessageId implements java.io.Serializable {
private static final long serialVersionUID = -2383999741202453456L;
@Size(max = 100)
@NotNull
@Column(name = "talk_id", nullable = false, length = 100)
private String talkId;
@Size(max = 10)
@NotNull
@Column(name = "sabun", nullable = false, length = 10)
private String sabun;
@NotNull
@Column(name = "ins_date", nullable = false)
private LocalDateTime insDate;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
TalkMessageId entity = (TalkMessageId) o;
return Objects.equals(this.talkId, entity.talkId) &&
Objects.equals(this.insDate, entity.insDate) &&
Objects.equals(this.sabun, entity.sabun);
}
@Override
public int hashCode() {
return Objects.hash(talkId, insDate, sabun);
}
}

View File

@@ -0,0 +1,30 @@
package com.kospo.talk.model;
import com.kospo.talk.payload.TalkReadDto;
import jakarta.persistence.Column;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.*;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "talk_read")
public class TalkRead {
@EmbeddedId
private TalkReadId id;
@Column(name = "read_yn")
private Boolean readYn;
public static TalkRead to(TalkReadDto talkReadDto) {
return TalkRead.builder()
.id(TalkReadId.builder().talkId(talkReadDto.getTalkId()).sabun(talkReadDto.getSabun()).insDate(talkReadDto.getInsDate()).build())
.readYn(talkReadDto.getReadYn()).build();
}
}

View File

@@ -0,0 +1,57 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Objects;
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Embeddable
public class TalkReadId implements Serializable {
private static final long serialVersionUID = -4604723107983277747L;
@Size(max = 10)
@NotNull
@Column(name = "sabun", nullable = false, length = 10)
private String sabun;
@Size(max = 100)
@NotNull
@Column(name = "talk_id", nullable = false, length = 100)
private String talkId;
@NotNull
@Column(name = "ins_date", nullable = false)
private LocalDateTime insDate;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof TalkReadId that)) return false;
return Objects.equals(sabun, that.sabun) && Objects.equals(talkId, that.talkId) && Objects.equals(insDate, that.insDate);
}
@Override
public int hashCode() {
return Objects.hash(sabun, talkId, insDate);
}
@Override
public String toString() {
return "ChatReadId{" +
"sabun='" + sabun + '\'' +
", talkId='" + talkId + '\'' +
", insDate=" + insDate +
'}';
}
}

View File

@@ -0,0 +1,102 @@
package com.kospo.talk.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.List;
@Getter
@Setter
@Entity
@Table(name = "users")
public class User implements UserDetails {
@Id
@Size(max = 10)
@Column(name = "sabun", nullable = false, length = 10)
private String sabun;
@Size(max = 200)
@Column(name = "name", length = 200)
private String name;
@Size(max = 20)
@Column(name = "dept_cd", length = 20)
private String deptCd;
@Size(max = 20)
@Column(name = "grade_cd", length = 20)
private String gradeCd;
@Size(max = 200)
@Column(name = "grade_nm", length = 200)
private String gradeNm;
@Size(max = 100)
@Column(name = "ptsn_nm", length = 100)
private String ptsnNm;
@Size(max = 20)
@Column(name = "ofce_phn", length = 20)
private String ofcePhn;
@Size(max = 20)
@Column(name = "mbl_phn", length = 20)
private String mblPhn;
@Size(max = 10)
@Column(name = "state", length = 10)
private String state;
@Column(name = "online_yn")
private boolean onlineYn = false;
@Column(name = "stress")
private String stress;
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "sabun")
List<Role> roles;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "dept_cd", updatable = false, insertable = false)
Dept dept;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return roles.stream().map(r -> new SimpleGrantedAuthority(r.getId().getRoleId())).toList();
}
@Override
public String getPassword() {
return "";
}
@Override
public String getUsername() {
return sabun;
}
@Override
public boolean isAccountNonExpired() {return true;
}
@Override
public boolean isAccountNonLocked() {return true;
}
@Override
public boolean isCredentialsNonExpired() {return true;
}
@Override
public boolean isEnabled() {return true;
}
}

View File

@@ -0,0 +1,69 @@
package com.kospo.talk.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import java.time.Instant;
import java.time.LocalDateTime;
@TableGenerator(
name = "v_manual_seq",
table = "sequence",
pkColumnName = "sequence_name",
valueColumnName = "next_val",
allocationSize = 1
)
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Getter
@Setter
@Entity
@Table(name = "v_manual")
public class VManual {
@Id
@Column(name = "id", nullable = false)
@GeneratedValue(strategy = GenerationType.TABLE,generator = "v_manual_seq")
private Integer id;
@Size(max = 20)
@Column(name = "work_id", length = 20)
private String workId;
@Size(max = 100)
@Column(name = "sonm", length = 100)
private String sonm;
@Size(max = 100)
@NotNull
@Column(name = "svnm", nullable = false, length = 100)
private String svnm;
@Size(max = 100)
@Column(name = "onm", length = 100)
private String onm;
@Size(max = 100)
@NotNull
@Column(name = "vnm", nullable = false, length = 100)
private String vnm;
@Size(max = 200)
@Column(name = "path", length = 200)
private String path;
@Column(name = "ins_date")
private LocalDateTime insDate;
@Column(name = "size")
private Integer size;
@Column(name = "delete_yn")
private Boolean deleteYn;
}

View File

@@ -0,0 +1,59 @@
package com.kospo.talk.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import lombok.*;
import java.util.Date;
import java.util.List;
@Getter
@Setter
@Entity
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "work")
public class Work {
@Id
@Size(max = 20)
@Column(name = "work_id", nullable = false, length = 20)
private String workId;
@Size(max = 50)
@Column(name = "work_nm", length = 50)
private String workNm;
@Size(max = 20)
@Column(name = "p_work_id", length = 20)
private String pWorkId;
@Column(name = "use_yn")
private boolean useYn;
@Column(name = "gubun", length = 1)
private char gubun;
@JsonIgnoreProperties
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name="work_id", nullable = false, insertable = false, updatable = false)
private List<SmUser> smUsers;
@JsonIgnoreProperties
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name="work_id", nullable = false, insertable = false, updatable = false)
private List<PiUser> piUsers;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="work_id", nullable = false, insertable = false, updatable = false)
private WorkLogo workLogo;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="work_id", nullable = false, insertable = false, updatable = false)
private WorkS workS;
}

View File

@@ -0,0 +1,56 @@
package com.kospo.talk.model;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.*;
import java.time.LocalDateTime;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "work_logo")
public class WorkLogo {
@Id
@Size(max = 20)
@Column(name = "work_id", nullable = false, length = 20)
private String workId;
@Size(max = 100)
@Column(name = "vnm", length = 100)
private String vnm;
@Size(max = 100)
@Column(name = "onm", length = 100)
private String onm;
@Size(max = 100)
@Column(name = "path", length = 100)
private String path;
@Size(max = 100)
@Column(name = "type", length = 100)
private String type;
@Column(name = "size")
private Long size;
@NotNull
@Column(name = "ins_date", nullable = false)
private LocalDateTime insDate;
/*
TODO [리버스 엔지니어링] 필드를 생성하여 'work_id' 열에 매핑
사용 가능한 액션: 현재 상태대로 주석 해제 | 열 매핑 제거
@MapsId
@OneToOne(fetch = FetchType.LAZY, optional = false)
@OnDelete(action = OnDeleteAction.CASCADE)
private Work work;
*/
}

View File

@@ -0,0 +1,39 @@
package com.kospo.talk.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.*;
import jakarta.validation.constraints.Size;
import lombok.*;
import java.util.List;
@Getter
@Setter
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "work_s")
public class WorkS {
@Id
@Size(max = 20)
@Column(name = "work_id", nullable = false, length = 50)
private String workId;
@Size(max = 255)
@Column(name = "work_url", length = 255)
private String workUrl;
@Column(name = "req_yn")
private boolean reqYn;
@Column(name = "simple_wrk_yn")
private boolean simpleWrkYn;
@Column(name = "simple_ord_yn")
private boolean simpleOrdYn;
@Column(name = "scm_yn")
private boolean scmYn;
}

View File

@@ -0,0 +1,62 @@
package com.kospo.talk.payload;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.kospo.talk.model.TalkAttach;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@Schema(name = "AttachDto", description = "채팅 첨부파일")
public class AttachDto {
@Schema(name = "key", description = "첨부파일업로드키")
private String key;
@Schema(name = "talkId", description = "채팅아이디")
private String talkId;
@Schema(name = "sabun", description = "사번")
private String sabun;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSSSSS", timezone = "Asia/Seoul")
@Schema(name = "insDate", description = "등록일")
private LocalDateTime insDate;
@Schema(name = "sort", description = "정렬")
private Integer sort;
@Schema(name = "onm", description = "논리명")
private String onm;
@Schema(name = "vnm", description = "물리명")
private String vnm;
@Schema(name = "path", description = "경로")
private String path;
@Schema(name = "type", description = "파일 종류")
private String type;
@Schema(name = "size", description = "파일 용량")
private long size;
@Schema(name = "totalSize", description = "(다중)파일 전체 용량")
private long totalSize;
@Schema(name = "data", description = "binary 데이터")
private byte[] data;
@Schema(name = "percent", description = "진행률")
private String percent;
public static AttachDto to(TalkAttach talkAttach) {
return AttachDto.builder()
.talkId(talkAttach.getId().getTalkId())
.sabun(talkAttach.getId().getSabun())
.insDate(talkAttach.getId().getInsDate())
.sort(talkAttach.getId().getSort())
.onm(talkAttach.getOnm())
.vnm(talkAttach.getVnm())
.path(talkAttach.getPath())
.size(talkAttach.getSize())
.type(talkAttach.getType()).build();
}
}

View File

@@ -0,0 +1,50 @@
package com.kospo.talk.payload;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.kospo.talk.model.AutoReply;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDateTime;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@Schema(name = "AutoReplyDto", description = "자동응답관리")
public class AutoReplyDto {
@Schema(name = "workId", description = "업무아이디")
private String workId;
@Schema(name = "type", description = "자동응답 타입")
private String type;
@Schema(name = "content", description = "내용")
private String content;
@Schema(name = "insDate", description = "등록일시")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSSSSS", timezone = "Asia/Seoul")
private LocalDateTime insDate;
@Schema(name = "insSabun", description = "등록자")
private String insSabun;
@Schema(name = "insName", description = "등록자명")
private String insName;
public static AutoReplyDto to(AutoReply autoReply) {
return AutoReplyDto.builder()
.workId(autoReply.getId().getWorkId())
.type(autoReply.getId().getType())
.content(autoReply.getContent())
.insSabun(autoReply.getInsSabun())
.insName(autoReply.getInsName())
.insDate(autoReply.getInsDate())
.build();
}
}

View File

@@ -0,0 +1,25 @@
package com.kospo.talk.payload;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDateTime;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@Schema(name = "ExternalMessageDto", description = "외부 메시지")
public class ExternalMessageDto {
@Schema(name = "talkId", description = "채팅 아이디")
private String talkId;
@Schema(name = "message", description = "메시지")
private String message;
@Schema(name = "type", description = "상태코드")
private String type;
}

View File

@@ -0,0 +1,43 @@
package com.kospo.talk.payload;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.kospo.talk.model.Favorite;
import com.kospo.talk.model.WorkLogo;
import com.kospo.talk.model.WorkS;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.io.Serializable;
/**
* DTO for {@link com.kospo.talk.model.Favorite}
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@Schema(name = "FavoriteDto", description = "즐겨찾기")
public class FavoriteDto implements Serializable {
@Schema(name = "sabun", description = "사번")
String sabun;
@Schema(name = "workId", description = "업무아이디")
String workId;
@Schema(name = "workNm", description = "업무명")
String workNm;
@Schema(name = "url", description = "url")
String url;
WorkLogoDto workLogo;
public static FavoriteDto to(Favorite favorite) {
WorkS workS = favorite.getWork().getWorkS();
WorkLogo workLogo = favorite.getWork().getWorkLogo();
return FavoriteDto.builder()
.workId(favorite.getId().getWorkId())
.sabun(favorite.getId().getSabun())
.url(workS.getWorkUrl())
.workLogo(workLogo == null ? null : WorkLogoDto.to(workLogo))
.workNm(favorite.getWork().getWorkNm()).build();
}
}

View File

@@ -0,0 +1,24 @@
package com.kospo.talk.payload;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.io.Serializable;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@ToString
@Schema(name = "HappyDto", description = "ITSM 만족도조사 전송")
public class HappyDto implements Serializable {
@Schema(name = "req_id", description = "요청번호")
String req_id;
@Schema(name = "h_point", description = "포인트")
String h_point;
@Schema(name = "opinion", description = "의견")
String opinion;
}

View File

@@ -0,0 +1,27 @@
package com.kospo.talk.payload;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.kospo.talk.model.SmUser;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
@JsonIgnoreProperties(ignoreUnknown = true)
@Schema(name = "ISmUserDto", description = "유지보수관리")
public interface ISmUserDto {
@Schema(name = "sabun", description = "사번")
String getSabun();
@Schema(name = "name", description = "이름")
String getName();
@Schema(name = "workId", description = "업무아이디")
String getWorkId();
@Schema(name = "workNm", description = "업무명")
String getWorkNm();
@Schema(name = "onlineYn", description = "온라인여부")
Boolean getOnlineYn();
}

View File

@@ -0,0 +1,28 @@
package com.kospo.talk.payload;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.Date;
@JsonIgnoreProperties(ignoreUnknown = true)
@Schema(name = "ITalkDto", description = "톡방")
public interface ITalkDto {
@Schema(name = "talkId", description = "톡방아이디")
String getTalkId();
@Schema(name = "closeYn", description = "종료여부")
Boolean getCloseYn();
@Schema(name = "insSabun", description = "등록자사번")
String getInsSabun();
@Schema(name = "workId", description = "업무아이디")
String getWorkId();
@Schema(name = "insDate", description = "등록일자")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "Asia/Seoul")
Date getInsDate();
@Schema(name = "workId", description = "등록자명")
String getInsName();
@Schema(name = "unReadCnt", description = "안읽은 메시지 갯수")
String getUnReadCnt();
}

View File

@@ -0,0 +1,22 @@
package com.kospo.talk.payload;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.Date;
@JsonIgnoreProperties(ignoreUnknown = true)
@Schema(name = "ITalkGroupDto", description = "그룹톡방")
public interface ITalkGroupDto {
@Schema(name = "talkId", description = "톡방아이디")
String getTalkId();
@Schema(name = "workNm", description = "업무명")
String getWorkNm();
@Schema(name = "members", description = "톡 멤버들")
String getMembers();
@Schema(name = "insDate", description = "등록일자")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "Asia/Seoul")
Date getInsDate();
}

View File

@@ -0,0 +1,24 @@
package com.kospo.talk.payload;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.v3.oas.annotations.media.Schema;
@JsonIgnoreProperties(ignoreUnknown = true)
@Schema(name = "ITalkMemberDto", description = "톡 멤버")
public interface ITalkMemberDto {
@Schema(name = "talkId", description = "톡방아이디")
String getTalkId();
@Schema(name = "sabun", description = "사번")
String getSabun();
@Schema(name = "name", description = "이름")
String getName();
@Schema(name = "markYn", description = "마크여부")
Boolean getMarkYn();
@Schema(name = "deleteYn", description = "삭제여부")
Boolean getDeleteYn();
@Schema(name = "onlineYn", description = "온라인여부")
Boolean getOnlineYn();
@Schema(name = "dummyYn", description = "더미 여부")
Boolean getDummyYn();
}

View File

@@ -0,0 +1,28 @@
package com.kospo.talk.payload;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
import java.util.Date;
@JsonIgnoreProperties(ignoreUnknown = true)
@Schema(name = "ITalkMessageDto", description = "톡 메시지")
public interface ITalkMessageDto {
@Schema(name = "talkId", description = "톡방아이디")
String getTalkId();
@Schema(name = "sabun", description = "사번")
String getSabun();
@Schema(name = "message", description = "내용")
String getMessage();
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSSSSS", timezone = "Asia/Seoul")
@Schema(name = "insDate", description = "등록일")
LocalDateTime getInsDate();
@Schema(name = "insName", description = "등록자")
String getInsName();
@Schema(name = "line", description = "라인")
Integer getLine();
@Schema(name = "searchYn", description = "검색여부")
boolean getSearchYn();
}

View File

@@ -0,0 +1,18 @@
package com.kospo.talk.payload;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
public class ListeningDto {
private String sabun;
private String talkId;
private int status;
}

View File

@@ -0,0 +1,55 @@
package com.kospo.talk.payload;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.kospo.talk.model.Manual;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column;
import jakarta.validation.constraints.Size;
import lombok.*;
import java.time.LocalDateTime;
import java.util.Date;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@Schema(name = "ManualDto", description = "매뉴얼관리")
public class ManualDto {
@Schema(name = "workId", description = "업무아이디")
private String workId;
@Schema(name = "version", description = "버전관리")
private String version;
@Schema(name = "type", description = "파일종류")
private String type;
@Schema(name = "onm", description = "논리명")
private String onm;
@Schema(name = "vnm", description = "물리명")
private String vnm;
@Schema(name = "path", description = "경로")
private String path;
@Schema(name = "insDate", description = "등록일")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSSSSS", timezone = "Asia/Seoul")
private LocalDateTime insDate;
@Schema(name = "deleteYn", description = "삭제여부")
private Boolean deleteYn;
@Schema(name = "size", description = "파일사이즈")
private Integer size;
@Schema(name = "data", description = "업로드 바이너리 데이터")
private byte[] data;
public static ManualDto to(Manual manual) {
return ManualDto.builder()
.workId(manual.getId().getWorkId())
.version(manual.getVersion())
.type(manual.getType())
.onm(manual.getOnm())
.vnm(manual.getId().getVnm())
.deleteYn(manual.getDeleteYn())
.size(manual.getSize())
.insDate(manual.getInsDate()).build();
}
}

Some files were not shown because too many files have changed in this diff Show More