Initial commit

This commit is contained in:
2026-05-29 17:49:25 +09:00
commit 330105cb27
1081 changed files with 148694 additions and 0 deletions
@@ -0,0 +1,686 @@
package com.onelogin.saml2;
import com.onelogin.saml2.authn.AuthnRequest;
import com.onelogin.saml2.authn.AuthnRequestParams;
import com.onelogin.saml2.authn.SamlResponse;
import com.onelogin.saml2.exception.Error;
import com.onelogin.saml2.exception.SettingsException;
import com.onelogin.saml2.exception.ValidationError;
import com.onelogin.saml2.exception.XMLEntityException;
import com.onelogin.saml2.http.HttpRequest;
import com.onelogin.saml2.logout.LogoutRequest;
import com.onelogin.saml2.logout.LogoutRequestParams;
import com.onelogin.saml2.servlet.ServletUtils;
import com.onelogin.saml2.settings.Saml2Settings;
import com.onelogin.saml2.settings.SettingsBuilder;
import com.onelogin.saml2.util.Constants;
import com.onelogin.saml2.util.Util;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.joda.time.DateTime;
import org.joda.time.Instant;
import org.xml.sax.SAXException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;
import java.io.IOException;
import java.security.PrivateKey;
import java.util.*;
/**
* SamlSSOAuth
*/
public class SamlSSOAuth {
/**
* Private property to construct a logger for this class.
*/
private static final Logger LOGGER = LogManager.getLogger(SamlSSOAuth.class);
private static final String SAML_REQUEST = "SAMLRequest";
/**
* Settings data.
*/
private Saml2Settings settings;
/**
* HttpServletRequest object to be processed (Contains GET and POST parameters, session, ...).
*/
private HttpServletRequest request;
public HttpServletRequest getRequest() {
return request;
}
/**
* HttpServletResponse object to be used (For example to execute the redirections).
*/
private HttpServletResponse response;
/**
* NameID.
*/
private String nameid;
/**
* NameIDFormat.
*/
private String nameidFormat;
/**
* SessionIndex. When the user is logged, this stored it from the AuthnStatement of the SAML Response
*/
private String sessionIndex;
/**
* SessionNotOnOrAfter. When the user is logged, this stored it from the AuthnStatement of the SAML Response
*/
private DateTime sessionExpiration;
/**
* The ID of the last message processed
*/
private String lastMessageId;
/**
* The ID of the last assertion processed
*/
private String lastAssertionId;
/**
* The NotOnOrAfter values of the last assertion processed
*/
private List<Instant> lastAssertionNotOnOrAfter;
/**
* User attributes data.
*/
private Map<String, List<String>> attributes = new HashMap<>();
/**
* If user is authenticated.
*/
private boolean authenticated = false;
/**
* Stores any error.
*/
private List<String> errors = new ArrayList<>();
/**
* Reason of the last error.
*/
private String errorReason;
/**
* The id of the last request (Authn or Logout) generated
*/
private String lastRequestId;
/**
* The most recently-constructed/processed XML SAML request
* (AuthNRequest, LogoutRequest)
*/
private String lastRequest;
/**
* The most recently-constructed/processed XML SAML response
* (SAMLResponse, LogoutResponse). If the SAMLResponse was
* encrypted, by default tries to return the decrypted XML
*/
private String lastResponse;
/**
* User Info Map
*/
private Map<String, String> userInfo = new HashMap<>();
/**
Initializes the SP SAML instance.
@param request : HttpServletRequest object to be processed
@param response : HttpServletResponse object to be used
@throws IOException
@throws SettingsException
@throws Error
*/
public SamlSSOAuth(HttpServletRequest request, HttpServletResponse response) throws SettingsException, Error, IOException {
this(new SettingsBuilder().fromFile("onelogin.saml.properties").build(), request, response);
}
/**
Initializes the SP SAML instance.
@param settings : Saml2Settings object. Setting data
@param request : HttpServletRequest object to be processed
@param response : HttpServletResponse object to be used
@throws SettingsException
*/
public SamlSSOAuth(Saml2Settings settings, HttpServletRequest request, HttpServletResponse response) throws SettingsException {
this.settings = settings;
this.request = request;
this.response = response;
// Check settings
List<String> settingsErrors = settings.checkSettings();
if (!settingsErrors.isEmpty()) {
errors.add("invalid_settings");
String errorMsg = "Invalid settings: ";
errorMsg += StringUtils.join(settingsErrors, ", ");
throw new SettingsException(errorMsg, SettingsException.SETTINGS_INVALID);
}
}
/**
Initiates the SSO process.
@param returnTo : The target URL the user should be returned to after login (relayState).
Will be a self-routed URL when null, or not be appended at all when an empty string is provided
@param forceAuthn : When true the AuthNRequest will set the ForceAuthn='true'
@param isPassive : When true the AuthNRequest will set the IsPassive='true'
@param setNameIdPolicy : When true the AuthNRequest will set a nameIdPolicy
@param stay : True if we want to stay (returns the url string) False to execute redirection
@return the SSO URL with the AuthNRequest if stay = True
@throws IOException
@throws SettingsException
*/
public String login(String returnTo, Boolean forceAuthn, Boolean isPassive, Boolean setNameIdPolicy, Boolean stay) throws IOException, SettingsException {
// Set parameter for ADFS authentication processing.
Map<String, String> parameters = new HashMap<>();
AuthnRequest authnRequest = new AuthnRequest(settings, new AuthnRequestParams(forceAuthn, isPassive, setNameIdPolicy, (String) null));
String samlRequest = authnRequest.getEncodedAuthnRequest();
parameters.put(SAML_REQUEST, samlRequest);
String relayState;
if (returnTo == null) {
relayState = ServletUtils.getSelfRoutedURLNoQuery(request);
} else {
relayState = returnTo;
}
if (!relayState.isEmpty()) {
parameters.put("RelayState", relayState);
}
if (settings.getAuthnRequestsSigned()) {
String sigAlg = settings.getSignatureAlgorithm();
String signature = this.buildRequestSignature(samlRequest, relayState, sigAlg);
parameters.put("SigAlg", sigAlg);
parameters.put("Signature", signature);
}
String ssoUrl = getSSOurl();
lastRequestId = authnRequest.getId();
lastRequest = authnRequest.getAuthnRequestXml();
if (Boolean.FALSE.equals(stay)) {
LOGGER.debug("AuthNRequest sent to {} --> {}", ssoUrl, samlRequest);
}
// Request ADFS authentication for ADFS authentication.
return ServletUtils.sendRedirect(response, ssoUrl, parameters, stay);
}
/**
Initiates the SSO process.
@throws IOException
@throws SettingsException
*/
public void login() throws IOException, SettingsException {
login(null ,false, false, true, false);
}
public void login(String returnTo) throws IOException, SettingsException {
login(returnTo ,false, false, true, false);
}
/**
* Initiates the SLO process.
*
* @param returnTo
* The target URL the user should be returned to after logout (relayState).
* Will be a self-routed URL when null, or not be appended at all when an empty string is provided
* @param nameId
* The NameID that will be set in the LogoutRequest.
* @param sessionIndex
* The SessionIndex (taken from the SAML Response in the SSO process).
* @param stay
* True if we want to stay (returns the url string) False to execute redirection
* @param nameidFormat
* The NameID Format will be set in the LogoutRequest.
*
* @return the SLO URL with the LogoutRequest if stay = True
*
* @throws IOException
* @throws XMLEntityException
* @throws SettingsException
*/
public String logout(String returnTo, String nameId, String sessionIndex, Boolean stay, String nameidFormat, Boolean keepLocalSession) throws IOException, XMLEntityException, SettingsException {
Map<String, String> parameters = new HashMap<>();
LogoutRequest logoutRequest = new LogoutRequest(settings, new LogoutRequestParams(sessionIndex, nameId, nameidFormat));
String samlLogoutRequest = logoutRequest.getEncodedLogoutRequest();
parameters.put(SAML_REQUEST, samlLogoutRequest);
// returnTo is not null
String relayState;
if (returnTo == null) {
relayState = StringUtils.EMPTY;
} else {
relayState = returnTo;
}
// If there is 'relayState', forwarding to that URL after logout.
if (!relayState.isEmpty()) {
parameters.put("wreply", relayState);
}
if (settings.getLogoutRequestSigned()) {
String sigAlg = settings.getSignatureAlgorithm();
String signature = this.buildRequestSignature(samlLogoutRequest, relayState, sigAlg);
parameters.put("SigAlg", sigAlg);
parameters.put("Signature", signature);
}
String sloUrl = getSLOurl();
lastRequestId = logoutRequest.getId();
lastRequest = logoutRequest.getLogoutRequestXml();
// local session kill
if (Boolean.FALSE.equals(keepLocalSession)) {
request.getSession().invalidate();
}
if (Boolean.FALSE.equals(stay)) {
LOGGER.debug("Logout request sent to {} --> {}" , sloUrl , samlLogoutRequest);
}
return ServletUtils.sendRedirect(response, sloUrl, parameters, stay);
}
/**
* Initiates the SLO process.
*
* @param returnTo
* The target URL the user should be returned to after logout (relayState).
* Will be a self-routed URL when null, or not be appended at all when an empty string is provided
* @throws IOException
* @throws XMLEntityException
* @throws SettingsException
*/
public void logout(String returnTo) throws IOException, XMLEntityException, SettingsException {
logout(returnTo, null, null, false, null, false);
}
/**
* Initiates the SLO process.
*
* @param keepLocalSession
* When false will destroy the local session, otherwise will destroy it
* @throws IOException
* @throws XMLEntityException
* @throws SettingsException
*/
public void logout(Boolean keepLocalSession) throws IOException, XMLEntityException, SettingsException {
logout(null, null, null, false, null, keepLocalSession);
}
/**
* Initiates the SLO process.
*
* @param returnTo
* The target URL the user should be returned to after logout (relayState).
* Will be a self-routed URL when null, or not be appended at all when an empty string is provided
* @param keepLocalSession
* When false will destroy the local session, otherwise will destroy it
* @throws IOException
* @throws XMLEntityException
* @throws SettingsException
*/
public void logout(String returnTo, Boolean keepLocalSession) throws IOException, XMLEntityException, SettingsException {
logout(returnTo, null, null, false, null, keepLocalSession);
}
/**
* Initiates the SLO process.
*
* @throws IOException
* @throws XMLEntityException
* @throws SettingsException
*/
public void logout() throws IOException, XMLEntityException, SettingsException {
logout(null, null, null, false, null, false);
}
/**
* @return The url of the Single Sign On Service
*/
public String getSSOurl() {
return settings.getIdpSingleSignOnServiceUrl().toString();
}
/**
* @return The url of the Single Logout Service
*/
public String getSLOurl() {
return settings.getIdpSingleLogoutServiceUrl().toString();
}
/**
* @return The url of the Single Logout Service Response.
*/
public String getSLOResponseUrl() {
return settings.getIdpSingleLogoutServiceResponseUrl().toString();
}
/**
* Process the SAML Response sent by the IdP.
*
* @throws Exception
*/
public void processResponse() throws XPathExpressionException, ParserConfigurationException, IOException, ValidationError, SettingsException, SAXException {
processResponse(null);
}
/**
* Process the SAML Response sent by the IdP.
*
* @param requestId
* The ID of the AuthNRequest sent by this SP to the IdP
*
* @throws Exception
*/
public void processResponse(String requestId) throws XPathExpressionException, ParserConfigurationException, IOException, ValidationError, SettingsException, SAXException {
authenticated = false;
// Search the forwarding variable of the authentication request (SAMLResponse)
final HttpRequest httpRequest = ServletUtils.makeHttpRequest(this.request);
final String samlResponseParameter = httpRequest.getParameter("SAMLResponse");
// When the result parameter information of the authentication request exists
if (samlResponseParameter != null) {
SamlResponse samlResponse = new SamlResponse(settings, httpRequest);
lastResponse = samlResponse.getSAMLResponseXml();
// Confirm that the response to the request is normal
if (samlResponse.isValid(requestId)) {
// In the case of successful authentication processing, the value of the state of the authentication processing is changed,
// and Set the value passed to Response to the 'attributes' variable
authenticated = true; // Change the authentication result flag to true (auth success)
attributes = samlResponse.getAttributes(); // Get auth info from ADFS
sessionIndex = samlResponse.getSessionIndex();
sessionExpiration = samlResponse.getSessionNotOnOrAfter();
lastMessageId = samlResponse.getId();
lastAssertionId = samlResponse.getAssertionId();
lastAssertionNotOnOrAfter = samlResponse.getAssertionNotOnOrAfter();
// Get the Key of the authentication information received from ADFS as a List
Collection<String> keys = attributes.keySet();
for(String name : keys) {
int startAttribute = name.lastIndexOf('/') + 1;
List<String> values = attributes.get(name);
userInfo.put(name.substring(startAttribute) , values.get(0));
}
LOGGER.debug("processResponse success --> {}" , samlResponseParameter);
} else {
errors.add(samlResponse.getError());
}
} else {
// If there is no parameter information for the authentication request
errors.add("invalid_binding");
String errorMsg = "SAML Response not found, Only supported HTTP_POST Binding";
LOGGER.error(errorMsg);
}
}
/**
* @return the authenticated
*/
public final boolean isAuthenticated() {
return authenticated;
}
/**
* @return the list of the names of the SAML attributes.
*/
public final List<String> getAttributesName() {
return new ArrayList<>(attributes.keySet());
}
/**
* @return the set of SAML attributes.
*/
public final Map<String, List<String>> getAttributes() {
return attributes;
}
/**
* @param name
* Name of the attribute
*
* @return the attribute value
*/
public final Collection<String> getAttribute(String name) {
return attributes.get(name);
}
/**
* @return the nameID of the assertion
*/
public final String getNameId()
{
return nameid;
}
/**
* @return the nameID Format of the assertion
*/
public final String getNameIdFormat()
{
return nameidFormat;
}
/**
* @return the SessionIndex of the assertion
*/
public final String getSessionIndex()
{
return sessionIndex;
}
/**
* @return the SessionNotOnOrAfter of the assertion
*/
public final DateTime getSessionExpiration()
{
return sessionExpiration;
}
/**
* @return The ID of the last message processed
*/
public String getLastMessageId() {
return lastMessageId;
}
/**
* @return The ID of the last assertion processed
*/
public String getLastAssertionId() {
return lastAssertionId;
}
/**
* @return The NotOnOrAfter values of the last assertion processed
*/
public List<Instant> getLastAssertionNotOnOrAfter() {
return lastAssertionNotOnOrAfter;
}
/**
* @return an array with the errors, the array is empty when the validation was successful
*/
public List<String> getErrors()
{
return errors;
}
/**
* @return the reason for the last error
*/
public String getLastErrorReason()
{
return errorReason;
}
/**
* @return the id of the last request generated (AuthnRequest or LogoutRequest), null if none
*/
public String getLastRequestId()
{
return lastRequestId;
}
/**
* @return the Saml2Settings object. The Settings data.
*/
public Saml2Settings getSettings()
{
return settings;
}
/**
* @return if debug mode is active
*/
public Boolean isDebugActive() {
return settings.isDebugActive();
}
/**
* Generates the Signature for a SAML Request
*
* @param samlRequest
* The SAML Request
* @param relayState
* The RelayState
* @param signAlgorithm
* Signature algorithm method
*
* @return a base64 encoded signature
*
* @throws SettingsException
*/
public String buildRequestSignature(String samlRequest, String relayState, String signAlgorithm) throws SettingsException
{
return buildSignature(samlRequest, relayState, signAlgorithm, SAML_REQUEST);
}
/**
* Generates the Signature for a SAML Response
*
* @param samlResponse
* The SAML Response
* @param relayState
* The RelayState
* @param signAlgorithm
* Signature algorithm method
*
* @return the base64 encoded signature
*
* @throws SettingsException
*/
public String buildResponseSignature(String samlResponse, String relayState, String signAlgorithm) throws SettingsException
{
return buildSignature(samlResponse, relayState, signAlgorithm, "SAMLResponse");
}
/**
* Generates the Signature for a SAML Response
*
* @param samlMessage
* The SAML Response
* @param relayState
* The RelayState
* @param signAlgorithm
* Signature algorithm method
* @param type
* The type of the message
*
* @return the base64 encoded signature
*
* @throws SettingsException
* @throws IllegalArgumentException
*/
private String buildSignature(String samlMessage, String relayState, String signAlgorithm, String type) throws SettingsException
{
String signature = "";
if (!settings.checkSPCerts()) {
String errorMsg = "Trying to sign the " + type + " but can't load the SP private key";
LOGGER.error("buildSignature error. {} ", errorMsg);
throw new SettingsException(errorMsg, SettingsException.PRIVATE_KEY_NOT_FOUND);
}
PrivateKey key = settings.getSPkey();
String msg = type + "=" + Util.urlEncoder(samlMessage);
if (StringUtils.isNotEmpty(relayState)) {
msg += "&RelayState=" + Util.urlEncoder(relayState);
}
if (StringUtils.isEmpty(signAlgorithm)) {
signAlgorithm = Constants.RSA_SHA1;
}
msg += "&SigAlg=" + Util.urlEncoder(signAlgorithm);
try {
signature = Util.base64encoder(Util.sign(msg, key, signAlgorithm));
} catch (Exception e) {
String errorMsg = "buildSignature error." + e.getMessage();
LOGGER.error(errorMsg);
}
if (signature.isEmpty()) {
String errorMsg = "There was a problem when calculating the Signature of the " + type;
LOGGER.error("buildSignature error. {}", errorMsg);
throw new IllegalArgumentException(errorMsg);
}
LOGGER.debug("buildResponseSignature success. --> {} ", signature);
return signature;
}
/**
* Returns the most recently-constructed/processed
* XML SAML request (AuthNRequest, LogoutRequest)
*
* @return the last Request XML
*/
public String getLastRequestXML()
{
return lastRequest;
}
/**
* Returns the most recently-constructed/processed
* XML SAML response (SAMLResponse, LogoutResponse).
* If the SAMLResponse was encrypted, by default tries
* to return the decrypted XML.
*
* @return the last Response XML
*/
public String getLastResponseXML()
{
return lastResponse;
}
/**
* Return UserInfo Map
*/
public Map<String, String> getUserInfo(){
return userInfo;
}
}
@@ -0,0 +1,215 @@
package com.onelogin.saml2.servlet;
import com.onelogin.saml2.http.HttpRequest;
import com.onelogin.saml2.util.Util;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* ServletUtils class of OneLogin's Java Toolkit.
*
* A class that contains several auxiliary methods related to HttpServletRequest and HttpServletResponse
*/
public class ServletUtils {
private ServletUtils() {
//not called
}
/**
* Creates an HttpRequest from an HttpServletRequest.
*
* @param req the incoming HttpServletRequest
* @return a HttpRequest
*/
public static HttpRequest makeHttpRequest(HttpServletRequest req) {
final Map<String, String[]> paramsAsArray = req.getParameterMap();
final Map<String, List<String>> paramsAsList = new HashMap<>();
for (Map.Entry<String, String[]> param : paramsAsArray.entrySet()) {
paramsAsList.put(param.getKey(), Arrays.asList(param.getValue()));
}
return new HttpRequest(req.getRequestURL().toString(), paramsAsList, req.getQueryString());
}
/**
* Returns the protocol + the current host + the port (if different than
* common ports).
*
* @param request
* HttpServletRequest object to be processed
*
* @return the HOST URL
*/
public static String getSelfURLhost(HttpServletRequest request) {
String hostUrl = "";
final int serverPort = request.getServerPort();
if ((serverPort == 80) || (serverPort == 443) || serverPort == 0) {
hostUrl = String.format("%s://%s", request.getScheme(), request.getServerName());
} else {
hostUrl = String.format("%s://%s:%s", request.getScheme(), request.getServerName(), serverPort);
}
return hostUrl;
}
/**
* @param request
* HttpServletRequest object to be processed
*
* @return the server name
*/
public static String getSelfHost(HttpServletRequest request) {
return request.getServerName();
}
/**
* Check if under https or http protocol
*
* @param request
* HttpServletRequest object to be processed
*
* @return false if https is not active
*/
public static boolean isHTTPS(HttpServletRequest request) {
return request.isSecure();
}
/**
* Returns the URL of the current context + current view + query
*
* @param request
* HttpServletRequest object to be processed
*
* @return current context + current view + query
*/
public static String getSelfURL(HttpServletRequest request) {
String url = getSelfURLhost(request);
String requestUri = request.getRequestURI();
String queryString = request.getQueryString();
if (null != requestUri && !requestUri.isEmpty()) {
url += requestUri;
}
if (null != queryString && !queryString.isEmpty()) {
url += '?' + queryString;
}
return url;
}
/**
* Returns the URL of the current host + current view.
*
* @param request
* HttpServletRequest object to be processed
*
* @return current host + current view
*/
public static String getSelfURLNoQuery(HttpServletRequest request) {
return request.getRequestURL().toString();
}
/**
* Returns the routed URL of the current host + current view.
*
* @param request
* HttpServletRequest object to be processed
*
* @return the current routed url
*/
public static String getSelfRoutedURLNoQuery(HttpServletRequest request) {
String url = getSelfURLhost(request);
String requestUri = request.getRequestURI();
if (null != requestUri && !requestUri.isEmpty()) {
url += requestUri;
}
return url;
}
/**
* Redirect to location url
*
* @param response
* HttpServletResponse object to be used
* @param location
* target location url
* @param parameters
* GET parameters to be added
* @param stay
* True if we want to stay (returns the url string) False to execute redirection
*
* @return string the target URL
* @throws IOException
*
* @see HttpServletResponse#sendRedirect(String)
*/
@SuppressWarnings("jasper:id:issue:redirection")
public static String sendRedirect(HttpServletResponse response, String location, Map<String, String> parameters, Boolean stay) throws IOException {
StringBuffer buf = new StringBuffer();
String target = location;
buf.append(target);
if (!parameters.isEmpty()) {
boolean first = !location.contains("?");
for (Map.Entry<String, String> parameter : parameters.entrySet())
{
if (first) {
buf.append("?");
first = false;
} else {
buf.append("&");
}
buf.append(parameter.getKey());
if (!parameter.getValue().isEmpty()) {
buf.append("=").append(Util.urlEncoder(parameter.getValue()));
}
}
}
if (!stay) {
response.sendRedirect(buf.toString());
}
return buf.toString();
}
/**
* Redirect to location url
*
* @param response
* HttpServletResponse object to be used
* @param location
* target location url
* @param parameters
* GET parameters to be added
*
* @throws IOException
*
* @see HttpServletResponse#sendRedirect(String)
*/
public static void sendRedirect(HttpServletResponse response, String location, Map<String, String> parameters) throws IOException {
sendRedirect(response, location, parameters, false);
}
/**
* Redirect to location url
*
* @param response
* HttpServletResponse object to be used
* @param location
* target location url
*
* @throws IOException
*
* @see HttpServletResponse#sendRedirect(String)
*/
public static void sendRedirect(HttpServletResponse response, String location) throws IOException {
Map<String, String> parameters =new HashMap<String, String>();
sendRedirect(response, location, parameters);
}
}
@@ -0,0 +1,19 @@
package com.samsung;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class SdlBaseBootApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SdlBaseBootApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SdlBaseBootApplication.class, args);
}
}
@@ -0,0 +1,29 @@
package com.samsung.aspect;
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpStatusCodeException;
@Aspect
@Service
@Log4j2
public class ExceptionHandler {
@Pointcut("execution(* com.samsung..*Impl.*(..))")
public void serviceMethod() {
}
@AfterThrowing(pointcut = "serviceMethod()", throwing = "exception")
public void transfer(JoinPoint thisJoinPoint, Exception exception) {
// Knox Rest 실패 시
if (exception instanceof HttpStatusCodeException) {
log.error(((HttpStatusCodeException) exception).getResponseBodyAsString(), exception);
} else {
log.error(exception.getMessage(), exception);
}
}
}
@@ -0,0 +1,7 @@
package com.samsung.batch;
public interface MboBatchService {
void execMboTest();
}
@@ -0,0 +1,5 @@
package com.samsung.batch;
public interface UserSyncBatchService {
void execUserSync();
}
@@ -0,0 +1,27 @@
package com.samsung.batch.controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import com.samsung.embo.cronJob.control.service.GHRPJobService;
@RestController
public class GhrpBatchController {
private final GHRPJobService legacyGHRPJob;
public GhrpBatchController(GHRPJobService legacyGHRPJob) {
this.legacyGHRPJob = legacyGHRPJob;
}
@PostMapping("/batch/recvDeptInfo")
public void recvDeptInfo() throws Exception {
legacyGHRPJob.recvDeptInfo();
}
@PostMapping("/batch/recvUserInfo")
public void recvUserInfo() throws Exception {
legacyGHRPJob.recvUserInfo();
}
}
@@ -0,0 +1,19 @@
package com.samsung.batch.controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import com.samsung.batch.MboBatchService;
@RestController
public class MboBatchController {
private final MboBatchService mboBatchService;
public MboBatchController(MboBatchService mboBatchService) {
this.mboBatchService = mboBatchService;
}
@PostMapping("/batch/execMboTest")
public void execMboTest() {
mboBatchService.execMboTest();
}
}
@@ -0,0 +1,19 @@
package com.samsung.batch.controller;
import com.samsung.batch.UserSyncBatchService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserSyncBatchController {
private final UserSyncBatchService userSyncBatchService;
public UserSyncBatchController(UserSyncBatchService userSyncBatchService) {
this.userSyncBatchService = userSyncBatchService;
}
@GetMapping("/batch/users/sync")
public void execUserSync() {
userSyncBatchService.execUserSync();
}
}
@@ -0,0 +1,34 @@
package com.samsung.batch.dao;
import com.samsung.batch.entity.UserSync;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
@Repository
public class UserSyncDao {
private final SqlSession sqlSession;
public UserSyncDao(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
public List<UserSync> getUserSyncList() {
return sqlSession.selectList("selectAllUserSyncList");
}
public void insertUserSync(UserSync userSync) {
sqlSession.insert("insertUserSync", userSync);
}
public void updateUserSync(UserSync userSync) {
sqlSession.update("updateUserSync", userSync);
}
public void deleteUserSync(String userId) {
sqlSession.delete("deleteUserSync", Map.of("userId", userId));
}
}
@@ -0,0 +1,11 @@
package com.samsung.batch.entity;
import lombok.Data;
import org.joda.time.DateTime;
@Data
public class BatchLog {
private String nodeId;
private String jobName;
private DateTime startTime;
}
@@ -0,0 +1,47 @@
package com.samsung.batch.entity;
import com.samsung.common.entity.MarkedObject;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = true)
public class UserSync extends MarkedObject {
private String userId;
private String password;
private String description;
private boolean activeFlag;
private String sysId;
private String empNo;
private String recentLoginIp;
private Date recentLoginDatetime;
private Date firstRegDatetime;
private String firstRegrId;
private Date lastModDatetime;
private String lastModrId;
private String knoxId;
private String firstName;
private String lastName;
private String userNameEn;
private String firstNameEn;
private String lastNameEn;
private String language;
private String displayName;
private String userName;
private String compName;
private String compNameEn;
private String compCode;
private String deptName;
private String deptNameEn;
private String deptCode;
private String grdName;
private String grdNameEn;
private String grdCode;
private String compTel;
private String mobile;
private String email;
private String nickName;
private boolean externalUser;
}
@@ -0,0 +1,32 @@
package com.samsung.batch.excutor;
import com.samsung.approval.knox.KnoxApprovalSyncService;
import lombok.extern.log4j.Log4j2;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
@Component
@Log4j2
public class KnoxSyncBatchExecutor extends QuartzJobBean {
@Value("${node-id}")
private String nodeId;
@Autowired
private KnoxApprovalSyncService knoxApprovalSyncService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) {
JobDetail jobDetail = jobExecutionContext.getJobDetail();
log.info(new StringBuilder()
.append("nodeId : ").append(nodeId).append(", ")
.append("jobName : ").append(jobDetail.getKey().getName()).append(", ")
.append("description : ").append(jobDetail.getDescription())
);
knoxApprovalSyncService.synchronizeKnox();
}
}
@@ -0,0 +1,40 @@
package com.samsung.batch.excutor;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import com.samsung.batch.MboBatchService;
import lombok.extern.log4j.Log4j2;
@Component
@Log4j2
public class MboBatchExecutor extends QuartzJobBean {
@Value("${node-id}")
private String nodeId;
@Autowired
private MboBatchService mboBatchService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) {
JobDetail jobDetail = jobExecutionContext.getJobDetail();
String jobName = jobDetail.getKey().getName();
log.info(new StringBuilder().append("nodeId : ").append(nodeId).append(", ").append("jobName : ")
.append(jobName).append(", ").append("description : ").append(jobDetail.getDescription()));
// batcMboTest
switch (jobName) {
case "batchMboTest" -> mboBatchService.execMboTest();
default -> {
}
}
}
}
@@ -0,0 +1,46 @@
package com.samsung.batch.excutor;
import com.samsung.accesslog.SysUseLogService;
import lombok.extern.log4j.Log4j2;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
@Log4j2
public class SysUseLogBatchExecutor extends QuartzJobBean {
@Value("${node-id}")
private String nodeId;
@Autowired
private SysUseLogService sysUseLogService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) {
JobDetail jobDetail = jobExecutionContext.getJobDetail();
String jobName = jobDetail.getKey().getName();
log.info(new StringBuilder()
.append("nodeId : ").append(nodeId).append(", ")
.append("jobName : ").append(jobName).append(", ")
.append("description : ").append(jobDetail.getDescription())
);
switch (jobName) {
case "batchSysUseLog" -> {
try {
sysUseLogService.loadBatchData("");
} catch (IOException e) {
log.error(e.getMessage());
}
}
case "batchMenuUseHistory" -> sysUseLogService.executeMenuUseHistory("");
default -> {
}
}
}
}
@@ -0,0 +1,48 @@
package com.samsung.batch.excutor;
import com.samsung.batch.UserBatchService;
import jakarta.mail.MessagingException;
import lombok.extern.log4j.Log4j2;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
@Log4j2
public class UserBatchExecutor extends QuartzJobBean {
@Value("${node-id}")
private String nodeId;
@Autowired
private UserBatchService userBatchService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) {
JobDetail jobDetail = jobExecutionContext.getJobDetail();
String jobName = jobDetail.getKey().getName();
log.info(new StringBuilder()
.append("nodeId : ").append(nodeId).append(", ")
.append("jobName : ").append(jobName).append(", ")
.append("description : ").append(jobDetail.getDescription())
);
switch (jobName) {
case "batchUserLongTermCheck" -> userBatchService.execUserLongTermCheck();
case "batchUserAuthExpired" -> userBatchService.execUserAuthValidCheck();
case "batchUserAuthExpiredMailing" -> {
try {
userBatchService.execUserAuthValidAlarmMail();
} catch (IOException | MessagingException e) {
log.error(e.getMessage(), e);
}
}
default -> {
}
}
}
}
@@ -0,0 +1,33 @@
package com.samsung.batch.excutor;
import com.samsung.batch.UserSyncBatchService;
import lombok.extern.log4j.Log4j2;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
@Component
@Log4j2
public class UserSyncBatchExecutor extends QuartzJobBean {
@Value("${node-id}")
private String nodeId;
@Autowired
private UserSyncBatchService userSyncBatchService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) {
JobDetail jobDetail = jobExecutionContext.getJobDetail();
String jobName = jobDetail.getKey().getName();
log.info(new StringBuilder()
.append("nodeId : ").append(nodeId).append(", ")
.append("jobName : ").append(jobName).append(", ")
.append("description : ").append(jobDetail.getDescription())
);
userSyncBatchService.execUserSync();
}
}
@@ -0,0 +1,24 @@
package com.samsung.batch.impl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.samsung.batch.MboBatchService;
import com.samsung.core.annotation.BatchJob;
import lombok.extern.log4j.Log4j2;
@Log4j2
@Service
public class MboBatchServiceImpl implements MboBatchService {
@Override
@Transactional
@BatchJob("com.samsung.batch.impl.MboBatchServiceImpl.execMboTest")
public void execMboTest() {
// TODO Auto-generated method stub
log.info("execMboTest Batch Job starting...");
log.info("execMboTest Batch Job finished!!!");
}
}
@@ -0,0 +1,107 @@
package com.samsung.batch.impl;
import com.samsung.batch.UserSyncBatchService;
import com.samsung.batch.dao.UserSyncDao;
import com.samsung.batch.entity.UserSync;
import com.samsung.core.annotation.BatchJob;
import com.samsung.user.dao.UserDao;
import com.samsung.user.entity.User;
import com.samsung.user.enums.ExpireStatus;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Log4j2
@Service
public class UserSyncBatchServiceImpl implements UserSyncBatchService {
@Value("${batch.user.sync.retire.enabled:false}")
private boolean retireEnabled;
private final UserSyncDao userSyncDao;
private final UserDao userDao;
public UserSyncBatchServiceImpl(UserSyncDao userSyncDao, UserDao userDao) {
this.userSyncDao = userSyncDao;
this.userDao = userDao;
}
@Override
@Transactional
@BatchJob("com.samsung.batch.impl.UserBatchServiceImpl.execUserSync")
public void execUserSync() {
log.info("User Sync Check Batch Job starting...");
syncUser();
log.info("User Sync Check Batch Job finished!!!");
}
/**
* 사용자테이블(TN_CF_USER)과 사용자동기화테이블(TN_CF_USER_SYNC) 동기화 <BR/>
* - 프로젝트 환경에 따라 적절히 수정하여 적용바랍니다.
*/
private void syncUser() {
// 현재 사용자 테이블의 미사용자, 대기자
Map<String, Object> condition = new HashMap<>();
condition.put("deleted", false);
condition.put("activeFlag", false);
List<User> currentUserList = userDao.getUserList(condition);
Map<String, User> userMap = getUserListToMap(currentUserList);
// 사전에 사용자동기화테이블(TN_CF_USER_SYNC)에 데이터 동기화 필요 (프로젝트별 구현)
List<UserSync> userSyncList = userSyncDao.getUserSyncList();
for (UserSync userSync : userSyncList) {
User user = userMap.get(userSync.getUserId());
if (user != null) {
BeanUtils.copyProperties(userSync, user, "deleted", "jwt");
userDao.update(user);
} else {
User newUser = new User();
BeanUtils.copyProperties(userSync, newUser, "deleted", "jwt");
newUser.setActiveFlag(true);
newUser.setExternalUser(false);
userDao.insert(newUser);
}
}
if (retireEnabled) {
userRetireCheck(currentUserList, userSyncList);
}
}
private void userRetireCheck(List<User> currentUserList, List<UserSync> userSyncList) {
Map<String, UserSync> userSyncMap = getUserSyncListToMap(userSyncList);
for (User user : currentUserList) {
UserSync userSync = userSyncMap.get(user.getUserId());
// userSync에 없는 사용자면 퇴직 처리함.
if (userSync == null) {
user.setActiveFlag(false);
user.setExpireStatus(ExpireStatus.RETIRE.toString());
userDao.update(user);
}
}
}
private Map<String, UserSync> getUserSyncListToMap(List<UserSync> userSyncList) {
Map<String, UserSync> userSyncMap = new HashMap<>();
for (UserSync userSync : userSyncList) {
if (userSyncMap.get(userSync.getUserId()) == null) {
userSyncMap.put(userSync.getUserId(), userSync);
}
}
return userSyncMap;
}
private Map<String, User> getUserListToMap(List<User> userList) {
Map<String, User> userMap = new HashMap<>();
for (User user : userList) {
if (userMap.get(user.getUserId()) == null) {
userMap.put(user.getUserId(), user);
}
}
return userMap;
}
}
@@ -0,0 +1,33 @@
package com.samsung.common.controller;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import jakarta.servlet.http.HttpServletRequest;
@Controller
public class SdlErrorController implements ErrorController{
@GetMapping("/error")
public String getHandleError(HttpServletRequest request){
return "forward:/index.html?redirect=" + request.getRequestURI();
}
@PostMapping("/error")
public String postHandleError(HttpServletRequest request){
return "forward:/index.html?redirect=" + request.getRequestURI();
}
@PutMapping("/error")
public String putHandleError(HttpServletRequest request){
return "forward:/index.html?redirect=" + request.getRequestURI();
}
@DeleteMapping("/error")
public String deleteHandleError(HttpServletRequest request){
return "forward:/index.html?redirect=" + request.getRequestURI();
}
}
@@ -0,0 +1,20 @@
package com.samsung.common.handler;
import lombok.extern.log4j.Log4j2;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.NoHandlerFoundException;
import jakarta.servlet.http.HttpServletRequest;
@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
@Log4j2
public class NoHandleExceptionHandler {
@ExceptionHandler(NoHandlerFoundException.class)
public String handleException(HttpServletRequest request, Exception ex) {
return "forward:/index.html?redirect=" + request.getRequestURI();
}
}
@@ -0,0 +1,18 @@
package com.samsung.common.handler;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.http.HttpStatus;
import java.util.Date;
@Data
public class RestErrorResponse {
private HttpStatus status;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
private Date timestamp;
private int code;
private String message;
private String reason;
private String exception;
}
@@ -0,0 +1,59 @@
package com.samsung.common.handler;
import com.samsung.core.exception.AuthenticationException;
import com.samsung.core.exception.AuthorizationException;
import lombok.extern.log4j.Log4j2;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
@Log4j2
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> springHandleNotFound(Exception ex) {
RestErrorResponse restErrorResponse = new RestErrorResponse();
ResponseStatus status = AnnotatedElementUtils.findMergedAnnotation(ex.getClass(), ResponseStatus.class);
if (status != null) {
//인증 오류 처리
if (ex instanceof AuthenticationException) {
setRestErrorResponse(ex, restErrorResponse, status);
restErrorResponse.setCode(((AuthenticationException) ex).getCode());
} else if (ex instanceof AuthorizationException) {
setRestErrorResponse(ex, restErrorResponse, status);
restErrorResponse.setCode(403);
}
} else {
restErrorResponse.setStatus(HttpStatus.OK);
restErrorResponse.setCode(500);
restErrorResponse.setReason("sdl.commonError");
restErrorResponse.setTimestamp(new Date());
}
Map<String, RestErrorResponse> error = new HashMap<>();
error.put("error", restErrorResponse);
if (ex instanceof AuthenticationException || ex instanceof AuthorizationException) {
log.error(ex.getMessage());
} else {
log.error(ex.getMessage(), ex);
}
return new ResponseEntity<>(error, restErrorResponse.getStatus());
}
private void setRestErrorResponse(Exception ex, RestErrorResponse restErrorResponse, ResponseStatus status) {
restErrorResponse.setStatus(status.code());
restErrorResponse.setReason(status.reason());
restErrorResponse.setTimestamp(new Date());
restErrorResponse.setMessage(ex.getMessage());
restErrorResponse.setException(ex.getClass().getSimpleName());
}
}
@@ -0,0 +1,29 @@
package com.samsung.common.security;
import com.fasterxml.jackson.core.SerializableString;
import com.fasterxml.jackson.core.io.CharacterEscapes;
import com.fasterxml.jackson.core.io.SerializedString;
import org.apache.commons.text.StringEscapeUtils;
public class HTMLCharacterEscapes extends CharacterEscapes {
private final int[] asciiEscapes;
public HTMLCharacterEscapes() {
asciiEscapes = CharacterEscapes.standardAsciiEscapesForJSON();
asciiEscapes['<'] = CharacterEscapes.ESCAPE_CUSTOM;
asciiEscapes['>'] = CharacterEscapes.ESCAPE_CUSTOM;
asciiEscapes['&'] = CharacterEscapes.ESCAPE_CUSTOM;
asciiEscapes['\"'] = CharacterEscapes.ESCAPE_CUSTOM;
asciiEscapes['\''] = CharacterEscapes.ESCAPE_CUSTOM;
}
@Override
public int[] getEscapeCodesForAscii() {
return asciiEscapes;
}
@Override
public SerializableString getEscapeSequence(int ch) {
return new SerializedString(StringEscapeUtils.escapeHtml4(Character.toString((char) ch)));
}
}
@@ -0,0 +1,27 @@
package com.samsung.config;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.lang.NonNull;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
public final class AutoWiringSpringBeanJobFactory extends SpringBeanJobFactory {
private AutowireCapableBeanFactory beanFactory;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
beanFactory = applicationContext.getAutowireCapableBeanFactory();
}
@NonNull
@Override
protected Object createJobInstance(@NonNull final TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
beanFactory.autowireBean(job);
return job;
}
}
@@ -0,0 +1,22 @@
package com.samsung.config;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import java.util.Arrays;
@Configuration
@EnableCaching
/*@Profile({"local"})*/ //prod 도 로칼과 동일한 설정으로
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
cacheManager.setCacheNames(Arrays.asList("message-all", "message", "menu-all", "menu-label-all", "api-user", "api-user-menu", "page-all-by-menu-auth", "menu-full-path-all", "page-full-path-all", "api-full-path-all"));
return cacheManager;
}
}
@@ -0,0 +1,48 @@
package com.samsung.config;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
@Configuration
@Profile({"local"})
public class DbcpDataSourceConfig {
@Value("${node-id}")
String nodeid;
@Value("${datasource.driver}")
String driver;
@Value("${datasource.url}")
String url;
@Value("${datasource.username}")
String userName;
@Value("${datasource.password}")
String password;
@Bean
@Primary
public DataSource dataSource() {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName(driver);
hikariConfig.setJdbcUrl(url);
hikariConfig.setUsername(userName);
hikariConfig.setPassword(password);
hikariConfig.setAutoCommit(false);
return new HikariDataSource(hikariConfig);
}
@Bean
@Primary
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
@@ -0,0 +1,53 @@
package com.samsung.config;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
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;
@Log4j2
@Configuration
public class JasyptConfig {
@Value("${jasypt.encryptor.pool-size:PBEWithMD5AndDES}")
private String ALGORITHM;
@Value("${jasypt.encryptor.key-obtention-iterations:1000}")
private String CNT;
@Value("${jasypt.encryptor.pool-size:1}")
private String POOL_SIZE;
@Value("${jasypt.encryptor.string-output-type:base64}")
private String BASE64;
@Value("${jasypt.encryptor.password-property-name:JASYPT_KEY}")
private String passwordPropertyName;
@Bean("jasyptStringEncryptor")
public StringEncryptor stringEncryptor() throws Exception {
String password = getPassword();
if (StringUtils.isEmpty(password))
throw new Exception("can not find encrypt/decrypt password. please confirm environment variable");
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(password);
config.setAlgorithm(ALGORITHM);
config.setKeyObtentionIterations(CNT);
config.setPoolSize(POOL_SIZE);
config.setStringOutputType(BASE64);
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
encryptor.setConfig(config);
return encryptor;
}
private String getPassword() {
return StringUtils.isNotEmpty(System.getenv(passwordPropertyName)) ? System.getenv(passwordPropertyName) : System.getProperty(passwordPropertyName);
}
}
@@ -0,0 +1,36 @@
package com.samsung.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
/* @Profile({"prod","dev"}) */
@Profile({ "!local" })
@EnableTransactionManagement
public class JpaDatasourceConfig {
@Value("${db.jndi}")
private String jndiName;
@Bean
@Primary
public DataSource dataSource() {
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(jndiName);
}
@Bean
@Primary
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
@@ -0,0 +1,34 @@
package com.samsung.config;
import com.samsung.batch.excutor.KnoxSyncBatchExecutor;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
@Configuration
public class KnoxSyncBatchConfig {
@Value("${knox.approval.sync.cron}")
private String knoxApprovalSyncCron;
@Bean
public JobDetail knoxApprovalSyncJobDetail() {
return JobBuilder
.newJob(KnoxSyncBatchExecutor.class)
.withIdentity("knoxApprovalSyncJob")
.withDescription("Knox Approval Sync Batch")
.storeDurably(true)
.build();
}
@Bean
public CronTriggerFactoryBean knoxApprovalSyncTrigger() {
CronTriggerFactoryBean approvalTrigger = new CronTriggerFactoryBean();
approvalTrigger.setJobDetail(knoxApprovalSyncJobDetail());
approvalTrigger.setCronExpression(knoxApprovalSyncCron);
return approvalTrigger;
}
}
@@ -0,0 +1,44 @@
package com.samsung.config;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import com.samsung.batch.excutor.MboBatchExecutor;
import com.samsung.embo.api.config.GhrpConfig;
import lombok.extern.log4j.Log4j2;
@Configuration
public class MboBatchConfig {
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(MboBatchConfig.class);
@Value("${batch.mbo001.cron}")
private String batchMbo001Cron;
@Bean
public JobDetail batchMbo001Job() {
return JobBuilder.newJob(MboBatchExecutor.class).withIdentity("batchMboTest")
.withDescription("Mbo Test Batch").storeDurably(true).build();
}
@Bean
public CronTriggerFactoryBean batchMbo001JobTrigger() {
log.info("=================================================== batchMbo001JobTrigger =================================================== ");
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
trigger.setJobDetail(batchMbo001Job());
trigger.setCronExpression(batchMbo001Cron);
return trigger;
}
}
@@ -0,0 +1,84 @@
package com.samsung.config;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.autoconfigure.quartz.QuartzDataSource;
import org.springframework.boot.autoconfigure.quartz.QuartzProperties;
import org.springframework.boot.autoconfigure.quartz.QuartzTransactionManager;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
@Profile({"xxx"})
public class QuartzClusteringConfig {
final
KnoxSyncBatchConfig knoxSyncBatchConfig;
final
SysUseLogBatchConfig sysUseLogBatchConfig;
final
UserBatchConfig userBatchConfig;
final
QuartzProperties quartzProperties;
public QuartzClusteringConfig(KnoxSyncBatchConfig knoxSyncBatchConfig, SysUseLogBatchConfig sysUseLogBatchConfig, UserBatchConfig userBatchConfig, QuartzProperties quartzProperties) {
this.knoxSyncBatchConfig = knoxSyncBatchConfig;
this.sysUseLogBatchConfig = sysUseLogBatchConfig;
this.userBatchConfig = userBatchConfig;
this.quartzProperties = quartzProperties;
}
@Bean
public SchedulerFactoryBean setSchedulerFactoryBean(ApplicationContext applicationContext) {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
AutoWiringSpringBeanJobFactory jobFactory = new AutoWiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
schedulerFactoryBean.setJobFactory(jobFactory);
schedulerFactoryBean.setDataSource(quartzDataSource());
schedulerFactoryBean.setApplicationContext(applicationContext);
schedulerFactoryBean.setTransactionManager(quartzTransactionManager());
schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(true);
schedulerFactoryBean.setStartupDelay(60);
schedulerFactoryBean.setOverwriteExistingJobs(true);
Properties properties = new Properties();
properties.putAll(quartzProperties.getProperties());
schedulerFactoryBean.setQuartzProperties(properties);
schedulerFactoryBean.setTriggers(
knoxSyncBatchConfig.knoxApprovalSyncTrigger().getObject(),
userBatchConfig.batchUserLongTermCheckTrigger().getObject(),
userBatchConfig.batchUserAuthExpiredTrigger().getObject(),
sysUseLogBatchConfig.batchSysUseLogTrigger().getObject(),
sysUseLogBatchConfig.batchMenuUseHistoryTrigger().getObject()
);
return schedulerFactoryBean;
}
@Bean
@ConfigurationProperties(prefix = "spring.quartz.datasource")
@QuartzDataSource
public DataSource quartzDataSource() {
//return DataSourceBuilder.create().build();
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean
@QuartzTransactionManager
public DataSourceTransactionManager quartzTransactionManager() {
return new DataSourceTransactionManager(quartzDataSource());
}
}
@@ -0,0 +1,86 @@
package com.samsung.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.quartz.QuartzProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import com.samsung.embo.cronJob.config.GhrpJobConfig;
import com.samsung.embo.formula.controller.FormulaController;
import lombok.extern.log4j.Log4j2;
import java.util.Properties;
@Configuration
/* @Profile({"local"}) */
public class QuartzConfig {
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(QuartzConfig.class);
final
KnoxSyncBatchConfig knoxSyncBatchConfig;
final
SysUseLogBatchConfig sysUseLogBatchConfig;
final
UserBatchConfig userBatchConfig;
final
MboBatchConfig mboBatchConfig;
final
QuartzProperties quartzProperties;
final
GhrpJobConfig ghrpJobConfig;
public QuartzConfig(KnoxSyncBatchConfig knoxSyncBatchConfig, SysUseLogBatchConfig sysUseLogBatchConfig, UserBatchConfig userBatchConfig, QuartzProperties quartzProperties,MboBatchConfig mboBatchConfig,GhrpJobConfig ghrpJobConfig) {
this.knoxSyncBatchConfig = knoxSyncBatchConfig;
this.sysUseLogBatchConfig = sysUseLogBatchConfig;
this.userBatchConfig = userBatchConfig;
this.quartzProperties = quartzProperties;
this.mboBatchConfig =mboBatchConfig;
this.ghrpJobConfig = ghrpJobConfig;
}
@Bean
public SchedulerFactoryBean setSchedulerFactoryBean(ApplicationContext applicationContext) {
log.info("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
log.info("$$$$$$$$$$ start SchedulerFactoryBean local");
log.info("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
AutoWiringSpringBeanJobFactory jobFactory = new AutoWiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
schedulerFactoryBean.setJobFactory(jobFactory);
schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(true);
schedulerFactoryBean.setStartupDelay(5);//60
schedulerFactoryBean.setOverwriteExistingJobs(true);
Properties properties = new Properties();
properties.putAll(quartzProperties.getProperties());
schedulerFactoryBean.setQuartzProperties(properties);
/*
* knoxSyncBatchConfig.knoxApprovalSyncTrigger().getObject(),
* userBatchConfig.batchUserLongTermCheckTrigger().getObject(),
* userBatchConfig.batchUserAuthExpiredTrigger().getObject(),
* sysUseLogBatchConfig.batchSysUseLogTrigger().getObject(),
* sysUseLogBatchConfig.batchMenuUseHistoryTrigger().getObject(),
*/
schedulerFactoryBean.setTriggers(
ghrpJobConfig.recvDeptInfoTrigger().getObject(),
ghrpJobConfig.recvUserInfoTrigger().getObject()
//,mboBatchConfig.batchMbo001JobTrigger().getObject()
);
return schedulerFactoryBean;
}
}
@@ -0,0 +1,63 @@
package com.samsung.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
@EnableCaching
@Profile({"xxx"})/*@Profile({"!local"})*/
public class RedisConfig {
@Value("${spring.data.redis.host}")
private String host;
@Value("${spring.data.redis.port}")
private int port;
@Bean
public RedisCacheConfiguration redisCacheConfiguration() {
return RedisCacheConfiguration.defaultCacheConfig()
.disableCachingNullValues()
.serializeKeysWith(
RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())
)
.serializeValuesWith(
RedisSerializationContext.SerializationPair.fromSerializer(new JdkSerializationRedisSerializer())
);
}
@Bean
public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
return (builder) -> builder
.withCacheConfiguration("message-all",
RedisCacheConfiguration.defaultCacheConfig())
.withCacheConfiguration("message",
RedisCacheConfiguration.defaultCacheConfig())
.withCacheConfiguration("menu-all",
RedisCacheConfiguration.defaultCacheConfig())
.withCacheConfiguration("menu-label-all",
RedisCacheConfiguration.defaultCacheConfig())
.withCacheConfiguration("menu-full-path-all",
RedisCacheConfiguration.defaultCacheConfig())
.withCacheConfiguration("page-full-path-all",
RedisCacheConfiguration.defaultCacheConfig())
.withCacheConfiguration("api-full-path-all",
RedisCacheConfiguration.defaultCacheConfig())
.withCacheConfiguration("api-user",
RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(300)))
.withCacheConfiguration("api-user-menu",
RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(300)))
.withCacheConfiguration("page-all-by-menu-auth",
RedisCacheConfiguration.defaultCacheConfig());
}
}
@@ -0,0 +1,81 @@
package com.samsung.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.context.ApplicationContext;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.*;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import javax.sql.DataSource;
import java.io.IOException;
@Configuration
@EnableTransactionManagement
@EnableScheduling
@PropertySource("classpath:/config.properties")
@PropertySource("classpath:/knox.properties")
@ComponentScan(basePackages = "com.samsung", useDefaultFilters = false, includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Service.class), @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Repository.class), @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Component.class)})
public class SpringConfig {
@Bean
public SqlSessionFactoryBean defaultSqlSessionFactory(DataSource dataSource,
ApplicationContext applicationContext) throws IOException {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setConfigLocation(applicationContext.getResource("classpath:sql/mybatis/mssql/mybatis-config.xml"));
factoryBean.setMapperLocations(applicationContext.getResources("classpath*:sql/mybatis/mssql/**/mapper-mybatis-*.xml"));
return factoryBean;
}
@Bean
public SqlSessionTemplate defaultSqlSession(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
@Bean
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource source = new ReloadableResourceBundleMessageSource();
source.setBasenames("classpath:/message/message-common", "classpath:/message/message-data-format");
source.setDefaultEncoding("UTF-8");
source.setCacheSeconds(0);
source.setUseCodeAsDefaultMessage(true);
return source;
}
@Bean
public MessageSourceAccessor messageSourceAccessor(MessageSource messageSource) {
return new MessageSourceAccessor(messageSource);
}
@Bean
public ConversionService conversionService() {
return new DefaultConversionService();
}
@Bean
public RestTemplate restTemplate() {
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
// 프로젝트별 개별 설정으로 적용.
// requestFactory.setConnectTimeout(2000);
// requestFactory.setReadTimeout(3000);
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(requestFactory);
restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
return restTemplate;
}
}
@@ -0,0 +1,173 @@
package com.samsung.config;
import com.samsung.approval.interceptor.ApprovalInterceptor;
import com.samsung.approval.interceptor.ApprovalInterceptorExecutor;
import com.samsung.interceptor.*;
import com.samsung.sample.approval.internal.interceptor.InternalApprovalSampleInterceptor;
import com.samsung.sample.approval.knox.interceptor.KnoxApprovalSampleInterceptor;
import com.samsung.user.interceptor.LoginInterceptor;
import com.samsung.user.interceptor.LoginInterceptorExecutor;
import jakarta.servlet.MultipartConfigElement;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.util.unit.DataSize;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.config.annotation.*;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.samsung", useDefaultFilters = false, includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class)})
public class SpringWebConfig implements WebMvcConfigurer {
/**
* Access Timeout 체크
*/
@Value("${security.check.access.timeout:false}")
private boolean checkTimeout;
@Value("${security.authentication.exclude-path}")
private List<String> authExcludePathList;
@Value("${access-log.exclude-path}")
private List<String> accessLogExcludePathList;
@Value("${common.upload.max-request-size:-1}")
private long maxRequestSize;
@Value("${common.upload.max-file-size:-1}")
private long maxFileSize;
@Value("${common.upload.default-encoding:UTF-8}")
private String defaultEncoding;
@Value("${web-resource-root}")
private String webResourceRoot;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor()).addPathPatterns("/**")
.excludePathPatterns(authExcludePathList);
if (checkTimeout) {
registry.addInterceptor(timeoutCheckInterceptor()).addPathPatterns("/**")
.excludePathPatterns(authExcludePathList);
}
registry.addInterceptor(authorizationInterceptor()).addPathPatterns("/**")
.excludePathPatterns(authExcludePathList);
registry.addInterceptor(privacyPolicyInterceptor()).addPathPatterns("/**")
.excludePathPatterns(authExcludePathList);
registry.addInterceptor(uploadFileExtensionCheckInterceptor()).addPathPatterns("/**");
registry.addInterceptor(loggingInterceptor()).addPathPatterns("/**").
excludePathPatterns(accessLogExcludePathList);
}
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
@Bean
public TimeoutCheckInterceptor timeoutCheckInterceptor() {
return new TimeoutCheckInterceptor();
}
@Bean
public PrivacyPolicyInterceptor privacyPolicyInterceptor() {
return new PrivacyPolicyInterceptor();
}
@Bean
public AuthorizationInterceptor authorizationInterceptor() {
return new AuthorizationInterceptor();
}
@Bean
public LoggingInterceptor loggingInterceptor() {
return new LoggingInterceptor();
}
@Bean
public UploadFileExtensionCheckInterceptor uploadFileExtensionCheckInterceptor() {
return new UploadFileExtensionCheckInterceptor();
}
@Bean
public MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxRequestSize(DataSize.ofBytes(maxRequestSize));
factory.setMaxFileSize(DataSize.ofBytes(maxFileSize));
return factory.createMultipartConfig();
}
@Bean
public InternalApprovalSampleInterceptor internalApprovalSampleInterceptor() {
return new InternalApprovalSampleInterceptor();
}
@Bean
public KnoxApprovalSampleInterceptor knoxApprovalSampleInterceptor() {
return new KnoxApprovalSampleInterceptor();
}
@Bean
public ApprovalInterceptorExecutor approvalInterceptorExecutor() {
List<ApprovalInterceptor> approvalInterceptorList = new ArrayList<>();
approvalInterceptorList.add(internalApprovalSampleInterceptor());
approvalInterceptorList.add(knoxApprovalSampleInterceptor());
return new ApprovalInterceptorExecutor(approvalInterceptorList);
}
// 로그인 관련 Interceptor
@Bean
public UserUpdateInterceptor userUpdateInterceptor() {
return new UserUpdateInterceptor();
}
@Bean
public LoginOutLogInterceptor loginOutLogInterceptor() {
return new LoginOutLogInterceptor();
}
@Bean
public LoginInterceptorExecutor loginInterceptorExecutor() {
List<LoginInterceptor> loginInterceptorList = new ArrayList<>();
loginInterceptorList.add(userUpdateInterceptor());
loginInterceptorList.add(loginOutLogInterceptor());
return new LoginInterceptorExecutor(loginInterceptorList);
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("index.html").
addResourceLocations(webResourceRoot);
registry.addResourceHandler("favicon.ico").
addResourceLocations(webResourceRoot + "static/");
registry.addResourceHandler("static/**")
.addResourceLocations(webResourceRoot + "static/");
registry.addResourceHandler("assets/**")
.addResourceLocations(webResourceRoot + "assets/");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:/index.html");
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
@@ -0,0 +1,15 @@
package com.samsung.config;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import org.springframework.context.annotation.Configuration;
@Configuration
@SecurityScheme(name = "x-auth-token", type = SecuritySchemeType.APIKEY, in = SecuritySchemeIn.HEADER)
@OpenAPIDefinition(info = @Info(title = "SDL API", description = "Authentication is required. Click the Authorize button to enter the token."), security = @SecurityRequirement(name = "x-auth-token"))
public class SwaggerConfig {
}
@@ -0,0 +1,55 @@
package com.samsung.config;
import com.samsung.batch.excutor.SysUseLogBatchExecutor;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
@Configuration
public class SysUseLogBatchConfig {
@Value("${batch.sys-use-log.menu-use-history.cron}")
private String menuUseHistoryCron;
@Value("${batch.sys-use-log.menu-utilization.cron}")
private String menuUtilizationCron;
@Bean
public JobDetail batchMenuUseHistoryJob() {
return JobBuilder
.newJob(SysUseLogBatchExecutor.class)
.withIdentity("batchMenuUseHistory")
.withDescription("MenuUseHistory Batch")
.storeDurably(true)
.build();
}
@Bean
public CronTriggerFactoryBean batchMenuUseHistoryTrigger() {
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
trigger.setJobDetail(batchMenuUseHistoryJob());
trigger.setCronExpression(menuUseHistoryCron);
return trigger;
}
@Bean
public JobDetail batchSysUseLogJob() {
return JobBuilder
.newJob(SysUseLogBatchExecutor.class)
.withIdentity("batchSysUseLog")
.withDescription("batchSysUseLog Batch")
.storeDurably(true)
.build();
}
@Bean
public CronTriggerFactoryBean batchSysUseLogTrigger() {
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
trigger.setJobDetail(batchSysUseLogJob());
trigger.setCronExpression(menuUtilizationCron);
return trigger;
}
}
@@ -0,0 +1,28 @@
package com.samsung.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.spring6.SpringTemplateEngine;
import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.templatemode.TemplateMode;
import java.nio.charset.StandardCharsets;
@Configuration
public class TemplateConfig {
@Bean
public SpringTemplateEngine springTemplateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(htmlTemplateResolver());
return templateEngine;
}
@Bean
public SpringResourceTemplateResolver htmlTemplateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setPrefix("classpath:/");
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
return templateResolver;
}
}
@@ -0,0 +1,43 @@
package com.samsung.config;
import org.apache.catalina.Context;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.util.descriptor.web.ContextResource;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
@Profile("dev")
public class TomcatEmbdded {
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
return new TomcatServletWebServerFactory() {
@Override
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
tomcat.enableNaming();
return super.getTomcatWebServer(tomcat);
}
@Override
protected void postProcessContext(Context context) {
ContextResource resource1 = new ContextResource();
resource1.setName("sdl_ds");
resource1.setAuth("Container");
resource1.setProperty("factory", "org.apache.commons.dbcp2.BasicDataSourceFactory");
resource1.setType("javax.sql.DataSource");
resource1.setProperty("driverClassName", "net.sf.log4jdbc.sql.jdbcapi.DriverSpy");
resource1.setProperty("url", "jdbc:log4jdbc:sqlserver://localhost:1333;database=embo;encrypt=false;trustServerCertificate=true;");
resource1.setProperty("username", "sa");
resource1.setProperty("password", "qazwsx12##");
context.getNamingResources().addResource(resource1);
}
};
}
}
@@ -0,0 +1,122 @@
package com.samsung.config;
import com.samsung.batch.excutor.UserBatchExecutor;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
@Configuration
public class UserBatchConfig {
@Value("${batch.user.long-term-check.cron}")
private String batchUserLongTermCheckCron;
@Value("${batch.user.auth-expired.cron}")
private String batchUserAuthExpiredCron;
@Value("${batch.user.auth-expired-mailing.cron}")
private String batchUserAuthExpiredMailingCron;
@Value("${batch.user.sync.cron}")
private String batchUserSyncCron;
/**
* 장기 미사용자 관리 Job
*/
@Bean
public JobDetail batchUserLongTermCheckJob() {
return JobBuilder
.newJob(UserBatchExecutor.class)
.withIdentity("batchUserLongTermCheck")
.withDescription("User LongTerm Check Batch")
.storeDurably(true)
.build();
}
/**
* 장기 미사용자 관리 Trigger
*/
@Bean
public CronTriggerFactoryBean batchUserLongTermCheckTrigger() {
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
trigger.setJobDetail(batchUserLongTermCheckJob());
trigger.setCronExpression(batchUserLongTermCheckCron);
return trigger;
}
/**
* 만료 권한 삭제 Job
*/
@Bean
public JobDetail batchUserAuthExpiredJob() {
return JobBuilder
.newJob(UserBatchExecutor.class)
.withIdentity("batchUserAuthExpired")
.withDescription("User Auth Expired Batch")
.storeDurably(true)
.build();
}
/**
* 만료 권한 삭제 Trigger
*/
@Bean
public CronTriggerFactoryBean batchUserAuthExpiredTrigger() {
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
trigger.setJobDetail(batchUserAuthExpiredJob());
trigger.setCronExpression(batchUserAuthExpiredCron);
return trigger;
}
// /**
// * 권한 만료 안내 메일 Job
// * @return
// */
// @Bean
// public JobDetail batchUserAuthExpiredMailingJob() {
// return JobBuilder
// .newJob(UserBatchExecutor.class)
// .withIdentity("batchUserAuthExpiredMailing")
// .withDescription("User Auth Expired Mailing Batch")
// .storeDurably(true)
// .build();
// }
// /**
// * 권한 만료 안내 메일 Trigger
// * @return
// */
// @Bean
// public CronTriggerFactoryBean batchUserAuthExpiredMailingTrigger() {
// CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
// trigger.setJobDetail(batchUserAuthExpiredMailingJob());
// trigger.setCronExpression(batchUserAuthExpiredMailingCron);
// return trigger;
// }
//
// /**
// * 사용자 동기화 Job
// * @return
// */
// @Bean
// public JobDetail batchUserSyncJob() {
// return JobBuilder
// .newJob(UserBatchExecutor.class)
// .withIdentity("batchUserSync")
// .withDescription("User Sync Batch")
// .storeDurably(true)
// .build();
// }
// /**
// * 사용자 동기화 Trigger
// * @return
// */
// @Bean
// public CronTriggerFactoryBean batchUserSyncTrigger() {
// CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
// trigger.setJobDetail(batchUserSyncJob());
// trigger.setCronExpression(batchUserSyncCron);
// return trigger;
// }
}
@@ -0,0 +1,87 @@
package com.samsung.config;
import io.netty.channel.ChannelOption;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import lombok.extern.log4j.Log4j2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.codec.LoggingCodecSupport;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
import javax.net.ssl.SSLException;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
@Configuration
public class WebClientConfig {
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(WebClientConfig.class);
private static final int TIME_OUT = 5000;//5000*20;
@Bean
public WebClient webClient(){
ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(1024*1024*500))//1024*1024*50
.build();
exchangeStrategies
.messageWriters().stream()
.filter(LoggingCodecSupport.class::isInstance)
.forEach(writer -> ((LoggingCodecSupport)writer).setEnableLoggingRequestDetails(true));
return WebClient.builder()
.clientConnector(
new ReactorClientHttpConnector(
HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, TIME_OUT)
.responseTimeout(Duration.ofMillis(TIME_OUT))
.doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(TIME_OUT*20, TimeUnit.MILLISECONDS))
.addHandlerLast(new WriteTimeoutHandler(TIME_OUT*20, TimeUnit.MILLISECONDS))
)
.secure(
sslContextSpec -> {
try {
sslContextSpec.sslContext(
SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build()
);
} catch (SSLException e) {
throw new RuntimeException(e);
}
}
)
)
)
.exchangeStrategies(exchangeStrategies)
.filter(ExchangeFilterFunction.ofRequestProcessor(
clientRequest -> {
log.debug("Request: {} {} ", clientRequest.method(), clientRequest.url());
clientRequest.headers().forEach(
(name, values) -> values.forEach(
value -> log.debug("{} : {}", name, value))
);
return Mono.just(clientRequest);
}
))
.filter(ExchangeFilterFunction.ofResponseProcessor(
clientResponse -> {
clientResponse.headers().asHttpHeaders().forEach(
(name, values) -> values.forEach(value -> log.debug("{} : {}", name, value))
);
return Mono.just(clientResponse);
}
))
.build();
}
}
@@ -0,0 +1,40 @@
package com.samsung.embo.api.config;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.samsung.config.WebClientConfig;
import com.samsung.embo.api.util.GhrpSupport;
import lombok.extern.log4j.Log4j2;
@Component
public class GhrpConfig implements InitializingBean{
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(GhrpConfig.class);
@Value("${ghrp.token}")
private String tokenStr;
@Value("${ghrp.address.prefix}")
private String hostStr;
@Value("${ghrp.default-protocol}")
public void setDefaultProtocol(String defaultProtocol) {
GhrpSupport.DEFAULT_PROTOCOL = defaultProtocol;
}
public void afterPropertiesSet() throws Exception {
log.debug("GhrpConfig afterPropertiesSet");
GhrpSupport.HOST = this.hostStr;
GhrpSupport.TOKEN = this.tokenStr;
}
}
@@ -0,0 +1,11 @@
package com.samsung.embo.api.service;
import java.util.ArrayList;
import java.util.Map;
public interface GhrpService {
ArrayList<Map<String, Object>> ghrpGvXstgOrgclmPasgvCdv() throws Exception;
ArrayList<Map<String, Object>> ghrpGvXstgEmpclmPasgvCdv() throws Exception;
}
@@ -0,0 +1,142 @@
package com.samsung.embo.api.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import org.springframework.core.env.Environment;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import com.samsung.embo.api.service.GhrpService;
import com.samsung.embo.api.util.GhrpSupport;
@Service
public class GhrpServiceImpl implements GhrpService {
final Environment environment;
final WebClient webClient;
private static final int MAX_RETRIES = 2;
public GhrpServiceImpl(Environment environment, WebClient webClient) {
this.environment = environment;
this.webClient = webClient;
}
/**
* 조직정보 조회
*
* @param
* @return
*/
@Override
public ArrayList<Map<String, Object>> ghrpGvXstgOrgclmPasgvCdv() throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
map.put("dateFormat", "yyyyMMdd");
map.put("timestampFormat", "yyyyMMddHHmmssSSS");
map.put("sqlType", "");
map.put("execSql", "");
ArrayList<Map<String, Object>> result = null;
// 오류발생 시 2번까지는 재처리 한다.
for (int i = 0; i <= MAX_RETRIES; i++) {
try {
result = this.ghrpGvXstgOrgclmPasgvCdv(map);
// 성공 시 재처리 시도하지 않음
break;
} catch (Exception e) {
System.out.println(e.getMessage());
// 재시도 전에 1초동안 텀을 둔다
Thread.sleep(1000);
// 마지막 재시도에서도 실패할 경우 로깅처리
if (i == MAX_RETRIES) {
System.out.println("GHRP 부서정보 : API 재처리 시도 실패 ");
}
}
}
return result;
}
@SuppressWarnings("unchecked")
private ArrayList<Map<String, Object>> ghrpGvXstgOrgclmPasgvCdv(Map<String, Object> map) {
//GhrpClient old
//public static final String TYPE = "ghrp";
//public static final String API_GROUP = "ghrp";
/* 조직정보 */
//@RestApiClient(value = "/kr/ghrp_gv/ghrp_gv_xstg_orgclm_pasgv_cdv/1.0/GHRP_GV_XSTG_ORGCLM_PASGV_CDV", httpMethod = HttpMethod.POST, resultClass = HashMap.class, resultName ="APIData",
// apiGroup = API_GROUP, apiKey = "ghrp.ghrpGvXstgOrgclmPasgvCdv", apiName = "ghrp.ghrpGvXstgOrgclmPasgvCdv", debug = false)
/* 임직원정보 */
//@RestApiClient(value = "/kr/ghrp_gv/ghrp_gv_xstg_empclm_pasgv_cdv/1.0/GHRP_GV_XSTG_EMPCLM_PASGV_CDV", httpMethod = HttpMethod.POST, resultClass = HashMap.class, resultName ="APIData",
// apiGroup = API_GROUP, apiKey = "ghrp.ghrpGvXstgEmpclmPasgvCdv", apiName = "ghrp.ghrpGvXstgEmpclmPasgvCdv", debug = false)
// URI 생성
String functionUrl = environment.getProperty("ghrp.dept-service");
UriComponents uriComponents = UriComponentsBuilder.newInstance()
.scheme(GhrpSupport.DEFAULT_PROTOCOL)
.host(GhrpSupport.getHost())
.path(functionUrl)
.build();
ResponseEntity<Object> responseEntity = webClient
.mutate()
.build()
.get()
.uri(uriComponents.toUri())
.headers(httpHeaders -> httpHeaders.addAll(GhrpSupport.getHeader(MediaType.APPLICATION_JSON)))
.retrieve()
.toEntity(Object.class)
.block();
return (ArrayList<Map<String, Object>>) Objects.requireNonNull(responseEntity).getBody();
}
/**
* 인사정보 조회
*
* @param
* @return
*/
@Override
public ArrayList<Map<String, Object>> ghrpGvXstgEmpclmPasgvCdv() throws Exception {
/*
* Map<String, Object> map = new HashMap<String, Object>();
* map.put("dateFormat", "yyyyMMdd"); map.put("timestampFormat",
* "yyyyMMddHHmmssSSS"); map.put("sqlType", ""); map.put("execSql", "");
*/
String functionUrl = environment.getProperty("ghrp.emp-service");
UriComponents uriComponents = UriComponentsBuilder.newInstance()
.scheme(GhrpSupport.DEFAULT_PROTOCOL)
.host(GhrpSupport.getHost())
.path(functionUrl)
.build();
ResponseEntity<Object> responseEntity = webClient
.mutate()
.build()
.get()
.uri(uriComponents.toUri())
.headers(httpHeaders -> httpHeaders.addAll(GhrpSupport.getHeader(MediaType.APPLICATION_JSON)))
.retrieve()
.toEntity(Object.class)
.block();
return (ArrayList<Map<String, Object>>) Objects.requireNonNull(responseEntity).getBody();
}
}
@@ -0,0 +1,32 @@
package com.samsung.embo.api.util;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
public class GhrpSupport {
public GhrpSupport() {
}
public static final String BEARER = "Bearer ";
public static String DEFAULT_PROTOCOL;
public static String HOST;
public static String TOKEN;
public static String getHost() {
return GhrpSupport.HOST;
}
public static String getToken() {
return GhrpSupport.TOKEN;
}
public static HttpHeaders getHeader(MediaType mediaType){
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
headers.setContentType(mediaType);
headers.add(HttpHeaders.AUTHORIZATION, GhrpSupport.BEARER + GhrpSupport.getToken());
return headers;
}
}
@@ -0,0 +1,73 @@
/**
* Project Name : 전사 법무/계약관리시스템 개선
* File Name : DeptDao.java
* Description : Dept 관련 서비스
* Author : 정성호(jsh)
* Date : 2023.04.19 - 부서정보 Migration및 조회
* Copyright : 2023 by SAMSUNG. All rights reserved.
*/
package com.samsung.embo.common.dept.dao;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.samsung.embo.common.dept.dto.DeptVO;
@Repository
public class DeptDao {
/**
* SqlSession
*/
@Autowired
private SqlSession sqlSession;
public List<Map<String, Object>> getDeptTree(DeptVO vo){
return sqlSession.selectList("dept.selectDeptTree", vo);
}
public int deleteTnInfHrDept() {
return sqlSession.delete("dept.deleteTnInfHrDept");
}
public int deleteComDept() {
return sqlSession.delete("dept.deleteComDept");
}
public int insertTnInfHrDept(List list) {
int skip = 0;
int limit = 50;
int iValue = 0;
while (skip < list.size()) {
final List perRequests = (List) list
.stream()
.skip(skip)
.limit(limit)
.collect(Collectors.toList());
skip += limit;
iValue += sqlSession.insert("dept.insertTnInfHrDept", perRequests);
}
return iValue;
}
public int insertComDept() {
return sqlSession.insert("dept.insertComDept");
}
public int insertEtcDept() {
return sqlSession.insert("dept.insertEtcDept");
}
}
@@ -0,0 +1,330 @@
/**
* Project Name : 전사 법무/계약관리시스템 개선
* File Name : DeptVO.java
* Description : Dto
* Author : hj77.jeong
* Date : 2023.01.09
* Copyright : 2023 by SAMSUNG. All rights reserved.
*/
package com.samsung.embo.common.dept.dto;
import java.util.Objects;
/**
* 부서정보 Value Object
*
* @version V1.0
*/
public class DeptVO {
/**********************************************************************
* 부서정보
**********************************************************************/
/**부서코드 */
private String dept_cd;
/**부서명 */
private String dept_nm;
/**부서영문명 */
private String dept_nm_eng;
/**부서레벨 */
private int dept_level;
/**부서간순위 */
private int dept_order;
/**내부부서코드 */
private String in_dept_cd;
/**상위부서코드 */
private String up_dept_cd;
/**상위부서명 */
private String up_dept_nm;
/**상위부서영문명 */
private String up_dept_nm_eng;
/**회사코드 */
private String comp_cd;
/**회사명 */
private String comp_nm;
/**회사영문명 */
private String comp_nm_eng;
/**부문코드 */
private String business_cd;
/**부문명 */
private String business_nm;
/**총괄코드 */
private String sub_org_cd;
/**총괄명 */
private String sub_org_nm;
/**영문총괄명 */
private String sub_org_nm_eng;
/**하위부서여부 */
private String down_dept_yn;
/**부서장사번 */
private String dept_mgr_emp_no;
/**부서장성명 */
private String dept_mgr_nm;
/**부서장직급명 */
private String dept_mgr_jikgup_nm;
/**부서장영문직급명 */
private String dept_mgr_jikgup_nm_eng;
/**등록자아이디 */
private String reg_id;
/**등록일시 */
private String reg_dt;
/**수정자아이디 */
private String mod_id;
/**수정일시 */
private String mod_dt;
/**********************************************************************
* DB 이외 추가
**********************************************************************/
/**(검색)부서명 */
private String srch_dept_nm;
/**(검색)부서검색 코드 */
private String tree_dept_cd;
/**선택부서코드 */
private String select_dept_cd;
private String menu_id;
/**검색명 */
private String search_name;
private String reorg_ymd;
public String getDept_cd() {
return dept_cd;
}
public void setDept_cd(String dept_cd) {
this.dept_cd = dept_cd;
}
public String getDept_nm() {
return dept_nm;
}
public void setDept_nm(String dept_nm) {
this.dept_nm = dept_nm;
}
public String getDept_nm_eng() {
return dept_nm_eng;
}
public void setDept_nm_eng(String dept_nm_eng) {
this.dept_nm_eng = dept_nm_eng;
}
public int getDept_level() {
return dept_level;
}
public void setDept_level(int dept_level) {
this.dept_level = dept_level;
}
public int getDept_order() {
return dept_order;
}
public void setDept_order(int dept_order) {
this.dept_order = dept_order;
}
public String getIn_dept_cd() {
return in_dept_cd;
}
public void setIn_dept_cd(String in_dept_cd) {
this.in_dept_cd = in_dept_cd;
}
public String getUp_dept_cd() {
return up_dept_cd;
}
public void setUp_dept_cd(String up_dept_cd) {
this.up_dept_cd = up_dept_cd;
}
public String getUp_dept_nm() {
return up_dept_nm;
}
public void setUp_dept_nm(String up_dept_nm) {
this.up_dept_nm = up_dept_nm;
}
public String getComp_cd() {
return comp_cd;
}
public void setComp_cd(String comp_cd) {
this.comp_cd = comp_cd;
}
public String getComp_nm() {
return comp_nm;
}
public void setComp_nm(String comp_nm) {
this.comp_nm = comp_nm;
}
public String getBusiness_cd() {
return business_cd;
}
public void setBusiness_cd(String business_cd) {
this.business_cd = business_cd;
}
public String getBusiness_nm() {
return business_nm;
}
public void setBusiness_nm(String business_nm) {
this.business_nm = business_nm;
}
public String getDown_dept_yn() {
return down_dept_yn;
}
public void setDown_dept_yn(String down_dept_yn) {
this.down_dept_yn = down_dept_yn;
}
public String getDept_mgr_emp_no() {
return dept_mgr_emp_no;
}
public void setDept_mgr_emp_no(String dept_mgr_emp_no) {
this.dept_mgr_emp_no = dept_mgr_emp_no;
}
public String getDept_mgr_nm() {
return dept_mgr_nm;
}
public void setDept_mgr_nm(String dept_mgr_nm) {
this.dept_mgr_nm = dept_mgr_nm;
}
public String getDept_mgr_jikgup_nm() {
return dept_mgr_jikgup_nm;
}
public void setDept_mgr_jikgup_nm(String dept_mgr_jikgup_nm) {
this.dept_mgr_jikgup_nm = dept_mgr_jikgup_nm;
}
public String getDept_mgr_jikgup_nm_eng() {
return dept_mgr_jikgup_nm_eng;
}
public void setDept_mgr_jikgup_nm_eng(String dept_mgr_jikgup_nm_eng) {
this.dept_mgr_jikgup_nm_eng = dept_mgr_jikgup_nm_eng;
}
public String getReg_id() {
return reg_id;
}
public void setReg_id(String reg_id) {
this.reg_id = reg_id;
}
public String getReg_dt() {
return reg_dt;
}
public void setReg_dt(String reg_dt) {
this.reg_dt = reg_dt;
}
public String getMod_id() {
return mod_id;
}
public void setMod_id(String mod_id) {
this.mod_id = mod_id;
}
public String getMod_dt() {
return mod_dt;
}
public void setMod_dt(String mod_dt) {
this.mod_dt = mod_dt;
}
public String getSrch_dept_nm() {
return srch_dept_nm;
}
public void setSrch_dept_nm(String srch_dept_nm) {
this.srch_dept_nm = srch_dept_nm;
}
public String getTree_dept_cd() {
return tree_dept_cd;
}
public void setTree_dept_cd(String tree_dept_cd) {
this.tree_dept_cd = tree_dept_cd;
}
public String getSelect_dept_cd() {
return select_dept_cd;
}
public void setSelect_dept_cd(String select_dept_cd) {
this.select_dept_cd = select_dept_cd;
}
public String getSearch_name() {
return search_name;
}
public void setSearch_name(String search_name) {
this.search_name = search_name;
}
public String getSub_org_cd() {
return sub_org_cd;
}
public void setSub_org_cd(String sub_org_cd) {
this.sub_org_cd = sub_org_cd;
}
public String getSub_org_nm() {
return sub_org_nm;
}
public void setSub_org_nm(String sub_org_nm) {
this.sub_org_nm = sub_org_nm;
}
public String getSub_org_nm_eng() {
return sub_org_nm_eng;
}
public void setSub_org_nm_eng(String sub_org_nm_eng) {
this.sub_org_nm_eng = sub_org_nm_eng;
}
public String getUp_dept_nm_eng() {
return up_dept_nm_eng;
}
public void setUp_dept_nm_eng(String up_dept_nm_eng) {
this.up_dept_nm_eng = up_dept_nm_eng;
}
public String getComp_nm_eng() {
return comp_nm_eng;
}
public void setComp_nm_eng(String comp_nm_eng) {
this.comp_nm_eng = comp_nm_eng;
}
public String getMenu_id() {
return menu_id;
}
public void setMenu_id(String menu_id) {
this.menu_id = menu_id;
}
public String getReorg_ymd() {
return reorg_ymd;
}
public void setReorg_ymd(String reorg_ymd) {
this.reorg_ymd = reorg_ymd;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + Objects.hash(business_cd, business_nm, comp_cd, comp_nm, comp_nm_eng, dept_cd,
dept_level, dept_mgr_emp_no, dept_mgr_jikgup_nm, dept_mgr_jikgup_nm_eng, dept_mgr_nm, dept_nm,
dept_nm_eng, dept_order, down_dept_yn, in_dept_cd, menu_id, mod_dt, mod_id, reg_dt, reg_id, reorg_ymd,
search_name, select_dept_cd, srch_dept_nm, sub_org_cd, sub_org_nm, sub_org_nm_eng, tree_dept_cd,
up_dept_cd, up_dept_nm, up_dept_nm_eng);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
DeptVO other = (DeptVO) obj;
return Objects.equals(business_cd, other.business_cd) && Objects.equals(business_nm, other.business_nm)
&& Objects.equals(comp_cd, other.comp_cd) && Objects.equals(comp_nm, other.comp_nm)
&& Objects.equals(comp_nm_eng, other.comp_nm_eng) && Objects.equals(dept_cd, other.dept_cd)
&& dept_level == other.dept_level && Objects.equals(dept_mgr_emp_no, other.dept_mgr_emp_no)
&& Objects.equals(dept_mgr_jikgup_nm, other.dept_mgr_jikgup_nm)
&& Objects.equals(dept_mgr_jikgup_nm_eng, other.dept_mgr_jikgup_nm_eng)
&& Objects.equals(dept_mgr_nm, other.dept_mgr_nm) && Objects.equals(dept_nm, other.dept_nm)
&& Objects.equals(dept_nm_eng, other.dept_nm_eng) && dept_order == other.dept_order
&& Objects.equals(down_dept_yn, other.down_dept_yn) && Objects.equals(in_dept_cd, other.in_dept_cd)
&& Objects.equals(menu_id, other.menu_id) && Objects.equals(mod_dt, other.mod_dt)
&& Objects.equals(mod_id, other.mod_id) && Objects.equals(reg_dt, other.reg_dt)
&& Objects.equals(reg_id, other.reg_id) && Objects.equals(reorg_ymd, other.reorg_ymd)
&& Objects.equals(search_name, other.search_name)
&& Objects.equals(select_dept_cd, other.select_dept_cd)
&& Objects.equals(srch_dept_nm, other.srch_dept_nm) && Objects.equals(sub_org_cd, other.sub_org_cd)
&& Objects.equals(sub_org_nm, other.sub_org_nm) && Objects.equals(sub_org_nm_eng, other.sub_org_nm_eng)
&& Objects.equals(tree_dept_cd, other.tree_dept_cd) && Objects.equals(up_dept_cd, other.up_dept_cd)
&& Objects.equals(up_dept_nm, other.up_dept_nm) && Objects.equals(up_dept_nm_eng, other.up_dept_nm_eng);
}
}
@@ -0,0 +1,83 @@
/**
* Project Name : 전사 법무/계약관리시스템 개선
* File Name : UsertDao.java
* Description : User 관련 서비스
* Author : 정성호(jsh)
* Date : 2023.04.19 - 임직원정보 Migration (TN_CF_USER)
* Copyright : 2023 by SAMSUNG. All rights reserved.
*/
package com.samsung.embo.common.user.dao;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class UserCfDao {
/**
* SqlSession
*/
@Autowired
private SqlSession sqlSession;
public int deleteTnInfHrEmpMas() {
return sqlSession.delete("usercf.deleteTnInfHrEmpMas");
}
public int insertTnInfHrEmpMas(List list) {
//20240514 GHRP → SMDM 변경
int skip = 0;
int limit = 50;
int iValue = 0;
while (skip < list.size()) {
final List perRequests = (List) list
.stream()
.skip(skip)
.limit(limit)
.collect(Collectors.toList());
skip += limit;
iValue += sqlSession.insert("usercf.insertTnInfHrEmpMas", perRequests);
}
return iValue;
//return sqlSession.insert("usercf.insertTnInfHrEmpMasSMDM");
}
//20240514 GHRP → SMDM 변경 되면서 code가 변경됨
/* 기존 GHRP
* T.EMP_STTS_CD = 'AA' THEN NULL
* T.EMP_STTS_CD = 'CA' THEN 'LONG_TERM'
* T.EMP_STTS_CD = 'DA' THEN 'RETIRE'
* T.EMP_STTS_CD = 'RC' THEN 'DELETED'
*
* SMDM
* 0 Active(재직)
* 3 Leave of Absence(휴직)
* R Termination(퇴직)
* M Transfer
*/
public int insertTnCfUser() {
return sqlSession.insert("usercf.insertTnCfUser");
}
public int insertTnCfUserRole() {
return sqlSession.insert("usercf.insertTnCfUserRole");
}
// P1SEC-6900 [3선]인사에서 받아오는 부서정보 관련 데이터 수정
public int updateTnCfUserDeptName() {
return sqlSession.update("usercf.updateTnCfUserDeptName");
}
}
@@ -0,0 +1,16 @@
package com.samsung.embo.common.util;
import java.util.List;
import java.util.Map;
import com.samsung.role.entity.UserRole;
public interface UtilService {
List<Map<String, Object>> getUserDivision(String userId);
List<Map<String, Object>> selectDivision();
List<Map<String, Object>> selectGroupMember(Map<String, Object> params);
}
@@ -0,0 +1,72 @@
package com.samsung.embo.common.util.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.samsung.authentication.Account;
import com.samsung.embo.common.util.UtilService;
import com.samsung.role.RoleService;
import com.samsung.role.entity.UserRole;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@RestController
@RequestMapping("/embo/util/")
public class UtilController {
private final RoleService roleService;
private final UtilService utilService;
public UtilController(UtilService utilService, RoleService roleService) {
this.utilService = utilService;
this.roleService = roleService;
}
// com.samsung.role.controller userRoleInfo 참조
@Operation(summary = "RoleInfo 조회")
@GetMapping("roles")
public List<UserRole> roles() throws Exception {
return roleService.getUserRoleList(Account.currentUser().getUserId());
}
@Operation(summary = "Division 조회")
@GetMapping("division")
public List<Map<String, Object>> division() throws Exception {
return utilService.selectDivision();
}
@Operation(summary = "RoleInfo 조회")
@GetMapping("userInfo")
public Map<String, Object> userInfo() throws Exception {
Map<String, Object> result = new HashMap<String, Object>();
String userId = Account.currentUser().getUserId();
result.put("role", roleService.getUserRoleList(userId));
result.put("division", utilService.getUserDivision(userId));
return result;
}
@Operation(summary = "my GroupMember 조회")
@GetMapping("myGroupMember")
public List<Map<String, Object>> myGroupMember() throws Exception {
Map<String, Object> params = new HashMap<String, Object>();
params.put("userId", Account.currentUser().getUserId());
return utilService.selectGroupMember(params);
}
@Operation(summary = "GroupMember by groupId 조회")
@GetMapping("groupMember/{groupId}")
public List<Map<String, Object>> groupMember(@Parameter(description = "group ID") @PathVariable String groupId) throws Exception {
Map<String, Object> params = new HashMap<String, Object>();
params.put("groupId", Account.currentUser().getUserId());
return utilService.selectGroupMember(params);
}
}
@@ -0,0 +1,38 @@
package com.samsung.embo.common.util.dao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
@Repository
public class UtilDao {
private static final String MAPPER = "utilMapper.";
private SqlSession sqlSession;
public UtilDao(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
public String selectSeqKpiMaster() {
return sqlSession.selectOne(MAPPER + "selectSeqKpiMaster");
}
public List<Map<String, Object>> selectUserDivision(String userId) {
Map<String, Object> params = new HashMap<String, Object>();
params.put("userId", userId);
return sqlSession.selectList(MAPPER + "selectUserDivision", params);
}
public List<Map<String, Object>> selectDivision() {
return sqlSession.selectList(MAPPER + "selectDivision");
}
public List<Map<String, Object>> selectGroupMember(Map<String, Object> params) {
return sqlSession.selectList(MAPPER + "selectGroupMember");
}
}
@@ -0,0 +1,34 @@
package com.samsung.embo.common.util.impl;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.samsung.embo.common.util.UtilService;
import com.samsung.embo.common.util.dao.UtilDao;
@Service
public class UtilServiceImpl implements UtilService{
private final UtilDao utilDao;
public UtilServiceImpl(UtilDao utilDao) {
this.utilDao = utilDao;
}
@Override
public List<Map<String, Object>> getUserDivision(String userId) {
return utilDao.selectUserDivision(userId);
}
@Override
public List<Map<String, Object>> selectDivision() {
return utilDao.selectDivision();
}
@Override
public List<Map<String, Object>> selectGroupMember(Map<String, Object> params) {
return utilDao.selectGroupMember(params);
}
}
@@ -0,0 +1,81 @@
/**
* Project Name : 전사 법무/계약관리시스템 개선
* File Name : GaisJobConfig.java
* Description :
* Author : basslee
* Date : 2023.03.03
* Copyright : 2023 by SAMSUNG. All rights reserved.
*/
package com.samsung.embo.cronJob.config;
import java.util.Objects;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import com.samsung.embo.cronJob.executor.GhrpJobExecutor;
@Configuration
public class GhrpJobConfig {
@Value("${batch.dept.cron}")
private String deptCron;
@Value("${batch.user.cron}")
private String userCron;
/**
* 부서정보 I/F
*
* @return
*/
@Bean
public JobDetailFactoryBean recvDeptInfo() {
JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
jobDetailFactoryBean.setName("recvDeptInfo");
jobDetailFactoryBean.setJobClass(GhrpJobExecutor.class);
jobDetailFactoryBean.setDescription("recvDeptInfo Batch");
jobDetailFactoryBean.setDurability(true);
return jobDetailFactoryBean;
}
@Bean
public CronTriggerFactoryBean recvDeptInfoTrigger() {
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
trigger.setJobDetail(Objects.requireNonNull(recvDeptInfo().getObject()));
trigger.setCronExpression(deptCron);
return trigger;
}
/**
* 임직원정보 I/F
*
* @return
*/
@Bean
public JobDetailFactoryBean recvUserInfo() {
JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
jobDetailFactoryBean.setName("recvUserInfo");
jobDetailFactoryBean.setJobClass(GhrpJobExecutor.class);
jobDetailFactoryBean.setDescription("recvUserInfo Batch");
jobDetailFactoryBean.setDurability(true);
return jobDetailFactoryBean;
}
@Bean
public CronTriggerFactoryBean recvUserInfoTrigger() {
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
trigger.setJobDetail(Objects.requireNonNull(recvUserInfo().getObject()));
trigger.setCronExpression(userCron);
return trigger;
}
}
@@ -0,0 +1,14 @@
/**
* Project Name : 전사 법무/계약관리시스템 개선
* File Name : LegacyGSEMSJob.java
* Description :
* Author : 강미선(miseon0.kang)
* Date : 2023.01.13
* Copyright : 2023 by SAMSUNG. All rights reserved.
*/
package com.samsung.embo.cronJob.control.service;
public interface GHRPJobService{
public void recvDeptInfo() throws Exception;
public void recvUserInfo() throws Exception;
}
@@ -0,0 +1,124 @@
/**
* Project Name : 전사 법무/계약관리시스템 개선
* File Name : LegacyGSEMSJob.java
* Description :
* Author : 강미선(miseon0.kang)
* Date : 2023.01.13
* Copyright : 2023 by SAMSUNG. All rights reserved.
*/
package com.samsung.embo.cronJob.control.service.impl;
import java.util.ArrayList;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.samsung.core.annotation.BatchJob;
import com.samsung.embo.api.service.GhrpService;
import com.samsung.embo.common.dept.dao.DeptDao;
import com.samsung.embo.common.user.dao.UserCfDao;
import com.samsung.embo.cronJob.control.service.GHRPJobService;
import lombok.extern.log4j.Log4j2;
@Service
@Log4j2
public class GHRPJobServiceImpl implements GHRPJobService {
@Autowired
private DeptDao deptDao;
@Autowired
private UserCfDao userCfDao;
@Autowired
private GhrpService ghrpService;
@Override
@BatchJob("com.samsung.embo.cronJob.control.service.impl.recvDeptInfo")
public void recvDeptInfo() throws Exception{
log.info("=============== SMDM 부서정보 IF 진입 =============== :");
System.out.println("=============== SMDM 부서정보 IF 진입 =============== :");
log.info("=============== Start . 부서정보 Receive ===============");
System.out.println("=============== Start . 부서정보 Receive ===============");
try {
// Rest 수신 받는 부분 추가
ArrayList<Map<String, Object>> result = ghrpService.ghrpGvXstgOrgclmPasgvCdv();
log.info("부서정보 Counts : [{}]", result.size());
System.out.println("부서정보 Counts : [" + result.size() + "]");
if(result.size() > 0) {
deptDao.deleteTnInfHrDept();
deptDao.insertTnInfHrDept(result);//20240514 GHRP → SMDM 변경
deptDao.deleteComDept();
int iValue = deptDao.insertComDept();
log.info("부서정보 Bulk Insert Count [{}]", iValue);
System.out.println("부서정보 Bulk Insert Count ["+iValue+"]");
//삼성전자_기타 추가등록
deptDao.insertEtcDept();
}
} catch (Exception e) {
log.error(e.getMessage());
System.out.println(e.getMessage());
}
log.info("=============== End . 부서정보 Receive ===============");
System.out.println("=============== End . 부서정보 Receive ===============");
}
@Override
@BatchJob("com.samsung.embo.cronJob.control.service.impl.recvUserInfo")
public void recvUserInfo() throws Exception{
log.info("=============== SMDM 임직원정보 IF 진입 =============== :");
log.info("=============== SMDM . 임직원정보 Receive ===============");
try {
// Rest 수신 받는 부분 추가
ArrayList<Map<String, Object>> result = ghrpService.ghrpGvXstgEmpclmPasgvCdv();
log.info("임직원정보 Counts : [{}]", result.size());
if(result.size() > 0) {
userCfDao.deleteTnInfHrEmpMas();
int iValue = userCfDao.insertTnInfHrEmpMas(result);//이것만 수정
log.info("임직원정보 Bulk Insert Count [{}]", iValue);
log.info("임직원 정보 테이블 Merge");
//임직원 insert
userCfDao.insertTnCfUser();
log.info("사용자 기본 Role Insert");
userCfDao.insertTnCfUserRole();
// P1SEC-6900 [3선]인사에서 받아오는 부서정보 관련 데이터 수정
log.info("사용자 부서명 update");
userCfDao.updateTnCfUserDeptName();
//20240731 퇴직자들 update 로직 추가
//userCfDao.updateTnCfUserExpireUser();
}
} catch (Exception e) {
log.error(e.getMessage());
}
log.info("=============== End . 임직원정보 Receive ===============");
}
}
@@ -0,0 +1,68 @@
/**
* Project Name : 전사 법무/계약관리시스템 개선
* File Name : GaisJobExecutor.java
* Description :
* Author : basslee
* Date : 2023.02.23
* Copyright : 2023 by SAMSUNG. All rights reserved.
*/
package com.samsung.embo.cronJob.executor;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import com.samsung.embo.cronJob.control.service.GHRPJobService;
import lombok.extern.log4j.Log4j2;
@Component
@Log4j2
public class GhrpJobExecutor extends QuartzJobBean {
@Value("node-id")
private String nodeId;
@Autowired
private GHRPJobService legacyGHRPJob;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDetail jobDetail = jobExecutionContext.getJobDetail();
String jobName = jobDetail.getKey().getName();
log.info(new StringBuilder()
.append("nodeId : ").append(nodeId).append(", ")
.append("jobName : ").append(jobDetail.getKey().getName()).append(", ")
.append("description : ").append(jobDetail.getDescription())
);
switch (jobName) {
case "recvDeptInfo":
// 부서정보 수신
try {
legacyGHRPJob.recvDeptInfo();
} catch (Exception e) {
log.error(e.getMessage());
}
break;
case "recvUserInfo":
// 임직원정보 수신
try {
legacyGHRPJob.recvUserInfo();
} catch (Exception e) {
log.error(e.getMessage());
}
break;
}
}
}
@@ -0,0 +1,20 @@
package com.samsung.embo.formula;
import java.util.List;
import java.util.Map;
import com.samsung.embo.formula.entity.Formula;
public interface FormulaService {
String insertFormula(Formula formula);
List<Map<String, Object>> selectFormula(Map<String, Object> params);
int deleteFormula(Map<String, Object> params);
Map<String, Object> getFormula(Map<String, Object> params);
String updateFormula(Formula formula);
}
@@ -0,0 +1,376 @@
package com.samsung.embo.formula.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.samsung.authentication.Account;
import com.samsung.embo.formula.FormulaService;
import com.samsung.embo.formula.entity.Formula;
import com.samsung.resource.FileManagerService;
import com.samsung.resource.entity.AttachFile;
import com.samsung.user.entity.User;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.log4j.Log4j2;
@RestController
@RequestMapping("/embo/formula/")
@Log4j2
public class FormulaController {
private final FormulaService formulaService;
private final FileManagerService fileManagerService;
public FormulaController(FormulaService formulaService, FileManagerService fileManagerService) {
this.formulaService = formulaService;
this.fileManagerService = fileManagerService;
}
@Operation(summary = "page 초기정보.")
@PostMapping(value = "list/main.do", params = "method=page")
public Map<String, Object> page(@RequestBody Map<String, Object> params) throws Exception {
User user = Account.currentUser();
Map<String, Object> result = new HashMap<String, Object>();
result.put("user", user);
result.put("item1", "메일 템플릿 항목1");
return result;
}
@Operation(summary = "formula 조회")
@PostMapping(value = "list/main.do", params = "method=search")
public Map<String, Object> list_search(@RequestBody Map<String, Object> params) throws Exception {
User user = Account.currentUser();
Map<String, Object> result = new HashMap<String, Object>();
result.put("user", user);
result.put("result", formulaService.selectFormula(params));
return result;
}
@Operation(summary = "Formula 상세조회")
@PostMapping(value = "item/main.do", params = "method=getFormula")
public Map<String, Object> item_getFormula(@RequestBody Map<String, Object> params) throws Exception {
Map<String, Object> result = new HashMap<String, Object>();
result.put("result", formulaService.getFormula(params));
List<AttachFile> attachFiles = fileManagerService.getAttachFileList(params.get("fmId").toString(), "FORMULA");
result.put("attachments", attachFiles);
if (attachFiles.size() > 0) {
AttachFile attachFile = attachFiles.get(0);
Resource resource = fileManagerService.getResource(attachFile.getFileExtensionName(),
attachFile.getFilePathName());
OPCPackage pkg = OPCPackage.open(resource.getInputStream());
XSSFWorkbook wb = new XSSFWorkbook(pkg);
XSSFSheet sheet = wb.getSheetAt(0);
DataFormatter formatter = new DataFormatter();
String measurePos = "A22";
String[] measureIds = { "MEASURE", "SCOPE1", "SCOPE2", "SCOPE3", "TARGET1", "TARGET2", "TARGET3", "VALUE" };
int measureSize = 10;
CellReference cellRefMeasure = new CellReference(measurePos);
List<Map<String, String>> measureList = IntStream.range(0, measureSize).boxed().map(rowIdx -> IntStream
.range(0, measureIds.length).boxed()
.collect(Collectors.toMap(colIdx -> measureIds[colIdx], colIdx -> formatter
.formatCellValue(sheet.getRow(cellRefMeasure.getRow() + rowIdx).getCell(1 + colIdx))))
).collect(Collectors.toList());
result.put("measureInfo", measureList);
String mboPos = "A7";
String[] mboIds = { "MBO_ITEM", "TYPE", "TARGET", "FORMULA", "GRADE" };
int mboSize = 10;
CellReference cellRefMbo = new CellReference(mboPos);
List<Map<String, String>> mboList = IntStream.range(0, mboSize).boxed()
.map(rowIdx -> IntStream.range(0, mboIds.length).boxed()
.collect(Collectors.toMap(colIdx -> mboIds[colIdx], colIdx -> formatter
.formatCellValue(sheet.getRow(cellRefMbo.getRow() + rowIdx).getCell(1 + colIdx))))
).collect(Collectors.toList());
result.put("mboInfo", mboList);
wb.close();
pkg.close();
}
return result;
}
@Operation(summary = "formula 등록")
@PostMapping(value = "item/main.do", params = "method=regist")
public String item_regist(@RequestBody Formula formula) throws Exception {
User user = Account.currentUser();
formula.setUserId(user.getUserId());
return formulaService.insertFormula(formula);
}
@Operation(summary = "formula 수정")
@PostMapping(value = "item/main.do", params = "method=update")
public String item_update(@RequestBody Formula formula) throws Exception {
User user = Account.currentUser();
formula.setUserId(user.getUserId());
return formulaService.updateFormula(formula);
}
@Operation(summary = "formula 삭제")
@PostMapping(value = "item/main.do", params = "method=delete")
public String item_delete(@RequestBody Map<String, Object> params) throws Exception {
User user = Account.currentUser();
// todo : admin & execute 권한 check
params.put("userId", user.getUserId());
int ret = formulaService.deleteFormula(params);
return "success";
}
@SuppressWarnings("unchecked")
@Operation(summary = "formula calc")
@PostMapping(value = "item/main.do", params = "method=calc")
public Map<String, Object> item_calc(@RequestBody Map<String, Object> params) throws Exception {
User user = Account.currentUser();
params.put("userId", user.getUserId());
Map<String, Object> result = new HashMap<String, Object>();
List<Map<String, String>> measureList = (List<Map<String, String>>) params.get("rows");
log.info(measureList);
List<AttachFile> attachFiles = fileManagerService.getAttachFileList(params.get("fmId").toString(), "FORMULA");
if (attachFiles.size() > 0) {
AttachFile attachFile = attachFiles.get(0);
Resource resource = fileManagerService.getResource(attachFile.getFileExtensionName(),
attachFile.getFilePathName());
OPCPackage pkg = OPCPackage.open(resource.getInputStream());
XSSFWorkbook wb = new XSSFWorkbook(pkg);
XSSFSheet sheet = wb.getSheetAt(0);
String valuePos = "I22";
int measureSize = 10;
// set measure value
CellReference cellReference = new CellReference(valuePos);
IntStream.range(0, measureSize).boxed().forEach(rowIdx -> {
XSSFRow rowSrc = sheet.getRow(cellReference.getRow() + rowIdx);
XSSFCell cellSrc = rowSrc.getCell(cellReference.getCol());
if ("".equals(measureList.get(rowIdx).get("VALUE"))) {
cellSrc.setCellValue("");
} else {
cellSrc.setCellValue(Double.parseDouble(measureList.get(rowIdx).get("VALUE")));
}
});
wb.getCreationHelper().createFormulaEvaluator().evaluateAll();
String mboPos = "A7";
String[] mboIds = { "MBO_ITEM", "TYPE", "TARGET", "FORMULA", "GRADE" };
int mboSize = 10;
CellReference cellRefMbo = new CellReference(mboPos);
DataFormatter formatter = new DataFormatter();
List<Map<String, String>> mboList = IntStream.range(0, mboSize).boxed().map(rowIdx ->
IntStream.range(0, mboIds.length).boxed().collect(Collectors.toMap(colIdx -> mboIds[colIdx], colIdx -> {
String cellValue = "";
XSSFCell cell = sheet.getRow(cellRefMbo.getRow() + rowIdx).getCell(1 + colIdx);
if (cell.getCellType() == CellType.NUMERIC) {
cellValue = String.valueOf(cell.getNumericCellValue());
} else if (cell.getCellType() == CellType.FORMULA) {
switch (cell.getCachedFormulaResultType()) {
case NUMERIC:
cellValue = String.valueOf(cell.getNumericCellValue());
break;
case STRING:
cellValue = cell.getStringCellValue();
break;
default:
break;
}
} else {
cellValue = cell.getStringCellValue();
}
return cellValue;
}))
).collect(Collectors.toList());
result.put("mboInfo", mboList);
wb.close();
pkg.close();
}
return result;
}
@Operation(summary = "formula merge")
@PostMapping(value = "list/main.do", params = "method=merge")
public Map<String, Object> list_merge(@RequestBody Map<String, Object> params) throws Exception {
// https://gist.github.com/davidsommer/7805574
User user = Account.currentUser();
Map<String, Object> result = new HashMap<String, Object>();
result.put("user", user);
result.put("result", formulaService.selectFormula(params));
List<FileInputStream> filePaths = new ArrayList<FileInputStream>();
List<Map<String, Object>> fmList = formulaService.selectFormula(params);
for (Map<String, Object> fmInfo : fmList) {
List<AttachFile> attachFiles = fileManagerService.getAttachFileList(fmInfo.get("fmId").toString(),
"FORMULA");
if (attachFiles.size() > 0) {
AttachFile attachFile = attachFiles.get(0);
Resource resource = fileManagerService.getResource(attachFile.getFileExtensionName(),
attachFile.getFilePathName());
filePaths.add(new FileInputStream(resource.getFile()));
} else {
log.info("error");
}
}
this.mergeExcelFiles(new File("D:\\temp\\all.xlsx"), filePaths);
System.out.println("Done!");
return result;
}
public void mergeExcelFiles(File file, List<FileInputStream> list) throws IOException {
XSSFWorkbook book = new XSSFWorkbook();
XSSFSheet sheet = book.createSheet(file.getName());
for (FileInputStream fin : list) {
XSSFWorkbook b = new XSSFWorkbook(fin);
copySheets(book, sheet, b.getSheetAt(0));
// for (int i = 0; i < b.getNumberOfSheets(); i++) {copySheets(book, sheet,
// b.getSheetAt(i));}
}
try {
writeFile(book, file);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected static void writeFile(XSSFWorkbook book, File file) throws Exception {
FileOutputStream out = new FileOutputStream(file);
book.write(out);
out.close();
}
private static void copySheets(XSSFWorkbook newWorkbook, XSSFSheet newSheet, XSSFSheet sheet) {
copySheets(newWorkbook, newSheet, sheet, true);
}
private static void copySheets(XSSFWorkbook newWorkbook, XSSFSheet newSheet, XSSFSheet sheet, boolean copyStyle) {
int newRownumber = (int) (Math.floor((newSheet.getLastRowNum() + 100) / 100) * 100);
int maxColumnNum = 0;
Map<Integer, XSSFCellStyle> styleMap = (copyStyle) ? new HashMap<Integer, XSSFCellStyle>() : null;
for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
XSSFRow srcRow = sheet.getRow(i);
XSSFRow destRow = newSheet.createRow(i + newRownumber);
if (srcRow != null) {
copyRow(newWorkbook, sheet, newSheet, srcRow, destRow, styleMap);
if (srcRow.getLastCellNum() > maxColumnNum) {
maxColumnNum = srcRow.getLastCellNum();
}
}
}
for (int i = 0; i <= maxColumnNum; i++) {
newSheet.setColumnWidth(i, sheet.getColumnWidth(i));
}
}
public static void copyRow(XSSFWorkbook newWorkbook, XSSFSheet srcSheet, XSSFSheet destSheet, XSSFRow srcRow,
XSSFRow destRow, Map<Integer, XSSFCellStyle> styleMap) {
destRow.setHeight(srcRow.getHeight());
for (int j = srcRow.getFirstCellNum(); j <= srcRow.getLastCellNum(); j++) {
XSSFCell oldCell = srcRow.getCell(j);
XSSFCell newCell = destRow.getCell(j);
if (oldCell != null) {
if (newCell == null) {
newCell = destRow.createCell(j);
}
copyCell(newWorkbook, oldCell, newCell, styleMap);
}
}
}
public static void copyCell(XSSFWorkbook newWorkbook, XSSFCell oldCell, XSSFCell newCell,
Map<Integer, XSSFCellStyle> styleMap) {
if (styleMap != null) {
int stHashCode = oldCell.getCellStyle().hashCode();
XSSFCellStyle newCellStyle = styleMap.get(stHashCode);
if (newCellStyle == null) {
newCellStyle = newWorkbook.createCellStyle();
newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
styleMap.put(stHashCode, newCellStyle);
}
newCell.setCellStyle(newCellStyle);
}
switch (oldCell.getCellType()) {
case STRING:
newCell.setCellValue(oldCell.getRichStringCellValue());
break;
case NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case BLANK:
newCell.setCellType(CellType.BLANK);
break;
case BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case FORMULA:
newCell.setCellFormula(oldCell.getCellFormula());
break;
default:
break;
}
}
}
@@ -0,0 +1,43 @@
package com.samsung.embo.formula.dao;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import com.samsung.embo.formula.entity.Formula;
@Repository
public class FormulaDao {
private static final String FORMULA_MAPPER = "formulaMapper.";
private final SqlSession sqlSession;
public FormulaDao(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
public void insertFormula(Formula formula) {
sqlSession.insert(FORMULA_MAPPER + "insertFormula", formula);
}
public List<Map<String, Object>> selectFormula(Map<String, Object> params) {
return sqlSession.selectList(FORMULA_MAPPER + "selectFormula", params);
}
public int deleteFormula(Map<String, Object> params) {
return sqlSession.delete(FORMULA_MAPPER+ "deleteFormula", params);
}
public Map<String, Object> getFormula(Map<String, Object> params) {
return sqlSession.selectOne(FORMULA_MAPPER+ "selectFormula", params);
}
public void updateFormula(Formula formula) {
sqlSession.update(FORMULA_MAPPER + "updateFormula", formula);
}
}
@@ -0,0 +1,20 @@
package com.samsung.embo.formula.entity;
import java.util.ArrayList;
import java.util.List;
import com.samsung.resource.entity.AttachFile;
import lombok.Data;
@Data
public class Formula {
private String fmId;
private String fmName;
private String fmType;
private String fmDesc;
private String userId;
// 첨부 파일
private List<AttachFile> attachments = new ArrayList<>();
}
@@ -0,0 +1,65 @@
package com.samsung.embo.formula.impl;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.samsung.common.IdGenService;
import com.samsung.embo.formula.FormulaService;
import com.samsung.embo.formula.dao.FormulaDao;
import com.samsung.embo.formula.entity.Formula;
import com.samsung.resource.FileManagerService;
@Service
public class FormulaServiceImpl implements FormulaService {
private static final String DOWNLOAD_TYPE = "FORMULA";
private final IdGenService idGenService;
private final FileManagerService fileManagerService;
private final FormulaDao formulaDao;
public FormulaServiceImpl(IdGenService idGenService, FileManagerService fileManagerService, FormulaDao formulaDao) {
this.idGenService = idGenService;
this.fileManagerService = fileManagerService;
this.formulaDao = formulaDao;
}
@Override
public String insertFormula(Formula formula) {
formula.setFmId(idGenService.getNextStringId());
formulaDao.insertFormula(formula);
fileManagerService.updateFileRefId(formula.getFmId(), formula.getAttachments(), DOWNLOAD_TYPE);
return formula.getFmId();
}
@Override
public String updateFormula(Formula formula) {
formulaDao.updateFormula(formula);
fileManagerService.updateFileRefId(formula.getFmId(), formula.getAttachments(), DOWNLOAD_TYPE);
return formula.getFmId();
}
@Override
public List<Map<String, Object>> selectFormula(Map<String, Object> params) {
return formulaDao.selectFormula(params);
}
@Override
public int deleteFormula(Map<String, Object> params) {
return formulaDao.deleteFormula(params);
}
@Override
public Map<String, Object> getFormula(Map<String, Object> params) {
return formulaDao.getFormula(params);
}
}
@@ -0,0 +1,14 @@
package com.samsung.embo.kpi;
import java.util.List;
import java.util.Map;
public interface KpiService {
List<Map<String, Object>> selectModule(Map<String, Object> params);
List<Map<String, Object>> selectTarget(Map<String, Object> params);
List<Map<String, Object>> selectKpi(Map<String, Object> params);
}
@@ -0,0 +1,16 @@
package com.samsung.embo.kpi;
import java.util.List;
import java.util.Map;
public interface ModuleService {
List<Map<String, Object>> selectModule(Map<String, Object> params);
String insertModule(Map<String, Object> params);
void updateModule(Map<String, Object> params);
int deleteModule(Map<String, Object> params);
}
@@ -0,0 +1,16 @@
package com.samsung.embo.kpi;
import java.util.List;
import java.util.Map;
public interface ParameterService {
List<Map<String, Object>> selectParameter(Map<String, Object> params);
String insertParameter(Map<String, Object> params);
void updateParameter(Map<String, Object> params);
int deleteParameter(Map<String, Object> params);
}
@@ -0,0 +1,62 @@
package com.samsung.embo.kpi.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.samsung.authentication.Account;
import com.samsung.embo.kpi.KpiService;
import com.samsung.role.RoleService;
import com.samsung.user.entity.User;
import io.swagger.v3.oas.annotations.Operation;
@RestController
@RequestMapping("/embo/kpi/")
public class KpiController {
private final KpiService kpiService;
public KpiController(KpiService kpiService, RoleService roleService) {
this.kpiService = kpiService;
}
@Operation(summary = "moduleInfo 조회")
@PostMapping(value = "main.do", params = "method=getModuleList")
public Map<String, Object> getModuleList(@RequestBody Map<String, Object> params) throws Exception {
User user = Account.currentUser();
params.put("user", user);
Map<String, Object> result = new HashMap<String, Object>();
result.put("user", user);
result.put("result", kpiService.selectModule(params));
return result;
}
@Operation(summary = "myKpi 조회")
@GetMapping(value = "main.do", params = "method=getKpiList")
public List<Map<String, Object>> getKpiList() throws Exception {
Map<String, Object> params = new HashMap<String, Object>();
params.put("userId", Account.currentUser().getUserId());
return kpiService.selectKpi(params);
}
@Operation(summary = "target 조회")
@GetMapping(value = "main.do", params = "method=getTargetList")
public List<Map<String, Object>> getTargetList() throws Exception {
Map<String, Object> params = new HashMap<String, Object>();
User user = Account.currentUser();
params.put("user", user.getUserId());
return kpiService.selectTarget(params);
}
}
@@ -0,0 +1,77 @@
package com.samsung.embo.kpi.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.samsung.authentication.Account;
import com.samsung.embo.formula.entity.Formula;
import com.samsung.embo.kpi.ModuleService;
import com.samsung.user.entity.User;
import io.swagger.v3.oas.annotations.Operation;
@RestController
@RequestMapping("/embo/module/")
public class ModuleController {
private final ModuleService moduleService;
public ModuleController(ModuleService moduleService) {
this.moduleService = moduleService;
}
@Operation(summary = "moduleInfo 조회")
@PostMapping(value = "main.do", params = "method=search")
public Map<String, Object> search(@RequestBody Map<String, Object> params) throws Exception {
User user = Account.currentUser();
params.put("userId", user.getUserId());
Map<String, Object> result = new HashMap<String, Object>();
result.put("result",moduleService.selectModule(params));
return result;
}
@Operation(summary = "moduleInfo 상세조회")
@PostMapping(value = "main.do", params = "method=getModule")
public Map<String, Object> getModule(@RequestBody Map<String, Object> params) throws Exception {
Map<String, Object> result = new HashMap<String, Object>();
result.put("result", moduleService.selectModule(params));
return result;
}
@Operation(summary = "moduleInfo 등록")
@PostMapping(value = "main.do", params = "method=regist")
public String regist(@RequestBody Map<String, Object> params) throws Exception {
User user = Account.currentUser();
params.put("userId", user.getUserId());
return moduleService.insertModule(params);
}
@Operation(summary = "moduleInfo 수정")
@PostMapping(value = "main.do", params = "method=update")
public String update(@RequestBody Map<String, Object> params) throws Exception {
User user = Account.currentUser();
params.put("userId", user.getUserId());
moduleService.updateModule(params);
return "success";
}
@Operation(summary = "moduleInfo 삭제")
@PostMapping(value = "main.do", params = "method=delete")
public String delete(@RequestBody Map<String, Object> params) throws Exception {
User user = Account.currentUser();
params.put("userId", user.getUserId());
int ret = moduleService.deleteModule(params);
return "success";
}
}
@@ -0,0 +1,77 @@
package com.samsung.embo.kpi.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.samsung.authentication.Account;
import com.samsung.embo.formula.entity.Formula;
import com.samsung.embo.kpi.ParameterService;
import com.samsung.user.entity.User;
import io.swagger.v3.oas.annotations.Operation;
@RestController
@RequestMapping("/embo/parameter/")
public class ParemeterController {
private final ParameterService parameterService;
public ParemeterController(ParameterService parameterService) {
this.parameterService = parameterService;
}
@Operation(summary = "parameterInfo 조회")
@PostMapping(value = "main.do", params = "method=search")
public Map<String, Object> search(@RequestBody Map<String, Object> params) throws Exception {
User user = Account.currentUser();
params.put("userId", user.getUserId());
Map<String, Object> result = new HashMap<String, Object>();
result.put("result",parameterService.selectParameter(params));
return result;
}
@Operation(summary = "parameterInfo 상세조회")
@PostMapping(value = "main.do", params = "method=getParameter")
public Map<String, Object> getParameter(@RequestBody Map<String, Object> params) throws Exception {
Map<String, Object> result = new HashMap<String, Object>();
result.put("result", parameterService.selectParameter(params));
return result;
}
@Operation(summary = "parameterInfo 등록")
@PostMapping(value = "main.do", params = "method=regist")
public String regist(@RequestBody Map<String, Object> params) throws Exception {
User user = Account.currentUser();
params.put("userId", user.getUserId());
return parameterService.insertParameter(params);
}
@Operation(summary = "parameterInfo 수정")
@PostMapping(value = "main.do", params = "method=update")
public String update(@RequestBody Map<String, Object> params) throws Exception {
User user = Account.currentUser();
params.put("userId", user.getUserId());
parameterService.updateParameter(params);
return "success";
}
@Operation(summary = "parameterInfo 삭제")
@PostMapping(value = "main.do", params = "method=delete")
public String delete(@RequestBody Map<String, Object> params) throws Exception {
User user = Account.currentUser();
params.put("userId", user.getUserId());
int ret = parameterService.deleteParameter(params);
return "success";
}
}
@@ -0,0 +1,25 @@
package com.samsung.embo.kpi.dao;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
@Repository
public class KpiDao {
private static final String MAPPER = "kpiMapper.";
private final SqlSession sqlSession;
public KpiDao(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
public List<Map<String, Object>> selectModule(Map<String, Object> params) {
return sqlSession.selectList(MAPPER + "selectModule", params);
}
public List<Map<String, Object>> selectTarget(Map<String, Object> params) {
return sqlSession.selectList(MAPPER + "selectTarget", params);
}
public List<Map<String, Object>> selectKpi(Map<String, Object> params) {
return sqlSession.selectList(MAPPER + "selectKpi", params);
}
}
@@ -0,0 +1,34 @@
package com.samsung.embo.kpi.dao;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
@Repository
public class ModuleDao {
private static final String MAPPER = "moduleMapper.";
private final SqlSession sqlSession;
public ModuleDao(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
public List<Map<String, Object>> selectModule(Map<String, Object> params) {
return sqlSession.selectList(MAPPER + "selectModule", params);
}
public String insertModule(Map<String, Object> params) {
sqlSession.insert(MAPPER + "insertModule", params);
return params.get("kpiModuleId").toString();
}
public void updateModule(Map<String, Object> params) {
sqlSession.update(MAPPER + "updateModule", params);
}
public int deleteModule(Map<String, Object> params) {
return sqlSession.delete(MAPPER + "deleteModule", params);
}
}
@@ -0,0 +1,34 @@
package com.samsung.embo.kpi.dao;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
@Repository
public class ParameterDao {
private static final String MAPPER = "parameterMapper.";
private final SqlSession sqlSession;
public ParameterDao(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
public List<Map<String, Object>> selectParameter(Map<String, Object> params) {
return sqlSession.selectList(MAPPER + "selectParameter", params);
}
public String insertParameter(Map<String, Object> params) {
sqlSession.insert(MAPPER + "insertParameter", params);
return params.get("parameterType").toString();
}
public void updateParameter(Map<String, Object> params) {
sqlSession.update(MAPPER + "updateParameter", params);
}
public int deleteParameter(Map<String, Object> params) {
return sqlSession.delete(MAPPER + "deleteParameter", params);
}
}
@@ -0,0 +1,36 @@
package com.samsung.embo.kpi.impl;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.samsung.embo.kpi.KpiService;
import com.samsung.embo.kpi.dao.KpiDao;
@Service
public class KpiServiceImpl implements KpiService{
private final KpiDao kpiDao;
public KpiServiceImpl(KpiDao kpiDao) {
this.kpiDao = kpiDao;
}
@Override
public List<Map<String, Object>> selectModule(Map<String, Object> params) {
return kpiDao.selectModule(params);
}
@Override
public List<Map<String, Object>> selectTarget(Map<String, Object> params) {
return kpiDao.selectTarget(params);
}
@Override
public List<Map<String, Object>> selectKpi(Map<String, Object> params) {
return kpiDao.selectKpi(params);
}
}
@@ -0,0 +1,43 @@
package com.samsung.embo.kpi.impl;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.samsung.embo.common.util.dao.UtilDao;
import com.samsung.embo.kpi.ModuleService;
import com.samsung.embo.kpi.dao.ModuleDao;
@Service
public class ModuleServiceImpl implements ModuleService{
private static final String MODULE_HEADER = "KM";
private final ModuleDao moduleDao;
private final UtilDao utilDao;
public ModuleServiceImpl(ModuleDao moduleDao,UtilDao utilDao) {
this.moduleDao = moduleDao;
this.utilDao = utilDao;
}
@Override
public List<Map<String, Object>> selectModule(Map<String, Object> params) {
return moduleDao.selectModule(params);
}
@Override
public String insertModule(Map<String, Object> params) {
params.put("kpiModuleId", MODULE_HEADER+utilDao.selectSeqKpiMaster());
return moduleDao.insertModule(params);
}
@Override
public void updateModule(Map<String, Object> params) {
moduleDao.updateModule(params);
}
@Override
public int deleteModule(Map<String, Object> params) {
return moduleDao.deleteModule(params);
}
}
@@ -0,0 +1,43 @@
package com.samsung.embo.kpi.impl;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.samsung.embo.common.util.dao.UtilDao;
import com.samsung.embo.kpi.ParameterService;
import com.samsung.embo.kpi.dao.ParameterDao;
@Service
public class ParameterServiceImpl implements ParameterService{
private static final String MODULE_HEADER = "PT";
private final ParameterDao parameterDao;
private final UtilDao utilDao;
public ParameterServiceImpl(ParameterDao parameterDao,UtilDao utilDao) {
this.parameterDao = parameterDao;
this.utilDao = utilDao;
}
@Override
public List<Map<String, Object>> selectParameter(Map<String, Object> params) {
return parameterDao.selectParameter(params);
}
@Override
public String insertParameter(Map<String, Object> params) {
params.put("parameterType", MODULE_HEADER+utilDao.selectSeqKpiMaster());
return parameterDao.insertParameter(params);
}
@Override
public void updateParameter(Map<String, Object> params) {
parameterDao.updateParameter(params);
}
@Override
public int deleteParameter(Map<String, Object> params) {
return parameterDao.deleteParameter(params);
}
}
@@ -0,0 +1,17 @@
package com.samsung.embo.util;
import java.util.LinkedHashMap;
import com.google.common.base.CaseFormat;
public class CamelHashMap extends LinkedHashMap {
@Override
public Object put(Object key, Object value) {
return super.put(toLowerCamel((String) key), value);
}
private static String toLowerCamel(String key) {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, key);
}
}
@@ -0,0 +1,33 @@
package com.samsung.filter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CorsFilter extends OncePerRequestFilter {
private static final String EXPOSE_HEADERS = "Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma, Accept, Accept-Language, Content-Disposition, x-auth-token, page-id, menu-id, " +
"Access-Control-Request-Headers, Origin, Referer, User-Agent, original-user-id, last-access-time, Date";
@Value("${cors.domain:*}")
private String domain;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
response.addHeader("Access-Control-Allow-Origin", domain);
if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH");
response.addHeader("Access-Control-Allow-Headers", EXPOSE_HEADERS);
response.addHeader("Access-Control-Max-Age", "3600");
}
response.addHeader("Access-Control-Expose-Headers", EXPOSE_HEADERS);
filterChain.doFilter(request, response);
}
}
@@ -0,0 +1,41 @@
package com.samsung.filter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
@Profile("prod")
public class SslFilter extends OncePerRequestFilter {
@Value("${ssl-port:443}")
private String sslPort;
@Override
@SuppressWarnings({"jasper:id:issue:redirection", "jasper:id:issue:httpresponse"})
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String url = request.getRequestURI();
String protocol = request.getHeader("X-Forwarded-Proto");
String domain = request.getServerName();
String queryString = request.getQueryString();
if (StringUtils.equals("http", protocol)) {
response.setContentType(request.getContentType());
//HTTPS 도메인 세팅 및 쿼리스트링 추가
StringBuilder httpsPath = new StringBuilder("https" + "://" + domain + ":" + sslPort + url);
if (StringUtils.isNotEmpty(queryString)) {
httpsPath.append("?").append(queryString);
}
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
response.setHeader("Location", httpsPath.toString());
}
filterChain.doFilter(request, response);
}
}
@@ -0,0 +1,83 @@
package com.samsung.interceptor;
import com.samsung.authentication.Account;
import com.samsung.common.util.JwtUtil;
import com.samsung.core.exception.*;
import com.samsung.role.RoleService;
import com.samsung.user.UserService;
import com.samsung.user.entity.User;
import io.jsonwebtoken.JwtException;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Log4j2
public class AuthenticationInterceptor implements HandlerInterceptor {
@Autowired
JwtUtil jwtUtil;
@Autowired
RoleService roleService;
@Value("${security.check.duplicate.login:false}")
private boolean checkDuplicateLogin;
@Autowired
UserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("x-auth-token");
// Token 값 유무
if (StringUtils.isEmpty(token)) {
throw new NotFoundTokenException("Not Found Token");
}
String userId;
try {
userId = jwtUtil.getUserIdFromToken(token);
} catch (JwtException ex) {
throw new InvalidTokenException("Invalid Token");
}
User user = userService.getUserById(userId);
String originalUserId = request.getHeader("original-user-id");
if (ObjectUtils.isEmpty(user)) {
// token이 있으면서 시스템 사용자가 아닐 경우는 없음
throw new NoSearchUserException("No Search User");
} else {
if (checkDuplicateLogin && StringUtils.isEmpty(originalUserId) && StringUtils.isNotEmpty(user.getJwt())) {
checkDuplicateLogin(token, user);
}
Boolean jwtValid = jwtUtil.validateToken(token, user);
if (Boolean.TRUE.equals(jwtValid)) {
if (user.isActiveFlag()) {
user.setSystemAdminUser(roleService.isSystemAdmin(userId));
Account.updateCurrentAccount(user);
return true;
} else {
// 시스템 승인 대기중
throw new WaitingUserException("Waiting User");
}
} else {
throw new InvalidTokenException("Token Expired");
}
}
}
private void checkDuplicateLogin(String token, User user) {
//중복 로그인 방지 현재 로그인된 JWT토큰과 현재 토큰값을 비교
if (!user.getJwt().equals(token.split("\\.")[2])) {
throw new DuplicateLoginException("Duplicate Login!");
}
}
}
@@ -0,0 +1,136 @@
package com.samsung.interceptor;
import com.samsung.adminaddress.AdminAddressService;
import com.samsung.authentication.Account;
import com.samsung.common.util.WebUtil;
import com.samsung.core.exception.AuthorizationException;
import com.samsung.core.exception.NoSearchUserException;
import com.samsung.menu.ApiService;
import com.samsung.menu.entity.Api;
import com.samsung.role.RoleService;
import com.samsung.user.entity.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.util.UriTemplate;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Log4j2
public class AuthorizationInterceptor implements HandlerInterceptor {
@Autowired
private RoleService roleService;
@Autowired
private ApiService apiService;
@Autowired
private AdminAddressService adminAddressService;
@Autowired
private WebUtil webUtil;
@Value("${admin.address.check:false}")
private boolean adminAddressCheck;
@SuppressWarnings("squid:S3516")
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
User user = Account.currentUser();
if (user == null) {
throw new NoSearchUserException("No Search User");
}
if (roleService.isSystemAdmin(user.getUserId())) {
if(adminAddressCheck) {
List<String> adminAddresses = adminAddressService.getAdminAddresses(null);
String remoteAddr = webUtil.getClientIp(request);
if(ObjectUtils.isNotEmpty(adminAddresses) && !adminAddresses.contains(remoteAddr)) {
throw new AuthorizationException("Remote address is not admin ip address.");
}
}
return true;
}
StringBuilder path = new StringBuilder(request.getRequestURI().substring(request.getContextPath().length()));
if (StringUtils.isNotEmpty(request.getQueryString())) path.append("?").append(request.getQueryString());
String menuId = request.getHeader("menu-id");
List<Api> authMenuList;
if (StringUtils.isNotEmpty(menuId)) {
authMenuList = apiService.getUserAuthApiListByUserIdAndMenuId(user.getUserId(), menuId);
} else {
authMenuList = apiService.getUserAuthApiListByUserId(user.getUserId());
}
String httpMethod = request.getMethod();
String decodedUrl = webUtil.getDecodedRequestUrl(path.toString());
String queryString = "";
if (decodedUrl.indexOf('?') > -1) {
String[] uri = decodedUrl.split("\\?");
decodedUrl = uri[0];
queryString = uri[1];
}
for (Api api : authMenuList) {
if (api.getHttpMethod().equals(httpMethod) && checkUriMatch(api.getApiPath(), api.getApiParameters(), decodedUrl, queryString)) {
return true;
}
}
throw new AuthorizationException("API 권한 없음");
}
private Map<String, String> getRequestParam(String query) {
if (StringUtils.isNotEmpty(query)) {
query = URLDecoder.decode(query, StandardCharsets.UTF_8);
return getParamToMap(query);
} else {
return new HashMap<>();
}
}
private Map<String, String> getParamToMap(String query) {
return Arrays.stream(query.split("&"))
.map(s -> s.split("=", 2))
.filter(arr -> arr.length == 2)
.collect(Collectors.toMap(arr -> arr[0].trim(), arr -> arr[1].trim()));
}
public boolean checkUriMatch(String apiPath, String apiParameters, String decodedUrl, String queryString){
Map<String, String> requiredParamMap = new HashMap<>();
if( StringUtils.isNotEmpty(apiParameters)){
requiredParamMap = getParamToMap(apiParameters);
}
UriTemplate uriTemplate = new UriTemplate(apiPath);
if ( uriTemplate.matches(decodedUrl) ){
if(requiredParamMap.isEmpty()) return true;
for (Map.Entry<String, String> entry : requiredParamMap.entrySet()) {
log.debug("Required Param : " + entry.getKey() + " Value : " + entry.getValue());
Map<String, String> requestParamMap = getRequestParam(queryString);
if( !requestParamMap.containsKey(entry.getKey()) || !(entry.getValue()).equals(requestParamMap.get(entry.getKey()))){
return false;
}
}
return true;
}else{
return false;
}
}
}
@@ -0,0 +1,146 @@
package com.samsung.interceptor;
import com.samsung.accesslog.AccessLogService;
import com.samsung.accesslog.entity.SysUseLog;
import com.samsung.accesslog.enums.ReqType;
import com.samsung.authentication.Account;
import com.samsung.batch.enums.LogFlag;
import com.samsung.common.IdGenService;
import com.samsung.common.util.WebUtil;
import com.samsung.menu.MenuService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.UriTemplate;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Log4j2
public class LoggingInterceptor implements HandlerInterceptor {
private static final String DATE_PATTERN = "yyyyMMdd HHmmssSSS";
@Autowired
private AccessLogService accessLogService;
@Autowired
private MenuService menuService;
@Autowired
private IdGenService idGenService;
@Autowired
private WebUtil webUtil;
@Value("${access-log.store-type}")
private String storeType;
@Value("${node-id}")
private String node;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
long start = System.nanoTime();
request.setAttribute("start", start);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) {
String requestMethod = request.getMethod();
if(HttpMethod.OPTIONS.name().equals(requestMethod)) return;
String requestURI = request.getRequestURI().substring(request.getContextPath().length());
String getDecodedRequestURI = webUtil.getDecodedRequestUrl(requestURI);
String query = request.getQueryString();
String menuId = request.getHeader("menu-Id");
String pageId = request.getHeader("page-id");
String originalUserId = request.getHeader("original-user-id");
SimpleDateFormat formatter = new SimpleDateFormat(DATE_PATTERN, Locale.getDefault());
String sTime = formatter.format(new Date());
long start = (long) request.getAttribute("start");
long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
String userId = "anonymous";
if (ObjectUtils.isNotEmpty(Account.currentUser())) userId = Account.currentUser().getUserId();
SysUseLog sysUseLog = new SysUseLog();
sysUseLog.setLogOccurId(idGenService.getNextStringId());
// 메뉴에 등록된 API 호출 시 API 전체 경로를 저장.
if(menuId != null) sysUseLog.setDescription(checkApiUrl(menuId, requestMethod, getDecodedRequestURI));
sysUseLog.setNodeId(node);
sysUseLog.setUserId(userId);
sysUseLog.setUseFromDate(sTime.substring(0, 8));
sysUseLog.setUseFromHhmmss(sTime.substring(9, 15));
sysUseLog.setUseThruDatetime(new Date());
sysUseLog.setResponseTime(elapsedTime);
sysUseLog.setPath(getDecodedRequestURI);
if (query != null) {
try {
query = URLDecoder.decode(query, "UTF-8");
} catch (UnsupportedEncodingException e) {
log.error(e.getMessage(), e);
}
String queryStr = StringUtils.replace(query, "'", "\\'");
sysUseLog.setParameter(queryStr);
sysUseLog.setUrl(requestURI + "?" + queryStr);
}
sysUseLog.setUseIp(webUtil.getClientIp(request));
sysUseLog.setBrowserTypeName(request.getHeader("User-Agent"));
sysUseLog.setLogFlag(LogFlag.ACCESS_LOG.getValue());
sysUseLog.setReqType(ReqType.WEB);
sysUseLog.setFirstRegDatetime(new Date());
sysUseLog.setMenuId(menuId);
sysUseLog.setPageId(pageId);
sysUseLog.setMethod(requestMethod);
// 대리 로그인 시 별도 이력 남김
if(StringUtils.isNotEmpty(originalUserId)){
sysUseLog.setLogFlag(LogFlag.IMPERSONATION_ACCESS.getValue());
sysUseLog.setDescription("Original User Id : " + originalUserId);
}
try {
if ("db".equalsIgnoreCase(storeType)) {
accessLogService.insertAccessLog(sysUseLog);
} else {
accessLogService.logAccess(sysUseLog);
}
} catch (Exception e) {
log.error(e.getMessage());
}
}
private String checkApiUrl(String menuId, String requestMethod, String requestUri) {
UriTemplate uriTemplate;
List<Map<String, String>> apiListByMenuId = new ArrayList<>();
if(menuService.getApiFullPathList().containsKey(menuId)) {
apiListByMenuId = menuService.getApiFullPathList().get(menuId);
}
for(Map<String, String> api : apiListByMenuId) {
uriTemplate = new UriTemplate(api.get("apiPath"));
if(uriTemplate.matches(requestUri) && requestMethod.equals(api.get("httpMethod"))) return api.get("fullPath");
}
return null;
}
}
@@ -0,0 +1,62 @@
package com.samsung.interceptor;
import com.samsung.common.util.WebUtil;
import com.samsung.loginout.LoginOutLogService;
import com.samsung.loginout.entity.LoginOut;
import com.samsung.user.UserService;
import com.samsung.user.entity.User;
import com.samsung.user.interceptor.LoginInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date;
import java.util.Map;
@Log4j2
public class LoginOutLogInterceptor implements LoginInterceptor {
@Autowired
private LoginOutLogService loginOutLogService;
@Autowired
private UserService userService;
@Autowired
private WebUtil webUtil;
@Override
public void postLogin(HttpServletRequest request, HttpServletResponse response, User user) {
LoginOut loginOut = new LoginOut();
if (StringUtils.isNotEmpty(user.getJwt())) {
loginOut.setToken(user.getJwt().substring(user.getJwt().lastIndexOf('.') + 1));
}
loginOut.setUserId(user.getUserId());
loginOut.setLoginTime(new Date());
loginOut.setUseIp(user.getRecentLoginIp());
loginOut.setReqType("WEB");
loginOutLogService.insertLogin(loginOut);
}
@Override
public void preLogout(HttpServletRequest request, HttpServletResponse response, User user) {
LoginOut loginOut = new LoginOut();
if (StringUtils.isNotEmpty(user.getJwt())) {
loginOut.setToken(user.getJwt().substring(user.getJwt().lastIndexOf('.') + 1));
}
loginOut.setUserId(user.getUserId());
loginOut.setLoginTime(user.getRecentLoginDatetime());
loginOut.setLogoutTime(new Date());
loginOut.setUseIp(webUtil.getClientIp(request));
loginOut.setReqType("WEB");
loginOutLogService.updateLogout(loginOut);
userService.updateUserJwt(Map.of("userId", user.getUserId(), "lastLogoutDate", new Date(), "jwt", ""));
}
}
@@ -0,0 +1,127 @@
package com.samsung.interceptor;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Properties;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import com.fasterxml.jackson.databind.ObjectMapper;
@Intercepts({
@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class,
RowBounds.class, ResultHandler.class }),
@Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class MybatisExecuteInterceptor implements Interceptor {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MybatisExecuteInterceptor.class);
@Override
public Object intercept(Invocation invocation) throws Throwable {
StringBuilder str = new StringBuilder();
String queryID = ((MappedStatement) invocation.getArgs()[0]).getId();
str.append("QUERYID ==================>>> ");
str.append(queryID);
str.append(" <<<==================\n");
Object param = invocation.getArgs()[1];
ObjectMapper mapper = new ObjectMapper();
str.append(mapper.writeValueAsString(param));
log.info(str.toString());
//BoundSql boundSql = ((MappedStatement) invocation.getArgs()[0]).getBoundSql(param);
//String queryString = boundSql.getSql();
//str.append("\n=========================== 쿼리검증 ==============================\n");
//if (queryID.indexOf("clms") > -1 && queryString.indexOf("2024#LAS 전환확인") < 0) str.append("====> 쿼리전환작업대상 <====\n");
//str.append(queryID);
//str.append("\n=========================================================\n");
//log.info(queryString);
/*
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@10.155.21.158:1621:LAS", "las",
"dlatl003!");
try {
PreparedStatement ps = conn.prepareStatement(
"INSERT INTO ZZ_CLM_QUERY_LOG ( SID,QUERY_ID,QUERY ) VALUES ( zz_seq.NEXTVAL, '" + queryID + "',? )");
((OraclePreparedStatement) ps).setStringForClob(1, queryString.replaceAll("(?m)^[ \t]*\r?\n", ""));
ps.execute();
}
finally {
conn.close();
}*/
return invocation.proceed();
}
private Object getObject(Object parameterObject, ParameterMapping parameterMapping, BoundSql boundSql)
throws IllegalAccessException, NoSuchFieldException {
if (parameterObject instanceof Number || parameterObject instanceof String)
return parameterObject;
else if (parameterObject instanceof Map) {
String propKey = parameterMapping.getProperty(); // <foreach>인 경우 propKey가 "__frch_%아이템명%_반복횟수"
Object value = ((Map<?, ?>) parameterObject).get(propKey);
if (value == null) {
// __frch_ PREFIX에 대한 처리
if (boundSql.hasAdditionalParameter(propKey)) { // myBatis가 추가 동적인수를 생성했는지 체크하고
value = boundSql.getAdditionalParameter(propKey); // 해당 추가 동적인수의 Value를 가져옴
return value;
}
}
return value;
// String property = parameterMapping.getProperty();
// return ((Map<?, ?>) parameterObject).get(property);
} else {
Class<?> aClass = parameterObject.getClass();
String property = parameterMapping.getProperty();
Field declaredField = null;
try {
declaredField = aClass.getDeclaredField(property);
} catch (NoSuchFieldException e) {
while (aClass.getSuperclass() != null) {
aClass = aClass.getSuperclass();
try {
declaredField = aClass.getDeclaredField(property);
break;
} catch (NoSuchFieldException ignored) {
}
}
}
if (declaredField == null)
throw new NoSuchFieldException(property);
declaredField.setAccessible(true);
return declaredField.get(parameterObject);
}
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
@@ -0,0 +1,50 @@
package com.samsung.interceptor;
import com.samsung.authentication.Account;
import com.samsung.core.exception.PrivacyPolicyException;
import com.samsung.user.entity.User;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Log4j2
public class PrivacyPolicyInterceptor implements HandlerInterceptor {
/**
* 약관동의 사용 여부
*/
@Value("${privacy-policy.check.enabled:true}")
private boolean privacyPolicyCheck;
/**
* 약관동의 인터셉터 체크 제외 URI
*/
@Value("${privacy-policy.check.exclude-path}")
private String privacyPolicyCheckExcludePath;
@Override
@SuppressWarnings("squid:S3516")
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (!privacyPolicyCheck) return true;
String requestUri = request.getRequestURI();
String[] privacyPolicyCheckExcludePathList = privacyPolicyCheckExcludePath.split(",");
for (String excludePath : privacyPolicyCheckExcludePathList) {
if (requestUri.contains(excludePath)) {
return true;
}
}
User user = Account.currentUser();
if (user != null && !user.isPrivacyPolicy()) {
throw new PrivacyPolicyException("Privacy policy agreement required.");
} else {
return true;
}
}
}
@@ -0,0 +1,35 @@
package com.samsung.interceptor;
import com.samsung.core.exception.TokenRetentionTimeoutException;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Log4j2
public class TimeoutCheckInterceptor implements HandlerInterceptor {
@Value("${security.access.limit.timeout:30}")
private int limitTimeout;
static final long MILLISECONDS_PER_MINUTE = 60L*1000L;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
String lastAccessTimeHeader = request.getHeader("last-access-time");
String impersonate = request.getHeader("original-user-id");
if(StringUtils.isNotEmpty(lastAccessTimeHeader) && !StringUtils.equals("undefined", lastAccessTimeHeader) && !StringUtils.equals("NaN", lastAccessTimeHeader) && StringUtils.isEmpty(impersonate)){
long lastActivityTime = Long.parseLong(lastAccessTimeHeader);
long currentTime = System.currentTimeMillis();
long jwtRetentionTime = currentTime - lastActivityTime;
if (jwtRetentionTime > (limitTimeout * MILLISECONDS_PER_MINUTE)) {
//limitTimeout 동안 사용하지 않으면 자동 로그아웃
throw new TokenRetentionTimeoutException("Token Retention Timeout");
}
}
return true;
}
}
@@ -0,0 +1,50 @@
package com.samsung.interceptor;
import com.samsung.resource.FileManagerException;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;
import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.List;
@Log4j2
public class UploadFileExtensionCheckInterceptor implements HandlerInterceptor {
private String allowedExtensions;
@Value("${common.upload.allowed-extensions}")
public void setAllowedExtensions(String allowedExtensions) {
this.allowedExtensions = allowedExtensions.toLowerCase();
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (request instanceof MultipartRequest) {
MultipartRequest req = ((MultipartRequest) request);
Collection<List<MultipartFile>> multiFiles = req.getMultiFileMap().values();
for (List<MultipartFile> fileList : multiFiles) {
for (MultipartFile file : fileList) {
String fileName = file.getOriginalFilename();
String fileExt = "";
if (fileName != null) {
fileExt = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
}
if (!isAllowedExtension(fileExt)) {
throw new FileManagerException("Not allowed file extension: " + fileName);
}
}
}
}
return true;
}
private boolean isAllowedExtension(String fileExt) {
return allowedExtensions.contains(fileExt);
}
}
@@ -0,0 +1,36 @@
package com.samsung.interceptor;
import com.samsung.common.util.WebUtil;
import com.samsung.user.UserService;
import com.samsung.user.entity.User;
import com.samsung.user.interceptor.LoginInterceptor;
import lombok.extern.log4j.Log4j2;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Date;
@Log4j2
public class UserUpdateInterceptor implements LoginInterceptor {
@Autowired
private UserService userService;
@Autowired
private WebUtil webUtil;
@Override
public void postLogin(HttpServletRequest request, HttpServletResponse response, User user) {
String recentLoginIp = user.getRecentLoginIp();
Date recentLoginDatetime = user.getRecentLoginDatetime();
user.setLastLoginDate(recentLoginDatetime);
user.setLastLoginIp(recentLoginIp);
user.setRecentLoginDatetime(new Date());
user.setRecentLoginIp(webUtil.getClientIp(request));
user.setLastActivityTime(System.currentTimeMillis());
userService.updateUser(user);
}
}
@@ -0,0 +1,54 @@
package com.samsung.sample.approval.internal;
import com.samsung.approval.entity.ApprovalStep;
import com.samsung.approval.enums.ApprovalDocStatus;
import com.samsung.core.entity.PagingResult;
import com.samsung.sample.approval.internal.dto.InternalSampleSearchDto;
import com.samsung.sample.approval.internal.entity.InternalApprovalSampleDocument;
import java.util.List;
public interface InternalApprovalSampleService {
/**
* 결재문서 목록 조회(페이징).
* @param internalSampleSearchDto 조회조건
* @return 결재문서 목록
*/
PagingResult<InternalApprovalSampleDocument> getSampleApprovalDocumentPagingList(InternalSampleSearchDto internalSampleSearchDto);
/**
* 결재문서 상세조회.
* @param docId 문서ID
* @return 결재문서 상세정보
*/
InternalApprovalSampleDocument getSampleApprovalDocument(String docId);
/**
* 결재문서 저장.
* @param internalApprovalSampleDocument 결재문서 정보
* @return
*/
void insertSampleApprovalDocument(InternalApprovalSampleDocument internalApprovalSampleDocument);
/**
* 결재문서 수정.
* @param internalApprovalSampleDocument 결재문서 정보
* @return
*/
void modifySampleApprovalDocument(InternalApprovalSampleDocument internalApprovalSampleDocument);
/**
* 결재문서 삭제.
* @param internalApprovalSampleDocument 결재문서 정보
* @return
*/
void deleteSampleApprovalDocument(InternalApprovalSampleDocument internalApprovalSampleDocument);
/**
* 결재문서 상태 업데이트.
* @param docId 문서ID
* @param approvalDocStatus 결재상태
*/
void updateSampleApprovalDocument(String docId, ApprovalDocStatus approvalDocStatus);
}
@@ -0,0 +1,156 @@
package com.samsung.sample.approval.internal.controller;
import com.samsung.approval.ApprovalService;
import com.samsung.approval.annotation.ApprovalDocument;
import com.samsung.approval.entity.DynamicApprovalPath;
import com.samsung.approval.entity.RequiredApprovalUser;
import com.samsung.approval.enums.ApprovalDocStatus;
import com.samsung.authentication.Account;
import com.samsung.common.IdGenService;
import com.samsung.core.entity.PagingResult;
import com.samsung.core.exception.KnoxApprovalException;
import com.samsung.resource.FileManagerService;
import com.samsung.sample.approval.internal.InternalApprovalSampleService;
import com.samsung.sample.approval.internal.dto.InternalApprovalSubmitDto;
import com.samsung.sample.approval.internal.dto.InternalSampleSearchDto;
import com.samsung.sample.approval.internal.entity.InternalApprovalSampleDocument;
import com.samsung.template.TemplateConstants;
import com.samsung.user.entity.User;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@RestController
@RequestMapping("/sample/approval/internal")
public class InternalApprovalSampleController {
private final FileManagerService fileManagerService;
private final IdGenService idGenService;
private final InternalApprovalSampleService internalApprovalSampleService;
private final ApprovalService approvalService;
private final MessageSourceAccessor messageSourceAccessor;
public InternalApprovalSampleController(FileManagerService fileManagerService, IdGenService idGenService, InternalApprovalSampleService internalApprovalSampleService, ApprovalService approvalService, MessageSourceAccessor messageSourceAccessor) {
this.fileManagerService = fileManagerService;
this.idGenService = idGenService;
this.internalApprovalSampleService = internalApprovalSampleService;
this.approvalService = approvalService;
this.messageSourceAccessor = messageSourceAccessor;
}
@Operation(summary = "결재문서 목록 조회(페이징)")
@GetMapping("/sample-document-with-paging")
public PagingResult<InternalApprovalSampleDocument> getSampleApprovalDocumentPagingList(
@ModelAttribute InternalSampleSearchDto internalSampleSearchDto) {
return internalApprovalSampleService.getSampleApprovalDocumentPagingList(internalSampleSearchDto);
}
@Operation(summary = "결재 문서 상세 조회")
@GetMapping("/sample-documents/{docId}")
public InternalApprovalSampleDocument getSampleApprovalDocument(
@Parameter(description = "문서 ID") @PathVariable String docId) {
// 문서 상세정보 조회.
InternalApprovalSampleDocument internalApprovalSampleDocument = internalApprovalSampleService.getSampleApprovalDocument(docId);
// 결재 상신전 문서의 결재경로, 필수결재자 여부 setting.
if(ApprovalDocStatus.SAVED.equals(internalApprovalSampleDocument.getDocStatus())) {
// 결재 경로 추가(재직중인 사용자만 추가).
String docType = InternalApprovalSampleDocument.class.getAnnotation(ApprovalDocument.class).docType();
List<DynamicApprovalPath> dynamicApprovalPathList = approvalService.getDynamicApprovalPath(docType);
List<DynamicApprovalPath> dynamicApprovalUserList = new ArrayList<>(0);
for(DynamicApprovalPath dynamicApprovalPath : dynamicApprovalPathList) {
if("B".equals(dynamicApprovalPath.getEmployeeStatus())) {
dynamicApprovalUserList.add(dynamicApprovalPath);
}
}
// 필수 결재자 존재 여부 확인.
boolean checkExistRequiredApprovalUser = false;
List<RequiredApprovalUser> requiredApprovalUserList = approvalService.getRequiredApprovalUserList(docType);
if(!requiredApprovalUserList.isEmpty()) checkExistRequiredApprovalUser = true;
internalApprovalSampleDocument.setDynamicApprovalUserList(dynamicApprovalUserList);
internalApprovalSampleDocument.setExistRequiredApprovalUser(checkExistRequiredApprovalUser);
internalApprovalSampleDocument.setRequiredApprovalUserList(requiredApprovalUserList);
}
internalApprovalSampleDocument.setAttachments(fileManagerService.getAttachFileList(docId, docId));
return internalApprovalSampleDocument;
}
@Operation(summary = "결재 문서 저장")
@PostMapping("/sample-documents")
public InternalApprovalSampleDocument saveDocument(
@Parameter(description = "문서 제목") @RequestParam String title,
@Parameter(description = "본문") @RequestParam String contents) {
InternalApprovalSampleDocument internalApprovalSampleDocument = new InternalApprovalSampleDocument();
String docId = idGenService.getNextStringId();
internalApprovalSampleDocument.setDocId(docId);
internalApprovalSampleDocument.setTitle(title);
internalApprovalSampleDocument.setContents(contents);
internalApprovalSampleDocument.setCreator(Objects.requireNonNull(Account.currentUser()).getUserName());
internalApprovalSampleService.insertSampleApprovalDocument(internalApprovalSampleDocument);
return internalApprovalSampleDocument;
}
@Operation(summary = "결재 문서 수정")
@PutMapping("/sample-documents/{docId}")
public InternalApprovalSampleDocument modifyDocument(
@Parameter(description = "문서 ID") @PathVariable String docId,
@Parameter(description = "본문") @RequestBody InternalApprovalSampleDocument tempDoc) {
internalApprovalSampleService.modifySampleApprovalDocument(tempDoc);
fileManagerService.updateFileRefId(docId, tempDoc.getAttachments(), docId);
return tempDoc;
}
@Operation(summary = "결재 문서 삭제")
@DeleteMapping("/sample-documents/{docId}")
public void deleteDocument(
@Parameter(description = "문서 ID") @PathVariable String docId) {
InternalApprovalSampleDocument internalApprovalSampleDocument = new InternalApprovalSampleDocument();
fileManagerService.updateFileRefId(docId, internalApprovalSampleDocument.getAttachments(), docId);
internalApprovalSampleDocument.setDocId(docId);
internalApprovalSampleService.deleteSampleApprovalDocument(internalApprovalSampleDocument);
fileManagerService.updateFileRefId(docId, null, docId);
}
@Operation(summary = "결재 문서 상신")
@PostMapping("/submit/sample-document")
public void submit(
@RequestBody InternalApprovalSubmitDto internalApprovalSubmitDto) {
if(StringUtils.isEmpty(internalApprovalSubmitDto.getDocId())) throw new KnoxApprovalException("문서 ID는 필수 입니다.");
if(ObjectUtils.isEmpty(internalApprovalSubmitDto.getApprovalStepList())) throw new KnoxApprovalException("결재 패스는 필수 입니다.");
//결재 문서 조회
InternalApprovalSampleDocument internalApprovalSampleDocument = internalApprovalSampleService.getSampleApprovalDocument(internalApprovalSubmitDto.getDocId());
ApprovalDocument approvalDocument = InternalApprovalSampleDocument.class.getAnnotation(ApprovalDocument.class);
String docType = approvalDocument.docType();
User requester = Account.currentUser();
String docId = internalApprovalSampleDocument.getDocId();
approvalService.submit(docType, internalApprovalSampleDocument.getDocId(), internalApprovalSampleDocument.getTitle(), approvalDocument, null, internalApprovalSubmitDto.getComment(), requester, internalApprovalSubmitDto.getApprovalStepList(),
TemplateConstants.DOC_NAME, internalApprovalSampleDocument, "attachments", fileManagerService.getAttachFileList(docId, docId), "messages", messageSourceAccessor,
"internalApproval", approvalDocument.isInternalApproval());
}
}
@@ -0,0 +1,52 @@
package com.samsung.sample.approval.internal.dao;
import com.samsung.core.entity.PagingResult;
import com.samsung.sample.approval.internal.dto.InternalSampleSearchDto;
import com.samsung.sample.approval.internal.entity.InternalApprovalSampleDocument;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
@Repository
public class InternalApprovalSampleDao {
final
SqlSession sqlSession;
public InternalApprovalSampleDao(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
public PagingResult<InternalApprovalSampleDocument> getSampleApprovalDocumentPagingList(InternalSampleSearchDto internalSampleSearchDto) {
internalSampleSearchDto.setStartDate(internalSampleSearchDto.getStartDate().replace("-", ""));
internalSampleSearchDto.setEndDate(internalSampleSearchDto.getEndDate().replace("-", ""));
List<InternalApprovalSampleDocument> internalApprovalSampleDocuments = sqlSession.selectList("sampleApprovalInternal.selectSampleApprovalDocumentPagingList", internalSampleSearchDto);
int cnt = sqlSession.selectOne("sampleApprovalInternal.countSampleApprovalDocument", internalSampleSearchDto);
return new PagingResult<>(internalSampleSearchDto.getPageIndex(), cnt, internalSampleSearchDto.getPageSize(), internalSampleSearchDto.getPageUnit(), internalApprovalSampleDocuments);
}
public InternalApprovalSampleDocument getSampleApprovalDocument(String docId) {
return sqlSession.selectOne("sampleApprovalInternal.selectSampleApprovalDocument", Map.of("docId", docId));
}
public void insertSampleApprovalDocument(InternalApprovalSampleDocument internalApprovalSampleDocument) {
sqlSession.insert("sampleApprovalInternal.insertSampleApprovalDocument", internalApprovalSampleDocument);
}
public void modifySampleApprovalDocument(InternalApprovalSampleDocument internalApprovalSampleDocument) {
sqlSession.update("sampleApprovalInternal.modifySampleApprovalDocument", internalApprovalSampleDocument);
}
public void deleteSampleApprovalDocument(InternalApprovalSampleDocument internalApprovalSampleDocument) {
sqlSession.update("sampleApprovalInternal.deleteSampleApprovalDocument", internalApprovalSampleDocument);
}
public void updateSampleApprovalDocument(Map<String, Object> condition) {
sqlSession.update("sampleApprovalInternal.updateSampleApprovalDocument", condition);
}
}
@@ -0,0 +1,10 @@
package com.samsung.sample.approval.internal.dto;
import com.samsung.approval.dto.DefaultApprovalSubmitDto;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class InternalApprovalSubmitDto extends DefaultApprovalSubmitDto {
}
@@ -0,0 +1,13 @@
package com.samsung.sample.approval.internal.dto;
import com.samsung.approval.dto.DefaultApprovalSearchDto;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class InternalSampleSearchDto extends DefaultApprovalSearchDto {
private boolean internalApproval = true;
private boolean systemAdmin;
}
@@ -0,0 +1,26 @@
package com.samsung.sample.approval.internal.entity;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.samsung.approval.annotation.ApprovalDocument;
import com.samsung.approval.entity.Approval;
import com.samsung.approval.entity.DefaultApprovalDocument;
import com.samsung.approval.enums.ApprovalBodyType;
import com.samsung.approval.enums.ApprovalDocSecuType;
import com.samsung.template.enums.TemplateEngineType;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@ApprovalDocument(docType = "internalSample", description = "Sample Approval Doc. (Internal)", approvalClass = Approval.class, templateEngine = TemplateEngineType.VELOCITY,
templateFile = "/templates/approval/approval-sample.vm", docSecuType = ApprovalDocSecuType.PERSONAL, isBodyModify = true,
isRouteModify = true, isArbitrary = true, bodyType = ApprovalBodyType.MIME, isInternalApproval = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class InternalApprovalSampleDocument extends DefaultApprovalDocument {
private static final long serialVersionUID = 1L;
private String docId;
private String contents;
private String creator;
}
@@ -0,0 +1,79 @@
package com.samsung.sample.approval.internal.impl;
import com.samsung.approval.enums.ApprovalDocStatus;
import com.samsung.authentication.Account;
import com.samsung.core.entity.PagingResult;
import com.samsung.resource.FileManagerService;
import com.samsung.sample.approval.internal.InternalApprovalSampleService;
import com.samsung.sample.approval.internal.dao.InternalApprovalSampleDao;
import com.samsung.sample.approval.internal.dto.InternalSampleSearchDto;
import com.samsung.sample.approval.internal.entity.InternalApprovalSampleDocument;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@Service
public class InternalApprovalSampleServiceImpl implements InternalApprovalSampleService {
final
InternalApprovalSampleDao internalApprovalSampleDao;
final
FileManagerService fileManagerService;
public InternalApprovalSampleServiceImpl(InternalApprovalSampleDao internalApprovalSampleDao, FileManagerService fileManagerService) {
this.internalApprovalSampleDao = internalApprovalSampleDao;
this.fileManagerService = fileManagerService;
}
@Override
public PagingResult<InternalApprovalSampleDocument> getSampleApprovalDocumentPagingList(InternalSampleSearchDto internalSampleSearchDto) {
// 시스템 어드민이 아닌 경우 해당 사용자가 등록한 목록만 확인 가능.
if(Account.currentUser().isSystemAdminUser()) {
internalSampleSearchDto.setSystemAdmin(true);
} else {
internalSampleSearchDto.setSystemAdmin(false);
internalSampleSearchDto.setFirstRegrId(Objects.requireNonNull(Account.currentUser()).getUserId());
}
return internalApprovalSampleDao.getSampleApprovalDocumentPagingList(internalSampleSearchDto);
}
@Override
public InternalApprovalSampleDocument getSampleApprovalDocument(String docId) {
return internalApprovalSampleDao.getSampleApprovalDocument(docId);
}
@Override
@Transactional
public void insertSampleApprovalDocument(InternalApprovalSampleDocument internalApprovalSampleDocument) {
internalApprovalSampleDao.insertSampleApprovalDocument(internalApprovalSampleDocument);
}
@Override
@Transactional
public void modifySampleApprovalDocument(InternalApprovalSampleDocument internalApprovalSampleDocument) {
internalApprovalSampleDao.modifySampleApprovalDocument(internalApprovalSampleDocument);
}
@Override
@Transactional
public void deleteSampleApprovalDocument(InternalApprovalSampleDocument internalApprovalSampleDocument) {
internalApprovalSampleDao.deleteSampleApprovalDocument(internalApprovalSampleDocument);
}
@Override
@Transactional
public void updateSampleApprovalDocument(String docId, ApprovalDocStatus approvalDocStatus) {
Map<String, Object> condition = new HashMap<>();
condition.put("docId", docId);
condition.put("approvalDocStatus", approvalDocStatus);
internalApprovalSampleDao.updateSampleApprovalDocument(condition);
}
}
@@ -0,0 +1,57 @@
package com.samsung.sample.approval.internal.interceptor;
import com.samsung.approval.annotation.ApprovalDocumentType;
import com.samsung.approval.entity.Approval;
import com.samsung.approval.entity.ApprovalStep;
import com.samsung.approval.enums.ApprovalDocStatus;
import com.samsung.approval.interceptor.ApprovalInterceptor;
import com.samsung.sample.approval.internal.InternalApprovalSampleService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import java.util.Map;
@Log4j2
@ApprovalDocumentType(names = {"internalSample"})
public class InternalApprovalSampleInterceptor implements ApprovalInterceptor {
@Autowired
InternalApprovalSampleService internalApprovalSampleService;
@Override
public void afterSubmit(Approval approval, List<ApprovalStep> approvalStepList, Map<String, Object> attribute) {
log.debug("execute ApprovalSampleInterceptor afterSubmit");
//상신 후 문서 상태 업데이트
internalApprovalSampleService.updateSampleApprovalDocument(approval.getDbDocId(), ApprovalDocStatus.INPROCESS);
}
/**
* 내부결재 상신취소 sampleApprovalDocument 문서 상태 업데이트.
* @param approval 결재 정보
* @return
*/
@Override
public void afterInternalApprovalCancel(Approval approval) {
internalApprovalSampleService.updateSampleApprovalDocument(approval.getDbDocId(), ApprovalDocStatus.CANCELLED);
}
/**
* 내부결재 반려 sampleApprovalDocument 문서 상태 업데이트.
* @param approval 결재 정보
* @return
*/
@Override
public void afterInternalApprovalReject(Approval approval) {
internalApprovalSampleService.updateSampleApprovalDocument(approval.getDbDocId(), ApprovalDocStatus.REJECTED);
}
/**
* 내부결재 완료 sampleApprovalDocument 문서 상태 업데이트.
* @param approval 결재 정보
* @return
*/
@Override
public void afterInternalApprovalCompleted(Approval approval) {
internalApprovalSampleService.updateSampleApprovalDocument(approval.getDbDocId(), ApprovalDocStatus.COMPLETED);
}
}
@@ -0,0 +1,55 @@
package com.samsung.sample.approval.knox;
import com.samsung.approval.entity.ApprovalStep;
import com.samsung.approval.enums.ApprovalDocStatus;
import com.samsung.core.entity.PagingResult;
import com.samsung.sample.approval.knox.dto.KnoxApprovalSampleSearchDto;
import com.samsung.sample.approval.knox.entity.KnoxApprovalSampleDocument;
import java.util.List;
public interface KnoxApprovalSampleService {
/**
* 결재문서 목록 조회(페이징).
* @param sampleSearchDto 조회조건
* @return 결재문서 목록
*/
PagingResult<KnoxApprovalSampleDocument> getSampleApprovalDocumentPagingList(KnoxApprovalSampleSearchDto sampleSearchDto);
/**
* 결재문서 상세조회.
* @param docId 문서ID
* @return 결재문서 상세정보
*/
KnoxApprovalSampleDocument getSampleApprovalDocument(String docId);
/**
* 결재문서 저장.
* @param sampleApprovalDocument 결재문서 정보
* @return
*/
void insertSampleApprovalDocument(KnoxApprovalSampleDocument sampleApprovalDocument);
/**
* 결재문서 수정.
* @param sampleApprovalDocument 결재문서 정보
* @return
*/
void modifySampleApprovalDocument(KnoxApprovalSampleDocument sampleApprovalDocument);
/**
* 결재문서 삭제.
* @param sampleApprovalDocument 결재문서 정보
* @return
*/
void deleteSampleApprovalDocument(KnoxApprovalSampleDocument sampleApprovalDocument);
/**
* 결재문서 상태 업데이트.
* @param docId 문서ID
* @param approvalDocStatus 결재상태
*/
void updateSampleApprovalDocument(String docId, ApprovalDocStatus approvalDocStatus);
}
@@ -0,0 +1,148 @@
package com.samsung.sample.approval.knox.controller;
import com.samsung.approval.ApprovalService;
import com.samsung.approval.annotation.ApprovalDocument;
import com.samsung.approval.entity.DynamicApprovalPath;
import com.samsung.approval.entity.RequiredApprovalUser;
import com.samsung.approval.enums.ApprovalDocStatus;
import com.samsung.authentication.Account;
import com.samsung.common.IdGenService;
import com.samsung.core.entity.PagingResult;
import com.samsung.core.exception.KnoxApprovalException;
import com.samsung.resource.FileManagerService;
import com.samsung.sample.approval.knox.KnoxApprovalSampleService;
import com.samsung.sample.approval.knox.dto.KnoxApprovalSampleSearchDto;
import com.samsung.sample.approval.knox.dto.KnoxApprovalSubmitDto;
import com.samsung.sample.approval.knox.entity.KnoxApprovalSampleDocument;
import com.samsung.template.TemplateConstants;
import com.samsung.user.entity.User;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@RestController
@RequestMapping("/sample/approval/knox")
public class KnoxApprovalSampleController {
private final FileManagerService fileManagerService;
private final IdGenService idGenService;
private final KnoxApprovalSampleService knoxApprovalSampleService;
private final ApprovalService approvalService;
private final MessageSourceAccessor messageSourceAccessor;
public KnoxApprovalSampleController(FileManagerService fileManagerService, IdGenService idGenService, KnoxApprovalSampleService knoxApprovalSampleService, ApprovalService approvalService, MessageSourceAccessor messageSourceAccessor) {
this.fileManagerService = fileManagerService;
this.idGenService = idGenService;
this.knoxApprovalSampleService = knoxApprovalSampleService;
this.approvalService = approvalService;
this.messageSourceAccessor = messageSourceAccessor;
}
@Operation(summary = "결재문서 목록 조회(페이징)")
@GetMapping("/sample-document-with-paging")
public PagingResult<KnoxApprovalSampleDocument> getSampleApprovalDocumentPagingList(@ModelAttribute KnoxApprovalSampleSearchDto sampleSearchDto) {
return knoxApprovalSampleService.getSampleApprovalDocumentPagingList(sampleSearchDto);
}
@Operation(summary = "결재 문서 상세 조회")
@GetMapping("/sample-documents/{docId}")
public KnoxApprovalSampleDocument getSampleApprovalDocument(@Parameter(description = "문서 ID") @PathVariable String docId) {
// 문서 상세정보 조회.
KnoxApprovalSampleDocument sampleApprovalDocument = knoxApprovalSampleService.getSampleApprovalDocument(docId);
// 결재 상신전 문서의 결재경로, 필수결재자 여부 setting.
if (ApprovalDocStatus.SAVED.equals(sampleApprovalDocument.getDocStatus())) {
// 결재 경로 추가(재직중인 사용자만 추가).
String docType = KnoxApprovalSampleDocument.class.getAnnotation(ApprovalDocument.class).docType();
List<DynamicApprovalPath> dynamicApprovalPathList = approvalService.getDynamicApprovalPath(docType);
List<DynamicApprovalPath> dynamicApprovalUserList = new ArrayList<>(0);
for (DynamicApprovalPath dynamicApprovalPath : dynamicApprovalPathList) {
if ("B".equals(dynamicApprovalPath.getEmployeeStatus())) {
dynamicApprovalUserList.add(dynamicApprovalPath);
}
}
// 필수 결재자 존재 여부 확인.
boolean checkExistRequiredApprovalUser = false;
List<RequiredApprovalUser> requiredApprovalUserList = approvalService.getRequiredApprovalUserList(docType);
if (!requiredApprovalUserList.isEmpty()) checkExistRequiredApprovalUser = true;
sampleApprovalDocument.setDynamicApprovalUserList(dynamicApprovalUserList);
sampleApprovalDocument.setExistRequiredApprovalUser(checkExistRequiredApprovalUser);
sampleApprovalDocument.setRequiredApprovalUserList(requiredApprovalUserList);
}
sampleApprovalDocument.setAttachments(fileManagerService.getAttachFileList(docId, docId));
return sampleApprovalDocument;
}
@Operation(summary = "결재 문서 저장")
@PostMapping("/sample-documents")
public KnoxApprovalSampleDocument saveDocument(@Parameter(description = "문서 제목") @RequestParam String title, @Parameter(description = "본문") @RequestParam String contents) {
KnoxApprovalSampleDocument sampleApprovalDocument = new KnoxApprovalSampleDocument();
String docId = idGenService.getNextStringId();
sampleApprovalDocument.setDocId(docId);
sampleApprovalDocument.setTitle(title);
sampleApprovalDocument.setContents(contents);
sampleApprovalDocument.setCreator(Objects.requireNonNull(Account.currentUser()).getUserName());
knoxApprovalSampleService.insertSampleApprovalDocument(sampleApprovalDocument);
return sampleApprovalDocument;
}
@Operation(summary = "결재 문서 수정")
@PutMapping("/sample-documents/{docId}")
public KnoxApprovalSampleDocument modifyDocument(@Parameter(description = "문서 ID") @PathVariable String docId, @Parameter(description = "본문") @RequestBody KnoxApprovalSampleDocument tempDoc) {
knoxApprovalSampleService.modifySampleApprovalDocument(tempDoc);
fileManagerService.updateFileRefId(docId, tempDoc.getAttachments(), docId);
return tempDoc;
}
@Operation(summary = "결재 문서 삭제")
@DeleteMapping("/sample-documents/{docId}")
public void deleteDocument(@Parameter(description = "문서 ID") @PathVariable String docId) {
KnoxApprovalSampleDocument sampleApprovalDocument = new KnoxApprovalSampleDocument();
fileManagerService.updateFileRefId(docId, sampleApprovalDocument.getAttachments(), docId);
sampleApprovalDocument.setDocId(docId);
knoxApprovalSampleService.deleteSampleApprovalDocument(sampleApprovalDocument);
fileManagerService.updateFileRefId(docId, null, docId);
}
@Operation(summary = "결재 문서 상신")
@PostMapping("/submit/sample-document")
public void submit(@RequestBody KnoxApprovalSubmitDto knoxApprovalSubmitDto) {
if (StringUtils.isEmpty(knoxApprovalSubmitDto.getDocId())) throw new KnoxApprovalException("문서 ID는 필수 입니다.");
if (ObjectUtils.isEmpty(knoxApprovalSubmitDto.getApprovalStepList()))
throw new KnoxApprovalException("결재 패스는 필수 입니다.");
//결재 문서 조회
KnoxApprovalSampleDocument knoxApprovalSampleDocument = knoxApprovalSampleService.getSampleApprovalDocument(knoxApprovalSubmitDto.getDocId());
ApprovalDocument approvalDocument = KnoxApprovalSampleDocument.class.getAnnotation(ApprovalDocument.class);
String docType = approvalDocument.docType();
User requester = Account.currentUser();
String docId = knoxApprovalSampleDocument.getDocId();
approvalService.submit(docType, knoxApprovalSampleDocument.getDocId(), knoxApprovalSampleDocument.getTitle(), approvalDocument, null, knoxApprovalSubmitDto.getComment(), requester, knoxApprovalSubmitDto.getApprovalStepList(), TemplateConstants.DOC_NAME, knoxApprovalSampleDocument, "attachments", fileManagerService.getAttachFileList(docId, docId), "messages", messageSourceAccessor, "internalApproval", approvalDocument.isInternalApproval());
}
}
@@ -0,0 +1,52 @@
package com.samsung.sample.approval.knox.dao;
import com.samsung.core.entity.PagingResult;
import com.samsung.sample.approval.knox.dto.KnoxApprovalSampleSearchDto;
import com.samsung.sample.approval.knox.entity.KnoxApprovalSampleDocument;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
@Repository
public class KnoxApprovalSampleDao {
final
SqlSession sqlSession;
public KnoxApprovalSampleDao(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
public PagingResult<KnoxApprovalSampleDocument> getSampleApprovalDocumentPagingList(KnoxApprovalSampleSearchDto sampleSearchDto) {
sampleSearchDto.setStartDate(sampleSearchDto.getStartDate().replace("-", ""));
sampleSearchDto.setEndDate(sampleSearchDto.getEndDate().replace("-", ""));
List<KnoxApprovalSampleDocument> sampleApprovalDocuments = sqlSession.selectList("sampleApprovalKnox.selectSampleApprovalDocumentPagingList", sampleSearchDto);
int cnt = sqlSession.selectOne("sampleApprovalKnox.countSampleApprovalDocument", sampleSearchDto);
return new PagingResult<>(sampleSearchDto.getPageIndex(), cnt, sampleSearchDto.getPageSize(), sampleSearchDto.getPageUnit(), sampleApprovalDocuments);
}
public KnoxApprovalSampleDocument getSampleApprovalDocument(String docId) {
return sqlSession.selectOne("sampleApprovalKnox.selectSampleApprovalDocument", Map.of("docId", docId));
}
public void insertSampleApprovalDocument(KnoxApprovalSampleDocument sampleApprovalDocument) {
sqlSession.insert("sampleApprovalKnox.insertSampleApprovalDocument", sampleApprovalDocument);
}
public void modifySampleApprovalDocument(KnoxApprovalSampleDocument sampleApprovalDocument) {
sqlSession.update("sampleApprovalKnox.modifySampleApprovalDocument", sampleApprovalDocument);
}
public void deleteSampleApprovalDocument(KnoxApprovalSampleDocument sampleApprovalDocument) {
sqlSession.update("sampleApprovalKnox.deleteSampleApprovalDocument", sampleApprovalDocument);
}
public void updateSampleApprovalDocument(Map<String, Object> condition) {
sqlSession.update("sampleApprovalKnox.updateSampleApprovalDocument", condition);
}
}
@@ -0,0 +1,12 @@
package com.samsung.sample.approval.knox.dto;
import com.samsung.approval.dto.DefaultApprovalSearchDto;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class KnoxApprovalSampleSearchDto extends DefaultApprovalSearchDto {
private boolean internalApproval = false;
private boolean systemAdmin;
}
@@ -0,0 +1,10 @@
package com.samsung.sample.approval.knox.dto;
import com.samsung.approval.dto.DefaultApprovalSubmitDto;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class KnoxApprovalSubmitDto extends DefaultApprovalSubmitDto {
}
@@ -0,0 +1,26 @@
package com.samsung.sample.approval.knox.entity;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.samsung.approval.annotation.ApprovalDocument;
import com.samsung.approval.entity.Approval;
import com.samsung.approval.entity.DefaultApprovalDocument;
import com.samsung.approval.enums.ApprovalBodyType;
import com.samsung.approval.enums.ApprovalDocSecuType;
import com.samsung.template.enums.TemplateEngineType;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@ApprovalDocument(docType = "knoxSample", description = "Sample Approval Doc. (Knox)", approvalClass = Approval.class, templateEngine = TemplateEngineType.VELOCITY,
templateFile = "/templates/approval/approval-sample.vm", docSecuType = ApprovalDocSecuType.PERSONAL,
isArbitrary = true, bodyType = ApprovalBodyType.MIME)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class KnoxApprovalSampleDocument extends DefaultApprovalDocument {
private static final long serialVersionUID = 1L;
private String docId;
private String contents;
private String creator;
}

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