Merge remote-tracking branch 'origin/master'
eapim-admin CI / build (push) Has been cancelled

This commit is contained in:
Rinjae-gf63
2026-06-18 17:58:26 +09:00
8 changed files with 226 additions and 148 deletions
+40 -23
View File
@@ -1,5 +1,10 @@
/**
* 문자열 마스킹 처리를 위한 유틸리티
*
* 보안아키텍처 표준 마스킹 규칙(Java MaskingUtils)과 동일한 결과를 내도록 구현한다.
* 이름 2자: 뒤 1자리(가나→가*) / 3자 이상: 앞뒤 제외 가운데 전체(가나다라→가**라)
* 이메일 아이디 앞2·뒤2 마스킹, 4자 이하 전체(test→****, test123→**st1**)
* 전화 2·3번째 세그먼트 각각 뒤 2자리(010-1234-1234→010-12**-12**)
*/
const StringMaskingUtil = {
@@ -8,41 +13,51 @@ const StringMaskingUtil = {
return str != null && str !== '';
},
// 이름 마스킹 처리
// '*' 반복 생성
_stars: function(count) {
return count > 0 ? '*'.repeat(count) : '';
},
// 세그먼트 뒤 count 자리 마스킹
_maskSegmentTail: function(segment, count) {
if (segment.length <= count) {
return this._stars(segment.length);
}
return segment.substring(0, segment.length - count) + this._stars(count);
},
// 이름 마스킹 처리 (2자: 뒤 1자리, 3자 이상: 앞뒤 제외 가운데 전체)
maskName: function(name) {
if (!this.isValidString(name)) {
return name;
}
return name.length > 1 ?
name.substring(0, name.length - 1) + "*" :
name;
const len = name.length;
if (len === 1) {
return name;
}
if (len === 2) {
return name.charAt(0) + '*';
}
return name.charAt(0) + this._stars(len - 2) + name.charAt(len - 1);
},
// 이메일 마스킹 처리
// 이메일 마스킹 처리 (아이디 앞2·뒤2, 4자 이하 전체)
maskEmail: function(email) {
if (!this.isValidString(email) || !email.includes('@')) {
return email;
}
const parts = email.split('@');
if (parts.length !== 2) {
return email;
const atIdx = email.indexOf('@');
const local = email.substring(0, atIdx);
const domain = email.substring(atIdx);
if (local.length <= 4) {
return this._stars(local.length) + domain;
}
const localPart = parts[0];
let maskedLocal;
if (localPart.length <= 3) {
maskedLocal = localPart.substring(0, 1) +
'*'.repeat(localPart.length - 1);
} else {
maskedLocal = localPart.substring(0, localPart.length - 3) + '***';
}
return maskedLocal + '@' + parts[1];
return this._stars(2) + local.substring(2, local.length - 2) + this._stars(2) + domain;
},
// 휴대폰 번호 마스킹 처리
// 휴대폰/전화 번호 마스킹 처리 (2·3번째 세그먼트 각각 뒤 2자리)
maskMobileNumber: function(number) {
if (!this.isValidString(number)) {
return number;
@@ -50,8 +65,10 @@ const StringMaskingUtil = {
const parts = number.split('-');
if (parts.length === 3) {
return parts[0] + '-****-' + parts[2];
return parts[0] + '-' +
this._maskSegmentTail(parts[1], 2) + '-' +
this._maskSegmentTail(parts[2], 2);
}
return number;
}
};
};
@@ -26,31 +26,6 @@ function formatFile(cellvalue, options, rowObject) {
return cellvalue + icon;
}
function formatDelete(cellvalue, options, rowObject) {
return '<button type="button" class="cssbtn" level="W" onclick="deleteRow(\'' + rowObject.id + '\');" '
+ 'style="background-color:#dc3545;border-color:#dc3545;color:white;padding:2px 8px;">삭제</button>';
}
function deleteRow(id) {
if (!confirm('선택한 항목을 삭제하시겠습니까?')) {
return;
}
$.ajax({
type: "POST",
url: url,
dataType: "json",
data: { cmd: 'DELETE', id: id },
success: function(data) {
alert('삭제되었습니다.');
$("#grid").trigger("reloadGrid");
},
error: function(e) {
alert('삭제 중 오류가 발생했습니다.');
}
});
}
function deleteSelectedRows() {
var selectedIds = $("#grid").jqGrid('getGridParam', 'selarrrow');
@@ -91,14 +66,13 @@ $(document).ready(function() {
searchBizSubject: $('input[name=searchBizSubject]').val() ,
searchBizDetail: $('input[name=searchBizDetail]').val()
},
colNames:['No.', 'ID', '제목', '작성자', '작성일시', '관리'],
colNames:['No.', 'ID', '제목', '작성자', '작성일시'],
colModel:[
{ name : 'rowNum' , align:'center', width: 40, sortable: false },
{ name : 'id' , align:'center', key: true, hidden: true},
{ name : 'bizSubject' , align:'center', width: 150, formatter: formatFile },
{ name : 'createdByName' , align:'center' ,width: 80},
{ name : 'createdDate' , align:'center', width: 100, formatter: timeStampFormat },
{ name : 'act' , align:'center', width: 60, sortable: false, formatter: formatDelete }
{ name : 'createdDate' , align:'center', width: 100, formatter: timeStampFormat }
],
jsonReader: {
repeatitems:false
@@ -92,6 +92,27 @@ $(document).ready(function() {
goNav(returnUrl);//LIST로 이동
});
$("#btn_delete").click(function(){
if (!confirm('선택한 항목을 삭제하시겠습니까?')) {
return;
}
$.ajax({
type: "POST",
url: url,
dataType: "json",
data: { cmd: 'DELETE', id: key },
success: function(data) {
alert('삭제되었습니다.');
var returnUrl = getReturnUrlForReturn();
goNav(returnUrl);//LIST로 이동
},
error: function(e) {
alert('삭제 중 오류가 발생했습니다.');
}
});
});
$("#btn_unmask").click(function () {
const reason = prompt("마스킹 해제 사유를 입력하세요:");
@@ -134,6 +155,7 @@ $(document).ready(function() {
<div class="content_middle">
<div class="search_wrap">
<button type="button" class="cssbtn" id="btn_unmask" level="W" status="DETAIL"><i class="material-icons">lock_open</i> 마스킹해제</button>
<button type="button" class="cssbtn" id="btn_delete" level="W" status="DETAIL" style="background-color: #dc3545; border-color: #dc3545; color: white;"><i class="material-icons">delete_forever</i> 삭제</button>
<button type="button" class="cssbtn" id="btn_previous" level="R" status="DETAIL,NEW"><i class="material-icons">arrow_back</i> <%= localeMessage.getString("button.previous") %></button>
</div>
<div class="title">피드백/개선요청 신청 상세</div>