미사용계정 현황(#11, 메뉴 9100037)이 대상이 개인정보취급자(EMP) 계정임을 화면·메뉴명에서 알 수 없어 오해 소지가 있었다. "장기 미사용 계정" → "장기 미사용 관리자 계정"으로 명시(요약표/목록 캡션, 메뉴명, 프로그램 설명). 이미 배포된 환경을 위해 재실행 안전한 UPDATE 문을 DML에 추가. 목록 행별 "말소"/"잠금" 버튼은 시각적으로 과도하게 커서 축소(.btn3.mini). 상단 "선택 말소" 일괄 버튼은 그대로 둠. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1156 lines
82 KiB
SQL
1156 lines
82 KiB
SQL
-- #####################################################################
|
||
-- arko_renual 설치용 통합 SQL (개인정보보호 기능개선 사업 · arko 대비 변동분)
|
||
-- 대상 DB : MySQL 5.7 / MariaDB (스키마 csv)
|
||
-- 구성 : [PART 1] DDL(테이블 생성·변경) → [PART 2] DML(기준/시드 데이터)
|
||
-- → [PART 3] 관리자 메뉴 등록 DML(좌측메뉴 노출, COMTNPROGRMLIST/
|
||
-- COMTNMENUINFO/COMTNMENUCREATDTLS, 9100035~9100039 + 9100044 + 9100045)
|
||
-- 실행순서: 반드시 PART 1 → PART 2 → PART 3 순서로 실행
|
||
-- (테이블 생성 → 시드 적재 → 메뉴 등록. 메뉴는 FK로 프로그램 등록을 먼저 요구)
|
||
-- 재실행 : **전 구간 재실행 안전(멱등)** — PART 1 은 CREATE TABLE IF NOT EXISTS 와
|
||
-- information_schema 존재 확인 후 실행되는 ALTER(컬럼/인덱스), PART 2·3 은
|
||
-- NOT EXISTS 가드를 쓴다. 이미 적용된 항목은 'SKIP: ...' 메시지만 출력하고
|
||
-- 넘어가므로, 기존 환경에도 이 파일 하나만 그대로 실행하면 된다.
|
||
-- (2026-08-05 이전 버전은 재실행 시 1050/1060/1061 오류가 났다)
|
||
-- ★★ PART 3 적용만으로는 좌측메뉴에 안 뜬다 — left.jsp 하드코딩 <c:when> 분기가
|
||
-- 반드시 함께 배포돼야 한다(소스에는 이미 반영됨). 상세는 PART 3 헤더 참조. ★★
|
||
-- #####################################################################
|
||
|
||
|
||
-- =====================================================================
|
||
-- PART 1. DDL (테이블 생성 / 컬럼 확장) ※ 시드 INSERT는 PART 2로 분리
|
||
-- =====================================================================
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.account_mng_policy_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 계정 관리 정책 : ACCOUNT_MNG_POLICY (단일행 정책 테이블)
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SFR-002, 장기 미사용 계정 관리)
|
||
-- 개발항목 #13(정책 설정) + #9(휴면 기준일수 정책값화) - 담당: arko-privacy-authctrl (Fork A)
|
||
-- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB
|
||
-- ---------------------------------------------------------------------
|
||
-- [용도] 휴면 기준일수·사전알림 시점·삭제 보존기간·배치주기 등 계정 관리 정책을
|
||
-- 하드코딩이 아닌 관리자 설정값으로 운영하기 위한 단일행 정책 테이블.
|
||
-- [#9] 휴면 select(EgovLoginUsr_SQL_Mysql.xml)의 365 하드코딩을
|
||
-- (SELECT DORMANT_DAY FROM ACCOUNT_MNG_POLICY) 로 대체(미설정 시 365 fallback).
|
||
-- [#10] ALERT_D1/D2/D3(기본 30/7/0) = 휴면예정 D-30/D-7/D-Day 사전알림 시점.
|
||
-- ADMIN_EMAIL = 사전알림 관리자 수신 주소.
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS ACCOUNT_MNG_POLICY (
|
||
POLICY_ID INT NOT NULL DEFAULT 1 COMMENT '정책 식별자(단일행=1)',
|
||
DORMANT_DAY INT NOT NULL DEFAULT 365 COMMENT '휴면 전환 기준 미접속 일수(#9)',
|
||
ALERT_D1 INT NOT NULL DEFAULT 30 COMMENT '사전알림 1차(휴면 D-일수)',
|
||
ALERT_D2 INT NOT NULL DEFAULT 7 COMMENT '사전알림 2차(휴면 D-일수)',
|
||
ALERT_D3 INT NOT NULL DEFAULT 0 COMMENT '사전알림 3차(D-Day, 0=당일)',
|
||
DELETE_PRESERVE_DAY INT NOT NULL DEFAULT 365 COMMENT '휴면/탈퇴 후 삭제 보존기간(일)',
|
||
BATCH_CYCLE VARCHAR(20) NOT NULL DEFAULT 'DAILY' COMMENT '배치 주기(DAILY/WEEKLY/MONTHLY)',
|
||
ADMIN_EMAIL VARCHAR(200) NULL COMMENT '사전알림 관리자 수신 이메일',
|
||
UPD_ID VARCHAR(20) NULL COMMENT '최종 수정자',
|
||
UPD_DT DATETIME NULL COMMENT '최종 수정일시',
|
||
PRIMARY KEY (POLICY_ID)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='계정 관리 정책(개인정보보호 SFR-002, 단일행)';
|
||
|
||
-- 기본 정책 시드(없을 때만). 기준 365일·알림 D-30/7/0·보존 365일.
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.account_unlock_history_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 계정 잠금 해제 이력 : ACCOUNT_UNLOCK_HISTORY
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SER-001, 계정 잠금 정책 정비)
|
||
-- 개발항목 #24 - 담당: arko-privacy-authctrl (Fork A)
|
||
-- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB
|
||
-- ---------------------------------------------------------------------
|
||
-- [목적] 잠긴 계정 해제를 DB 직접조작이 아니라 관리자 화면(EgovAccountUnlockManage)
|
||
-- 에서 처리하고, 해제자·해제일시·대상·사유를 이력으로 남긴다.
|
||
-- [무결성] 애플리케이션 계층에 UPDATE/DELETE statement 미정의(INSERT/SELECT 한정).
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS ACCOUNT_UNLOCK_HISTORY (
|
||
UNLOCK_HIST_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '해제 이력 일련번호(PK)',
|
||
TRGET_ID VARCHAR(50) NULL COMMENT '해제 대상 계정 ID(전체해제 시 NULL 가능)',
|
||
TRGET_SE VARCHAR(10) NULL COMMENT '대상 회원구분 GNR/GRO/ENT/USR',
|
||
UNLOCK_TY CHAR(1) NOT NULL DEFAULT 'I' COMMENT '해제 유형 I:개별 A:전체',
|
||
UNLOCK_USER_ID VARCHAR(50) NULL COMMENT '해제 처리자(관리자) ID',
|
||
UNLOCK_RESN VARCHAR(500) NULL COMMENT '해제 사유',
|
||
UNLOCK_IP VARCHAR(45) NULL COMMENT '해제자 접속 IP(IPv6 대응)',
|
||
UNLOCK_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '해제 일시',
|
||
PRIMARY KEY (UNLOCK_HIST_ID),
|
||
KEY IX_AUH_TRGET (TRGET_ID, UNLOCK_DT),
|
||
KEY IX_AUH_USER (UNLOCK_USER_ID, UNLOCK_DT),
|
||
KEY IX_AUH_DT (UNLOCK_DT)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='계정 잠금 해제 이력(개인정보보호 SER-001 #24)';
|
||
|
||
|
||
-- =====================================================================
|
||
-- 계정 잠금 임계값 10회 → 5회 (#24)
|
||
-- 임계값은 하드코딩이 아니라 LOGIN_LOCK_COUNT.LOCK_COUNT(단일행) 데이터에서 조회됨
|
||
-- (loginDAO.selectFailTotalCount). 아래 UPDATE 로 운영 정책값을 5회로 조정한다.
|
||
-- ※ 소스(EgovLoginController)에는 값 부재 시 기본 5회 fallback 이 반영되어 있음.
|
||
-- =====================================================================
|
||
UPDATE LOGIN_LOCK_COUNT SET LOCK_COUNT = 5;
|
||
-- 행이 없을 경우 대비(최초 세팅):
|
||
-- INSERT INTO LOGIN_LOCK_COUNT (LOCK_COUNT) SELECT 5 FROM DUAL
|
||
-- WHERE NOT EXISTS (SELECT 1 FROM LOGIN_LOCK_COUNT);
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.author_change_history_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 권한 변경 이력 테이블 : AUTHOR_CHANGE_HISTORY
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SFR-001, 역할별 차등 접근/권한 변경 추적)
|
||
-- 개발항목 #4 - 담당: arko-privacy-authctrl (Fork A → 오케스트레이터 완료)
|
||
-- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB
|
||
-- ---------------------------------------------------------------------
|
||
-- [목적] 권한 신설·변경·회수(#1 getAuthorities 대상 COMTNEMPLYRSCRTYESTBS 등)의
|
||
-- 모든 변경을 변경자·변경일시·변경전/후 권한과 함께 이력으로 적재한다.
|
||
-- 권한 신청·승인 워크플로(#3)의 승인 반영 시점에 권한반영과 단일 트랜잭션으로 적재.
|
||
--
|
||
-- [보관·파기] 3년(1,095일) 이상 보관 전제. 월 1회 @Scheduled 파기 배치(#5)가
|
||
-- 보관기간(1,095일) 경과 이력만 선별 파기한다. 개별 삭제 API 미제공.
|
||
-- 다운로드 시 사유 입력 필수 + 다운로드 이력 적재(#6)는 별도 처리.
|
||
--
|
||
-- [무결성] 이력 위·변조 억제를 위해 변경전/후 권한을 함께 보관(사후 대사 가능).
|
||
-- 애플리케이션 계층에 UPDATE statement 미정의(INSERT/SELECT/파기 DELETE 한정).
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS AUTHOR_CHANGE_HISTORY (
|
||
HIST_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '이력 일련번호(PK)',
|
||
TRGET_UNIQ_ID VARCHAR(20) NOT NULL COMMENT '변경 대상자 고유식별자(ESNTL_ID)',
|
||
TRGET_ID VARCHAR(20) NULL COMMENT '변경 대상자 계정ID(참고용)',
|
||
CHG_SE_CODE CHAR(1) NOT NULL COMMENT '변경구분 G:부여(grant) R:회수(revoke) M:변경(modify)',
|
||
BEFORE_AUTHOR VARCHAR(1000) NULL COMMENT '변경 전 권한(코드 CSV 또는 스냅샷)',
|
||
AFTER_AUTHOR VARCHAR(1000) NULL COMMENT '변경 후 권한(코드 CSV 또는 스냅샷)',
|
||
CHG_RESN VARCHAR(500) NULL COMMENT '변경 사유(신청/승인 워크플로 연계 #3)',
|
||
APROVL_ID VARCHAR(20) NULL COMMENT '승인자 계정ID(승인 워크플로 #3)',
|
||
CHANGER_UNIQ_ID VARCHAR(20) NOT NULL COMMENT '변경자(처리자) 고유식별자',
|
||
CHANGER_ID VARCHAR(20) NULL COMMENT '변경자 계정ID(참고용)',
|
||
CHANGER_IP VARCHAR(45) NULL COMMENT '변경자 접속 IP(IPv6 대응)',
|
||
CHG_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '변경 일시',
|
||
PRIMARY KEY (HIST_ID),
|
||
KEY IX_ACH_TRGET (TRGET_UNIQ_ID, CHG_DT),
|
||
KEY IX_ACH_CHANGER (CHANGER_UNIQ_ID, CHG_DT),
|
||
KEY IX_ACH_CHGDT (CHG_DT)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='권한 변경 이력(개인정보보호 SFR-001, 3년 이상 보관)';
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.author_workflow_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 권한 신청·승인 워크플로 + 권한이력 다운로드 이력
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SFR-001, 권한 신설·변경·회수 승인통제)
|
||
-- 개발항목 #3(신청·승인 워크플로) / #6(권한이력 조회·다운로드) - 담당: arko-privacy-authctrl (Fork A 6차)
|
||
-- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB
|
||
-- ---------------------------------------------------------------------
|
||
-- [#3] AUTHOR_CHANGE_REQUEST : 권한 변경 신청→승인/반려 워크플로.
|
||
-- 승인(A) 시 권한 반영(COMTNEMPLYRSCRTYESTBS)과 이력 적재(AUTHOR_CHANGE_HISTORY)를
|
||
-- 단일 트랜잭션으로 처리한다(egovframework.com..*Impl AOP tx advisor).
|
||
-- [#6] AUTHOR_HIST_DOWNLOAD_HISTORY : 권한이력 다운로드 증빙(사유 필수).
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS AUTHOR_CHANGE_REQUEST (
|
||
REQUEST_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '신청 일련번호(PK)',
|
||
TRGET_UNIQ_ID VARCHAR(20) NOT NULL COMMENT '권한변경 대상자 고유식별자(ESNTL_ID)',
|
||
TRGET_ID VARCHAR(20) NULL COMMENT '권한변경 대상자 계정ID(참고용)',
|
||
REQUEST_SE CHAR(1) NOT NULL COMMENT '신청구분 N:신설(부여) C:변경 R:회수',
|
||
BEFORE_AUTHOR VARCHAR(1000) NULL COMMENT '신청 시점 현재 권한(스냅샷)',
|
||
AFTER_AUTHOR VARCHAR(1000) NULL COMMENT '신청 목표 권한(코드/CSV)',
|
||
REQUEST_RESN VARCHAR(500) NOT NULL COMMENT '신청 사유(필수)',
|
||
REQSTER_ID VARCHAR(20) NOT NULL COMMENT '신청자 계정ID',
|
||
REQSTER_UNIQ_ID VARCHAR(20) NULL COMMENT '신청자 고유식별자',
|
||
REQUEST_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '신청 일시',
|
||
CONFM_STTUS CHAR(1) NOT NULL DEFAULT 'R' COMMENT '처리상태 R:신청 A:승인 J:반려',
|
||
CONFM_ID VARCHAR(20) NULL COMMENT '승인/반려 처리자 계정ID',
|
||
CONFM_UNIQ_ID VARCHAR(20) NULL COMMENT '승인/반려 처리자 고유식별자',
|
||
CONFM_DT DATETIME NULL COMMENT '승인/반려 일시',
|
||
CONFM_RESN VARCHAR(500) NULL COMMENT '반려 사유',
|
||
PRIMARY KEY (REQUEST_ID),
|
||
KEY IX_ACR_TRGET (TRGET_UNIQ_ID, REQUEST_DT),
|
||
KEY IX_ACR_STTUS (CONFM_STTUS, REQUEST_DT)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='권한 변경 신청·승인 워크플로(개인정보보호 SFR-001 #3)';
|
||
|
||
CREATE TABLE IF NOT EXISTS AUTHOR_HIST_DOWNLOAD_HISTORY (
|
||
DWLD_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '다운로드 일련번호(PK)',
|
||
DOWNLOADER_ID VARCHAR(20) NOT NULL COMMENT '다운로드자 계정ID',
|
||
DOWNLOADER_UNIQ_ID VARCHAR(20) NULL COMMENT '다운로드자 고유식별자',
|
||
DOWNLOADER_IP VARCHAR(45) NULL COMMENT '다운로드자 접속 IP(IPv6 대응)',
|
||
DWLD_RESN VARCHAR(500) NOT NULL COMMENT '다운로드 사유(필수·미입력 차단)',
|
||
SEARCH_COND VARCHAR(1000) NULL COMMENT '다운로드 시 검색조건 스냅샷',
|
||
DWLD_CNT INT NOT NULL DEFAULT 0 COMMENT '다운로드 건수',
|
||
DWLD_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '다운로드 일시',
|
||
PRIMARY KEY (DWLD_ID),
|
||
KEY IX_AHD_DWLD (DOWNLOADER_ID, DWLD_DT)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='권한이력 다운로드 증빙 이력(개인정보보호 SFR-001 #6)';
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.job_mapping_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 개인정보 처리 업무유형 매핑 테이블 : PDAL_JOB_MAPPING
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SFR-004 / SER-002)
|
||
-- 개발항목 #32 - 담당: arko-privacy-auditlog (Fork B)
|
||
-- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB
|
||
-- ---------------------------------------------------------------------
|
||
-- [목적] 접속기록 수집(#31 PersonalDataLogAspect)이 가로챈 서비스 메서드를
|
||
-- 업무코드(JOB_SE_CODE)·업무명(JOB_SE_NM)으로 매핑한다.
|
||
-- AOP pointcut 범위(개인정보 처리 서비스 패키지) 안에서 신규 화면이 추가되면
|
||
-- 이 테이블에 행만 등록하면 수집되며, Aspect/pointcut 소스 수정이 불요하다.
|
||
--
|
||
-- [매칭 규칙] Aspect가 (대상클래스 단순명, 메서드명)으로 조회.
|
||
-- - TARGET_CLASS : 서비스 impl 단순 클래스명(예: EgovMberManageServiceImpl) 또는 FQN
|
||
-- - METHOD_PTTRN : 메서드명 접두 매칭(예: 'select','insertMber') 또는 '*'(전체)
|
||
-- - DML_GUBUN : 지정 시 우선, NULL이면 메서드명 접두로 유도(insert*→I/update*→U/delete*→D/그외 S)
|
||
-- - SORT_ORDR : 다중 매칭 시 낮은 값 우선(구체 규칙을 위로)
|
||
--
|
||
-- ※ URL 패턴 기반 수집이 필요하면(서블릿 필터형) 동일 테이블에 URL_PTTRN 컬럼을 추가해 확장.
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS PDAL_JOB_MAPPING (
|
||
MAPPING_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '매핑 일련번호(PK)',
|
||
TARGET_CLASS VARCHAR(200) NOT NULL COMMENT '대상 서비스 impl 단순 클래스명 또는 FQN',
|
||
METHOD_PTTRN VARCHAR(100) NOT NULL DEFAULT '*' COMMENT '메서드명 접두 매칭(또는 * 전체)',
|
||
JOB_SE_CODE VARCHAR(30) NOT NULL COMMENT '수행업무 유형 코드',
|
||
JOB_SE_NM VARCHAR(100) NOT NULL COMMENT '수행업무 유형(화면·기능명)',
|
||
DML_GUBUN CHAR(1) NULL COMMENT '처리구분 강제값 S/I/U/D (NULL=메서드명 유도)',
|
||
SORT_ORDR INT NOT NULL DEFAULT 100 COMMENT '매칭 우선순위(낮을수록 우선)',
|
||
USE_AT CHAR(1) NOT NULL DEFAULT 'Y' COMMENT '사용여부 Y/N',
|
||
RM VARCHAR(300) NULL COMMENT '비고',
|
||
PRIMARY KEY (MAPPING_ID),
|
||
KEY IX_PJM_LOOKUP (USE_AT, TARGET_CLASS, SORT_ORDR)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='개인정보 처리 업무유형 매핑(접속기록 #31/#32)';
|
||
|
||
-- ---------------------------------------------------------------------
|
||
-- 초기 매핑 시드 : 현행 개인정보 처리 서비스(#31 pointcut 대상과 일치)
|
||
-- 신규 개인정보 화면 추가 시 아래 형식으로 행만 추가하면 수집된다.
|
||
-- ※ 시드 INSERT 본문은 PART 2 로 분리되어 있다.
|
||
-- ---------------------------------------------------------------------
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.job_mapping_audit_cols_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 업무유형 매핑 테이블 확장 : PDAL_JOB_MAPPING 에 변경자·변경일시 컬럼 추가
|
||
-- 개발항목 #32-1 (관리 화면) - 2026-08-07
|
||
-- ---------------------------------------------------------------------
|
||
-- [사유] 관리 화면에서 취급자가 매핑을 등록·수정·사용중지할 수 있게 되면
|
||
-- "누가 접속기록 분류를 바꿨는가"가 감사 대상이 된다.
|
||
-- [멱등] information_schema 존재 확인 후 ALTER (재실행 안전).
|
||
-- ★ 관리 화면 sqlMap(PrivacyJobMapping_SQL_Mysql.xml)이 이 4개 컬럼을 SELECT/INSERT 하므로
|
||
-- 소스 배포보다 이 DDL 적용이 반드시 선행돼야 한다(미적용 시 1054 Unknown column).
|
||
-- =====================================================================
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'PDAL_JOB_MAPPING' AND COLUMN_NAME = 'REGISTER_ID') > 0,
|
||
'SELECT ''SKIP: PDAL_JOB_MAPPING.REGISTER_ID already exists'' AS msg',
|
||
'ALTER TABLE PDAL_JOB_MAPPING
|
||
ADD COLUMN REGISTER_ID VARCHAR(20) NULL COMMENT ''등록자 계정ID(시드행은 NULL)'''
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'PDAL_JOB_MAPPING' AND COLUMN_NAME = 'REG_DT') > 0,
|
||
'SELECT ''SKIP: PDAL_JOB_MAPPING.REG_DT already exists'' AS msg',
|
||
'ALTER TABLE PDAL_JOB_MAPPING
|
||
ADD COLUMN REG_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ''등록 일시'''
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'PDAL_JOB_MAPPING' AND COLUMN_NAME = 'UPDUSR_ID') > 0,
|
||
'SELECT ''SKIP: PDAL_JOB_MAPPING.UPDUSR_ID already exists'' AS msg',
|
||
'ALTER TABLE PDAL_JOB_MAPPING
|
||
ADD COLUMN UPDUSR_ID VARCHAR(20) NULL COMMENT ''최종 변경자 계정ID'''
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'PDAL_JOB_MAPPING' AND COLUMN_NAME = 'UPDT_DT') > 0,
|
||
'SELECT ''SKIP: PDAL_JOB_MAPPING.UPDT_DT already exists'' AS msg',
|
||
'ALTER TABLE PDAL_JOB_MAPPING
|
||
ADD COLUMN UPDT_DT DATETIME NULL COMMENT ''최종 변경 일시'''
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.download_history_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 개인정보 접속기록 다운로드 이력 : PDAL_DOWNLOAD_HISTORY
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SFR-004 / SER-002)
|
||
-- 개발항목 #42 - 담당: arko-privacy-auditlog (Fork B)
|
||
-- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB
|
||
-- ---------------------------------------------------------------------
|
||
-- [목적] 개인정보 접속기록(PERSONAL_DATA_ACCESS_LOG) 조회결과 다운로드 시,
|
||
-- 다운로드 사유(필수)·다운로드자·일시·IP·건수를 이력으로 남긴다.
|
||
-- 사유 미입력 시 다운로드는 서비스 계층에서 차단(본 테이블 미적재).
|
||
-- [원칙] 개인정보 본문 미적재 — 다운로드 검색조건 요약(SEARCH_COND)만 보관.
|
||
-- 이 테이블은 INSERT/SELECT 만 수행(위·변조 방지, UPDATE/DELETE 미정의).
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS PDAL_DOWNLOAD_HISTORY (
|
||
DL_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '다운로드 이력 일련번호(PK)',
|
||
DOWNLOADER_ID VARCHAR(20) NOT NULL COMMENT '다운로드자 계정ID',
|
||
DOWNLOAD_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '다운로드 일시',
|
||
DOWNLOADER_IP VARCHAR(45) NULL COMMENT '다운로드자 접속 IP(IPv6 대응)',
|
||
DL_REASON VARCHAR(500) NOT NULL COMMENT '다운로드 사유(필수 — 미입력 시 차단)',
|
||
SEARCH_COND VARCHAR(1000) NULL COMMENT '다운로드 검색조건 요약(개인정보 본문 미포함)',
|
||
RESULT_CNT INT NOT NULL DEFAULT 0 COMMENT '다운로드 건수',
|
||
REG_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '등록 일시',
|
||
PRIMARY KEY (DL_ID),
|
||
KEY IX_PDDH_DT (DOWNLOAD_DT),
|
||
KEY IX_PDDH_USER (DOWNLOADER_ID, DOWNLOAD_DT)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='개인정보 접속기록 다운로드 이력(#42, SER-002)';
|
||
|
||
-- [Oracle] 시퀀스 필요:
|
||
-- CREATE SEQUENCE PDAL_DOWNLOAD_HISTORY_SEQ START WITH 1 INCREMENT BY 1 NOCACHE;
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.inspection_report_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 개인정보 접속기록 정기점검 리포트 : PDAL_INSPECTION_REPORT
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SFR-004 / SER-002)
|
||
-- 개발항목 #43 - 담당: arko-privacy-auditlog (Fork B)
|
||
-- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB
|
||
-- ---------------------------------------------------------------------
|
||
-- [목적] 월 1회 정기점검 배치가 전월분 접속기록을 집계해 1행으로 적재한다.
|
||
-- "월 1회 이상 점검 내역"을 화면 출력으로 제출(개인정보보호위 점검 대응).
|
||
--
|
||
-- [집계원] PERSONAL_DATA_ACCESS_LOG(#30) + 해시체인 무결성 검증(#40) 재사용.
|
||
-- [자리표시] 이상징후 5유형(#35)·다운로드 이력(#42)은 미구현 → 컬럼만 두고 배치가 0/요약만 적재.
|
||
-- [화면입력] INSPECTOR_ID/INSPECT_RESULT/ACTN_MATTER 는 배치가 아닌 점검자가 화면(#48)에서 입력.
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS PDAL_INSPECTION_REPORT (
|
||
RPT_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '리포트 일련번호(PK)',
|
||
RPT_YM CHAR(6) NOT NULL COMMENT '점검 대상 연월(전월, yyyyMM)',
|
||
PERIOD_FROM DATETIME NOT NULL COMMENT '집계 시작일시',
|
||
PERIOD_TO DATETIME NOT NULL COMMENT '집계 종료일시',
|
||
TOTAL_LOG_CNT INT NOT NULL DEFAULT 0 COMMENT '총 접속기록 건수',
|
||
FAIL_CNT INT NOT NULL DEFAULT 0 COMMENT '처리결과 F(실패/차단) 건수 = 이상징후 일부',
|
||
ABNORMAL_SUMMARY VARCHAR(2000) NULL COMMENT '이상징후 5유형 요약(#35 연계 전 자리표시)',
|
||
INTEGRITY_RESULT VARCHAR(20) NOT NULL DEFAULT 'OK' COMMENT '해시체인 무결성: OK / VIOLATION',
|
||
INTEGRITY_MISMATCH_ID BIGINT NULL COMMENT '최초 불일치 LOG_ID(위반 시)',
|
||
INTEGRITY_TOTAL_CNT INT NOT NULL DEFAULT 0 COMMENT '무결성 검증 대상 건수',
|
||
HANDLER_SUMMARY VARCHAR(4000) NULL COMMENT '취급자별 처리현황 요약',
|
||
DOWNLOAD_CNT INT NOT NULL DEFAULT 0 COMMENT '다운로드 이력 건수(#42 연계 전 0)',
|
||
INSPECTOR_ID VARCHAR(20) NULL COMMENT '점검자 계정ID(화면 입력, #44)',
|
||
INSPECT_RESULT VARCHAR(500) NULL COMMENT '점검결과(화면 입력, #44)',
|
||
ACTN_MATTER VARCHAR(1000) NULL COMMENT '조치사항(화면 입력, #44)',
|
||
INSPECT_DT DATETIME NULL COMMENT '점검일시(점검결과 입력 시각, #44 감사증빙)',
|
||
REG_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '리포트 생성일시',
|
||
PRIMARY KEY (RPT_ID),
|
||
UNIQUE KEY UX_PIR_YM (RPT_YM),
|
||
KEY IX_PIR_REGDT (REG_DT)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='개인정보 접속기록 정기점검 리포트(#43, 월 1회)';
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.pdal_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 개인정보 접속기록 표준 테이블 : PERSONAL_DATA_ACCESS_LOG
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SFR-004 / DBR-001 / SER-002)
|
||
-- 개발항목 #30 - 담당: arko-privacy-auditlog (Fork B)
|
||
-- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB
|
||
-- ---------------------------------------------------------------------
|
||
-- [설계 원칙] 신규 스키마 설계가 아니라 기존 표준 PERSONAL_DATA_DML_HISTORY 를
|
||
-- 표준 접속기록 테이블로 "승격" + 보관/무결성 컬럼 확장이다.
|
||
--
|
||
-- [기존 PERSONAL_DATA_DML_HISTORY → PERSONAL_DATA_ACCESS_LOG 컬럼 매핑]
|
||
-- CHG_USER_ID → CONECT_ID (① 사용자 식별자)
|
||
-- CREATE_DATE → CONECT_DT (② 접속일시, SYSDATE())
|
||
-- CHG_CONECT_IP → CONECT_IP (③ 접속지 IP) * VARCHAR(45) IPv6 대응
|
||
-- UI_GUBUN → JOB_SE_CODE/NM (④ 수행업무 유형) * 업무유형 매핑 테이블로 코드/명 분리
|
||
-- ESNTL_ID → TRGET_ID (⑤ 처리대상 식별자)
|
||
-- DML_GUBUN → DML_GUBUN (처리구분 S/I/U/D 그대로 계승)
|
||
-- CHG_USER_SE → USER_SE (처리자 구분)
|
||
-- [신규 확장 컬럼]
|
||
-- TRGET_CN - 처리대상 건수/범위 (⑤ 보강)
|
||
-- PROCESS_RESULT - 처리결과 S:성공 F:실패/차단 (비정상접근 탐지 5유형 적재 겸용)
|
||
-- HASH_VAL - 위·변조 방지 해시 (SHA-256, 개발항목 #39)
|
||
-- PREV_HASH_VAL - 직전 레코드 해시 (해시체인)
|
||
--
|
||
-- [보관·파기] 730일 보관 전제. 월 단위 RANGE COLUMNS 파티셔닝으로
|
||
-- 파기 배치가 만료 파티션을 ALTER TABLE ... DROP PARTITION 으로 제거
|
||
-- (개별 DELETE 미사용). 애플리케이션 계층에 UPDATE/DELETE statement 미정의.
|
||
-- [분리 원칙] COMTNSYSLOG 의 7일 삭제정책은 본 테이블에 절대 적용하지 않는다.
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS PERSONAL_DATA_ACCESS_LOG
|
||
(
|
||
LOG_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '로그 일련번호',
|
||
CONECT_ID VARCHAR(20) NOT NULL COMMENT '① 사용자 식별자(ID)',
|
||
CONECT_DT DATETIME NOT NULL COMMENT '② 접속일시(파티션 키)',
|
||
CONECT_IP VARCHAR(45) NOT NULL COMMENT '③ 접속지 정보(IP, IPv6 대응)',
|
||
JOB_SE_CODE VARCHAR(30) NOT NULL COMMENT '④ 수행업무 유형 코드',
|
||
JOB_SE_NM VARCHAR(100) NOT NULL COMMENT '④ 수행업무 유형 명(화면/기능명)',
|
||
TRGET_ID VARCHAR(50) NULL COMMENT '⑤ 처리대상 식별자',
|
||
TRGET_CN VARCHAR(200) NULL COMMENT '⑤ 처리대상 건수/범위',
|
||
DML_GUBUN CHAR(1) NOT NULL COMMENT '처리구분 S:조회 I:등록 U:수정 D:삭제',
|
||
PROCESS_RESULT CHAR(1) NOT NULL DEFAULT 'S' COMMENT '처리결과 S:성공 F:실패/차단',
|
||
USER_SE VARCHAR(10) NULL COMMENT '처리자 구분',
|
||
HASH_VAL VARCHAR(64) NOT NULL COMMENT '위·변조 방지 해시(SHA-256 Hex)',
|
||
PREV_HASH_VAL VARCHAR(64) NULL COMMENT '직전 레코드 해시(해시체인)',
|
||
PRIMARY KEY (LOG_ID, CONECT_DT),
|
||
KEY IDX_PDAL_01 (CONECT_ID, CONECT_DT), -- 접속자 ID 검색 (현행 CONECT_MTHD LIKE 결함 해소)
|
||
KEY IDX_PDAL_02 (CONECT_DT), -- 기간 검색 / 파티션 프루닝
|
||
KEY IDX_PDAL_03 (TRGET_ID, CONECT_DT), -- 처리대상 추적
|
||
KEY IDX_PDAL_04 (JOB_SE_CODE, CONECT_DT) -- 업무유형/이상탐지유형 집계
|
||
)
|
||
ENGINE=InnoDB DEFAULT CHARSET=utf8
|
||
COMMENT='개인정보 접속기록 표준 테이블(PERSONAL_DATA_DML_HISTORY 승격, 730일 보관)'
|
||
PARTITION BY RANGE COLUMNS(CONECT_DT)
|
||
(
|
||
-- 파티션 키(CONECT_DT)를 PK에 포함해야 RANGE COLUMNS 파티셔닝 성립 (MySQL/MariaDB 제약)
|
||
-- 월 단위 사전 생성. 유지보수 배치가 매월 다음 달 파티션을 ADD PARTITION 으로 선행 생성하고,
|
||
-- 파기 배치(월 1회)가 보관기간(기본 730일) 경과 파티션을 DROP PARTITION 으로 제거한다.
|
||
-- ※ MAXVALUE 파티션은 두지 않는다 — 만료 데이터가 catch-all 에 갇혀 DROP 불가해지는 것을 방지.
|
||
PARTITION p202607 VALUES LESS THAN ('2026-08-01'),
|
||
PARTITION p202608 VALUES LESS THAN ('2026-09-01'),
|
||
PARTITION p202609 VALUES LESS THAN ('2026-10-01'),
|
||
PARTITION p202610 VALUES LESS THAN ('2026-11-01'),
|
||
PARTITION p202611 VALUES LESS THAN ('2026-12-01'),
|
||
PARTITION p202612 VALUES LESS THAN ('2027-01-01'),
|
||
PARTITION p202701 VALUES LESS THAN ('2027-02-01'),
|
||
PARTITION p202702 VALUES LESS THAN ('2027-03-01')
|
||
)
|
||
;
|
||
|
||
-- ---------------------------------------------------------------------
|
||
-- [유지보수 참고] 월별 파티션 추가/삭제 예시 (배치가 동적으로 수행)
|
||
--
|
||
-- -- 다음 달 파티션 선행 생성
|
||
-- ALTER TABLE PERSONAL_DATA_ACCESS_LOG
|
||
-- ADD PARTITION (PARTITION p202703 VALUES LESS THAN ('2027-04-01'));
|
||
--
|
||
-- -- 보관기간(730일) 경과 파티션 파기
|
||
-- ALTER TABLE PERSONAL_DATA_ACCESS_LOG DROP PARTITION p202607;
|
||
-- ---------------------------------------------------------------------
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.pdal_purge_history_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 개인정보 접속기록 파기·증설 이력 : PDAL_PURGE_HISTORY
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SFR-004 / DBR-001)
|
||
-- 개발항목 #37 - 담당: arko-privacy-auditlog (Fork B)
|
||
-- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB
|
||
-- ---------------------------------------------------------------------
|
||
-- [목적] PERSONAL_DATA_ACCESS_LOG 의 보관정책(730일) 파기 배치가 수행한
|
||
-- 파티션 DROP(파기)·ADD(선행 증설) 내역을 증빙으로 기록한다.
|
||
-- 개인정보 접속기록의 유일한 삭제 경로가 "파티션 DROP"임을 감사에서 입증하는 근거.
|
||
--
|
||
-- [원칙] 접속기록 본문(PERSONAL_DATA_ACCESS_LOG)에는 UPDATE/DELETE 를 정의하지 않으며,
|
||
-- 파기는 개별 DELETE 가 아니라 파티션 단위 DROP 으로만 수행한다(개발항목 #37).
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS PDAL_PURGE_HISTORY
|
||
(
|
||
PURGE_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '이력 일련번호',
|
||
PARTITION_NAME VARCHAR(64) NOT NULL COMMENT '대상 파티션명(예: p202607)',
|
||
BOUNDARY_DT VARCHAR(30) NULL COMMENT '파티션 상한 경계값(LESS THAN, 예: 2026-08-01)',
|
||
PURGE_TYPE VARCHAR(10) NOT NULL COMMENT '유형 DROP:파기 ADD:선행증설',
|
||
PURGE_DT DATETIME NOT NULL COMMENT '수행 일시',
|
||
NOTE VARCHAR(300) NULL COMMENT '비고(보관기간·사유)',
|
||
PRIMARY KEY (PURGE_ID),
|
||
KEY IDX_PDAL_PURGE_01 (PURGE_DT),
|
||
KEY IDX_PDAL_PURGE_02 (PARTITION_NAME)
|
||
)
|
||
ENGINE=InnoDB DEFAULT CHARSET=utf8
|
||
COMMENT='개인정보 접속기록 파티션 파기·증설 이력(개발항목 #37, 파기 증빙)';
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.otp_device_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- OTP(2단계 인증) 비밀키 영구 저장 테이블
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SFR-003 / IAR-001, 추가 인증수단 1차 OTP)
|
||
-- 개발항목 No.18 후속 - 담당: arko-privacy-authctrl
|
||
-- 작성일: 2026-07-22 DB: MySQL 5.7/8 / MariaDB
|
||
-- ---------------------------------------------------------------------
|
||
-- [배경] OtpSecretStore 기본 구현이 InMemory(재기동 시 유실)라 이를 대체하는
|
||
-- DB 영속 저장소(DaoOtpSecretStore)가 사용하는 테이블.
|
||
-- [보안] SECRET_ENC 는 OtpSecretCipher(AES-GCM) 암호문(Base64)만 저장한다.
|
||
-- 평문 비밀키/OTP 코드는 저장하지 않는다(SER-003).
|
||
-- [키] UNIQ_ID = 개인정보취급자 고유식별자(ESNTL_ID), 취급자당 1건(PK).
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS OTP_DEVICE (
|
||
UNIQ_ID VARCHAR(20) NOT NULL COMMENT '개인정보취급자 고유식별자(ESNTL_ID, PK)',
|
||
SECRET_ENC VARCHAR(255) NOT NULL COMMENT 'OTP 비밀키 AES-GCM 암호문(Base64) - 평문 금지',
|
||
REG_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '등록(발급) 일시',
|
||
LAST_VERIFY_DT DATETIME NULL COMMENT '최종 검증 성공 일시(참고용)',
|
||
USE_CNT INT NOT NULL DEFAULT 0 COMMENT '검증 성공 누적 횟수(참고용)',
|
||
DEVICE_LABEL VARCHAR(100) NULL COMMENT '기기/계정 라벨(참고용)',
|
||
USE_YN CHAR(1) NOT NULL DEFAULT 'Y' COMMENT '사용여부 Y:사용 N:해지',
|
||
PRIMARY KEY (UNIQ_ID)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='OTP 2단계 인증 비밀키 영구 저장(개인정보보호 SFR-003 No.18)';
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.diapause_emplyr_extend_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 휴면(장기 미사용) 대상 확장 : COMTNDIAPAUSEMBER 회원유형 구분 컬럼 추가
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SFR-002, 장기 미사용 계정 관리)
|
||
-- 개발항목 #7 - 담당: arko-privacy-authctrl (Fork A)
|
||
-- 작성일: 2026-07-21 DB: MySQL 8 / MariaDB
|
||
-- ---------------------------------------------------------------------
|
||
-- [배경] 기존 휴면 대상은 일반회원(COMTNGNRLMBER)뿐이며, 휴면 테이블
|
||
-- COMTNDIAPAUSEMBER 에는 회원유형 구분 컬럼이 없다. 개인정보취급자
|
||
-- (COMTNEMPLYRINFO)를 휴면 대상에 포함(#7)하면서 일반회원 휴면/해제
|
||
-- 흐름과 혼선되지 않도록 회원유형 구분 컬럼을 신설한다.
|
||
--
|
||
-- [안전] DEFAULT 'GNR'(일반회원)로 신설 → 기존 적재 행은 자동 'GNR' 처리되어
|
||
-- 기존 selectDiapauseList(일반회원 join COMTNGNRLMBER) 흐름 무영향.
|
||
-- 취급자 휴면 행은 'EMP'로 적재하여 별도 select/notify 경로로 처리한다.
|
||
--
|
||
-- [멱등] MySQL 8 은 ADD COLUMN/INDEX IF NOT EXISTS 미지원 → information_schema 로
|
||
-- 존재를 확인해 없을 때만 실행한다(재실행 안전, MySQL 8 / MariaDB 공통).
|
||
-- =====================================================================
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'COMTNDIAPAUSEMBER' AND COLUMN_NAME = 'MBER_TY_CODE') > 0,
|
||
'SELECT ''SKIP: COMTNDIAPAUSEMBER.MBER_TY_CODE already exists'' AS msg',
|
||
'ALTER TABLE COMTNDIAPAUSEMBER
|
||
ADD COLUMN MBER_TY_CODE CHAR(3) NOT NULL DEFAULT ''GNR''
|
||
COMMENT ''회원유형 GNR:일반회원 EMP:개인정보취급자'''
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
-- 조회 성능(취급자/일반 분리 조회) 보조 인덱스
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'COMTNDIAPAUSEMBER' AND INDEX_NAME = 'IX_DIAPAUSE_MBERTY') > 0,
|
||
'SELECT ''SKIP: IX_DIAPAUSE_MBERTY already exists'' AS msg',
|
||
'ALTER TABLE COMTNDIAPAUSEMBER
|
||
ADD INDEX IX_DIAPAUSE_MBERTY (MBER_TY_CODE, DIAPAUSE_STAT)'
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.account_mng_policy_purge_useyn_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 계정 관리 정책 확장 : ACCOUNT_MNG_POLICY 에 파기 배치 사용여부 컬럼 추가
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SFR-002, 개발항목 #12)
|
||
-- 작성일: 2026-07-28
|
||
-- ---------------------------------------------------------------------
|
||
-- 파기(#12)는 되돌릴 수 없는 처리라 배치를 항상 등록해 두되 실제 수행 여부를
|
||
-- 이 플래그로 제어한다('N'이면 서비스가 즉시 0건 반환). 기본 'N'이므로 설치
|
||
-- 직후에는 아무것도 파기되지 않으며, 관리자가 계정 관리 정책 화면(#13)에서
|
||
-- '사용'으로 바꿔야 시작된다. 파기 기준일은 기존 DELETE_PRESERVE_DAY 를 사용.
|
||
--
|
||
-- ※ 신규 설치(위 PART 1 에서 ACCOUNT_MNG_POLICY 를 막 생성한 경우)에는 컬럼이
|
||
-- 없으므로 추가되고, 기존 환경 재실행 시에는 존재 확인 후 건너뛴다(재실행 안전).
|
||
-- =====================================================================
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'ACCOUNT_MNG_POLICY' AND COLUMN_NAME = 'PURGE_USE_YN') > 0,
|
||
'SELECT ''SKIP: ACCOUNT_MNG_POLICY.PURGE_USE_YN already exists'' AS msg',
|
||
'ALTER TABLE ACCOUNT_MNG_POLICY
|
||
ADD COLUMN PURGE_USE_YN CHAR(1) NOT NULL DEFAULT ''N''
|
||
COMMENT ''장기 미사용 계정 파기 배치 사용여부 Y:사용 N:미사용(#12)'''
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.account_delete_history_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 장기 미사용 계정 개인정보 파기 이력 : ACCOUNT_DELETE_HISTORY
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SFR-002, 개발항목 #12 계정 삭제 기능)
|
||
-- 작성일: 2026-07-28 DB: MySQL 8 / MariaDB
|
||
-- ---------------------------------------------------------------------
|
||
-- [목적] 휴면 확정(COMTNDIAPAUSEMBER.DIAPAUSE_STAT='P') 후 정책상 보존기간
|
||
-- (ACCOUNT_MNG_POLICY.DELETE_PRESERVE_DAY)이 경과한 계정의 개인정보를
|
||
-- 파기(마스킹)한 이력을 남긴다. 실제 파기 방식은 행 DELETE가 아니라
|
||
-- PII 컬럼 마스킹(기존 회원탈퇴 MBER_STTUS='D' 컨벤션과 동일) — 다른
|
||
-- 테이블(게시글·마일리지·활동확인 등)이 MBER_ID/EMPLYR_ID를 참조하는
|
||
-- 소프트 조인이 많아 행 자체를 지우면 그쪽이 깨지기 때문.
|
||
--
|
||
-- [보존기간] ACCOUNT_MNG_POLICY.DELETE_PRESERVE_DAY 값을 실행 시점에 그대로
|
||
-- 조회해 사용(하드코딩 없음). 이 테이블의 PRESERVE_DAY 컬럼은
|
||
-- 그 시점에 적용된 값의 스냅샷(정책이 나중에 바뀌어도 이력은 불변).
|
||
--
|
||
-- [처리량 제한] 배치가 오래 정지돼 있다가 재가동되는 날 백로그가 한꺼번에
|
||
-- 몰리는 것을 막기 위해 1회 처리건수를 상한(LIMIT 200)으로 제한.
|
||
--
|
||
-- ★ 배치(BatchScheduler.purgeExpiredAccountScheduler)는 파기가 되돌릴 수 없는
|
||
-- 처리라 기본 비활성(@Scheduled 주석) 상태다. 보존기간 확정·운영협의 후 활성화.
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS ACCOUNT_DELETE_HISTORY (
|
||
DEL_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '파기 일련번호(PK)',
|
||
MBER_ID VARCHAR(32) NOT NULL COMMENT '파기 대상 계정ID(MBER_ID/EMPLYR_ID)',
|
||
MBER_TY_CODE CHAR(3) NOT NULL COMMENT '회원유형 GNR:일반회원 EMP:개인정보취급자',
|
||
ESNTL_ID VARCHAR(20) NULL COMMENT '고유식별자(파기 시점 스냅샷, 참고용)',
|
||
DIAPAUSE_DT DATETIME NULL COMMENT '휴면 확정 기준일시(파기 판단 기준)',
|
||
PRESERVE_DAY INT NOT NULL COMMENT '파기 시점 적용된 보존기간(정책값 스냅샷, 일)',
|
||
DEL_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '파기 처리 일시',
|
||
PRIMARY KEY (DEL_ID),
|
||
KEY IX_ADH_MBER (MBER_ID),
|
||
KEY IX_ADH_DELDT (DEL_DT)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='장기 미사용 계정 개인정보 파기 이력(개인정보보호 SFR-002 #12)';
|
||
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.login_history_extend_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 인증 실패 이력 확장 : LOGIN_HISTORY (IP 기록 · 보관기간)
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SER-001, 개발항목 #22-1)
|
||
-- 작성일: 2026-08-05
|
||
-- ---------------------------------------------------------------------
|
||
-- [목적] #22 로 살아난 실패이력 적재에 ① 접속 IP ② 보존(성공 시 DELETE→소프트
|
||
-- 리셋) ③ 보관기간 정책을 추가한다. 잠금 카운트는 RESET_YN='N' 인
|
||
-- 당일 행만 세므로 계정잠금 동작은 종전과 동일하다.
|
||
--
|
||
-- ★ 이 ALTER 는 sqlmap 동반 배포 필수 ★
|
||
-- loginDAO.insertFailHistory 가 컬럼목록 없는 `VALUES(...)` 3값 INSERT 라
|
||
-- 컬럼 추가 후 ERROR 1136(Column count doesn't match)로 실패한다.
|
||
-- 컬럼 명시 INSERT 로 교체된 EgovLoginUsr_SQL_Mysql.xml 과 함께 배포할 것.
|
||
--
|
||
-- [재실행] MySQL 8 은 ADD COLUMN/KEY IF NOT EXISTS 미지원 → 항목마다 information_schema
|
||
-- 로 존재를 확인해 없을 때만 실행한다(일부만 적용된 환경도 나머지가 채워짐).
|
||
-- =====================================================================
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'LOGIN_HISTORY' AND COLUMN_NAME = 'CONECT_IP') > 0,
|
||
'SELECT ''SKIP: LOGIN_HISTORY.CONECT_IP already exists'' AS msg',
|
||
'ALTER TABLE LOGIN_HISTORY
|
||
ADD COLUMN CONECT_IP VARCHAR(45) NULL COMMENT ''접속 IP(#22-1, ClientIpResolver 취득)'''
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'LOGIN_HISTORY' AND COLUMN_NAME = 'RESET_YN') > 0,
|
||
'SELECT ''SKIP: LOGIN_HISTORY.RESET_YN already exists'' AS msg',
|
||
'ALTER TABLE LOGIN_HISTORY
|
||
ADD COLUMN RESET_YN CHAR(1) NOT NULL DEFAULT ''N''
|
||
COMMENT ''잠금카운터 리셋여부 Y:성공으로 리셋됨 N:유효(#22-1)'''
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'LOGIN_HISTORY' AND INDEX_NAME = 'IX_LOGIN_HISTORY_01') > 0,
|
||
'SELECT ''SKIP: IX_LOGIN_HISTORY_01 already exists'' AS msg',
|
||
'ALTER TABLE LOGIN_HISTORY ADD KEY IX_LOGIN_HISTORY_01 (CREATE_DATE)'
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'LOGIN_HISTORY' AND INDEX_NAME = 'IX_LOGIN_HISTORY_02') > 0,
|
||
'SELECT ''SKIP: IX_LOGIN_HISTORY_02 already exists'' AS msg',
|
||
'ALTER TABLE LOGIN_HISTORY ADD KEY IX_LOGIN_HISTORY_02 (ID, GUBUN, CREATE_DATE)'
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'ACCOUNT_MNG_POLICY' AND COLUMN_NAME = 'LOGIN_HIST_KEEP_DAY') > 0,
|
||
'SELECT ''SKIP: ACCOUNT_MNG_POLICY.LOGIN_HIST_KEEP_DAY already exists'' AS msg',
|
||
'ALTER TABLE ACCOUNT_MNG_POLICY
|
||
ADD COLUMN LOGIN_HIST_KEEP_DAY INT NOT NULL DEFAULT 730
|
||
COMMENT ''인증 실패 이력 보관기간(일, 기본 730=2년, #22-1)'''
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.conect_log_extend_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 로그인·로그아웃 접속기록 확장 : COMTNLOGINLOG + CONECT_IP_LOCATION
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SER-001 / SER-002)
|
||
-- 개발항목 62 - 관리자 로그인·로그아웃 접속기록 조회·다운로드
|
||
-- 작성일: 2026-08-07 DB: MySQL 8 / MariaDB
|
||
-- ---------------------------------------------------------------------
|
||
-- [AS-IS 실측 2026-08-07] COMTNLOGINLOG 는 이미 살아 있으나(373,959행)
|
||
-- CONECT_IP 가 전 건 NULL 이고 접속위치 컬럼이 없다. 인덱스도 PK 하나뿐.
|
||
-- 또 CONECT_ID(고유식별자) 적재값이 16자리 hex 라 회원 테이블 4종 어디와도 0건 매칭된다(실측).
|
||
-- → 접속 계정ID·사용자구분을 별도 컬럼(CONECT_ACNT_ID / CONECT_USER_SE)에 직접 적재한다.
|
||
-- ★★ sqlmap(EgovLoginLog_SQL_Mysql.xml) 동반 배포 필수 ★★
|
||
-- logInsertLoginLog 가 CONECT_LC / CONECT_ACNT_ID / CONECT_USER_SE 를 컬럼 목록에 넣도록 바뀐다.
|
||
-- DDL 없이 sqlmap 만 올리면 Unknown column 으로 접속기록 적재가 깨진다.
|
||
-- =====================================================================
|
||
|
||
SET @ddl := IF(
|
||
(SELECT CHARACTER_MAXIMUM_LENGTH FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'COMTNLOGINLOG' AND COLUMN_NAME = 'CONECT_IP') >= 45,
|
||
'SELECT ''SKIP: COMTNLOGINLOG.CONECT_IP already >= 45'' AS msg',
|
||
'ALTER TABLE COMTNLOGINLOG
|
||
MODIFY COLUMN CONECT_IP VARCHAR(45) NULL COMMENT ''접속 IP(IPv6 대응)'''
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'COMTNLOGINLOG' AND COLUMN_NAME = 'CONECT_LC') > 0,
|
||
'SELECT ''SKIP: COMTNLOGINLOG.CONECT_LC already exists'' AS msg',
|
||
'ALTER TABLE COMTNLOGINLOG
|
||
ADD COLUMN CONECT_LC VARCHAR(100) NULL COMMENT ''접속위치명(적재시점 스냅샷)'''
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'COMTNLOGINLOG' AND COLUMN_NAME = 'CONECT_ACNT_ID') > 0,
|
||
'SELECT ''SKIP: COMTNLOGINLOG.CONECT_ACNT_ID already exists'' AS msg',
|
||
'ALTER TABLE COMTNLOGINLOG
|
||
ADD COLUMN CONECT_ACNT_ID VARCHAR(20) NULL COMMENT ''접속 계정ID(로그인 ID)'''
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'COMTNLOGINLOG' AND COLUMN_NAME = 'CONECT_USER_SE') > 0,
|
||
'SELECT ''SKIP: COMTNLOGINLOG.CONECT_USER_SE already exists'' AS msg',
|
||
'ALTER TABLE COMTNLOGINLOG
|
||
ADD COLUMN CONECT_USER_SE VARCHAR(3) NULL COMMENT ''사용자구분 USR/GNR/GRO/ENT'''
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'COMTNLOGINLOG' AND INDEX_NAME = 'IX_CLG_ACNT_DT') > 0,
|
||
'SELECT ''SKIP: IX_CLG_ACNT_DT already exists'' AS msg',
|
||
'CREATE INDEX IX_CLG_ACNT_DT ON COMTNLOGINLOG (CONECT_ACNT_ID, CREAT_DT)'
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'COMTNLOGINLOG' AND INDEX_NAME = 'IX_CLG_DT') > 0,
|
||
'SELECT ''SKIP: IX_CLG_DT already exists'' AS msg',
|
||
'CREATE INDEX IX_CLG_DT ON COMTNLOGINLOG (CREAT_DT)'
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'COMTNLOGINLOG' AND INDEX_NAME = 'IX_CLG_ID_DT') > 0,
|
||
'SELECT ''SKIP: IX_CLG_ID_DT already exists'' AS msg',
|
||
'CREATE INDEX IX_CLG_ID_DT ON COMTNLOGINLOG (CONECT_ID, CREAT_DT)'
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'COMTNLOGINLOG' AND INDEX_NAME = 'IX_CLG_MTHD_DT') > 0,
|
||
'SELECT ''SKIP: IX_CLG_MTHD_DT already exists'' AS msg',
|
||
'CREATE INDEX IX_CLG_MTHD_DT ON COMTNLOGINLOG (CONECT_MTHD, CREAT_DT)'
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = DATABASE()
|
||
AND TABLE_NAME = 'COMTNLOGINLOG' AND INDEX_NAME = 'IX_CLG_LC') > 0,
|
||
'SELECT ''SKIP: IX_CLG_LC already exists'' AS msg',
|
||
'CREATE INDEX IX_CLG_LC ON COMTNLOGINLOG (CONECT_LC)'
|
||
);
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS CONECT_IP_LOCATION (
|
||
LOC_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '일련번호(PK)',
|
||
IP_CIDR VARCHAR(45) NOT NULL COMMENT 'IP 대역(CIDR 표기)',
|
||
LOC_NM VARCHAR(100) NOT NULL COMMENT '접속위치명',
|
||
LOC_SE CHAR(1) NOT NULL DEFAULT 'E' COMMENT '내외부 구분 I:내부망 E:외부',
|
||
SORT_ORDR INT NOT NULL DEFAULT 0 COMMENT '정렬순서',
|
||
USE_AT CHAR(1) NOT NULL DEFAULT 'Y' COMMENT '사용여부 Y/N',
|
||
REMARK VARCHAR(200) NULL COMMENT '비고',
|
||
REGISTER_ID VARCHAR(20) NULL COMMENT '등록자 계정ID',
|
||
REG_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '등록일시',
|
||
UPDUSR_ID VARCHAR(20) NULL COMMENT '최종 변경자 계정ID',
|
||
UPDT_DT DATETIME NULL COMMENT '최종 변경일시',
|
||
PRIMARY KEY (LOC_ID),
|
||
UNIQUE KEY UK_CIL_CIDR (IP_CIDR)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='접속위치 매핑(IP 대역 → 위치명) — 로그인·로그아웃 접속기록 62';
|
||
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.author_hist_download_job_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 권한변경 이력 CSV 비동기 다운로드 작업 : AUTHOR_HIST_DOWNLOAD_JOB
|
||
-- 문화품앗이 개인정보보호 기능개선 사업 (SFR-001 / 개발항목 6)
|
||
-- ---------------------------------------------------------------------
|
||
-- 종전 동기 다운로드는 조건 전체를 메모리에 올려 응답에 실었다. 이 테이블은
|
||
-- '다운로드 요청'을 작업으로 등록해 두고 백그라운드가 파일을 만든 뒤, 완료된 것만
|
||
-- 내려받게 하기 위한 작업 대장이다. 상태 전이: W(대기) -> R(생성중) -> S(완료) -> X(파기), 실패는 F.
|
||
-- FILE_PATH 는 반드시 웹 루트 밖(Globals.privacyDownloadPath). 파일은 암호화 저장하고
|
||
-- EXPIRE_DT 경과분은 파기 배치가 삭제한다. 내려받기 증빙은 AUTHOR_HIST_DOWNLOAD_HISTORY 가 담당.
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS AUTHOR_HIST_DOWNLOAD_JOB (
|
||
JOB_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '작업 일련번호(PK)',
|
||
REQUESTER_ID VARCHAR(20) NOT NULL COMMENT '요청자 계정ID(취급자)',
|
||
REQUESTER_IP VARCHAR(45) NULL COMMENT '요청 IP(IPv6 대응 45)',
|
||
DL_REASON VARCHAR(500) NOT NULL COMMENT '다운로드 사유(필수)',
|
||
SEARCH_COND VARCHAR(1000) NULL COMMENT '검색조건 요약(표시용)',
|
||
F_TRGET_ID VARCHAR(50) NULL COMMENT '조건: 대상자ID(계정ID 또는 고유식별자)',
|
||
F_CHANGER_ID VARCHAR(50) NULL COMMENT '조건: 변경자 계정ID',
|
||
F_CHG_SE_CODE CHAR(1) NULL COMMENT '조건: 변경구분 G/M/R',
|
||
F_FROM_DT VARCHAR(19) NULL COMMENT '조건: 기간 시작',
|
||
F_TO_DT VARCHAR(19) NULL COMMENT '조건: 기간 종료',
|
||
STATUS CHAR(1) NOT NULL DEFAULT 'W' COMMENT '상태 W:대기 R:생성중 S:완료 F:실패 X:파기',
|
||
TOTAL_CNT INT NOT NULL DEFAULT 0 COMMENT '대상 총건수',
|
||
DONE_CNT INT NOT NULL DEFAULT 0 COMMENT '기록 완료 건수(진행률)',
|
||
FILE_NM VARCHAR(200) NULL COMMENT '내려받을 때 보여줄 파일명',
|
||
FILE_PATH VARCHAR(300) NULL COMMENT '서버 저장 절대경로(웹 루트 밖, 암호화 저장)',
|
||
FILE_SIZE BIGINT NOT NULL DEFAULT 0 COMMENT '암호화 파일 크기(byte)',
|
||
ERR_MSG VARCHAR(500) NULL COMMENT '실패 사유',
|
||
DOWNLOAD_CNT INT NOT NULL DEFAULT 0 COMMENT '내려받은 횟수',
|
||
LAST_DL_DT DATETIME NULL COMMENT '마지막 내려받은 일시',
|
||
REG_DT DATETIME NOT NULL COMMENT '요청 일시',
|
||
START_DT DATETIME NULL COMMENT '생성 시작 일시',
|
||
END_DT DATETIME NULL COMMENT '생성 종료 일시',
|
||
EXPIRE_DT DATETIME NULL COMMENT '파기 예정 일시(경과 시 파일 삭제)',
|
||
PRIMARY KEY (JOB_ID),
|
||
KEY IX_AHDJ_REQUESTER (REQUESTER_ID, REG_DT),
|
||
KEY IX_AHDJ_STATUS (STATUS, REG_DT)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='권한변경 이력 CSV 비동기 다운로드 작업';
|
||
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.account_action_history_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 장기 미사용 계정 조치 이력 : ACCOUNT_ACTION_HISTORY
|
||
-- 개발항목 #11 — 미사용계정 현황 화면의 '선택 잠금 / 선택 말소' 조치 기록.
|
||
-- 잠금 '해제' 이력은 ACCOUNT_UNLOCK_HISTORY(SER-001 #24)가 담당하며 역할이 다르다.
|
||
-- 애플리케이션 계층은 INSERT 만 정의(UPDATE/DELETE statement 없음).
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS ACCOUNT_ACTION_HISTORY (
|
||
ACTION_HIST_ID BIGINT NOT NULL AUTO_INCREMENT COMMENT '조치 이력 일련번호(PK)',
|
||
TRGET_ID VARCHAR(50) NOT NULL COMMENT '조치 대상 계정 ID(EMPLYR_ID)',
|
||
TRGET_SE VARCHAR(10) NULL DEFAULT 'EMP' COMMENT '대상 회원구분(취급자 EMP)',
|
||
ACTION_TY CHAR(1) NOT NULL COMMENT '조치 유형 L:잠금(휴면확정) D:말소',
|
||
ACTION_USER_ID VARCHAR(50) NULL COMMENT '조치 처리자(관리자) ID',
|
||
ACTION_RESN VARCHAR(500) NULL COMMENT '조치 사유(화면 입력 필수)',
|
||
ACTION_IP VARCHAR(45) NULL COMMENT '조치자 접속 IP(IPv6 대응, X-Forwarded-For 보정값)',
|
||
NO_CONECT_DAY INT NULL DEFAULT 0 COMMENT '조치 시점의 미접속 일수(사후 검증용 스냅샷)',
|
||
ACTION_DT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '조치 일시',
|
||
PRIMARY KEY (ACTION_HIST_ID),
|
||
KEY IX_AAH_TRGET (TRGET_ID, ACTION_DT),
|
||
KEY IX_AAH_USER (ACTION_USER_ID, ACTION_DT),
|
||
KEY IX_AAH_DT (ACTION_DT)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='장기 미사용 계정 조치(잠금/말소) 이력(개인정보보호 SFR-002 #11)';
|
||
|
||
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- [privacy.login_lock_exempt_create_mysql.sql]
|
||
-- ─────────────────────────────────────────────────────────────
|
||
-- =====================================================================
|
||
-- 로그인 실패 계정잠금 예외 : LOGIN_LOCK_EXEMPT (화이트리스트, SER-001 24)
|
||
-- ---------------------------------------------------------------------
|
||
-- 인증 실패 5회 잠금은 userSe 구분 없이 전 계정에 적용되고, 잠금 해제 화면도
|
||
-- 관리자 로그인이 있어야 들어갈 수 있어 최고관리자가 잠기면 아무도 해제할 수 없다.
|
||
-- 이 테이블은 그 break-glass 통로다. 잠금 '판정'만 면제하며, 실패 이력(LOGIN_HISTORY)
|
||
-- 적재와 2차 인증(OTP)은 예외 계정에도 그대로 적용된다.
|
||
-- 시드 없음 — 예외 대상 ID는 관리자 화면(접근통제 정책)에서 운영팀이 직접 등록한다.
|
||
-- =====================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS LOGIN_LOCK_EXEMPT (
|
||
EXEMPT_ID VARCHAR(20) NOT NULL COMMENT '잠금 예외 대상 계정ID(COMTNEMPLYRINFO.EMPLYR_ID)',
|
||
EXEMPT_RESN VARCHAR(500) NOT NULL COMMENT '예외 등록 사유(필수 - 감사 대응)',
|
||
REG_ID VARCHAR(20) NULL COMMENT '등록한 관리자 계정ID',
|
||
REG_DT DATETIME NULL COMMENT '등록일시',
|
||
PRIMARY KEY (EXEMPT_ID)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||
COMMENT='로그인 실패 계정잠금 예외 계정(개인정보보호 SER-001 24, 최고관리자 잠김 방지)';
|
||
|
||
|
||
-- =====================================================================
|
||
-- PART 2. DML (기준/시드 데이터) ※ 멱등: NOT EXISTS 가드로 중복 적재 방지
|
||
-- 수록: PDAL_JOB_MAPPING(업무유형 매핑 13행), ACCOUNT_MNG_POLICY(기본정책 1행)
|
||
-- 미수록: OTP_DEVICE / PERSONAL_DATA_ACCESS_LOG / *_HISTORY = 런타임 적재(시드 없음)
|
||
-- =====================================================================
|
||
|
||
-- 1) PDAL_JOB_MAPPING — 개인정보 처리 업무유형 매핑(접속기록 AOP 분류 기준, 필수)
|
||
INSERT INTO PDAL_JOB_MAPPING (TARGET_CLASS, METHOD_PTTRN, JOB_SE_CODE, JOB_SE_NM, DML_GUBUN, SORT_ORDR, RM)
|
||
SELECT * FROM (
|
||
SELECT 'EgovMberManageServiceImpl' AS TARGET_CLASS, 'select' AS METHOD_PTTRN, 'MBER_VIEW' AS JOB_SE_CODE, '회원관리-조회' AS JOB_SE_NM, 'S' AS DML_GUBUN, 10 AS SORT_ORDR, '회원 개인정보 조회' AS RM UNION ALL
|
||
SELECT 'EgovMberManageServiceImpl', 'insert', 'MBER_REG', '회원관리-등록', 'I', 10, NULL UNION ALL
|
||
SELECT 'EgovMberManageServiceImpl', 'update', 'MBER_MOD', '회원관리-수정', 'U', 10, NULL UNION ALL
|
||
SELECT 'EgovMberManageServiceImpl', 'delete', 'MBER_DEL', '회원관리-삭제', 'D', 10, NULL UNION ALL
|
||
SELECT 'EgovMberManageServiceImpl', '*', 'MBER_ETC', '회원관리-기타', NULL, 90, '미분류 폴백' UNION ALL
|
||
SELECT 'EgovEntrprsManageServiceImpl', 'select', 'ENTRPRS_VIEW', '업체관리-조회', 'S', 10, '업체 담당자 개인정보 조회' UNION ALL
|
||
SELECT 'EgovEntrprsManageServiceImpl', 'insert', 'ENTRPRS_REG', '업체관리-등록', 'I', 10, NULL UNION ALL
|
||
SELECT 'EgovEntrprsManageServiceImpl', 'update', 'ENTRPRS_MOD', '업체관리-수정', 'U', 10, NULL UNION ALL
|
||
SELECT 'EgovEntrprsManageServiceImpl', 'delete', 'ENTRPRS_DEL', '업체관리-삭제', 'D', 10, NULL UNION ALL
|
||
SELECT 'EgovEntrprsManageServiceImpl', '*', 'ENTRPRS_ETC', '업체관리-기타', NULL, 90, '미분류 폴백' UNION ALL
|
||
SELECT 'MberSsnServiceImpl', '*', 'MBER_SSN', '회원 고유식별정보 처리', NULL, 20, '주민등록번호 등 고유식별정보' UNION ALL
|
||
SELECT 'BizMberMergeServiceImpl', '*', 'MBER_MERGE', '회원 통합/이관', NULL, 30, NULL UNION ALL
|
||
SELECT 'BizTalentMberManageServiceImpl', '*', 'TALENT_MBER', '재능나눔 회원관리', NULL, 30, NULL
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM PDAL_JOB_MAPPING pjm WHERE pjm.JOB_SE_CODE = seed.JOB_SE_CODE);
|
||
|
||
-- 2) ACCOUNT_MNG_POLICY — 장기 미사용 계정 관리 기본정책(단일행 POLICY_ID=1)
|
||
INSERT INTO ACCOUNT_MNG_POLICY (POLICY_ID, DORMANT_DAY, ALERT_D1, ALERT_D2, ALERT_D3, DELETE_PRESERVE_DAY, BATCH_CYCLE, UPD_ID, UPD_DT)
|
||
SELECT 1, 365, 30, 7, 0, 365, 'DAILY', 'SYSTEM', NOW()
|
||
FROM DUAL
|
||
WHERE NOT EXISTS (SELECT 1 FROM ACCOUNT_MNG_POLICY WHERE POLICY_ID = 1);
|
||
|
||
-- (부록) LOGIN_LOCK_COUNT — 기존 arko 테이블(변동분 아님). 미존재 신규 환경에서만 사용(기본 5):
|
||
-- INSERT INTO LOGIN_LOCK_COUNT (LOCK_COUNT)
|
||
-- SELECT 5 FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM LOGIN_LOCK_COUNT);
|
||
|
||
-- 3) CONECT_IP_LOCATION — 접속위치 매핑 기본 시드(개발항목 62)
|
||
-- 운영 대역(본부·전산실·지역문화원 등)은 확정 후 같은 형식으로 INSERT 만 추가한다.
|
||
-- 매칭이 없으면 소스 fallback(루프백/사설/외부)이 적용되므로 비어 있어도 동작한다.
|
||
INSERT INTO CONECT_IP_LOCATION (IP_CIDR, LOC_NM, LOC_SE, SORT_ORDR, USE_AT, REMARK, REGISTER_ID)
|
||
SELECT * FROM (
|
||
SELECT '127.0.0.0/8' AS IP_CIDR, '서버 로컬' AS LOC_NM, 'I' AS LOC_SE, 1 AS SORT_ORDR,
|
||
'Y' AS USE_AT, '루프백 — WAS 자체 호출' AS REMARK, 'SYSTEM' AS REGISTER_ID
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM CONECT_IP_LOCATION x WHERE x.IP_CIDR = seed.IP_CIDR);
|
||
|
||
INSERT INTO CONECT_IP_LOCATION (IP_CIDR, LOC_NM, LOC_SE, SORT_ORDR, USE_AT, REMARK, REGISTER_ID)
|
||
SELECT * FROM (
|
||
SELECT '10.0.0.0/8' AS IP_CIDR, '내부망' AS LOC_NM, 'I' AS LOC_SE, 2 AS SORT_ORDR, 'Y' AS USE_AT, '사설 대역 — 세부 위치는 더 긴 CIDR 로 덮어쓰기' AS REMARK, 'SYSTEM' AS REGISTER_ID
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM CONECT_IP_LOCATION x WHERE x.IP_CIDR = seed.IP_CIDR);
|
||
|
||
INSERT INTO CONECT_IP_LOCATION (IP_CIDR, LOC_NM, LOC_SE, SORT_ORDR, USE_AT, REMARK, REGISTER_ID)
|
||
SELECT * FROM (
|
||
SELECT '172.16.0.0/12' AS IP_CIDR, '내부망' AS LOC_NM, 'I' AS LOC_SE, 3 AS SORT_ORDR, 'Y' AS USE_AT, '사설 대역' AS REMARK, 'SYSTEM' AS REGISTER_ID
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM CONECT_IP_LOCATION x WHERE x.IP_CIDR = seed.IP_CIDR);
|
||
|
||
INSERT INTO CONECT_IP_LOCATION (IP_CIDR, LOC_NM, LOC_SE, SORT_ORDR, USE_AT, REMARK, REGISTER_ID)
|
||
SELECT * FROM (
|
||
SELECT '192.168.0.0/16' AS IP_CIDR, '내부망' AS LOC_NM, 'I' AS LOC_SE, 4 AS SORT_ORDR, 'Y' AS USE_AT, '사설 대역' AS REMARK, 'SYSTEM' AS REGISTER_ID
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM CONECT_IP_LOCATION x WHERE x.IP_CIDR = seed.IP_CIDR);
|
||
|
||
-- =====================================================================
|
||
-- PART 3. 관리자 메뉴 등록 DML (좌측/상단 메뉴 노출)
|
||
-- 구성: 권한관리(9100030) 하위에 순서대로 9100035~9100039 5건 등록
|
||
-- 권한 신청·승인 / 권한 변경 이력 / 미사용계정 현황 / 계정 관리 정책 / 인증 실패 이력
|
||
-- 원본: src/script/mysql/dml/privacy.menu_author_request_insert_mysql.sql
|
||
-- src/script/mysql/dml/privacy.menu_author_history_insert_mysql.sql
|
||
-- src/script/mysql/dml/privacy.menu_dormant_status_insert_mysql.sql
|
||
-- src/script/mysql/dml/privacy.menu_account_policy_insert_mysql.sql
|
||
-- (개별 파일에 화면별 배치 근거·롤백 SQL이 더 상세히 있음 — 여기서는 통합 실행용)
|
||
--
|
||
-- ★★ 이 DML만으로는 좌측메뉴에 안 뜬다 — left.jsp 수정 배포 필수 ★★
|
||
-- src/main/webapp/WEB-INF/jsp/site/mnt/left.jsp 는 메뉴번호 하드코딩 JSP라
|
||
-- 권한관리(9100030) 블록에 9100035~9100038 각각의 <c:when> 분기 +
|
||
-- 시스템관리/권한관리 상위 하이라이트 조건(param.page eq '910003x')이
|
||
-- 반드시 함께 배포돼야 렌더된다. (arko_renual 소스에는 4건 모두 이미 반영 완료 —
|
||
-- 운영 배포 시 WAR/배포본에 이 JSP가 포함됐는지만 확인하면 됨)
|
||
--
|
||
-- [재실행 안전] 모든 INSERT NOT EXISTS 가드 → 반복 실행 무해.
|
||
-- [노출권한] 4건 모두 IS_AUTHENTICATED_FULLY, ROLE_ADMIN 동일
|
||
-- [Oracle] 대상 운영 DB가 MySQL(csv)이라 Oracle 쌍 미작성
|
||
-- =====================================================================
|
||
|
||
-- ── [1] 프로그램(URL) 등록 (COMTNMENUINFO.PROGRM_FILE_NM → COMTNPROGRMLIST FK, 메뉴보다 먼저) ──
|
||
INSERT INTO COMTNPROGRMLIST (PROGRM_FILE_NM, PROGRM_STRE_PATH, PROGRM_KOREAN_NM, PROGRM_DC, URL)
|
||
SELECT * FROM (
|
||
SELECT 'AuthorRequestList' AS PROGRM_FILE_NM, '/mnt/sec/authorRequest/' AS PROGRM_STRE_PATH, '개인정보취급자 권한 관리' AS PROGRM_KOREAN_NM, '개인정보취급자 권한 관리(SFR-001 #46)' AS PROGRM_DC, '/mnt/sec/authorRequest/listView.do?page=9100035' AS URL UNION ALL
|
||
SELECT 'AuthorHistoryList', '/mnt/sec/authorHistory/', '권한변경 이력조회', '권한변경 이력조회·검색·다운로드(SFR-001 #6)', '/mnt/sec/authorHistory/listView.do?page=9100036' UNION ALL
|
||
SELECT 'DormantStatusList', '/mnt/sec/dormantStatus/', '장기 미사용 관리자 계정 현황', '장기 미사용 관리자 계정 현황 조회(SFR-002 #11)', '/mnt/sec/dormantStatus/listView.do?page=9100037' UNION ALL
|
||
SELECT 'AccountPolicySet', '/mnt/sec/accountPolicy/', '계정 관리 정책 설정', '장기 미사용 계정 관리 정책 설정(SFR-002 #13)', '/mnt/sec/accountPolicy/policyView.do?page=9100038'
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM COMTNPROGRMLIST p WHERE p.PROGRM_FILE_NM = seed.PROGRM_FILE_NM);
|
||
|
||
-- ── [2] 메뉴 등록 : 권한관리(9100030) 하위, MENU_ORDR 5~8 순서 ──
|
||
INSERT INTO COMTNMENUINFO (MENU_NM, PROGRM_FILE_NM, MENU_NO, UPPER_MENU_NO, MENU_ORDR, MENU_DC, RELATE_IMAGE_PATH, RELATE_IMAGE_NM)
|
||
SELECT * FROM (
|
||
SELECT '개인정보취급자 권한 관리' AS MENU_NM, 'AuthorRequestList' AS PROGRM_FILE_NM, 9100035 AS MENU_NO, 9100030 AS UPPER_MENU_NO, 5 AS MENU_ORDR, '개인정보취급자 권한 부여·변경·말소 현황 및 승인 처리' AS MENU_DC, '/' AS RELATE_IMAGE_PATH, '/' AS RELATE_IMAGE_NM UNION ALL
|
||
SELECT '권한변경 이력조회', 'AuthorHistoryList', 9100036, 9100030, 6, '권한변경 이력조회·검색·다운로드', '/', '/' UNION ALL
|
||
SELECT '미사용 관리자 계정 현황', 'DormantStatusList', 9100037, 9100030, 7, '장기 미사용 관리자 계정 현황 조회', '/', '/' UNION ALL
|
||
SELECT '계정 관리 정책', 'AccountPolicySet', 9100038, 9100030, 8, '장기 미사용 계정 관리 정책 설정', '/', '/'
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM COMTNMENUINFO m WHERE m.MENU_NO = seed.MENU_NO);
|
||
|
||
-- ── [2-1] 명칭 정정(2026-08-10, 재실행 안전/멱등) — 9100037 이 관리자(EMP) 전용 화면임을 명시.
|
||
-- 이미 9100037 이 위 INSERT 로 적재된 환경은 NOT EXISTS 가드 때문에 INSERT 값이
|
||
-- 반영되지 않으므로 이 UPDATE 가 실제 적용 지점이다. 한글 리터럴은 UNHEX 우회 권장
|
||
-- (python3 -c "print('미사용 관리자 계정 현황'.encode('utf-8').hex().upper())").
|
||
UPDATE COMTNMENUINFO SET MENU_NM = '미사용 관리자 계정 현황' WHERE MENU_NO = 9100037;
|
||
UPDATE COMTNPROGRMLIST SET PROGRM_KOREAN_NM = '장기 미사용 관리자 계정 현황',
|
||
PROGRM_DC = '장기 미사용 관리자 계정 현황 조회(SFR-002 #11)'
|
||
WHERE PROGRM_FILE_NM = 'DormantStatusList';
|
||
|
||
-- ── [3] 권한↔메뉴 노출 매핑 (4건 × 2권한, FK 안전) ──
|
||
INSERT INTO COMTNMENUCREATDTLS (MENU_NO, AUTHOR_CODE)
|
||
SELECT seed.menu_no, g.ac
|
||
FROM (SELECT 9100035 AS menu_no UNION ALL SELECT 9100036 UNION ALL SELECT 9100037 UNION ALL SELECT 9100038) seed
|
||
CROSS JOIN (SELECT 'IS_AUTHENTICATED_FULLY' AS ac UNION ALL SELECT 'ROLE_ADMIN') g
|
||
WHERE g.ac IN (SELECT AUTHOR_CODE FROM COMTNAUTHORINFO) -- FK 안전
|
||
AND NOT EXISTS (SELECT 1 FROM COMTNMENUCREATDTLS x
|
||
WHERE x.MENU_NO = seed.menu_no AND x.AUTHOR_CODE = g.ac);
|
||
|
||
-- ── [4] 인증 실패 이력 조회 메뉴(9100039) — SER-001 #22-1, 2026-08-05 추가 ──
|
||
-- 원본: src/script/mysql/dml/privacy.menu_login_fail_history_insert_mysql.sql
|
||
-- ★ left.jsp 9100039 <c:when> 분기 동반 배포 필수(위와 동일 제약)
|
||
INSERT INTO COMTNPROGRMLIST (PROGRM_FILE_NM, PROGRM_STRE_PATH, PROGRM_KOREAN_NM, PROGRM_DC, URL)
|
||
SELECT * FROM (
|
||
SELECT 'LoginFailHistoryList' AS PROGRM_FILE_NM, '/mnt/sec/loginFailHistory/' AS PROGRM_STRE_PATH,
|
||
'인증 실패 이력' AS PROGRM_KOREAN_NM, '로그인 인증 실패 이력 조회(SER-001 #22-1)' AS PROGRM_DC,
|
||
'/mnt/sec/loginFailHistory/listView.do?page=9100039' AS URL
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM COMTNPROGRMLIST p WHERE p.PROGRM_FILE_NM = seed.PROGRM_FILE_NM);
|
||
|
||
INSERT INTO COMTNMENUINFO (MENU_NM, PROGRM_FILE_NM, MENU_NO, UPPER_MENU_NO, MENU_ORDR, MENU_DC, RELATE_IMAGE_PATH, RELATE_IMAGE_NM)
|
||
SELECT * FROM (
|
||
SELECT '인증 실패 이력' AS MENU_NM, 'LoginFailHistoryList' AS PROGRM_FILE_NM, 9100039 AS MENU_NO,
|
||
9100030 AS UPPER_MENU_NO, 9 AS MENU_ORDR, '로그인 인증 실패 이력 조회' AS MENU_DC,
|
||
'/' AS RELATE_IMAGE_PATH, '/' AS RELATE_IMAGE_NM
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM COMTNMENUINFO m WHERE m.MENU_NO = seed.MENU_NO);
|
||
|
||
INSERT INTO COMTNMENUCREATDTLS (MENU_NO, AUTHOR_CODE)
|
||
SELECT 9100039, g.ac
|
||
FROM (SELECT 'IS_AUTHENTICATED_FULLY' AS ac UNION ALL SELECT 'ROLE_ADMIN') g
|
||
WHERE g.ac IN (SELECT AUTHOR_CODE FROM COMTNAUTHORINFO)
|
||
AND NOT EXISTS (SELECT 1 FROM COMTNMENUCREATDTLS x
|
||
WHERE x.MENU_NO = 9100039 AND x.AUTHOR_CODE = g.ac);
|
||
|
||
-- ── [5] 개인정보 접속기록 조회·다운로드 메뉴(9100044) — SFR-004 #47, 2026-08-06 추가 ──
|
||
-- 원본: src/script/mysql/dml/privacy.menu_access_log_insert_mysql.sql
|
||
-- ★ left.jsp 9100044 <c:when> 분기 + 하이라이트 조건 4곳 동반 배포 필수(위와 동일 제약)
|
||
-- ※ 9100040~9100043 은 '게시판관리' 그룹이 선점 → 미사용 번호 9100044 사용(MENU_ORDR 10)
|
||
INSERT INTO COMTNPROGRMLIST (PROGRM_FILE_NM, PROGRM_STRE_PATH, PROGRM_KOREAN_NM, PROGRM_DC, URL)
|
||
SELECT * FROM (
|
||
SELECT 'AccessLogList' AS PROGRM_FILE_NM, '/mnt/sec/accessLog/' AS PROGRM_STRE_PATH,
|
||
'개인정보 접속기록' AS PROGRM_KOREAN_NM, '개인정보 접속기록 조회·다운로드(SFR-004 #47)' AS PROGRM_DC,
|
||
'/mnt/sec/accessLog/listView.do?page=9100044' AS URL
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM COMTNPROGRMLIST p WHERE p.PROGRM_FILE_NM = seed.PROGRM_FILE_NM);
|
||
|
||
INSERT INTO COMTNMENUINFO (MENU_NM, PROGRM_FILE_NM, MENU_NO, UPPER_MENU_NO, MENU_ORDR, MENU_DC, RELATE_IMAGE_PATH, RELATE_IMAGE_NM)
|
||
SELECT * FROM (
|
||
SELECT '개인정보 접속기록' AS MENU_NM, 'AccessLogList' AS PROGRM_FILE_NM, 9100044 AS MENU_NO,
|
||
9100030 AS UPPER_MENU_NO, 10 AS MENU_ORDR, '개인정보 접속기록 조회·다운로드' AS MENU_DC,
|
||
'/' AS RELATE_IMAGE_PATH, '/' AS RELATE_IMAGE_NM
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM COMTNMENUINFO m WHERE m.MENU_NO = seed.MENU_NO);
|
||
|
||
INSERT INTO COMTNMENUCREATDTLS (MENU_NO, AUTHOR_CODE)
|
||
SELECT 9100044, g.ac
|
||
FROM (SELECT 'IS_AUTHENTICATED_FULLY' AS ac UNION ALL SELECT 'ROLE_ADMIN') g
|
||
WHERE g.ac IN (SELECT AUTHOR_CODE FROM COMTNAUTHORINFO)
|
||
AND NOT EXISTS (SELECT 1 FROM COMTNMENUCREATDTLS x
|
||
WHERE x.MENU_NO = 9100044 AND x.AUTHOR_CODE = g.ac);
|
||
|
||
-- ── [6] 업무유형 매핑 관리 메뉴(9100045) — SFR-004 #32-1, 2026-08-07 추가 ──
|
||
-- 원본: src/script/mysql/dml/privacy.menu_job_mapping_insert_mysql.sql
|
||
-- ★ left.jsp 9100045 <c:when> 분기 + 하이라이트 조건 4곳 동반 배포 필수(위와 동일 제약)
|
||
-- ※ 접속기록(9100044)의 '수행업무' 분류 기준을 편집하는 화면이라 바로 다음(MENU_ORDR 11)에 배치
|
||
INSERT INTO COMTNPROGRMLIST (PROGRM_FILE_NM, PROGRM_STRE_PATH, PROGRM_KOREAN_NM, PROGRM_DC, URL)
|
||
SELECT * FROM (
|
||
SELECT 'JobMappingList' AS PROGRM_FILE_NM, '/mnt/sec/jobMapping/' AS PROGRM_STRE_PATH,
|
||
'업무유형 매핑 관리' AS PROGRM_KOREAN_NM, '개인정보 접속기록 업무유형 매핑 관리(SFR-004 #32-1)' AS PROGRM_DC,
|
||
'/mnt/sec/jobMapping/listView.do?page=9100045' AS URL
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM COMTNPROGRMLIST p WHERE p.PROGRM_FILE_NM = seed.PROGRM_FILE_NM);
|
||
|
||
INSERT INTO COMTNMENUINFO (MENU_NM, PROGRM_FILE_NM, MENU_NO, UPPER_MENU_NO, MENU_ORDR, MENU_DC, RELATE_IMAGE_PATH, RELATE_IMAGE_NM)
|
||
SELECT * FROM (
|
||
SELECT '업무유형 매핑 관리' AS MENU_NM, 'JobMappingList' AS PROGRM_FILE_NM, 9100045 AS MENU_NO,
|
||
9100030 AS UPPER_MENU_NO, 11 AS MENU_ORDR, '접속기록 업무유형 매핑 등록·수정' AS MENU_DC,
|
||
'/' AS RELATE_IMAGE_PATH, '/' AS RELATE_IMAGE_NM
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM COMTNMENUINFO m WHERE m.MENU_NO = seed.MENU_NO);
|
||
|
||
INSERT INTO COMTNMENUCREATDTLS (MENU_NO, AUTHOR_CODE)
|
||
SELECT 9100045, g.ac
|
||
FROM (SELECT 'IS_AUTHENTICATED_FULLY' AS ac UNION ALL SELECT 'ROLE_ADMIN') g
|
||
WHERE g.ac IN (SELECT AUTHOR_CODE FROM COMTNAUTHORINFO)
|
||
AND NOT EXISTS (SELECT 1 FROM COMTNMENUCREATDTLS x
|
||
WHERE x.MENU_NO = 9100045 AND x.AUTHOR_CODE = g.ac);
|
||
|
||
-- ── [7] 로그인·로그아웃 접속기록 메뉴(9100046) — 개발항목 62, 2026-08-07 추가 ──
|
||
-- 원본: src/script/mysql/dml/privacy.menu_conect_log_insert_mysql.sql
|
||
-- ★ left.jsp 9100046 <c:when> 분기 + 하이라이트 조건 4곳 동반 배포 필수(위와 동일 제약)
|
||
-- ※ 인증 실패 이력(9100039)·개인정보 접속기록(9100044)과 같은 보안 로그 묶음(MENU_ORDR 12)
|
||
INSERT INTO COMTNPROGRMLIST (PROGRM_FILE_NM, PROGRM_STRE_PATH, PROGRM_KOREAN_NM, PROGRM_DC, URL)
|
||
SELECT * FROM (
|
||
SELECT 'ConectLogList' AS PROGRM_FILE_NM, '/mnt/sec/conectLog/' AS PROGRM_STRE_PATH,
|
||
'로그인 접속기록' AS PROGRM_KOREAN_NM,
|
||
'로그인·로그아웃 접속기록 조회·다운로드(접속ID·접속일시·IP·접속위치, 개발항목 62)' AS PROGRM_DC,
|
||
'/mnt/sec/conectLog/listView.do?page=9100046' AS URL
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM COMTNPROGRMLIST p WHERE p.PROGRM_FILE_NM = seed.PROGRM_FILE_NM);
|
||
|
||
INSERT INTO COMTNMENUINFO (MENU_NM, PROGRM_FILE_NM, MENU_NO, UPPER_MENU_NO, MENU_ORDR, MENU_DC, RELATE_IMAGE_PATH, RELATE_IMAGE_NM)
|
||
SELECT * FROM (
|
||
SELECT '로그인 접속기록' AS MENU_NM, 'ConectLogList' AS PROGRM_FILE_NM, 9100046 AS MENU_NO,
|
||
9100030 AS UPPER_MENU_NO, 12 AS MENU_ORDR, '로그인·로그아웃 접속기록 조회' AS MENU_DC,
|
||
'/' AS RELATE_IMAGE_PATH, '/' AS RELATE_IMAGE_NM
|
||
) seed
|
||
WHERE NOT EXISTS (SELECT 1 FROM COMTNMENUINFO m WHERE m.MENU_NO = seed.MENU_NO);
|
||
|
||
INSERT INTO COMTNMENUCREATDTLS (MENU_NO, AUTHOR_CODE)
|
||
SELECT 9100046, g.ac
|
||
FROM (SELECT 'IS_AUTHENTICATED_FULLY' AS ac UNION ALL SELECT 'ROLE_ADMIN') g
|
||
WHERE g.ac IN (SELECT AUTHOR_CODE FROM COMTNAUTHORINFO)
|
||
AND NOT EXISTS (SELECT 1 FROM COMTNMENUCREATDTLS x
|
||
WHERE x.MENU_NO = 9100046 AND x.AUTHOR_CODE = g.ac);
|
||
|
||
-- ── [검증] ──
|
||
-- SELECT m.MENU_NO,m.UPPER_MENU_NO,m.MENU_NM,m.MENU_ORDR,p.URL,
|
||
-- (SELECT COUNT(*) FROM COMTNMENUCREATDTLS d WHERE d.MENU_NO=m.MENU_NO) grants
|
||
-- FROM COMTNMENUINFO m JOIN COMTNPROGRMLIST p ON m.PROGRM_FILE_NM=p.PROGRM_FILE_NM
|
||
-- WHERE m.MENU_NO IN (9100035,9100036,9100037,9100038,9100039,9100044,9100045,9100046) ORDER BY m.MENU_ORDR;
|
||
|
||
-- ── [롤백] (역순 권장, 4건 일괄) ──
|
||
-- DELETE FROM COMTNMENUCREATDTLS WHERE MENU_NO BETWEEN 9100035 AND 9100038;
|
||
-- DELETE FROM COMTNMENUINFO WHERE MENU_NO BETWEEN 9100035 AND 9100038;
|
||
-- DELETE FROM COMTNPROGRMLIST WHERE PROGRM_FILE_NM IN
|
||
-- ('AuthorRequestList','AuthorHistoryList','DormantStatusList','AccountPolicySet');
|
||
|
||
-- ############################## END ##############################
|