From 75c7a96f4e648b51700abb763c54d7ec95d7061e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=98=84=EC=84=B1=ED=95=84?= Date: Sat, 1 Nov 2025 11:51:11 +0900 Subject: [PATCH 01/24] =?UTF-8?q?=EC=95=B1=20=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db_migration_add_app_fields.sql | 19 +++ .../apim/portal/app/entity/Credential.java | 8 ++ .../apim/portal/app/entity/ProdClient.java | 121 ------------------ .../app/repository/CredentialRepository.java | 8 +- .../app/repository/ProdClientRepository.java | 18 --- .../portal/apprequest/entity/AppRequest.java | 12 ++ .../apprequest/entity/AppRequestType.java | 5 +- .../repository/AppRequestRepository.java | 2 + .../apim/portal/file/service/FileService.java | 94 ++++++++++++++ 9 files changed, 140 insertions(+), 147 deletions(-) create mode 100644 db_migration_add_app_fields.sql delete mode 100644 src/main/java/com/eactive/apim/portal/app/entity/ProdClient.java delete mode 100644 src/main/java/com/eactive/apim/portal/app/repository/ProdClientRepository.java diff --git a/db_migration_add_app_fields.sql b/db_migration_add_app_fields.sql new file mode 100644 index 0000000..8a2db86 --- /dev/null +++ b/db_migration_add_app_fields.sql @@ -0,0 +1,19 @@ +-- 1. Add fields to ptl_app_request table +ALTER TABLE ptl_app_request ADD app_description VARCHAR2(500); +COMMENT ON COLUMN ptl_app_request.app_description IS '앱 설명'; + +ALTER TABLE ptl_app_request ADD callback_url VARCHAR2(255); +COMMENT ON COLUMN ptl_app_request.callback_url IS '콜백 URL'; + +ALTER TABLE ptl_app_request ADD ip_whitelist VARCHAR2(1000); +COMMENT ON COLUMN ptl_app_request.ip_whitelist IS 'IP 화이트리스트 (comma-separated)'; + +ALTER TABLE ptl_app_request ADD app_icon_file_id VARCHAR2(38); +COMMENT ON COLUMN ptl_app_request.app_icon_file_id IS '앱 아이콘 파일 ID (ptl_file 참조)'; + +-- 2. Add fields to ptl_credential table +ALTER TABLE ptl_credential ADD app_description VARCHAR2(500); +COMMENT ON COLUMN ptl_credential.app_description IS '앱 설명'; + +ALTER TABLE ptl_credential ADD app_icon_file_id VARCHAR2(38); +COMMENT ON COLUMN ptl_credential.app_icon_file_id IS '앱 아이콘 파일 ID (ptl_file 참조)'; diff --git a/src/main/java/com/eactive/apim/portal/app/entity/Credential.java b/src/main/java/com/eactive/apim/portal/app/entity/Credential.java index 6c3288e..70cc0b7 100644 --- a/src/main/java/com/eactive/apim/portal/app/entity/Credential.java +++ b/src/main/java/com/eactive/apim/portal/app/entity/Credential.java @@ -111,6 +111,14 @@ public class Credential extends AbstractEntity implements Serializable { @Comment("기관이름") private String orgname; + @Column(name = "app_description", length = 500) + @Comment("앱 설명") + private String appDescription; + + @Column(name = "app_icon_file_id", length = 38) + @Comment("앱 아이콘 파일 ID") + private String appIconFileId; + @Comment("일별 토큰 제한 수 (0:무제한)") private int dailytokenlimit; diff --git a/src/main/java/com/eactive/apim/portal/app/entity/ProdClient.java b/src/main/java/com/eactive/apim/portal/app/entity/ProdClient.java deleted file mode 100644 index 76345ef..0000000 --- a/src/main/java/com/eactive/apim/portal/app/entity/ProdClient.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.eactive.apim.portal.app.entity; - -import com.eactive.apim.portal.apispec.entity.ApiSpecInfo; -import com.eactive.eai.data.converter.LocalDateTimeToStringConverter14; -import com.eactive.eai.data.entity.AbstractEntity; -import java.io.Serializable; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import javax.persistence.Column; -import javax.persistence.Convert; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.Table; -import lombok.Data; -import lombok.NonNull; -import org.hibernate.annotations.Comment; -import org.hibernate.annotations.LazyCollection; -import org.hibernate.annotations.LazyCollectionOption; -import org.springframework.data.annotation.LastModifiedBy; -import org.springframework.data.annotation.LastModifiedDate; - -@Entity -@Data -@Table(name = "ptl_prod_client") -@org.hibernate.annotations.Table(appliesTo = "ptl_prod_client", comment = "사용자 정보") -public class ProdClient extends AbstractEntity implements Serializable { - - private static final long serialVersionUID = 1L; - - @Id - @Column(unique = true, nullable = false, length = 256) - @Comment("client id") - private String clientid; - - @Column(length = 11) - @Comment("Access Token 유효 기간(초)") - private String accesstokenvalidityseconds; - - @Column(length = 256) - @Comment("허용된 IP") - private String allowedips; - - @Column(length = 256) - @Comment("권한") - private String authorities; - - @Column(length = 256) - @Comment("자동 승인 스코프") - private String autoapprove; - - @Column(length = 40) - @Comment("client명") - private String clientname; - - @Column(length = 512) - @Comment("Client 비밀번호") - private String clientsecret; - - @Column(length = 256) - @Comment("권한타입") - private String granttypes; - - @Column(length = 8) - @Comment("수정인") - @LastModifiedBy - private String modifiedby; - - @Column(length = 14) - @Comment("수정일") - @Convert(converter = LocalDateTimeToStringConverter14.class) - @LastModifiedDate - private LocalDateTime modifiedon; - - @Column(length = 256) - @Comment("Redirect URI") - private String redirecturi; - - @Column(length = 11) - @Comment("Refresh Token 유효 기간(초)") - private String refreshtokenvalidityseconds; - - @Column(length = 4000) - @Comment("리소스 id") - private String resourceids; - - @Column(length = 1024) - @Comment("scope") - private String scope; - - @Column(length = 4000) - @Comment("암호key") - private String securitykey; - - @Column(length = 38) - @Comment("기관ID") - private String orgid; - - @Comment("APP 상태") - private String appstatus; //0: 차단, 1: 정상 - - @Column(length = 255) - @Comment("기관이름") - private String orgname; - - @Comment("일별 토큰 제한 수 (0:무제한)") - private int dailytokenlimit; - - @Override - public @NonNull String getId() { - return clientid; - } - - @ManyToMany - @LazyCollection(LazyCollectionOption.FALSE) - @JoinTable(name = "ptl_prod_client_api", joinColumns = @JoinColumn(name = "client_id"), inverseJoinColumns = @JoinColumn(name = "eaisvcname")) - private List apiList = new ArrayList<>(); -} diff --git a/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java b/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java index 1710070..c940645 100644 --- a/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java +++ b/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java @@ -11,11 +11,11 @@ import org.springframework.data.domain.Pageable; @EMSDataSource public interface CredentialRepository extends BaseRepository { - Page findAllByOrgidAndServer(Pageable pageable, String id, String server); + Page findAllByOrgid(Pageable pageable, String id); - int countAllByOrgidAndServer(String orgid, String server); + int countAllByOrgid(String orgid); - List findAllByOrgidAndServer(String orgid, String server); + List findAllByOrgid(String orgid); - Optional findByClientidAndOrgidAndServer(String clientid, String orgid, String server); + Optional findByClientidAndOrgid(String clientid, String orgid); } diff --git a/src/main/java/com/eactive/apim/portal/app/repository/ProdClientRepository.java b/src/main/java/com/eactive/apim/portal/app/repository/ProdClientRepository.java deleted file mode 100644 index c1adafa..0000000 --- a/src/main/java/com/eactive/apim/portal/app/repository/ProdClientRepository.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.eactive.apim.portal.app.repository; - -import com.eactive.apim.portal.app.entity.ProdClient; -import com.eactive.apim.portal.approval.entity.Approval; -import com.eactive.apim.portal.approval.entity.ApprovalType; -import com.eactive.eai.data.jpa.BaseRepository; -import com.eactive.eai.rms.data.EMSDataSource; -import java.util.Optional; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - -@EMSDataSource -public interface ProdClientRepository extends BaseRepository { - - Page findAllByOrgid(Pageable pageable, String id); - - Optional findByClientidAndOrgid(String clientid, String orgid); -} diff --git a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java index 3d74331..f95caf9 100644 --- a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java +++ b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java @@ -64,6 +64,18 @@ public class AppRequest implements com.eactive.eai.data.Data { @Column(name = "reason") private String reason; + @Column(name = "app_description", length = 500) + private String appDescription; + + @Column(name = "callback_url", length = 255) + private String callbackUrl; + + @Column(name = "ip_whitelist", length = 1000) + private String ipWhitelist; + + @Column(name = "app_icon_file_id", length = 38) + private String appIconFileId; + @Column(length = 17, name = "created_date") @Convert(converter = LocalDateTimeToStringConverter17.class) @CreationTimestamp diff --git a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequestType.java b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequestType.java index 3178ca0..61c340b 100644 --- a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequestType.java +++ b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequestType.java @@ -3,10 +3,7 @@ package com.eactive.apim.portal.apprequest.entity; public enum AppRequestType { NEW("API키 신규"), MODIFY("API 변경"), - DELETE("API키 삭제"), - PROD_NEW("운영 API키 신규"), - PROD_MODIFY("운영 API 변경"), - PROD_DELETE("운영 API키 삭제"); + DELETE("API키 삭제"); private final String description; diff --git a/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java b/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java index 30e1f4e..9bbbe36 100644 --- a/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java +++ b/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java @@ -20,6 +20,8 @@ public interface AppRequestRepository extends BaseRepository Optional findAppRequestByApproval(Approval approval); + List findAllByOrgAndTypeIsInAndApproval_ApprovalStatusIn(PortalOrg org, List types, List approvalStates); + int countAllByOrgAndTypeIsInAndApproval_ApprovalStatusIn(PortalOrg org, List types, List approvalStates); Optional findByIdAndOrg(String id, PortalOrg org); diff --git a/src/main/java/com/eactive/apim/portal/file/service/FileService.java b/src/main/java/com/eactive/apim/portal/file/service/FileService.java index c8ff92e..efe26fc 100644 --- a/src/main/java/com/eactive/apim/portal/file/service/FileService.java +++ b/src/main/java/com/eactive/apim/portal/file/service/FileService.java @@ -220,6 +220,100 @@ public class FileService { return fileDetail; } + + /** + * byte[] 데이터로 단일 파일을 생성합니다. + * + * @param fileName 파일 이름 (확장자 포함) + * @param contentType 파일 MIME 타입 + * @param fileData 파일 바이트 데이터 + * @return 파일 정보 + * @throws IOException 파일 처리 중 오류 발생 시 + */ + public FileInfo createSingleFileFromBytes(String fileName, String contentType, byte[] fileData) throws IOException { + // 파일 타입 검증 + String type = fileTypeDetector.detectFileType(fileData); + log.debug("upload file type from bytes: {}", type); + + if (type.equalsIgnoreCase("unknown")) { + throw new InvalidFileException("허용된 파일 형식이 아닙니다.
문서파일과 이미지 파일만 등록 가능합니다.
(pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, gif, jpg, png)"); + } + + // FileInfo 생성 + FileInfo fileInfo = new FileInfo(); + String fileId = UUID.randomUUID().toString(); + fileInfo.setFileId(fileId); + fileInfo.setCreatedDate(LocalDateTime.now()); + fileInfo.setUseYn("Y"); + + // FileDetail 생성 + FileDetail fileDetail = new FileDetail(); + fileDetail.setFileId(fileId); + fileDetail.setFileSn(1); + fileDetail.setFileSize(fileData.length); + fileDetail.setOriginalFileName(FilenameUtils.getBaseName(fileName)); + fileDetail.setFileExtension(FilenameUtils.getExtension(fileName)); + + // 파일 내용 저장 + String contentReference = binaryStorageService.store(fileData); + fileDetail.setFileContents(contentReference); + + // FileInfo에 FileDetail 추가 + fileInfo.getFileDetails().add(fileDetail); + + // 저장 및 반환 + return fileRepository.save(fileInfo); + } + + /** + * byte[] 데이터로 기존 파일을 업데이트하거나 새로 생성합니다. + * + * @param existingFileId 기존 파일 ID (null이면 새로 생성) + * @param fileName 파일 이름 (확장자 포함) + * @param contentType 파일 MIME 타입 + * @param fileData 파일 바이트 데이터 + * @return 파일 정보 + * @throws IOException 파일 처리 중 오류 발생 시 + */ + public FileInfo createOrUpdateSingleFileFromBytes(String existingFileId, String fileName, String contentType, byte[] fileData) throws IOException { + // 신규 등록 또는 기존 파일 정보 조회 + FileInfo fileInfo = Optional.ofNullable(existingFileId) + .filter(StringUtils::isNotBlank) + .map(this::findById) + .orElseGet(() -> { + FileInfo newFile = new FileInfo(); + newFile.setFileId(UUID.randomUUID().toString()); + newFile.setCreatedDate(LocalDateTime.now()); + newFile.setUseYn("Y"); + return newFile; + }); + + // 파일 타입 검증 + String type = fileTypeDetector.detectFileType(fileData); + log.debug("upload file type from bytes: {}", type); + + if (type.equalsIgnoreCase("unknown")) { + throw new InvalidFileException("허용된 파일 형식이 아닙니다.
문서파일과 이미지 파일만 등록 가능합니다.
(pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, gif, jpg, png)"); + } + + // FileDetail 생성 + FileDetail fileDetail = new FileDetail(); + fileDetail.setFileId(fileInfo.getFileId()); + fileDetail.setFileSn(1); + fileDetail.setFileSize(fileData.length); + fileDetail.setOriginalFileName(FilenameUtils.getBaseName(fileName)); + fileDetail.setFileExtension(FilenameUtils.getExtension(fileName)); + + // 파일 내용 저장 + String contentReference = binaryStorageService.store(fileData); + fileDetail.setFileContents(contentReference); + + // 기존 파일 상세 정보 제거 후 새로운 정보 추가 + fileInfo.getFileDetails().clear(); + fileInfo.getFileDetails().add(fileDetail); + + return fileRepository.save(fileInfo); + } } From 739877d9a1c2fe957d55d54b562634b30ed4f063 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Wed, 19 Nov 2025 14:36:41 +0900 Subject: [PATCH 02/24] =?UTF-8?q?=EC=9D=BC=EB=B6=80=20=EC=84=A0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20=EC=BD=94=EB=93=9C=20=EB=A1=A4=EB=B0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revert "앱 관리" This reverts commit 75c7a96f4e648b51700abb763c54d7ec95d7061e. --- db_migration_add_app_fields.sql | 19 --- .../apim/portal/app/entity/Credential.java | 8 -- .../apim/portal/app/entity/ProdClient.java | 121 ++++++++++++++++++ .../app/repository/CredentialRepository.java | 8 +- .../app/repository/ProdClientRepository.java | 18 +++ .../portal/apprequest/entity/AppRequest.java | 12 -- .../apprequest/entity/AppRequestType.java | 5 +- .../repository/AppRequestRepository.java | 2 - .../apim/portal/file/service/FileService.java | 94 -------------- 9 files changed, 147 insertions(+), 140 deletions(-) delete mode 100644 db_migration_add_app_fields.sql create mode 100644 src/main/java/com/eactive/apim/portal/app/entity/ProdClient.java create mode 100644 src/main/java/com/eactive/apim/portal/app/repository/ProdClientRepository.java diff --git a/db_migration_add_app_fields.sql b/db_migration_add_app_fields.sql deleted file mode 100644 index 8a2db86..0000000 --- a/db_migration_add_app_fields.sql +++ /dev/null @@ -1,19 +0,0 @@ --- 1. Add fields to ptl_app_request table -ALTER TABLE ptl_app_request ADD app_description VARCHAR2(500); -COMMENT ON COLUMN ptl_app_request.app_description IS '앱 설명'; - -ALTER TABLE ptl_app_request ADD callback_url VARCHAR2(255); -COMMENT ON COLUMN ptl_app_request.callback_url IS '콜백 URL'; - -ALTER TABLE ptl_app_request ADD ip_whitelist VARCHAR2(1000); -COMMENT ON COLUMN ptl_app_request.ip_whitelist IS 'IP 화이트리스트 (comma-separated)'; - -ALTER TABLE ptl_app_request ADD app_icon_file_id VARCHAR2(38); -COMMENT ON COLUMN ptl_app_request.app_icon_file_id IS '앱 아이콘 파일 ID (ptl_file 참조)'; - --- 2. Add fields to ptl_credential table -ALTER TABLE ptl_credential ADD app_description VARCHAR2(500); -COMMENT ON COLUMN ptl_credential.app_description IS '앱 설명'; - -ALTER TABLE ptl_credential ADD app_icon_file_id VARCHAR2(38); -COMMENT ON COLUMN ptl_credential.app_icon_file_id IS '앱 아이콘 파일 ID (ptl_file 참조)'; diff --git a/src/main/java/com/eactive/apim/portal/app/entity/Credential.java b/src/main/java/com/eactive/apim/portal/app/entity/Credential.java index 70cc0b7..6c3288e 100644 --- a/src/main/java/com/eactive/apim/portal/app/entity/Credential.java +++ b/src/main/java/com/eactive/apim/portal/app/entity/Credential.java @@ -111,14 +111,6 @@ public class Credential extends AbstractEntity implements Serializable { @Comment("기관이름") private String orgname; - @Column(name = "app_description", length = 500) - @Comment("앱 설명") - private String appDescription; - - @Column(name = "app_icon_file_id", length = 38) - @Comment("앱 아이콘 파일 ID") - private String appIconFileId; - @Comment("일별 토큰 제한 수 (0:무제한)") private int dailytokenlimit; diff --git a/src/main/java/com/eactive/apim/portal/app/entity/ProdClient.java b/src/main/java/com/eactive/apim/portal/app/entity/ProdClient.java new file mode 100644 index 0000000..76345ef --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/app/entity/ProdClient.java @@ -0,0 +1,121 @@ +package com.eactive.apim.portal.app.entity; + +import com.eactive.apim.portal.apispec.entity.ApiSpecInfo; +import com.eactive.eai.data.converter.LocalDateTimeToStringConverter14; +import com.eactive.eai.data.entity.AbstractEntity; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.Table; +import lombok.Data; +import lombok.NonNull; +import org.hibernate.annotations.Comment; +import org.hibernate.annotations.LazyCollection; +import org.hibernate.annotations.LazyCollectionOption; +import org.springframework.data.annotation.LastModifiedBy; +import org.springframework.data.annotation.LastModifiedDate; + +@Entity +@Data +@Table(name = "ptl_prod_client") +@org.hibernate.annotations.Table(appliesTo = "ptl_prod_client", comment = "사용자 정보") +public class ProdClient extends AbstractEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @Column(unique = true, nullable = false, length = 256) + @Comment("client id") + private String clientid; + + @Column(length = 11) + @Comment("Access Token 유효 기간(초)") + private String accesstokenvalidityseconds; + + @Column(length = 256) + @Comment("허용된 IP") + private String allowedips; + + @Column(length = 256) + @Comment("권한") + private String authorities; + + @Column(length = 256) + @Comment("자동 승인 스코프") + private String autoapprove; + + @Column(length = 40) + @Comment("client명") + private String clientname; + + @Column(length = 512) + @Comment("Client 비밀번호") + private String clientsecret; + + @Column(length = 256) + @Comment("권한타입") + private String granttypes; + + @Column(length = 8) + @Comment("수정인") + @LastModifiedBy + private String modifiedby; + + @Column(length = 14) + @Comment("수정일") + @Convert(converter = LocalDateTimeToStringConverter14.class) + @LastModifiedDate + private LocalDateTime modifiedon; + + @Column(length = 256) + @Comment("Redirect URI") + private String redirecturi; + + @Column(length = 11) + @Comment("Refresh Token 유효 기간(초)") + private String refreshtokenvalidityseconds; + + @Column(length = 4000) + @Comment("리소스 id") + private String resourceids; + + @Column(length = 1024) + @Comment("scope") + private String scope; + + @Column(length = 4000) + @Comment("암호key") + private String securitykey; + + @Column(length = 38) + @Comment("기관ID") + private String orgid; + + @Comment("APP 상태") + private String appstatus; //0: 차단, 1: 정상 + + @Column(length = 255) + @Comment("기관이름") + private String orgname; + + @Comment("일별 토큰 제한 수 (0:무제한)") + private int dailytokenlimit; + + @Override + public @NonNull String getId() { + return clientid; + } + + @ManyToMany + @LazyCollection(LazyCollectionOption.FALSE) + @JoinTable(name = "ptl_prod_client_api", joinColumns = @JoinColumn(name = "client_id"), inverseJoinColumns = @JoinColumn(name = "eaisvcname")) + private List apiList = new ArrayList<>(); +} diff --git a/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java b/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java index c940645..1710070 100644 --- a/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java +++ b/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java @@ -11,11 +11,11 @@ import org.springframework.data.domain.Pageable; @EMSDataSource public interface CredentialRepository extends BaseRepository { - Page findAllByOrgid(Pageable pageable, String id); + Page findAllByOrgidAndServer(Pageable pageable, String id, String server); - int countAllByOrgid(String orgid); + int countAllByOrgidAndServer(String orgid, String server); - List findAllByOrgid(String orgid); + List findAllByOrgidAndServer(String orgid, String server); - Optional findByClientidAndOrgid(String clientid, String orgid); + Optional findByClientidAndOrgidAndServer(String clientid, String orgid, String server); } diff --git a/src/main/java/com/eactive/apim/portal/app/repository/ProdClientRepository.java b/src/main/java/com/eactive/apim/portal/app/repository/ProdClientRepository.java new file mode 100644 index 0000000..c1adafa --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/app/repository/ProdClientRepository.java @@ -0,0 +1,18 @@ +package com.eactive.apim.portal.app.repository; + +import com.eactive.apim.portal.app.entity.ProdClient; +import com.eactive.apim.portal.approval.entity.Approval; +import com.eactive.apim.portal.approval.entity.ApprovalType; +import com.eactive.eai.data.jpa.BaseRepository; +import com.eactive.eai.rms.data.EMSDataSource; +import java.util.Optional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +@EMSDataSource +public interface ProdClientRepository extends BaseRepository { + + Page findAllByOrgid(Pageable pageable, String id); + + Optional findByClientidAndOrgid(String clientid, String orgid); +} diff --git a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java index f95caf9..3d74331 100644 --- a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java +++ b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java @@ -64,18 +64,6 @@ public class AppRequest implements com.eactive.eai.data.Data { @Column(name = "reason") private String reason; - @Column(name = "app_description", length = 500) - private String appDescription; - - @Column(name = "callback_url", length = 255) - private String callbackUrl; - - @Column(name = "ip_whitelist", length = 1000) - private String ipWhitelist; - - @Column(name = "app_icon_file_id", length = 38) - private String appIconFileId; - @Column(length = 17, name = "created_date") @Convert(converter = LocalDateTimeToStringConverter17.class) @CreationTimestamp diff --git a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequestType.java b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequestType.java index 61c340b..3178ca0 100644 --- a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequestType.java +++ b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequestType.java @@ -3,7 +3,10 @@ package com.eactive.apim.portal.apprequest.entity; public enum AppRequestType { NEW("API키 신규"), MODIFY("API 변경"), - DELETE("API키 삭제"); + DELETE("API키 삭제"), + PROD_NEW("운영 API키 신규"), + PROD_MODIFY("운영 API 변경"), + PROD_DELETE("운영 API키 삭제"); private final String description; diff --git a/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java b/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java index 9bbbe36..30e1f4e 100644 --- a/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java +++ b/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java @@ -20,8 +20,6 @@ public interface AppRequestRepository extends BaseRepository Optional findAppRequestByApproval(Approval approval); - List findAllByOrgAndTypeIsInAndApproval_ApprovalStatusIn(PortalOrg org, List types, List approvalStates); - int countAllByOrgAndTypeIsInAndApproval_ApprovalStatusIn(PortalOrg org, List types, List approvalStates); Optional findByIdAndOrg(String id, PortalOrg org); diff --git a/src/main/java/com/eactive/apim/portal/file/service/FileService.java b/src/main/java/com/eactive/apim/portal/file/service/FileService.java index 66497d2..2731326 100644 --- a/src/main/java/com/eactive/apim/portal/file/service/FileService.java +++ b/src/main/java/com/eactive/apim/portal/file/service/FileService.java @@ -252,100 +252,6 @@ public class FileService { return fileDetail; } - - /** - * byte[] 데이터로 단일 파일을 생성합니다. - * - * @param fileName 파일 이름 (확장자 포함) - * @param contentType 파일 MIME 타입 - * @param fileData 파일 바이트 데이터 - * @return 파일 정보 - * @throws IOException 파일 처리 중 오류 발생 시 - */ - public FileInfo createSingleFileFromBytes(String fileName, String contentType, byte[] fileData) throws IOException { - // 파일 타입 검증 - String type = fileTypeDetector.detectFileType(fileData); - log.debug("upload file type from bytes: {}", type); - - if (type.equalsIgnoreCase("unknown")) { - throw new InvalidFileException("허용된 파일 형식이 아닙니다.
문서파일과 이미지 파일만 등록 가능합니다.
(pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, gif, jpg, png)"); - } - - // FileInfo 생성 - FileInfo fileInfo = new FileInfo(); - String fileId = UUID.randomUUID().toString(); - fileInfo.setFileId(fileId); - fileInfo.setCreatedDate(LocalDateTime.now()); - fileInfo.setUseYn("Y"); - - // FileDetail 생성 - FileDetail fileDetail = new FileDetail(); - fileDetail.setFileId(fileId); - fileDetail.setFileSn(1); - fileDetail.setFileSize(fileData.length); - fileDetail.setOriginalFileName(FilenameUtils.getBaseName(fileName)); - fileDetail.setFileExtension(FilenameUtils.getExtension(fileName)); - - // 파일 내용 저장 - String contentReference = binaryStorageService.store(fileData); - fileDetail.setFileContents(contentReference); - - // FileInfo에 FileDetail 추가 - fileInfo.getFileDetails().add(fileDetail); - - // 저장 및 반환 - return fileRepository.save(fileInfo); - } - - /** - * byte[] 데이터로 기존 파일을 업데이트하거나 새로 생성합니다. - * - * @param existingFileId 기존 파일 ID (null이면 새로 생성) - * @param fileName 파일 이름 (확장자 포함) - * @param contentType 파일 MIME 타입 - * @param fileData 파일 바이트 데이터 - * @return 파일 정보 - * @throws IOException 파일 처리 중 오류 발생 시 - */ - public FileInfo createOrUpdateSingleFileFromBytes(String existingFileId, String fileName, String contentType, byte[] fileData) throws IOException { - // 신규 등록 또는 기존 파일 정보 조회 - FileInfo fileInfo = Optional.ofNullable(existingFileId) - .filter(StringUtils::isNotBlank) - .map(this::findById) - .orElseGet(() -> { - FileInfo newFile = new FileInfo(); - newFile.setFileId(UUID.randomUUID().toString()); - newFile.setCreatedDate(LocalDateTime.now()); - newFile.setUseYn("Y"); - return newFile; - }); - - // 파일 타입 검증 - String type = fileTypeDetector.detectFileType(fileData); - log.debug("upload file type from bytes: {}", type); - - if (type.equalsIgnoreCase("unknown")) { - throw new InvalidFileException("허용된 파일 형식이 아닙니다.
문서파일과 이미지 파일만 등록 가능합니다.
(pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, gif, jpg, png)"); - } - - // FileDetail 생성 - FileDetail fileDetail = new FileDetail(); - fileDetail.setFileId(fileInfo.getFileId()); - fileDetail.setFileSn(1); - fileDetail.setFileSize(fileData.length); - fileDetail.setOriginalFileName(FilenameUtils.getBaseName(fileName)); - fileDetail.setFileExtension(FilenameUtils.getExtension(fileName)); - - // 파일 내용 저장 - String contentReference = binaryStorageService.store(fileData); - fileDetail.setFileContents(contentReference); - - // 기존 파일 상세 정보 제거 후 새로운 정보 추가 - fileInfo.getFileDetails().clear(); - fileInfo.getFileDetails().add(fileDetail); - - return fileRepository.save(fileInfo); - } } From 77c060b01bc4511331dad319d23d1ec470aa8fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=98=84=EC=84=B1=ED=95=84?= Date: Sat, 1 Nov 2025 11:51:11 +0900 Subject: [PATCH 03/24] =?UTF-8?q?=EC=95=B1=20=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db_migration_add_app_fields.sql | 19 +++ .../apim/portal/app/entity/Credential.java | 8 ++ .../apim/portal/app/entity/ProdClient.java | 121 ------------------ .../app/repository/CredentialRepository.java | 8 +- .../app/repository/ProdClientRepository.java | 18 --- .../portal/apprequest/entity/AppRequest.java | 12 ++ .../apprequest/entity/AppRequestType.java | 5 +- .../repository/AppRequestRepository.java | 2 + .../apim/portal/file/service/FileService.java | 94 ++++++++++++++ 9 files changed, 140 insertions(+), 147 deletions(-) create mode 100644 db_migration_add_app_fields.sql delete mode 100644 src/main/java/com/eactive/apim/portal/app/entity/ProdClient.java delete mode 100644 src/main/java/com/eactive/apim/portal/app/repository/ProdClientRepository.java diff --git a/db_migration_add_app_fields.sql b/db_migration_add_app_fields.sql new file mode 100644 index 0000000..8a2db86 --- /dev/null +++ b/db_migration_add_app_fields.sql @@ -0,0 +1,19 @@ +-- 1. Add fields to ptl_app_request table +ALTER TABLE ptl_app_request ADD app_description VARCHAR2(500); +COMMENT ON COLUMN ptl_app_request.app_description IS '앱 설명'; + +ALTER TABLE ptl_app_request ADD callback_url VARCHAR2(255); +COMMENT ON COLUMN ptl_app_request.callback_url IS '콜백 URL'; + +ALTER TABLE ptl_app_request ADD ip_whitelist VARCHAR2(1000); +COMMENT ON COLUMN ptl_app_request.ip_whitelist IS 'IP 화이트리스트 (comma-separated)'; + +ALTER TABLE ptl_app_request ADD app_icon_file_id VARCHAR2(38); +COMMENT ON COLUMN ptl_app_request.app_icon_file_id IS '앱 아이콘 파일 ID (ptl_file 참조)'; + +-- 2. Add fields to ptl_credential table +ALTER TABLE ptl_credential ADD app_description VARCHAR2(500); +COMMENT ON COLUMN ptl_credential.app_description IS '앱 설명'; + +ALTER TABLE ptl_credential ADD app_icon_file_id VARCHAR2(38); +COMMENT ON COLUMN ptl_credential.app_icon_file_id IS '앱 아이콘 파일 ID (ptl_file 참조)'; diff --git a/src/main/java/com/eactive/apim/portal/app/entity/Credential.java b/src/main/java/com/eactive/apim/portal/app/entity/Credential.java index 6c3288e..70cc0b7 100644 --- a/src/main/java/com/eactive/apim/portal/app/entity/Credential.java +++ b/src/main/java/com/eactive/apim/portal/app/entity/Credential.java @@ -111,6 +111,14 @@ public class Credential extends AbstractEntity implements Serializable { @Comment("기관이름") private String orgname; + @Column(name = "app_description", length = 500) + @Comment("앱 설명") + private String appDescription; + + @Column(name = "app_icon_file_id", length = 38) + @Comment("앱 아이콘 파일 ID") + private String appIconFileId; + @Comment("일별 토큰 제한 수 (0:무제한)") private int dailytokenlimit; diff --git a/src/main/java/com/eactive/apim/portal/app/entity/ProdClient.java b/src/main/java/com/eactive/apim/portal/app/entity/ProdClient.java deleted file mode 100644 index 76345ef..0000000 --- a/src/main/java/com/eactive/apim/portal/app/entity/ProdClient.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.eactive.apim.portal.app.entity; - -import com.eactive.apim.portal.apispec.entity.ApiSpecInfo; -import com.eactive.eai.data.converter.LocalDateTimeToStringConverter14; -import com.eactive.eai.data.entity.AbstractEntity; -import java.io.Serializable; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import javax.persistence.Column; -import javax.persistence.Convert; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.Table; -import lombok.Data; -import lombok.NonNull; -import org.hibernate.annotations.Comment; -import org.hibernate.annotations.LazyCollection; -import org.hibernate.annotations.LazyCollectionOption; -import org.springframework.data.annotation.LastModifiedBy; -import org.springframework.data.annotation.LastModifiedDate; - -@Entity -@Data -@Table(name = "ptl_prod_client") -@org.hibernate.annotations.Table(appliesTo = "ptl_prod_client", comment = "사용자 정보") -public class ProdClient extends AbstractEntity implements Serializable { - - private static final long serialVersionUID = 1L; - - @Id - @Column(unique = true, nullable = false, length = 256) - @Comment("client id") - private String clientid; - - @Column(length = 11) - @Comment("Access Token 유효 기간(초)") - private String accesstokenvalidityseconds; - - @Column(length = 256) - @Comment("허용된 IP") - private String allowedips; - - @Column(length = 256) - @Comment("권한") - private String authorities; - - @Column(length = 256) - @Comment("자동 승인 스코프") - private String autoapprove; - - @Column(length = 40) - @Comment("client명") - private String clientname; - - @Column(length = 512) - @Comment("Client 비밀번호") - private String clientsecret; - - @Column(length = 256) - @Comment("권한타입") - private String granttypes; - - @Column(length = 8) - @Comment("수정인") - @LastModifiedBy - private String modifiedby; - - @Column(length = 14) - @Comment("수정일") - @Convert(converter = LocalDateTimeToStringConverter14.class) - @LastModifiedDate - private LocalDateTime modifiedon; - - @Column(length = 256) - @Comment("Redirect URI") - private String redirecturi; - - @Column(length = 11) - @Comment("Refresh Token 유효 기간(초)") - private String refreshtokenvalidityseconds; - - @Column(length = 4000) - @Comment("리소스 id") - private String resourceids; - - @Column(length = 1024) - @Comment("scope") - private String scope; - - @Column(length = 4000) - @Comment("암호key") - private String securitykey; - - @Column(length = 38) - @Comment("기관ID") - private String orgid; - - @Comment("APP 상태") - private String appstatus; //0: 차단, 1: 정상 - - @Column(length = 255) - @Comment("기관이름") - private String orgname; - - @Comment("일별 토큰 제한 수 (0:무제한)") - private int dailytokenlimit; - - @Override - public @NonNull String getId() { - return clientid; - } - - @ManyToMany - @LazyCollection(LazyCollectionOption.FALSE) - @JoinTable(name = "ptl_prod_client_api", joinColumns = @JoinColumn(name = "client_id"), inverseJoinColumns = @JoinColumn(name = "eaisvcname")) - private List apiList = new ArrayList<>(); -} diff --git a/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java b/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java index 1710070..c940645 100644 --- a/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java +++ b/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java @@ -11,11 +11,11 @@ import org.springframework.data.domain.Pageable; @EMSDataSource public interface CredentialRepository extends BaseRepository { - Page findAllByOrgidAndServer(Pageable pageable, String id, String server); + Page findAllByOrgid(Pageable pageable, String id); - int countAllByOrgidAndServer(String orgid, String server); + int countAllByOrgid(String orgid); - List findAllByOrgidAndServer(String orgid, String server); + List findAllByOrgid(String orgid); - Optional findByClientidAndOrgidAndServer(String clientid, String orgid, String server); + Optional findByClientidAndOrgid(String clientid, String orgid); } diff --git a/src/main/java/com/eactive/apim/portal/app/repository/ProdClientRepository.java b/src/main/java/com/eactive/apim/portal/app/repository/ProdClientRepository.java deleted file mode 100644 index c1adafa..0000000 --- a/src/main/java/com/eactive/apim/portal/app/repository/ProdClientRepository.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.eactive.apim.portal.app.repository; - -import com.eactive.apim.portal.app.entity.ProdClient; -import com.eactive.apim.portal.approval.entity.Approval; -import com.eactive.apim.portal.approval.entity.ApprovalType; -import com.eactive.eai.data.jpa.BaseRepository; -import com.eactive.eai.rms.data.EMSDataSource; -import java.util.Optional; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - -@EMSDataSource -public interface ProdClientRepository extends BaseRepository { - - Page findAllByOrgid(Pageable pageable, String id); - - Optional findByClientidAndOrgid(String clientid, String orgid); -} diff --git a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java index 3d74331..f95caf9 100644 --- a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java +++ b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java @@ -64,6 +64,18 @@ public class AppRequest implements com.eactive.eai.data.Data { @Column(name = "reason") private String reason; + @Column(name = "app_description", length = 500) + private String appDescription; + + @Column(name = "callback_url", length = 255) + private String callbackUrl; + + @Column(name = "ip_whitelist", length = 1000) + private String ipWhitelist; + + @Column(name = "app_icon_file_id", length = 38) + private String appIconFileId; + @Column(length = 17, name = "created_date") @Convert(converter = LocalDateTimeToStringConverter17.class) @CreationTimestamp diff --git a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequestType.java b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequestType.java index 3178ca0..61c340b 100644 --- a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequestType.java +++ b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequestType.java @@ -3,10 +3,7 @@ package com.eactive.apim.portal.apprequest.entity; public enum AppRequestType { NEW("API키 신규"), MODIFY("API 변경"), - DELETE("API키 삭제"), - PROD_NEW("운영 API키 신규"), - PROD_MODIFY("운영 API 변경"), - PROD_DELETE("운영 API키 삭제"); + DELETE("API키 삭제"); private final String description; diff --git a/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java b/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java index 30e1f4e..9bbbe36 100644 --- a/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java +++ b/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java @@ -20,6 +20,8 @@ public interface AppRequestRepository extends BaseRepository Optional findAppRequestByApproval(Approval approval); + List findAllByOrgAndTypeIsInAndApproval_ApprovalStatusIn(PortalOrg org, List types, List approvalStates); + int countAllByOrgAndTypeIsInAndApproval_ApprovalStatusIn(PortalOrg org, List types, List approvalStates); Optional findByIdAndOrg(String id, PortalOrg org); diff --git a/src/main/java/com/eactive/apim/portal/file/service/FileService.java b/src/main/java/com/eactive/apim/portal/file/service/FileService.java index 2731326..66497d2 100644 --- a/src/main/java/com/eactive/apim/portal/file/service/FileService.java +++ b/src/main/java/com/eactive/apim/portal/file/service/FileService.java @@ -252,6 +252,100 @@ public class FileService { return fileDetail; } + + /** + * byte[] 데이터로 단일 파일을 생성합니다. + * + * @param fileName 파일 이름 (확장자 포함) + * @param contentType 파일 MIME 타입 + * @param fileData 파일 바이트 데이터 + * @return 파일 정보 + * @throws IOException 파일 처리 중 오류 발생 시 + */ + public FileInfo createSingleFileFromBytes(String fileName, String contentType, byte[] fileData) throws IOException { + // 파일 타입 검증 + String type = fileTypeDetector.detectFileType(fileData); + log.debug("upload file type from bytes: {}", type); + + if (type.equalsIgnoreCase("unknown")) { + throw new InvalidFileException("허용된 파일 형식이 아닙니다.
문서파일과 이미지 파일만 등록 가능합니다.
(pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, gif, jpg, png)"); + } + + // FileInfo 생성 + FileInfo fileInfo = new FileInfo(); + String fileId = UUID.randomUUID().toString(); + fileInfo.setFileId(fileId); + fileInfo.setCreatedDate(LocalDateTime.now()); + fileInfo.setUseYn("Y"); + + // FileDetail 생성 + FileDetail fileDetail = new FileDetail(); + fileDetail.setFileId(fileId); + fileDetail.setFileSn(1); + fileDetail.setFileSize(fileData.length); + fileDetail.setOriginalFileName(FilenameUtils.getBaseName(fileName)); + fileDetail.setFileExtension(FilenameUtils.getExtension(fileName)); + + // 파일 내용 저장 + String contentReference = binaryStorageService.store(fileData); + fileDetail.setFileContents(contentReference); + + // FileInfo에 FileDetail 추가 + fileInfo.getFileDetails().add(fileDetail); + + // 저장 및 반환 + return fileRepository.save(fileInfo); + } + + /** + * byte[] 데이터로 기존 파일을 업데이트하거나 새로 생성합니다. + * + * @param existingFileId 기존 파일 ID (null이면 새로 생성) + * @param fileName 파일 이름 (확장자 포함) + * @param contentType 파일 MIME 타입 + * @param fileData 파일 바이트 데이터 + * @return 파일 정보 + * @throws IOException 파일 처리 중 오류 발생 시 + */ + public FileInfo createOrUpdateSingleFileFromBytes(String existingFileId, String fileName, String contentType, byte[] fileData) throws IOException { + // 신규 등록 또는 기존 파일 정보 조회 + FileInfo fileInfo = Optional.ofNullable(existingFileId) + .filter(StringUtils::isNotBlank) + .map(this::findById) + .orElseGet(() -> { + FileInfo newFile = new FileInfo(); + newFile.setFileId(UUID.randomUUID().toString()); + newFile.setCreatedDate(LocalDateTime.now()); + newFile.setUseYn("Y"); + return newFile; + }); + + // 파일 타입 검증 + String type = fileTypeDetector.detectFileType(fileData); + log.debug("upload file type from bytes: {}", type); + + if (type.equalsIgnoreCase("unknown")) { + throw new InvalidFileException("허용된 파일 형식이 아닙니다.
문서파일과 이미지 파일만 등록 가능합니다.
(pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, gif, jpg, png)"); + } + + // FileDetail 생성 + FileDetail fileDetail = new FileDetail(); + fileDetail.setFileId(fileInfo.getFileId()); + fileDetail.setFileSn(1); + fileDetail.setFileSize(fileData.length); + fileDetail.setOriginalFileName(FilenameUtils.getBaseName(fileName)); + fileDetail.setFileExtension(FilenameUtils.getExtension(fileName)); + + // 파일 내용 저장 + String contentReference = binaryStorageService.store(fileData); + fileDetail.setFileContents(contentReference); + + // 기존 파일 상세 정보 제거 후 새로운 정보 추가 + fileInfo.getFileDetails().clear(); + fileInfo.getFileDetails().add(fileDetail); + + return fileRepository.save(fileInfo); + } } From 16e60e146a8f85022cccced90507f9ac3f608135 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Tue, 25 Nov 2025 11:25:25 +0900 Subject: [PATCH 04/24] =?UTF-8?q?=EB=B2=95=EC=9D=B8=20=EC=9D=B4=EC=9A=A9?= =?UTF-8?q?=EC=9E=90=20=EC=B4=88=EB=8C=80=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apim/portal/invitation/event/UserInvitationEvent.java | 7 ++++--- .../invitation/repository/UserInvitationRepository.java | 4 ++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/eactive/apim/portal/invitation/event/UserInvitationEvent.java b/src/main/java/com/eactive/apim/portal/invitation/event/UserInvitationEvent.java index ab59632..ecf3455 100644 --- a/src/main/java/com/eactive/apim/portal/invitation/event/UserInvitationEvent.java +++ b/src/main/java/com/eactive/apim/portal/invitation/event/UserInvitationEvent.java @@ -21,10 +21,11 @@ public class UserInvitationEvent implements MessageEventHandler { @Override public MessageSendEvent createEvent(Object source, MessageRecipient recipient, Map params) { Map requestParams = new HashMap<>(); - requestParams.put("company", params.get("company").toString()); - requestParams.put("manager", params.get("manager").toString()); + requestParams.put("corpName", params.get("corpName").toString()); + requestParams.put("managerName", params.get("managerName").toString()); requestParams.put("url", params.get("url").toString()); - requestParams.put("userName",params.get("company").toString() + " 이용자"); + requestParams.put("loginId",params.get("corpName").toString() + " 이용자"); + requestParams.put("authNumber", params.get("authNumber").toString()); return new MessageSendEvent(source, KEY, recipient, requestParams); } diff --git a/src/main/java/com/eactive/apim/portal/invitation/repository/UserInvitationRepository.java b/src/main/java/com/eactive/apim/portal/invitation/repository/UserInvitationRepository.java index e9c0f4b..f79fe17 100644 --- a/src/main/java/com/eactive/apim/portal/invitation/repository/UserInvitationRepository.java +++ b/src/main/java/com/eactive/apim/portal/invitation/repository/UserInvitationRepository.java @@ -18,4 +18,8 @@ public interface UserInvitationRepository extends JpaRepository findByStatus(InvitationStatus status); Optional findFirstByInvitationEmailAndStatus(String email, InvitationStatus status); + + Optional findFirstByInvitationEmailAndOrgIdAndStatus(String email, String orgId, InvitationStatus status); + + Optional findFirstByInvitationEmailAndOrgId(String email, String orgId); } From 44f50d0d212c45c5301ce33b0ed6859b922269ad Mon Sep 17 00:00:00 2001 From: Rinjae Date: Wed, 26 Nov 2025 14:27:36 +0900 Subject: [PATCH 05/24] =?UTF-8?q?=ED=8C=8C=ED=8A=B8=EB=84=88=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../portalorg/entity/OrgCodeGenerator.java | 4 ++++ .../apim/portal/portalorg/entity/PortalOrg.java | 16 +++++----------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/eactive/apim/portal/portalorg/entity/OrgCodeGenerator.java b/src/main/java/com/eactive/apim/portal/portalorg/entity/OrgCodeGenerator.java index 526cd11..98e4b8c 100644 --- a/src/main/java/com/eactive/apim/portal/portalorg/entity/OrgCodeGenerator.java +++ b/src/main/java/com/eactive/apim/portal/portalorg/entity/OrgCodeGenerator.java @@ -12,6 +12,10 @@ import java.sql.ResultSet; import java.sql.SQLException; +/** + * 25.11.26 - 광주은행에서는 기관코드를 OBP 파트너코드와 매칭 시킴. 즉, 자동 생성 사용안함 + */ +@Deprecated @Slf4j public class OrgCodeGenerator implements ValueGenerator { private static final String TABLE_NAME = "PTL_ID"; diff --git a/src/main/java/com/eactive/apim/portal/portalorg/entity/PortalOrg.java b/src/main/java/com/eactive/apim/portal/portalorg/entity/PortalOrg.java index 1e42fbc..11fbae4 100644 --- a/src/main/java/com/eactive/apim/portal/portalorg/entity/PortalOrg.java +++ b/src/main/java/com/eactive/apim/portal/portalorg/entity/PortalOrg.java @@ -3,18 +3,12 @@ package com.eactive.apim.portal.portalorg.entity; import com.eactive.apim.portal.common.entity.Auditable; import com.eactive.apim.portal.portalorg.entity.PortalOrgEnums.ApprovalStatus; import com.eactive.apim.portal.portalorg.entity.PortalOrgEnums.OrgStatus; -import java.io.Serializable; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Id; -import javax.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.annotations.Comment; -import org.hibernate.annotations.GenerationTime; -import org.hibernate.annotations.GeneratorType; + +import javax.persistence.*; +import java.io.Serializable; @Data @EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = true) @@ -40,8 +34,8 @@ public class PortalOrg extends Auditable implements Serializable, com.eactive.ea private String orgName; @Column(name = "org_code") - @Comment("제휴기관코드") - @GeneratorType(type = OrgCodeGenerator.class, when = GenerationTime.INSERT) + @Comment("제휴기관코드 - OBP 파트너코드") +// @GeneratorType(type = OrgCodeGenerator.class, when = GenerationTime.INSERT) private String orgCode; @Column(name = "org_desc", length = 255) From 25d46ed5d29eeea84b71c3541aa30262bdb5a093 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Fri, 28 Nov 2025 18:29:34 +0900 Subject: [PATCH 06/24] =?UTF-8?q?=EB=B2=95=EC=9D=B8=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=20=EA=B0=80=EC=9E=85=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apim/portal/portaluser/repository/PortalUserRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/eactive/apim/portal/portaluser/repository/PortalUserRepository.java b/src/main/java/com/eactive/apim/portal/portaluser/repository/PortalUserRepository.java index 154868e..7453cfa 100644 --- a/src/main/java/com/eactive/apim/portal/portaluser/repository/PortalUserRepository.java +++ b/src/main/java/com/eactive/apim/portal/portaluser/repository/PortalUserRepository.java @@ -15,7 +15,7 @@ import java.util.Optional; @EMSDataSource public interface PortalUserRepository extends BaseRepository { - Optional findByLoginId(String userName); + Optional findByLoginId(String String); Optional findPortalUserByEmailAddr(String loginId); From e74b51a769428c75732ad762e51eaa447fca6e26 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Wed, 3 Dec 2025 16:13:45 +0900 Subject: [PATCH 07/24] merge --- .../apim/portal/obp/entity/ObpGwMetric.java | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java diff --git a/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java b/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java new file mode 100644 index 0000000..424676c --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java @@ -0,0 +1,148 @@ +package com.eactive.apim.portal.obp.entity; + +import com.eactive.eai.data.converter.LocalDateTimeToStringConverter17; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.hibernate.annotations.Comment; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Parameter; + +import javax.persistence.*; +import java.time.LocalDateTime; + +@Data +@EqualsAndHashCode(callSuper = false) +@Entity +@Table(name = "ptl_obp_gw_metric") +public class ObpGwMetric { + @Id + @GeneratedValue(generator = "uuid-v1") + @GenericGenerator( + name = "uuid-v1", + strategy = "org.hibernate.id.UUIDGenerator", + parameters = { + @Parameter( + name = "uuid_gen_strategy_class", + value = "org.hibernate.id.uuid.CustomVersionOneStrategy" + ) + } + ) + @Column(length = 36) + @Comment("id") + private String id; + + + // json : appKey + @Column(length = 256, name = "client_id") + @Comment("클라이언트 ID") + private String clientId; + + // json : clusterHostname + @Column(length = 50, name = "hostname") + @Comment("호스트 이름") + private String hostname; + + // json : timeslice + @Column(length = 17, name = "timeslice") + @Convert(converter = LocalDateTimeToStringConverter17.class) + @CreationTimestamp + @Comment("타임슬라이스") + private LocalDateTime timeslice; + + // json : apiName + @Column(name = "api_name", length = 255) + @Comment("API 이름") + private String apiName; + + // json : apiRoutingUri + @Column(length = 255, name = "uri") + @Comment("URI") + private String uri; + + // json : attemptedCount + @Column(name = "attempted_count") + @Comment("시도 횟수") + private Long attemptedCount; + + // json : completedCount + @Column(name = "completed_count") + @Comment("완료 횟수") + private Long completedCount; + +// // registeredOn +// @Column(name = "created_at", nullable = false) +// @Comment("생성 날짜와 시간. 레코드가 생성된 시간") +// private LocalDateTime createdAt; +// +// // registeredBy +// @Column(name = "created_by", nullable = false, length = 50) +// @Comment("생성한 사용자") +// private String createdBy = "_ANONYMOUS_SUBJECT_ID______"; +// +// // modifiedOn +// @Column(name = "updated_at") +// @Comment("최종 업데이트 날짜와 시간. 레코드가 마지막으로 업데이트된 시간") +// private LocalDateTime updatedAt; +// +// // modifiedBy +// @Column(name = "updated_by", length = 50) +// @Comment("최종 업데이트한 사용자") +// private String modifiedBy; + + + + // eapim ID + // json : apiIdByEapim + @Column(length = 36, name = "api_id") + @Comment("API ID(EAPIM)") + private String apiId; + + // json : appIdByEapim + @Column(length = 36, name = "app_id") + private String appId; + + // json : orgIdByEapim + @Column(length = 36, name = "org_id") + private String orgId; + + + // AS-IS 호환용 필드 + + // json : appId + @Column(length = 50, name = "app_id_by_ca_portal") + @Comment("애플리케이션 ID(CA 포탈)") + private String appIdByCaPortal; + + // json : portalOrgId + @Column(length = 50, name = "org_id_by_ca_portal") + @Comment("기관 ID(CA 포탈)") + private String orgIdByCaPortal; + + // json : portalApiId + @Column(length = 50, name = "api_id_by_ca_portal") + @Comment("API ID(CA 포탈)") + private String apiIdByCaPortal; + + // json : partnerCode + @Column(length = 20, name = "partner_code") + @Comment("파트너 코드(OBP)") + private String partnerCode; + + // json : apiId + @Column(name = "app_id_by_ca", length = 36) + @Comment("API ID(CA)") + private String apiIdByCa; + + + @Column + @Comment("업데이트(보정) 횟수") + private int updateCount; + + + // 더미 + + // requestUri + @Transient + private String requestUri = "-1"; +} From a41f99b721236f5ba7283012bb54f15cac047fff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=98=84=EC=84=B1=ED=95=84?= Date: Fri, 5 Dec 2025 16:33:38 +0900 Subject: [PATCH 08/24] =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20repo=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../portal/portaluser/repository/PortalUserRepository.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/eactive/apim/portal/portaluser/repository/PortalUserRepository.java b/src/main/java/com/eactive/apim/portal/portaluser/repository/PortalUserRepository.java index 7453cfa..fbe2813 100644 --- a/src/main/java/com/eactive/apim/portal/portaluser/repository/PortalUserRepository.java +++ b/src/main/java/com/eactive/apim/portal/portaluser/repository/PortalUserRepository.java @@ -10,6 +10,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.util.List; import java.util.Optional; @EMSDataSource @@ -21,6 +22,8 @@ public interface PortalUserRepository extends BaseRepository PortalUser findByUserNameAndMobileNumber(String userName, String mobileNumber); + List findAllByUserNameAndMobileNumber(String userName, String mobileNumber); + Optional findByLoginIdAndUserNameAndMobileNumber(String loginId, String userName, String mobileNumber); boolean existsByLoginId(String loginId); From 861df4d08e98ad218b46a6035b2ed8c88cc5b027 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Fri, 5 Dec 2025 17:30:22 +0900 Subject: [PATCH 09/24] gw metric --- .../com/eactive/apim/portal/obp/entity/ObpGwMetric.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java b/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java index 424676c..8e61f6e 100644 --- a/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java +++ b/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java @@ -4,7 +4,6 @@ import com.eactive.eai.data.converter.LocalDateTimeToStringConverter17; import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.annotations.Comment; -import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Parameter; @@ -46,8 +45,7 @@ public class ObpGwMetric { // json : timeslice @Column(length = 17, name = "timeslice") @Convert(converter = LocalDateTimeToStringConverter17.class) - @CreationTimestamp - @Comment("타임슬라이스") + @Comment("타임슬라이스 (yyyyMMddHH0000000)") private LocalDateTime timeslice; // json : apiName @@ -94,8 +92,8 @@ public class ObpGwMetric { // eapim ID // json : apiIdByEapim - @Column(length = 36, name = "api_id") - @Comment("API ID(EAPIM)") + @Column(length = 40, name = "api_id") + @Comment("API ID(EAPIM) - EAISVCNAME 최대 40자") private String apiId; // json : appIdByEapim From 4d30702c3116c11deb2664327ccf3bc188db28d6 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Wed, 10 Dec 2025 15:14:51 +0900 Subject: [PATCH 10/24] =?UTF-8?q?ObpGwMetric=20Entity=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apim/portal/obp/entity/ObpGwMetric.java | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java b/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java index 8e61f6e..47fa5f8 100644 --- a/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java +++ b/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java @@ -45,7 +45,7 @@ public class ObpGwMetric { // json : timeslice @Column(length = 17, name = "timeslice") @Convert(converter = LocalDateTimeToStringConverter17.class) - @Comment("타임슬라이스 (yyyyMMddHH0000000)") + @Comment("타임슬라이스 (yyyyMMddHHmmssSSS)") private LocalDateTime timeslice; // json : apiName @@ -68,25 +68,25 @@ public class ObpGwMetric { @Comment("완료 횟수") private Long completedCount; -// // registeredOn -// @Column(name = "created_at", nullable = false) -// @Comment("생성 날짜와 시간. 레코드가 생성된 시간") -// private LocalDateTime createdAt; -// -// // registeredBy -// @Column(name = "created_by", nullable = false, length = 50) -// @Comment("생성한 사용자") -// private String createdBy = "_ANONYMOUS_SUBJECT_ID______"; -// -// // modifiedOn -// @Column(name = "updated_at") -// @Comment("최종 업데이트 날짜와 시간. 레코드가 마지막으로 업데이트된 시간") -// private LocalDateTime updatedAt; -// -// // modifiedBy -// @Column(name = "updated_by", length = 50) -// @Comment("최종 업데이트한 사용자") -// private String modifiedBy; + // registeredOn + @Column(name = "created_at", nullable = false) + @Comment("생성 날짜와 시간. 레코드가 생성된 시간") + private LocalDateTime createdAt; + + // registeredBy + @Column(name = "created_by", nullable = false, length = 50) + @Comment("생성한 사용자") + private String createdBy = "GwMetricHourJob"; + + // modifiedOn + @Column(name = "updated_at") + @Comment("최종 업데이트 날짜와 시간. 레코드가 마지막으로 업데이트된 시간") + private LocalDateTime updatedAt; + + // modifiedBy + @Column(name = "updated_by", length = 50) + @Comment("최종 업데이트한 사용자") + private String updatedBy; @@ -133,7 +133,7 @@ public class ObpGwMetric { private String apiIdByCa; - @Column + @Column(name = "update_count") @Comment("업데이트(보정) 횟수") private int updateCount; From d5b8fcd476293cb23de5cbd4f04b50aca63aca19 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Mon, 15 Dec 2025 16:27:06 +0900 Subject: [PATCH 11/24] OBP GW Metric Repository --- .../obp/repository/ObpGwMetricRepository.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java diff --git a/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java b/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java new file mode 100644 index 0000000..17fbecc --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java @@ -0,0 +1,44 @@ +package com.eactive.apim.portal.obp.repository; + +import com.eactive.apim.portal.obp.entity.ObpGwMetric; +import com.eactive.eai.data.jpa.BaseRepository; +import com.eactive.eai.rms.data.EMSDataSource; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +/** + * ObpGwMetric Repository + * API Gateway 시간별 거래량 지표 조회/저장 + */ +@EMSDataSource +public interface ObpGwMetricRepository extends BaseRepository { + + /** + * UPSERT 판단을 위한 기존 데이터 조회 + * Unique Key: (timeslice, api_id, client_id, hostname, org_id) + */ + Optional findByTimesliceAndApiIdAndClientIdAndHostnameAndOrgId( + LocalDateTime timeslice, + String apiId, + String clientId, + String hostname, + String orgId + ); + + /** + * 특정 시간대의 모든 지표 조회 (REST API 용) + */ + List findByTimeslice(LocalDateTime timeslice); + + /** + * 특정 시간대 범위의 지표 조회 + */ + List findByTimesliceBetween(LocalDateTime startTime, LocalDateTime endTime); + + /** + * API ID로 지표 조회 + */ + List findByApiIdAndTimeslice(String apiId, LocalDateTime timeslice); +} From b7500a04a2e3f3aa539094305cec65023b514341 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Tue, 16 Dec 2025 17:20:09 +0900 Subject: [PATCH 12/24] =?UTF-8?q?OBP=20GwMetric=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=EC=9A=A9=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apim/portal/obp/repository/ObpGwMetricRepository.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java b/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java index 17fbecc..ba58e8b 100644 --- a/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java +++ b/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java @@ -41,4 +41,9 @@ public interface ObpGwMetricRepository extends BaseRepository findByApiIdAndTimeslice(String apiId, LocalDateTime timeslice); + + /** + * 특정 시간대 이후의 모든 지표 조회 (REST API 용) + */ + List findByTimesliceGreaterThanEqual(LocalDateTime timeslice); } From 3cabbd584b5e062fd0294ddb8055982b2d207a65 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Wed, 17 Dec 2025 17:03:14 +0900 Subject: [PATCH 13/24] =?UTF-8?q?GwMetric=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java b/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java index 47fa5f8..29da51d 100644 --- a/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java +++ b/src/main/java/com/eactive/apim/portal/obp/entity/ObpGwMetric.java @@ -58,6 +58,11 @@ public class ObpGwMetric { @Comment("URI") private String uri; + // HTTP 메서드 (GET, POST, PUT, DELETE 등) + @Column(length = 10, name = "method") + @Comment("HTTP 메서드 (GET, POST, PUT, DELETE 등)") + private String method; + // json : attemptedCount @Column(name = "attempted_count") @Comment("시도 횟수") From 85f32d2a2c1abe824caffb243e603358f587e223 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Fri, 19 Dec 2025 14:14:51 +0900 Subject: [PATCH 14/24] =?UTF-8?q?GwMetric=20ibatis=20->=20jpa=20=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../obp/repository/ObpGwMetricRepository.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java b/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java index ba58e8b..235f372 100644 --- a/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java +++ b/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java @@ -3,6 +3,8 @@ package com.eactive.apim.portal.obp.repository; import com.eactive.apim.portal.obp.entity.ObpGwMetric; import com.eactive.eai.data.jpa.BaseRepository; import com.eactive.eai.rms.data.EMSDataSource; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.time.LocalDateTime; import java.util.List; @@ -16,9 +18,30 @@ import java.util.Optional; public interface ObpGwMetricRepository extends BaseRepository { /** - * UPSERT 판단을 위한 기존 데이터 조회 + * UPSERT 판단을 위한 기존 데이터 조회 (NULL 안전) * Unique Key: (timeslice, api_id, client_id, hostname, org_id) + * + *

Spring Data JPA의 메서드 이름 기반 쿼리는 NULL 비교를 제대로 처리하지 못함. + * SQL에서 {@code column = NULL}은 항상 false이므로, NULL 값이 있는 레코드를 찾지 못함. + * 이 쿼리는 {@code (column = :param OR (column IS NULL AND :param IS NULL))} 패턴으로 NULL을 안전하게 처리함.

*/ + @Query("SELECT m FROM ObpGwMetric m WHERE m.timeslice = :timeslice " + + "AND (m.apiId = :apiId OR (m.apiId IS NULL AND :apiId IS NULL)) " + + "AND (m.clientId = :clientId OR (m.clientId IS NULL AND :clientId IS NULL)) " + + "AND (m.hostname = :hostname OR (m.hostname IS NULL AND :hostname IS NULL)) " + + "AND (m.orgId = :orgId OR (m.orgId IS NULL AND :orgId IS NULL))") + Optional findByUniqueKeyNullSafe( + @Param("timeslice") LocalDateTime timeslice, + @Param("apiId") String apiId, + @Param("clientId") String clientId, + @Param("hostname") String hostname, + @Param("orgId") String orgId + ); + + /** + * @deprecated NULL 비교 문제로 {@link #findByUniqueKeyNullSafe} 사용 권장 + */ + @Deprecated Optional findByTimesliceAndApiIdAndClientIdAndHostnameAndOrgId( LocalDateTime timeslice, String apiId, From 356e0e8c9a9d009b484868bb8e85298165eb8f88 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Mon, 29 Dec 2025 11:47:44 +0900 Subject: [PATCH 15/24] =?UTF-8?q?=EC=9D=B8=EB=8D=B1=EC=8A=A4=20API=20?= =?UTF-8?q?=ED=86=B5=EA=B3=84=20=EB=B6=80=EB=B6=84=20=EC=8B=A4=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/repository/CredentialRepository.java | 24 ++++++++ .../service/PortalPropertyService.java | 55 +++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java b/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java index c940645..82fc2fb 100644 --- a/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java +++ b/src/main/java/com/eactive/apim/portal/app/repository/CredentialRepository.java @@ -7,6 +7,8 @@ import java.util.List; import java.util.Optional; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; @EMSDataSource public interface CredentialRepository extends BaseRepository { @@ -18,4 +20,26 @@ public interface CredentialRepository extends BaseRepository List findAllByOrgid(String orgid); Optional findByClientidAndOrgid(String clientid, String orgid); + + /** + * 특정 기관 ID 목록에 속하고 이용 가능 상태(appstatus='1')인 앱의 수를 조회 + */ + @Query("SELECT COUNT(c) FROM Credential c WHERE c.appstatus = '1' AND c.orgid IN :orgIds") + long countActiveAppsByOrgIds(@Param("orgIds") List orgIds); + + /** + * 특정 기관 ID 목록에 속하고 이용 가능 상태(appstatus='1')인 앱 목록 조회 + */ + @Query("SELECT c FROM Credential c WHERE c.appstatus = '1' AND c.orgid IN :orgIds") + List findActiveAppsByOrgIds(@Param("orgIds") List orgIds); + + /** + * 이용 가능 상태인 모든 앱의 수를 조회 + */ + long countByAppstatus(String appstatus); + + /** + * 이용 가능 상태인 모든 앱 목록 조회 + */ + List findByAppstatus(String appstatus); } diff --git a/src/main/java/com/eactive/apim/portal/portalproperty/service/PortalPropertyService.java b/src/main/java/com/eactive/apim/portal/portalproperty/service/PortalPropertyService.java index eae3bf0..e56af6b 100644 --- a/src/main/java/com/eactive/apim/portal/portalproperty/service/PortalPropertyService.java +++ b/src/main/java/com/eactive/apim/portal/portalproperty/service/PortalPropertyService.java @@ -2,21 +2,27 @@ package com.eactive.apim.portal.portalproperty.service; import com.eactive.apim.portal.portalproperty.entity.PortalProperty; import com.eactive.apim.portal.portalproperty.entity.PortalPropertyGroup; +import com.eactive.apim.portal.portalproperty.entity.PortalPropertyId; import com.eactive.apim.portal.portalproperty.repository.PortalPropertyGroupRepository; +import com.eactive.apim.portal.portalproperty.repository.PortalPropertyRepository; import com.eactive.eai.data.jpa.AbstractDataService; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; +@Slf4j @Service @RequiredArgsConstructor @Transactional public class PortalPropertyService extends AbstractDataService { private final PortalPropertyGroupRepository portalPropertyGroupRepository; + private final PortalPropertyRepository portalPropertyRepository; @Transactional(readOnly = true) public Map getPortalPropertiesAsMap(String propertyGroupName) { @@ -31,5 +37,54 @@ public class PortalPropertyService extends AbstractDataService existingProperty = portalPropertyRepository.findById(propertyId); + if (existingProperty.isPresent()) { + return existingProperty.get().getPropertyValue(); + } + + // 프로퍼티가 없으면 기본값으로 생성 + return createDefaultProperty(groupName, propertyName, defaultValue, description); + } + + /** + * 기본 프로퍼티를 DB에 생성 + */ + private String createDefaultProperty(String groupName, String propertyName, String defaultValue, String description) { + try { + // 그룹이 존재하는지 확인 + PortalPropertyGroup group = portalPropertyGroupRepository.findById(groupName) + .orElse(null); + + if (group == null) { + log.warn("프로퍼티 그룹 '{}'이 존재하지 않아 기본값 저장을 건너뜁니다.", groupName); + return defaultValue; + } + + // 새 프로퍼티 생성 + PortalProperty newProperty = new PortalProperty(); + newProperty.setId(new PortalPropertyId(groupName, propertyName)); + newProperty.setPropertyValue(defaultValue); + newProperty.setPropertyDesc(description); + + portalPropertyRepository.save(newProperty); + log.info("기본 프로퍼티 생성 완료 - 그룹: {}, 키: {}, 값: {}", groupName, propertyName, defaultValue); + + return defaultValue; + } catch (Exception e) { + log.error("기본 프로퍼티 생성 실패 - 그룹: {}, 키: {}", groupName, propertyName, e); + return defaultValue; + } + } } From 6fe004686bbf9d17a81457615f2103297c41ed3f Mon Sep 17 00:00:00 2001 From: Rinjae Date: Wed, 7 Jan 2026 14:30:36 +0900 Subject: [PATCH 16/24] =?UTF-8?q?=EC=95=BD=EA=B4=80=20=EC=B2=A8=EB=B6=80?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/eactive/apim/portal/agreements/entity/Agreements.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/eactive/apim/portal/agreements/entity/Agreements.java b/src/main/java/com/eactive/apim/portal/agreements/entity/Agreements.java index 15c8eed..0b9efc7 100644 --- a/src/main/java/com/eactive/apim/portal/agreements/entity/Agreements.java +++ b/src/main/java/com/eactive/apim/portal/agreements/entity/Agreements.java @@ -61,4 +61,8 @@ public class Agreements extends Auditable { @Column(name = "SCHEDULED_ON") @Convert(converter = LocalDateTimeToStringConverter14.class) private LocalDateTime scheduledOn; + + @Column(name = "ATTACHED_FILE_ID", length = 36) + @Comment("첨부파일 ID (PTL_FILE.FILE_ID)") + private String attachedFileId; } \ No newline at end of file From 69106223867b4aded39485022313a3f419ab51c7 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Mon, 12 Jan 2026 16:14:56 +0900 Subject: [PATCH 17/24] =?UTF-8?q?AppRequest=20JPA=20Entity=20not=20found?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apprequest/repository/AppRequestRepository.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java b/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java index 9bbbe36..5e4bb04 100644 --- a/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java +++ b/src/main/java/com/eactive/apim/portal/apprequest/repository/AppRequestRepository.java @@ -8,6 +8,7 @@ import com.eactive.apim.portal.approval.statemachine.ApprovalState; import com.eactive.apim.portal.portalorg.entity.PortalOrg; import com.eactive.eai.data.jpa.BaseRepository; import com.eactive.eai.rms.data.EMSDataSource; +import java.util.Collection; import java.util.List; import java.util.Optional; import org.springframework.data.domain.Page; @@ -31,4 +32,12 @@ public interface AppRequestRepository extends BaseRepository List findAllByClientIdsContainsAndTypeIsIn(String clientId, List types); List findAllByOrgAndStatus(PortalOrg org, ApprovalStatus status); + + /** + * org.id 목록으로 AppRequest 조회 (ObpGwMetric 집계용) + * + * @param orgIds 기관 ID 목록 + * @return AppRequest 목록 + */ + List findByOrg_IdIn(Collection orgIds); } From 04315d3c75de655bc0dd70e14a8e13b97b979c4a Mon Sep 17 00:00:00 2001 From: Rinjae Date: Tue, 13 Jan 2026 22:44:44 +0900 Subject: [PATCH 18/24] =?UTF-8?q?EMS=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=20=EC=95=94=ED=98=B8=ED=99=94=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/eactive/apim/portal/user/entity/UserInfo.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/eactive/apim/portal/user/entity/UserInfo.java b/src/main/java/com/eactive/apim/portal/user/entity/UserInfo.java index a9a9b4f..fdd9058 100644 --- a/src/main/java/com/eactive/apim/portal/user/entity/UserInfo.java +++ b/src/main/java/com/eactive/apim/portal/user/entity/UserInfo.java @@ -18,6 +18,7 @@ import org.springframework.data.annotation.LastModifiedDate; import com.eactive.eai.data.converter.LocalDateTimeToStringConverter14; import com.eactive.eai.data.converter.StringTrimConverter; import com.eactive.eai.data.entity.AbstractEntity; +import kjb.safedb.KjbNotRnnoJpaAttributeConverter; import lombok.Data; import lombok.EqualsAndHashCode; @@ -53,6 +54,7 @@ public class UserInfo extends AbstractEntity implements Serializable { @Column(length = 40) @Comment("휴대폰 번호") + @Convert(converter = KjbNotRnnoJpaAttributeConverter.class) private String cphnno; @Column(length = 40) @@ -61,6 +63,7 @@ public class UserInfo extends AbstractEntity implements Serializable { @Column(length = 100) @Comment("이메일 주소") + @Convert(converter = KjbNotRnnoJpaAttributeConverter.class) private String emad; @Column(length = 3) From e02004532f9e74735115a9d2e9477a19e6ce7816 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Sun, 18 Jan 2026 16:25:58 +0900 Subject: [PATCH 19/24] =?UTF-8?q?=ED=8F=AC=ED=83=88=20Q&A,=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=EA=B4=80=EB=A0=A8=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eactive/apim/portal/portaluser/entity/PortalUserEnums.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/eactive/apim/portal/portaluser/entity/PortalUserEnums.java b/src/main/java/com/eactive/apim/portal/portaluser/entity/PortalUserEnums.java index 00e4814..4b18771 100644 --- a/src/main/java/com/eactive/apim/portal/portaluser/entity/PortalUserEnums.java +++ b/src/main/java/com/eactive/apim/portal/portaluser/entity/PortalUserEnums.java @@ -3,6 +3,7 @@ package com.eactive.apim.portal.portaluser.entity; public class PortalUserEnums { public enum UserStatus { + PENDING("대기"), READY("준비"), ACTIVE("정상"), PW_FAIL("비밀번호 5회 실패"), From c9028d77fc30a6622fe0ce75afc9004b94df0f75 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Sun, 18 Jan 2026 18:22:32 +0900 Subject: [PATCH 20/24] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=ED=8C=90=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../partnershipapplication/entity/PartnershipApplication.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/eactive/apim/portal/partnershipapplication/entity/PartnershipApplication.java b/src/main/java/com/eactive/apim/portal/partnershipapplication/entity/PartnershipApplication.java index f8fcfe4..6755ead 100644 --- a/src/main/java/com/eactive/apim/portal/partnershipapplication/entity/PartnershipApplication.java +++ b/src/main/java/com/eactive/apim/portal/partnershipapplication/entity/PartnershipApplication.java @@ -26,7 +26,6 @@ public class PartnershipApplication extends Auditable { @Comment("비즈니스제목") private String bizSubject; - @Lob @Column(name = "biz_detail", nullable = false) @Comment("비즈니스내용") private String bizDetail; From 37dcf9d537d1b86c50bcefd32d7ffe7a370bd3ad Mon Sep 17 00:00:00 2001 From: Rinjae Date: Thu, 29 Jan 2026 15:34:05 +0900 Subject: [PATCH 21/24] =?UTF-8?q?kjbank.com=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apim/portal/file/service/FileService.java | 60 ++++++++++++++++--- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/eactive/apim/portal/file/service/FileService.java b/src/main/java/com/eactive/apim/portal/file/service/FileService.java index 66497d2..d3438fb 100644 --- a/src/main/java/com/eactive/apim/portal/file/service/FileService.java +++ b/src/main/java/com/eactive/apim/portal/file/service/FileService.java @@ -29,6 +29,30 @@ public class FileService { private final BinaryStorageService binaryStorageService; private final FileTypeDetector fileTypeDetector; + private static final ThreadLocal internalUserContext = new ThreadLocal<>(); + + /** + * 현재 스레드에 내부 사용자 컨텍스트 설정 + */ + public static void setInternalUserContext(boolean isInternal) { + internalUserContext.set(isInternal); + } + + /** + * 내부 사용자 컨텍스트 조회 + */ + public static boolean isInternalUserContext() { + Boolean isInternal = internalUserContext.get(); + return isInternal != null && isInternal; + } + + /** + * 내부 사용자 컨텍스트 정리 + */ + public static void clearInternalUserContext() { + internalUserContext.remove(); + } + /** * 특정 파일 ID를 기반으로 파일 정보를 검색합니다. * @@ -71,8 +95,15 @@ public class FileService { String type = fileTypeDetector.detectFileType(file.getBytes()); log.debug("upload file type:{}", type); - if(type.equalsIgnoreCase("unknown")) { - throw new InvalidFileException("허용된 파일 형식이 아닙니다.
문서파일과 이미지 파일만 등록 가능합니다.
(pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, gif, jpg, png)"); + boolean isValidType = !type.equalsIgnoreCase("unknown"); + + if (!isValidType) { + if (isInternalUserContext()) { + log.warn("Internal user bypassed file validation - File: {}, Type: {}", + file.getOriginalFilename(), type); + } else { + throw new InvalidFileException("허용된 파일 형식이 아닙니다.
문서파일과 이미지 파일만 등록 가능합니다.
(pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, gif, jpg, png)"); + } } if (StringUtils.isNotBlank(file.getOriginalFilename()) && file.getSize() > 0) { @@ -82,7 +113,13 @@ public class FileService { fileDetail.setFileSn(fileSn); fileDetail.setFileSize((int) file.getSize()); fileDetail.setOriginalFileName(FilenameUtils.getBaseName(file.getOriginalFilename())); - fileDetail.setFileExtension(type); + + if (isValidType) { + fileDetail.setFileExtension(type); + } else { + fileDetail.setFileExtension(FilenameUtils.getExtension(file.getOriginalFilename())); + } + String contentReference = binaryStorageService.store(file.getBytes()); fileDetail.setFileContents(contentReference); fileInfo.getFileDetails().add(fileDetail); @@ -232,12 +269,17 @@ public class FileService { String type = fileTypeDetector.detectFileType(file.getBytes()); log.debug("upload file type:{}", type); - if (isCheckMime) { - if(type.equalsIgnoreCase("unknown")) { - throw new InvalidFileException("허용된 파일 형식이 아닙니다.
문서파일과 이미지 파일만 등록 가능합니다.
(pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, gif, jpg, png)"); - } - } else { - log.debug("파일 체크 옵션 해제 - FileType : {}", type); + boolean isValidType = !type.equalsIgnoreCase("unknown"); + + if (isCheckMime && !isValidType) { + if (isInternalUserContext()) { + log.warn("Internal user bypassed file validation - File: {}, Type: {}", + fileName, type); + } else { + throw new InvalidFileException("허용된 파일 형식이 아닙니다.
문서파일과 이미지 파일만 등록 가능합니다.
(pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, gif, jpg, png)"); + } + } else if (!isCheckMime) { + log.debug("파일 체크 옵션 해제 - FileType : {}", type); } FileDetail fileDetail = new FileDetail(); From af75587550e4303f730db990b6854566c5c5c20a Mon Sep 17 00:00:00 2001 From: Rinjae Date: Wed, 4 Feb 2026 17:49:40 +0900 Subject: [PATCH 22/24] =?UTF-8?q?OBP=20GwMetric=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=EB=B2=94=EC=9C=84=20=EC=A0=9C=ED=95=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../portal/obp/repository/ObpGwMetricRepository.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java b/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java index 235f372..26d3c6c 100644 --- a/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java +++ b/src/main/java/com/eactive/apim/portal/obp/repository/ObpGwMetricRepository.java @@ -3,6 +3,7 @@ package com.eactive.apim.portal.obp.repository; import com.eactive.apim.portal.obp.entity.ObpGwMetric; import com.eactive.eai.data.jpa.BaseRepository; import com.eactive.eai.rms.data.EMSDataSource; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -69,4 +70,13 @@ public interface ObpGwMetricRepository extends BaseRepository findByTimesliceGreaterThanEqual(LocalDateTime timeslice); + + /** + * 특정 시간대 이후의 지표 조회 (페이징 지원) + * + * @param timeslice 조회 시작 시간대 + * @param pageable 페이징 및 정렬 정보 + * @return 조회된 지표 목록 + */ + List findByTimesliceGreaterThanEqual(LocalDateTime timeslice, Pageable pageable); } From ceabf19a77b7db63abce388eca4a36ed31f3f2b9 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Thu, 5 Mar 2026 15:01:27 +0900 Subject: [PATCH 23/24] =?UTF-8?q?=EA=B0=9C=EB=B0=9C=EC=9E=90=ED=8F=AC?= =?UTF-8?q?=ED=83=88=20=EC=82=AC=EC=9A=A9=EC=9E=90/=EB=B2=95=EC=9D=B8=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EC=84=A0=20?= =?UTF-8?q?=EB=B0=8F=20=EC=99=84=EC=A0=84=EC=82=AD=EC=A0=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eactive/apim/portal/apprequest/entity/AppRequest.java | 8 ++++++-- .../com/eactive/apim/portal/approval/entity/Approval.java | 5 +++-- .../eactive/apim/portal/portaluser/entity/PortalUser.java | 3 +++ .../java/com/eactive/apim/portal/qna/entity/Inquiry.java | 5 ++++- .../apim/portal/template/entity/MessageRequest.java | 3 +++ 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java index f95caf9..0150efe 100644 --- a/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java +++ b/src/main/java/com/eactive/apim/portal/apprequest/entity/AppRequest.java @@ -12,6 +12,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.NotFound; +import org.hibernate.annotations.NotFoundAction; @Data @EqualsAndHashCode @@ -27,7 +29,8 @@ public class AppRequest implements com.eactive.eai.data.Data { private String id; @ManyToOne - @JoinColumn(name = "org_id") + @JoinColumn(name = "org_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + @NotFound(action = NotFoundAction.IGNORE) private PortalOrg org; @Enumerated(EnumType.STRING) @@ -37,7 +40,8 @@ public class AppRequest implements com.eactive.eai.data.Data { private AppRequestType type; @OneToOne - @JoinColumn(name = "approval_id") + @JoinColumn(name = "approval_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + @NotFound(action = NotFoundAction.IGNORE) private Approval approval; @Column(name = "api_list") diff --git a/src/main/java/com/eactive/apim/portal/approval/entity/Approval.java b/src/main/java/com/eactive/apim/portal/approval/entity/Approval.java index 2a2bb72..0ddfc7d 100644 --- a/src/main/java/com/eactive/apim/portal/approval/entity/Approval.java +++ b/src/main/java/com/eactive/apim/portal/approval/entity/Approval.java @@ -12,6 +12,7 @@ import org.hibernate.annotations.*; import javax.persistence.CascadeType; import javax.persistence.Entity; +import javax.persistence.ForeignKey; import javax.persistence.Table; import javax.persistence.*; import javax.validation.constraints.NotNull; @@ -50,9 +51,9 @@ public class Approval implements Serializable, com.eactive.eai.data.Data { @Column(name = "target_id", nullable = false) private String targetId; //승인하는 대상 객체의 ID - @NotNull @ManyToOne - @JoinColumn(name = "REQUESTER_ID", nullable = false) + @JoinColumn(name = "REQUESTER_ID", nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + @NotFound(action = NotFoundAction.IGNORE) private PortalUser requester; @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "approval") diff --git a/src/main/java/com/eactive/apim/portal/portaluser/entity/PortalUser.java b/src/main/java/com/eactive/apim/portal/portaluser/entity/PortalUser.java index 74b8715..7982593 100644 --- a/src/main/java/com/eactive/apim/portal/portaluser/entity/PortalUser.java +++ b/src/main/java/com/eactive/apim/portal/portaluser/entity/PortalUser.java @@ -12,6 +12,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.annotations.Comment; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.NotFound; +import org.hibernate.annotations.NotFoundAction; import javax.persistence.*; import java.time.LocalDateTime; @@ -60,6 +62,7 @@ public class PortalUser extends Auditable implements Serializable, com.eactive.e @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "org_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + @NotFound(action = NotFoundAction.IGNORE) private PortalOrg portalOrg; @Enumerated(EnumType.STRING) diff --git a/src/main/java/com/eactive/apim/portal/qna/entity/Inquiry.java b/src/main/java/com/eactive/apim/portal/qna/entity/Inquiry.java index 69111b6..e2265b5 100644 --- a/src/main/java/com/eactive/apim/portal/qna/entity/Inquiry.java +++ b/src/main/java/com/eactive/apim/portal/qna/entity/Inquiry.java @@ -8,6 +8,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.NotFound; +import org.hibernate.annotations.NotFoundAction; import javax.persistence.*; import java.time.LocalDateTime; @@ -55,7 +57,8 @@ public class Inquiry extends Auditable { * 문의자 */ @ManyToOne - @JoinColumn(name = "INQUIRER_ID") + @JoinColumn(name = "INQUIRER_ID", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + @NotFound(action = NotFoundAction.IGNORE) private PortalUser inquirer; /** diff --git a/src/main/java/com/eactive/apim/portal/template/entity/MessageRequest.java b/src/main/java/com/eactive/apim/portal/template/entity/MessageRequest.java index b4529b5..031f0e9 100644 --- a/src/main/java/com/eactive/apim/portal/template/entity/MessageRequest.java +++ b/src/main/java/com/eactive/apim/portal/template/entity/MessageRequest.java @@ -9,6 +9,8 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.hibernate.annotations.Comment; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.NotFound; +import org.hibernate.annotations.NotFoundAction; import javax.persistence.*; import java.io.Serializable; @@ -59,6 +61,7 @@ public class MessageRequest implements Serializable { @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "user_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) + @NotFound(action = NotFoundAction.IGNORE) @Comment("발송 대상 사용자") private PortalUser user; From 980fb37b1acfb025846316b0b9dd2e41932e617d Mon Sep 17 00:00:00 2001 From: curry772 Date: Wed, 11 Mar 2026 10:17:42 +0900 Subject: [PATCH 24/24] =?UTF-8?q?=EB=B9=8C=EB=93=9C=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20=EB=B0=8F=20kjb-safedb=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - build.gradle: nexus 저장소 및 의존성 설정 정리 --- build.gradle | 11 +- .../KjbNotRnnoJpaAttributeConverter.java | 127 +++++++++--------- 2 files changed, 74 insertions(+), 64 deletions(-) diff --git a/build.gradle b/build.gradle index b1e8352..6df5fe6 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,15 @@ idea { def nexusUrl = "https://nexus.eactive.synology.me:8090" +allprojects { + repositories { + maven { + url "${nexusUrl}/repository/maven-public/" + allowInsecureProtocol = true + } + } +} + def springVersion = "5.3.27" //def quartzVersion = "2.2.1" def queryDslVersion = "5.0.0" @@ -72,7 +81,7 @@ tasks.withType(JavaCompile) { } dependencies { - api project(':kjb-safedb') +// api project(':kjb-safedb') api "com.querydsl:querydsl-jpa:${queryDslVersion}" api "com.querydsl:querydsl-apt:${queryDslVersion}" diff --git a/src/main/java/kjb/safedb/KjbNotRnnoJpaAttributeConverter.java b/src/main/java/kjb/safedb/KjbNotRnnoJpaAttributeConverter.java index 43f3772..20a0ec3 100644 --- a/src/main/java/kjb/safedb/KjbNotRnnoJpaAttributeConverter.java +++ b/src/main/java/kjb/safedb/KjbNotRnnoJpaAttributeConverter.java @@ -1,8 +1,8 @@ package kjb.safedb; -import com.eactive.ext.kjb.safedb.KjbSafedbWrapper; -import com.eactive.ext.kjb.safedb.SafeDBColumns; -import com.eactive.ext.kjb.safedb.Utils; +//import com.eactive.ext.kjb.safedb.KjbSafedbWrapper; +//import com.eactive.ext.kjb.safedb.SafeDBColumns; +//import com.eactive.ext.kjb.safedb.Utils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -25,26 +25,26 @@ public class KjbNotRnnoJpaAttributeConverter implements AttributeConverter {}", originalAttribute, attribute); - } - } +// String originalAttribute = attribute; +// if (StringUtils.isNotEmpty(attribute)) { +// KjbSafedbWrapper wrapper = KjbSafedbWrapper.getInstance(); +// attribute = wrapper.encryptNotRnnoString(attribute); +// +// if (log.isDebugEnabled()) { +// // originalAttribute 홀수 글자 마스킹 +// StringBuilder sb = new StringBuilder(); +// for (int i = 0; i < originalAttribute.length(); i++) { +// if (i % 2 == 0) { +// sb.append(originalAttribute.charAt(i)); +// } else { +// sb.append("*"); +// } +// } +// +// originalAttribute = sb.toString(); +// log.debug("DB 암호화 #2 : {} -> {}", originalAttribute, attribute); +// } +// } return attribute; } @@ -59,23 +59,23 @@ public class KjbNotRnnoJpaAttributeConverter implements AttributeConverter {}", dbDataOriginal, dbData); @@ -88,28 +88,29 @@ public class KjbNotRnnoJpaAttributeConverter implements AttributeConverter