Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a45819cbce | |||
| fe1138b480 | |||
| 88c1cc4918 | |||
| 97b1e0a28a | |||
| 31c08a7284 | |||
| dc5d2df166 | |||
| e3619b385f | |||
| 94724d3952 | |||
| 6a64d35a94 | |||
| 72d2150a6e | |||
| c8049dd881 | |||
| 2e2ac8f462 | |||
| f3a9e19b89 | |||
| b5866b087d | |||
| 6f00de61d9 | |||
| e5d0acf694 |
@@ -0,0 +1,21 @@
|
||||
package com.eactive.apim.portal.apprequest.entity;
|
||||
|
||||
/**
|
||||
* API 이용해지(DELETE) 승인 시 게이트웨이 클라이언트(TSEAIAU01) 처리 방식.
|
||||
* 승인 시점에 관리자가 선택하며 PTL_APP_REQUEST.GW_ACTION 에 영속화된다.
|
||||
* null(미지정)은 BLOCK 과 동일하게 처리한다.
|
||||
*/
|
||||
public enum GwAction {
|
||||
BLOCK("차단"),
|
||||
DELETE("완전삭제");
|
||||
|
||||
private final String description;
|
||||
|
||||
GwAction(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ public interface AppRequestRepository extends BaseRepository<AppRequest, String>
|
||||
|
||||
List<AppRequest> findAllByOrgAndTypeIsInAndApproval_ApprovalStatusIn(PortalOrg org, List<AppRequestType> types, List<ApprovalState> approvalStates);
|
||||
|
||||
List<AppRequest> findAllByOrgAndTypeIsInAndApprovalIsNull(PortalOrg org, List<AppRequestType> types);
|
||||
|
||||
int countAllByOrgAndTypeIsInAndApproval_ApprovalStatusIn(PortalOrg org, List<AppRequestType> types, List<ApprovalState> approvalStates);
|
||||
|
||||
Optional<AppRequest> findByIdAndOrg(String id, PortalOrg org);
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.eactive.apim.portal.jpa;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* UUID version 7 (time-ordered, RFC 9562) 생성기.
|
||||
*
|
||||
* <p>상위 48비트에 Unix epoch 밀리초 타임스탬프를 두어 생성 시각 순으로 정렬되므로,
|
||||
* 무작위 v4 대비 인덱스(B-Tree) 삽입 지역성이 좋아 PK 인덱스 단편화를 줄인다.
|
||||
* canonical 36자 문자열로 반환하여 기존 {@code VARCHAR2(36)} 컬럼과 호환된다.</p>
|
||||
*
|
||||
* <p>레이아웃(128비트): unix_ts_ms(48) | ver=0b0111(4) | rand_a(12) | var=0b10(2) | rand_b(62)</p>
|
||||
*
|
||||
* <p>Java 8 호환(java.util.UUID + SecureRandom). Hibernate {@link IdentifierGenerator} 구현이며
|
||||
* 엔티티에서 {@code @GenericGenerator(strategy = "...UuidV7Generator")} 로 지정한다.</p>
|
||||
*/
|
||||
public class UuidV7Generator implements IdentifierGenerator {
|
||||
|
||||
private static final SecureRandom RANDOM = new SecureRandom();
|
||||
|
||||
@Override
|
||||
public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
|
||||
return generateString();
|
||||
}
|
||||
|
||||
/** UUID v7 을 canonical 36자 문자열로 생성한다. */
|
||||
public static String generateString() {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
|
||||
byte[] value = new byte[16];
|
||||
|
||||
// 상위 48비트: unix epoch millis (big-endian)
|
||||
value[0] = (byte) ((timestamp >>> 40) & 0xFF);
|
||||
value[1] = (byte) ((timestamp >>> 32) & 0xFF);
|
||||
value[2] = (byte) ((timestamp >>> 24) & 0xFF);
|
||||
value[3] = (byte) ((timestamp >>> 16) & 0xFF);
|
||||
value[4] = (byte) ((timestamp >>> 8) & 0xFF);
|
||||
value[5] = (byte) (timestamp & 0xFF);
|
||||
|
||||
// 나머지 10바이트는 난수로 채운다.
|
||||
byte[] rand = new byte[10];
|
||||
RANDOM.nextBytes(rand);
|
||||
System.arraycopy(rand, 0, value, 6, 10);
|
||||
|
||||
// version 7: value[6] 상위 니블을 0111 로 설정
|
||||
value[6] = (byte) ((value[6] & 0x0F) | 0x70);
|
||||
// variant 10xx: value[8] 상위 2비트를 10 으로 설정
|
||||
value[8] = (byte) ((value[8] & 0x3F) | 0x80);
|
||||
|
||||
long msb = 0L;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
msb = (msb << 8) | (value[i] & 0xFFL);
|
||||
}
|
||||
long lsb = 0L;
|
||||
for (int i = 8; i < 16; i++) {
|
||||
lsb = (lsb << 8) | (value[i] & 0xFFL);
|
||||
}
|
||||
|
||||
return new java.util.UUID(msb, lsb).toString();
|
||||
}
|
||||
}
|
||||
@@ -121,5 +121,8 @@ public class PortalOrg extends Auditable implements Serializable, com.eactive.ea
|
||||
this.orgSectors = null;
|
||||
this.orgIndustryType = null;
|
||||
this.serviceName = null;
|
||||
this.orgDesc = null;
|
||||
this.ipWhitelist = null;
|
||||
this.reverseProxyPath = null;
|
||||
}
|
||||
}
|
||||
|
||||
+15
@@ -4,8 +4,23 @@ import com.eactive.apim.portal.portalproperty.entity.PortalProperty;
|
||||
import com.eactive.apim.portal.portalproperty.entity.PortalPropertyId;
|
||||
import com.eactive.eai.data.jpa.BaseRepository;
|
||||
import com.eactive.eai.rms.data.EMSDataSource;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@EMSDataSource
|
||||
public interface PortalPropertyRepository extends BaseRepository<PortalProperty, PortalPropertyId> {
|
||||
|
||||
/**
|
||||
* (PROPERTY_GROUP_NAME, PROPERTY_NAME) 조합이 2건 이상인 중복 키를 조회한다.
|
||||
* DB에 유니크 제약을 걸지 않으므로 기동 시 무결성 점검용으로 사용한다.
|
||||
*
|
||||
* @return {@code Object[]{propertyGroupName, propertyName, count}} 목록 (중복 없으면 빈 리스트)
|
||||
*/
|
||||
@Query("SELECT p.id.propertyGroupName, p.id.propertyName, COUNT(p) "
|
||||
+ "FROM PortalProperty p "
|
||||
+ "GROUP BY p.id.propertyGroupName, p.id.propertyName "
|
||||
+ "HAVING COUNT(p) > 1")
|
||||
List<Object[]> findDuplicatePropertyKeys();
|
||||
|
||||
}
|
||||
|
||||
@@ -88,7 +88,11 @@ public class PortalUser extends Auditable implements Serializable, com.eactive.e
|
||||
@Comment("로그인실패횟수")
|
||||
private Integer loginFailureCount;
|
||||
|
||||
@Column(name = "password_change_date")
|
||||
// PASSWORD_CHANGE_DATE 컬럼은 VARCHAR2(14) yyyyMMddHHmmss 문자열이다.
|
||||
// LocalDateTime 을 그대로 바인딩하면 27자로 변환되어 ORA-12899(값 초과)가 발생하므로
|
||||
// 14자 문자열로 변환하는 컨버터를 적용한다.
|
||||
@Column(name = "password_change_date", length = 14)
|
||||
@Convert(converter = com.eactive.eai.data.converter.LocalDateTimeToStringConverter14.class)
|
||||
@Comment("비밀번호변경일시")
|
||||
private LocalDateTime passwordChangeDate;
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ public class TwoFactorAuth {
|
||||
|
||||
@Id
|
||||
@Column(name = "id", length = 36, nullable = false)
|
||||
@GenericGenerator(name = "uuid-gen", strategy = "uuid2")
|
||||
// UUID v7(타임스탬프 기반, 시간순 정렬) — PK 인덱스 삽입 지역성 개선. 기존 v4 행과 컬럼 호환.
|
||||
@GenericGenerator(name = "uuid-gen", strategy = "com.eactive.apim.portal.jpa.UuidV7Generator")
|
||||
@GeneratedValue(generator = "uuid-gen", strategy = GenerationType.IDENTITY)
|
||||
private String id;
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.eactive.apim.portal.portaluser.entity;
|
||||
|
||||
import com.eactive.eai.data.converter.LocalDateTimeToStringConverter14;
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.Comment;
|
||||
import org.hibernate.annotations.Parameter;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 사용자 역할(권한) 변경 감사 이력.
|
||||
*
|
||||
* <p>법인 관리자 위임/회수, 소속 제외 등으로 {@code PortalUser.roleCode} 가 변경될 때
|
||||
* 이전 역할 → 새 역할, 변경 유형, 변경 수행자(관리자)를 이력으로 남긴다.
|
||||
* {@link UserPasswordHistory} 와 동일한 저장 패턴(시퀀스 PK, 14자리 문자열 일시)을 따른다.</p>
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "ptl_user_role_history")
|
||||
public class UserRoleHistory implements Serializable, com.eactive.eai.data.Data {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GenericGenerator(
|
||||
name = "ptl_user_role_history_seq_gen",
|
||||
strategy = "com.eactive.eai.rms.data.jpa.SchemaPrefixedSequenceGenerator",
|
||||
parameters = {
|
||||
@Parameter(name = "sequence_name", value = "PTL_USER_ROLE_HISTORY_SEQ"),
|
||||
@Parameter(name = "initial_value", value = "1"),
|
||||
@Parameter(name = "increment_size", value = "1")
|
||||
}
|
||||
)
|
||||
@GeneratedValue(
|
||||
strategy = GenerationType.SEQUENCE,
|
||||
generator = "ptl_user_role_history_seq_gen"
|
||||
)
|
||||
@Column(name = "id", columnDefinition = "number(19)")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "user_id", length = 255, nullable = false)
|
||||
@Comment("대상 사용자 ID(loginId)")
|
||||
private String userId;
|
||||
|
||||
@Column(name = "before_role", length = 30)
|
||||
@Comment("변경 전 역할")
|
||||
private String beforeRole;
|
||||
|
||||
@Column(name = "after_role", length = 30, nullable = false)
|
||||
@Comment("변경 후 역할")
|
||||
private String afterRole;
|
||||
|
||||
@Column(name = "change_type", length = 30, nullable = false)
|
||||
@Comment("변경 유형(MANAGER_ASSIGN/MANAGER_REVOKE/ORG_REMOVE 등)")
|
||||
private String changeType;
|
||||
|
||||
@Column(name = "changed_by", length = 255, nullable = false)
|
||||
@Comment("변경 수행자(loginId)")
|
||||
private String changedBy;
|
||||
|
||||
@Column(name = "change_date", length = 14, nullable = false)
|
||||
@Comment("변경 일시")
|
||||
@Convert(converter = LocalDateTimeToStringConverter14.class)
|
||||
private LocalDateTime changeDate;
|
||||
|
||||
@Column(name = "created_by", length = 255, nullable = false)
|
||||
@Comment("생성자")
|
||||
private String createdBy;
|
||||
|
||||
@Column(name = "created_date", length = 14, nullable = false)
|
||||
@Comment("생성일시")
|
||||
@Convert(converter = LocalDateTimeToStringConverter14.class)
|
||||
private LocalDateTime createdDate;
|
||||
}
|
||||
+10
@@ -2,7 +2,9 @@ package com.eactive.apim.portal.portaluser.repository;
|
||||
|
||||
import com.eactive.apim.portal.portaluser.entity.TwoFactorAuth;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface TwoFactorAuthRepository extends JpaRepository<TwoFactorAuth, String> {
|
||||
@@ -12,6 +14,14 @@ public interface TwoFactorAuthRepository extends JpaRepository<TwoFactorAuth, St
|
||||
|
||||
void deleteAllByRecipientKey(String recipientKey);
|
||||
|
||||
/**
|
||||
* 만료된 인증번호 레코드를 일괄 삭제한다. (정리 스케줄러용)
|
||||
* expires_on 은 LocalDateTimeToStringConverter14(yyyyMMddHHmmss) 로 저장되며,
|
||||
* 해당 포맷은 사전식 정렬이 시간순과 일치하므로 문자열 < 비교가 곧 시간 비교다.
|
||||
*/
|
||||
@Modifying
|
||||
int deleteAllByExpiresAtBefore(LocalDateTime threshold);
|
||||
|
||||
// 아래 두 메서드는 recipient(암호화 컬럼) 기반이라 신뢰할 수 없음 — 신규 코드에서는 RecipientKey 버전을 사용할 것.
|
||||
@Deprecated
|
||||
Optional<TwoFactorAuth> findByRecipient(String recipientKey);
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.eactive.apim.portal.portaluser.repository;
|
||||
|
||||
import com.eactive.apim.portal.portaluser.entity.UserRoleHistory;
|
||||
import com.eactive.eai.rms.data.EMSDataSource;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@EMSDataSource
|
||||
public interface UserRoleHistoryRepository extends JpaRepository<UserRoleHistory, Long> {
|
||||
|
||||
List<UserRoleHistory> findByUserIdOrderByChangeDateDesc(String userId);
|
||||
}
|
||||
@@ -1,7 +1,37 @@
|
||||
package com.eactive.apim.portal.portaluser.service;
|
||||
|
||||
public class AuthNumberException extends RuntimeException{
|
||||
/**
|
||||
* 인증번호(2FA/이메일/SMS) 검증·발송 실패 예외.
|
||||
*
|
||||
* <p>기존에는 메시지 문자열만 있었으나, 감사 로그에서 실패 사유(만료/불일치/미존재)를
|
||||
* 코드로 구분해야 하므로 {@link Reason} 을 추가했다. 기존 메시지 전용 생성자는 유지되며
|
||||
* 이 경우 {@code reason == null} 이다(하위호환).</p>
|
||||
*/
|
||||
public class AuthNumberException extends RuntimeException {
|
||||
|
||||
/** 실패 사유 분류 */
|
||||
public enum Reason {
|
||||
/** 저장된 인증번호가 없음(미발송/이미 소비/스케줄러 정리) */
|
||||
NOT_FOUND,
|
||||
/** 유효시간 초과 */
|
||||
EXPIRED,
|
||||
/** 인증번호 불일치 */
|
||||
MISMATCH
|
||||
}
|
||||
|
||||
private final Reason reason;
|
||||
|
||||
public AuthNumberException(String message) {
|
||||
super(message);
|
||||
this.reason = null;
|
||||
}
|
||||
|
||||
public AuthNumberException(String message, Reason reason) {
|
||||
super(message);
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public Reason getReason() {
|
||||
return reason;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,4 +86,23 @@ public class Inquiry extends Auditable {
|
||||
|
||||
@Column(name = "ATTACH_FILE")
|
||||
private String attachFile;
|
||||
|
||||
/**
|
||||
* 공개범위 (전체공개/법인공개/비공개). 기본값 ORG.
|
||||
* PTL_PROPERTY 기관 기본값이 상한(ceiling)이며 읽기/쓰기 시 clamp 된다.
|
||||
*/
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "VISIBILITY", length = 16)
|
||||
private VisibilityScope visibility = VisibilityScope.ORG;
|
||||
|
||||
/**
|
||||
* 조회수. sessionStorage 기반 dedup 후 POST 요청으로만 증가한다.
|
||||
*/
|
||||
@Column(name = "VIEW_COUNT")
|
||||
private long viewCount = 0L;
|
||||
|
||||
/** 조회수 1 증가. */
|
||||
public void increaseViewCount() {
|
||||
this.viewCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,18 @@ public class InquiryComment extends Auditable implements Serializable {
|
||||
@Column(name = "ADMIN_YN", length = 1)
|
||||
private String adminYn = "N";
|
||||
|
||||
/**
|
||||
* 댓글 공개범위. 개념상 공개(ALL)/비공개(PRIVATE) 2단계.
|
||||
* 비공개 댓글은 작성자·같은 법인 corp-manager·관리자만 열람 가능.
|
||||
*/
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "VISIBILITY", length = 16)
|
||||
private VisibilityScope visibility = VisibilityScope.ALL;
|
||||
|
||||
public boolean isPrivate() {
|
||||
return this.visibility == VisibilityScope.PRIVATE;
|
||||
}
|
||||
|
||||
public void markDeleted() {
|
||||
this.delYn = "Y";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.eactive.apim.portal.qna.entity;
|
||||
|
||||
/**
|
||||
* 문의(Q&A) 게시물/댓글의 공개범위.
|
||||
*
|
||||
* <p>{@code width}는 공개 범위의 넓이 랭크로, 값이 클수록 더 넓게 공개된다.
|
||||
* {@code PTL_PROPERTY}에 설정된 기관 기본값이 상한(ceiling)이 되며, 게시물이 상한보다
|
||||
* 넓게 설정될 수 없다({@link #clampTo}). property가 항상 우선한다.</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code ALL} : 전체 로그인 사용자 공개</li>
|
||||
* <li>{@code ORG} : 같은 법인 소속 사용자 공개 (게시물 기본값)</li>
|
||||
* <li>{@code PRIVATE} : 작성자 본인만 (댓글의 "비공개")</li>
|
||||
* </ul>
|
||||
*/
|
||||
public enum VisibilityScope {
|
||||
|
||||
ALL(3, "전체공개"),
|
||||
ORG(2, "법인공개"),
|
||||
PRIVATE(1, "비공개");
|
||||
|
||||
private final int width;
|
||||
private final String label;
|
||||
|
||||
VisibilityScope(int width, String label) {
|
||||
this.width = width;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
/** 공개 범위 넓이 랭크. 클수록 넓게 공개. */
|
||||
public int width() {
|
||||
return width;
|
||||
}
|
||||
|
||||
/** 화면 표기용 한글 라벨. */
|
||||
public String label() {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* 문자열을 enum으로 안전 변환. null/빈값/미해당은 defaultScope 반환.
|
||||
*/
|
||||
public static VisibilityScope fromString(String value, VisibilityScope defaultScope) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return defaultScope;
|
||||
}
|
||||
try {
|
||||
return VisibilityScope.valueOf(value.trim().toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return defaultScope;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 요청 공개범위를 상한으로 clamp 한다. 요청이 상한보다 넓으면 상한으로 낮춘다.
|
||||
* (property가 항상 우선하므로, 저장값이 옛 상한이라 더 넓더라도 읽기 시 재-clamp 한다.)
|
||||
*/
|
||||
public static VisibilityScope clampTo(VisibilityScope requested, VisibilityScope ceiling) {
|
||||
if (requested == null) {
|
||||
return ceiling;
|
||||
}
|
||||
if (ceiling == null) {
|
||||
return requested;
|
||||
}
|
||||
return requested.width() > ceiling.width() ? ceiling : requested;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.eactive.apim.portal.template.entity;
|
||||
|
||||
|
||||
import com.eactive.apim.portal.common.util.PhoneNumberUtil;
|
||||
import com.eactive.apim.portal.jpa.PersonalDataEncryptConverter;
|
||||
import com.eactive.apim.portal.portaluser.entity.PortalUser;
|
||||
import com.eactive.eai.data.converter.LocalDateTimeToStringConverter14;
|
||||
@@ -83,4 +84,11 @@ public class MessageRequest implements Serializable {
|
||||
|
||||
@Column(name = "service_id")
|
||||
private String serviceId;
|
||||
|
||||
/** 저장 시 전화번호를 하이픈 구분 정규형으로 통일 */
|
||||
@PrePersist
|
||||
@PreUpdate
|
||||
private void normalizePhones() {
|
||||
this.phone = PhoneNumberUtil.normalize(this.phone);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ public class MessageSendService {
|
||||
String subject = buildMessage(template.getSubjectTemplate(), messageParams);
|
||||
|
||||
if (template.getEnableSms().equalsIgnoreCase("Y")) {
|
||||
String smsEaiInterfaceId = portalProperties.get("ums.sms.if_id");
|
||||
String smsEaiInterfaceId = portalProperties.get("djb.ums.sms.if_id");
|
||||
MessageRequest smsRequest = new MessageRequest();
|
||||
smsRequest.setMessageCode(MessageCode.valueOf(template.getMessageCode().toUpperCase()));
|
||||
smsRequest.setSubject(subject);
|
||||
@@ -88,19 +88,15 @@ public class MessageSendService {
|
||||
smsRequest.setUsername(user.getUsername());
|
||||
smsRequest.setPhone(user.getPhone());
|
||||
smsRequest.setEaiInterfaceId(smsEaiInterfaceId);
|
||||
smsRequest.setServiceId(portalProperties.get("ums.sms.tx_id"));
|
||||
smsRequest.setServiceId(portalProperties.get("djb.ums.sms.tx_id"));
|
||||
smsRequest.setUserId(user.getUserId());
|
||||
if ("ADMIN_VERIFICATION_MOBILEPHONE".equals(template.getMessageCode().toUpperCase())) {
|
||||
smsRequest.setMessageType("KAKAO");
|
||||
} else {
|
||||
smsRequest.setMessageType("SMS");
|
||||
}
|
||||
smsRequest.setMessageType("KAKAO");
|
||||
messageRequestRepository.save(smsRequest);
|
||||
logger.debug(smsRequest.toString());
|
||||
}
|
||||
|
||||
if (template.getEnableEmail().equalsIgnoreCase("Y")) {
|
||||
String mailEaiInterfaceId = portalProperties.get("ums.email.if_id");
|
||||
String mailEaiInterfaceId = portalProperties.get("djb.ums.email.if_id");
|
||||
MessageRequest emailRequest = new MessageRequest();
|
||||
emailRequest.setMessageCode(MessageCode.valueOf(template.getMessageCode().toUpperCase()));
|
||||
emailRequest.setSubject(subject);
|
||||
@@ -110,7 +106,7 @@ public class MessageSendService {
|
||||
emailRequest.setUsername(user.getUsername());
|
||||
emailRequest.setEmail(user.getUserId());
|
||||
emailRequest.setEaiInterfaceId(mailEaiInterfaceId);
|
||||
emailRequest.setServiceId(portalProperties.get("ums.email.tx_id"));
|
||||
emailRequest.setServiceId(portalProperties.get("djb.ums.email.tx_id"));
|
||||
emailRequest.setMessageType("EMAIL");
|
||||
emailRequest.setUserId(user.getUserId());
|
||||
messageRequestRepository.save(emailRequest);
|
||||
@@ -118,7 +114,7 @@ public class MessageSendService {
|
||||
}
|
||||
|
||||
if (template.getEnableMessenger().equalsIgnoreCase("Y")) {
|
||||
String swingEaiInterfaceId = portalProperties.get("ums.messenger.if_id");
|
||||
String swingEaiInterfaceId = portalProperties.get("djb.ums.messenger.if_id");
|
||||
MessageRequest messengerRequest = new MessageRequest();
|
||||
messengerRequest.setMessageCode(MessageCode.valueOf(template.getMessageCode()));
|
||||
messengerRequest.setSubject(subject);
|
||||
@@ -128,7 +124,7 @@ public class MessageSendService {
|
||||
messengerRequest.setUsername(user.getUsername());
|
||||
messengerRequest.setMessengerId(user.getUserId());
|
||||
messengerRequest.setEaiInterfaceId(swingEaiInterfaceId);
|
||||
messengerRequest.setServiceId(portalProperties.get("ums.messenger.tx_id"));
|
||||
messengerRequest.setServiceId(portalProperties.get("djb.ums.messenger.tx_id"));
|
||||
messengerRequest.setMessageType("MESSENGER");
|
||||
messengerRequest.setUserId(user.getUserId());
|
||||
messageRequestRepository.save(messengerRequest);
|
||||
|
||||
@@ -11,6 +11,7 @@ import lombok.NonNull;
|
||||
import org.hibernate.annotations.Cache;
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
import org.hibernate.annotations.Comment;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
|
||||
import javax.persistence.*;
|
||||
@@ -73,6 +74,12 @@ public class UserInfo extends AbstractEntity<String> implements Serializable {
|
||||
@LastModifiedDate
|
||||
private LocalDateTime lastamndyms;
|
||||
|
||||
@Column(length = 14)
|
||||
@Comment("등록 일시")
|
||||
@Convert(converter = LocalDateTimeToStringConverter14.class)
|
||||
@CreatedDate
|
||||
private LocalDateTime regdyms;
|
||||
|
||||
@Column(length = 80)
|
||||
@Comment("부서명")
|
||||
private String dvsnname;
|
||||
@@ -136,6 +143,10 @@ public class UserInfo extends AbstractEntity<String> implements Serializable {
|
||||
@Comment("사용자 계정 상태")
|
||||
private String status;
|
||||
|
||||
@Column
|
||||
@Comment("로그인 실패 횟수")
|
||||
private Integer loginfailcount;
|
||||
|
||||
@Override
|
||||
public @NonNull String getId() {
|
||||
return userid;
|
||||
|
||||
@@ -45,4 +45,12 @@ public class UserLog {
|
||||
@Column(name = "success", nullable = false)
|
||||
private boolean success;
|
||||
|
||||
/** 실패 사유 코드 (LoginFailureReason). 성공 행은 null */
|
||||
@Column(name = "failure_reason", length = 64)
|
||||
private String failureReason;
|
||||
|
||||
/** 로그인 유형 코드 (LoginType: NORMAL/TWO_FACTOR/SIGNUP_AUTO). 실패 행·과거 행은 null */
|
||||
@Column(name = "login_type", length = 32)
|
||||
private String loginType;
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user