From 57ac2b0b3bad6b7c8cf0285002e8aa7d031a680f Mon Sep 17 00:00:00 2001 From: chym1217 Date: Thu, 9 Jul 2026 18:21:55 +0900 Subject: [PATCH] =?UTF-8?q?feat(verification=5Fkginicis):=20=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=EB=B8=8C=20MID=20=EC=9E=90=EB=8F=99=EC=99=84=EC=84=B1?= =?UTF-8?q?=20=EB=B0=A9=EC=A7=80=20+=20SRB=20=ED=94=84=EB=A6=AC=ED=94=BD?= =?UTF-8?q?=EC=8A=A4=20=EC=A0=84=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 라이브 자격증명 입력칸 브라우저 자동완성 자동 채움 차단 (live_mid: one-time-code / live_api_key: new-password — 크롬이 autoComplete=off 를 무시함을 실측 후 강화) - 라이브 가맹점 MID 프리픽스를 이니시스 정책 변경에 맞춰 SRA→SRB 전환. 런타임 프리픽스를 InicisIdentityProvider::LIVE_MID_PREFIX 상수로 추출, 표시 문자열(라벨·Span·힌트 ko/en/ja)은 값 교체. - 설정 저장 테스트가 실제 스토리지 설정 파일을 오염시키던 결함 격리 (PluginTestCase 에서 plugins 디스크를 테스트 전용 경로로 격리) - 설정 화면 배너 아이콘 크기 시맨틱 정정 (w-N h-N → text-*, 정렬 회귀 해결) - 프리픽스 상수 ↔ 표시 문자열 정합 audit 룰 추가 (이중관리 불일치 차단) --- .../CHANGELOG.md | 6 + .../backend/ja/messages.php | 2 +- .../frontend/ja.json | 2 +- .../language-pack.json | 2 +- .../CHANGELOG.md | 10 ++ .../composer.json | 2 +- .../lang/en/messages.php | 4 +- .../lang/ko/messages.php | 4 +- .../package.json | 2 +- .../sirsoft-verification_kginicis/plugin.json | 2 +- .../layouts/pluginSettingsLiveMid.test.tsx | 76 ++++++++++ .../resources/lang/en.json | 2 +- .../resources/lang/ko.json | 2 +- .../layouts/admin/plugin_settings.json | 11 +- .../src/Identity/InicisIdentityProvider.php | 25 +++- .../ValidateInicisSettingsListener.php | 2 +- .../InicisLiveModeSettingsValidationTest.php | 9 +- .../tests/PluginTestCase.php | 55 +++++++ .../InicisIdentityProviderWithConfigTest.php | 4 +- .../Unit/Identity/InicisLiveMidPrefixTest.php | 139 ++++++++++++++++++ .../live-mode-settings-validation.yaml | 2 +- 21 files changed, 331 insertions(+), 32 deletions(-) create mode 100644 plugins/_bundled/sirsoft-verification_kginicis/resources/js/__tests__/layouts/pluginSettingsLiveMid.test.tsx create mode 100644 plugins/_bundled/sirsoft-verification_kginicis/tests/Unit/Identity/InicisLiveMidPrefixTest.php diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/CHANGELOG.md b/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/CHANGELOG.md index f956069a..6f5dccdf 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/CHANGELOG.md +++ b/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/CHANGELOG.md @@ -4,6 +4,12 @@ 형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며, [Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다. +## [1.0.1] - 2026-07-09 + +### Changed + +- 라이브 가맹점 MID 프리픽스 표기를 이니시스 정책 변경에 맞춰 SRB 로 갱신했습니다 (라이브 MID 라벨·입력 안내 문구). + ## [1.0.0] - 2026-07-01 ### Added diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/backend/ja/messages.php b/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/backend/ja/messages.php index 696cd478..ea66ea55 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/backend/ja/messages.php +++ b/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/backend/ja/messages.php @@ -8,7 +8,7 @@ return [ ], 'settings' => [ 'test_mode' => 'テストモード', - 'live_mid' => 'ライブMID(SRAプレフィックス)', + 'live_mid' => 'ライブMID(SRBプレフィックス)', 'live_api_key' => 'ライブAPIキー', 'duplicate_field' => '同一人識別基準', 'duplicate_block_enabled' => [ diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/frontend/ja.json b/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/frontend/ja.json index ae72d36a..28f7717e 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/frontend/ja.json +++ b/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/frontend/ja.json @@ -14,7 +14,7 @@ "live_mode_warning_body": "ライブモードは実際の加盟店MIDで本人認証を実行します。ライブMIDとAPIキーを入力してから運用してください。", "section_live_keys": "ライブ資格情報", "live_mid": "ライブMID", - "live_mid_hint": "イニシスライブ加盟店MIDはSRAで始まります (例:SRA1234567)。運用モード使用前に必須入力です。", + "live_mid_hint": "イニシスライブ加盟店MIDはSRBで始まります (例:SRB1234567)。運用モード使用前に必須入力です。", "live_api_key": "ライブAPIキー", "section": { "duplicate_field": "同一人識別" diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/language-pack.json b/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/language-pack.json index 24c9503a..8516a335 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/language-pack.json +++ b/lang-packs/_bundled/g7-plugin-sirsoft-verification_kginicis-ja/language-pack.json @@ -12,7 +12,7 @@ "en": "G7 plugin (sirsoft-verification_kginicis) Japanese language pack (bundled)", "ja": "G7 プラグイン (sirsoft-verification_kginicis) 日本語 言語パック(バンドル)" }, - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "scope": "plugin", "target_identifier": "sirsoft-verification_kginicis", diff --git a/plugins/_bundled/sirsoft-verification_kginicis/CHANGELOG.md b/plugins/_bundled/sirsoft-verification_kginicis/CHANGELOG.md index 29dbb21e..da0a374b 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/CHANGELOG.md +++ b/plugins/_bundled/sirsoft-verification_kginicis/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this plugin will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## [1.0.1] - 2026-07-09 + +### Changed + +- 라이브 가맹점 MID 프리픽스를 이니시스 정책 변경에 맞춰 SRB 로 갱신했습니다 (설정 화면 고정 프리픽스 표시·입력 안내 문구 포함). + +### Fixed + +- 라이브 자격증명 입력칸(라이브 MID·라이브 API 키)에 브라우저 자동완성으로 계정 이메일 등 의도치 않은 값이 자동으로 채워지던 문제를 수정했습니다. 잘못 채워진 값이 저장되어 라이브 본인인증이 실패하는 상황을 방지합니다. + ## [1.0.0] - 2026-07-01 ### Changed diff --git a/plugins/_bundled/sirsoft-verification_kginicis/composer.json b/plugins/_bundled/sirsoft-verification_kginicis/composer.json index 50e9ba1d..68ee5576 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/composer.json +++ b/plugins/_bundled/sirsoft-verification_kginicis/composer.json @@ -1,7 +1,7 @@ { "name": "plugins/sirsoft-verification_kginicis", "description": "KG Inicis Identity Verification provider for G7", - "version": "1.0.0", + "version": "1.0.1", "type": "library", "authors": [ { diff --git a/plugins/_bundled/sirsoft-verification_kginicis/lang/en/messages.php b/plugins/_bundled/sirsoft-verification_kginicis/lang/en/messages.php index 0edb6eea..cf147e51 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/lang/en/messages.php +++ b/plugins/_bundled/sirsoft-verification_kginicis/lang/en/messages.php @@ -12,9 +12,9 @@ return [ 'settings' => [ 'test_mode' => 'Test Mode', - 'live_mid' => 'Live MID (SRA prefix)', + 'live_mid' => 'Live MID (SRB prefix)', 'live_api_key' => 'Live API Key', - // Short field labels for validation error messages (without "(SRA prefix)" hint). + // Short field labels for validation error messages (without "(SRB prefix)" hint). 'live_mid_attribute' => 'Live MID', 'live_api_key_attribute' => 'Live API Key', 'duplicate_field' => 'Duplicate Identifier', diff --git a/plugins/_bundled/sirsoft-verification_kginicis/lang/ko/messages.php b/plugins/_bundled/sirsoft-verification_kginicis/lang/ko/messages.php index cee1c6bd..b0b27047 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/lang/ko/messages.php +++ b/plugins/_bundled/sirsoft-verification_kginicis/lang/ko/messages.php @@ -12,9 +12,9 @@ return [ 'settings' => [ 'test_mode' => '테스트 모드', - 'live_mid' => '라이브 MID (SRA 프리픽스)', + 'live_mid' => '라이브 MID (SRB 프리픽스)', 'live_api_key' => '라이브 API 키', - // 검증 에러 메시지의 필드 이름용 짧은 라벨 (화면 라벨의 부가 설명 "(SRA 프리픽스)" 제외) + // 검증 에러 메시지의 필드 이름용 짧은 라벨 (화면 라벨의 부가 설명 "(SRB 프리픽스)" 제외) 'live_mid_attribute' => '라이브 MID', 'live_api_key_attribute' => '라이브 API 키', 'duplicate_field' => '동일인 식별 기준', diff --git a/plugins/_bundled/sirsoft-verification_kginicis/package.json b/plugins/_bundled/sirsoft-verification_kginicis/package.json index c5fae8c9..4a8c6579 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/package.json +++ b/plugins/_bundled/sirsoft-verification_kginicis/package.json @@ -1,6 +1,6 @@ { "name": "@g7/sirsoft-verification_kginicis", - "version": "1.0.0", + "version": "1.0.1", "type": "module", "private": true, "scripts": { diff --git a/plugins/_bundled/sirsoft-verification_kginicis/plugin.json b/plugins/_bundled/sirsoft-verification_kginicis/plugin.json index 2742febf..e52cc5cb 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/plugin.json +++ b/plugins/_bundled/sirsoft-verification_kginicis/plugin.json @@ -5,7 +5,7 @@ "ko": "KG이니시스 본인인증", "en": "KG Inicis Identity Verification" }, - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "description": { "ko": "KG이니시스 통합인증의 본인확인(reqSvcCd=03)을 G7 코어 IDV 인프라에 Provider 로 등록하는 플러그인", diff --git a/plugins/_bundled/sirsoft-verification_kginicis/resources/js/__tests__/layouts/pluginSettingsLiveMid.test.tsx b/plugins/_bundled/sirsoft-verification_kginicis/resources/js/__tests__/layouts/pluginSettingsLiveMid.test.tsx new file mode 100644 index 00000000..2c658887 --- /dev/null +++ b/plugins/_bundled/sirsoft-verification_kginicis/resources/js/__tests__/layouts/pluginSettingsLiveMid.test.tsx @@ -0,0 +1,76 @@ +/** + * @file pluginSettingsLiveMid.test.tsx + * @description sirsoft-verification_kginicis 플러그인 환경설정 라이브 MID 입력칸 회귀 테스트 (#458) + * + * 작업 A — 라이브 MID 입력칸(live_mid)에 autoComplete="off" 가 적용되어 브라우저 자동완성 + * (계정 이메일 등)이 채워지지 않도록 한다. + * 작업 B — 라이브 MID 고정 프리픽스 Span 이 이니시스 정책 변경값 SRB 로 표시된다. + */ + +import { describe, it, expect } from 'vitest'; +import pluginSettingsLayout from '../../../layouts/admin/plugin_settings.json'; + +/** 레이아웃 트리에서 props.name 이 일치하는 첫 노드를 찾는다. */ +function findByPropName(node: unknown, name: string): Record | undefined { + if (!node || typeof node !== 'object') { + return undefined; + } + const value = node as Record; + const props = (value.props ?? {}) as Record; + if (props.name === name) { + return value; + } + for (const child of Object.values(value)) { + const found = findByPropName(child, name); + if (found) { + return found; + } + } + return undefined; +} + +/** 레이아웃 트리에서 text 가 일치하는 첫 노드를 찾는다. */ +function findByText(node: unknown, text: string): Record | undefined { + if (!node || typeof node !== 'object') { + return undefined; + } + const value = node as Record; + if (value.text === text) { + return value; + } + for (const child of Object.values(value)) { + const found = findByText(child, text); + if (found) { + return found; + } + } + return undefined; +} + +describe('plugin_settings 라이브 MID 입력칸 (#458)', () => { + it('live_mid input 에 autoComplete="one-time-code" 가 적용되어 있어야 한다 (크롬 autofill/제안 차단)', () => { + // 크롬은 autoComplete="off" 를 무시하고 저장된 계정(이메일)을 채운다. live_mid 는 비밀번호가 + // 아닌 일반 텍스트 MID 칸이므로, autofill/제안을 차단하되 "비밀번호 생성" 제안이 뜨지 않는 + // one-time-code 토큰을 사용한다 (new-password 는 live_api_key 처럼 실제 비번 칸에만) (#458). + const liveMid = findByPropName(pluginSettingsLayout, 'live_mid'); + expect(liveMid).toBeDefined(); + + const props = (liveMid?.props ?? {}) as Record; + expect(props.autoComplete).toBe('one-time-code'); + }); + + it('live_api_key input 에 autoComplete="new-password" 가 적용되어 있어야 한다 (저장 비번 autofill 차단)', () => { + // live_api_key 는 실제 새 API 키(비밀번호 성격) 입력칸이므로 의미상으로도 정확한 new-password 사용. + const liveApiKey = findByPropName(pluginSettingsLayout, 'live_api_key'); + expect(liveApiKey).toBeDefined(); + + const props = (liveApiKey?.props ?? {}) as Record; + expect(props.autoComplete).toBe('new-password'); + }); + + it('라이브 MID 고정 프리픽스 Span 이 SRB 로 표시되어야 한다', () => { + // 정책 전환 후 SRA 는 존재하지 않아야 한다. + expect(findByText(pluginSettingsLayout, 'SRA')).toBeUndefined(); + expect(findByText(pluginSettingsLayout, 'SRB')).toBeDefined(); + }); +}); diff --git a/plugins/_bundled/sirsoft-verification_kginicis/resources/lang/en.json b/plugins/_bundled/sirsoft-verification_kginicis/resources/lang/en.json index e80e5c45..bdc4a5c3 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/resources/lang/en.json +++ b/plugins/_bundled/sirsoft-verification_kginicis/resources/lang/en.json @@ -20,7 +20,7 @@ "live_mode_warning_body": "Live mode performs verification with your real merchant MID. Enter your Live MID and API key before going live.", "section_live_keys": "Live Credentials", "live_mid": "Live MID", - "live_mid_hint": "Inicis live merchant MIDs start with SRA (e.g., SRA1234567). Required before switching to Live mode.", + "live_mid_hint": "Inicis live merchant MIDs start with SRB (e.g., SRB1234567). Required before switching to Live mode.", "live_api_key": "Live API Key", "section": { "duplicate_field": "Duplicate Check Basis" diff --git a/plugins/_bundled/sirsoft-verification_kginicis/resources/lang/ko.json b/plugins/_bundled/sirsoft-verification_kginicis/resources/lang/ko.json index 20504249..fad2be1b 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/resources/lang/ko.json +++ b/plugins/_bundled/sirsoft-verification_kginicis/resources/lang/ko.json @@ -20,7 +20,7 @@ "live_mode_warning_body": "라이브 모드는 실제 가맹점 MID 로 본인인증을 수행합니다. 라이브 MID 와 API 키를 입력한 뒤 운영하세요.", "section_live_keys": "라이브 자격증명", "live_mid": "라이브 MID", - "live_mid_hint": "이니시스 라이브 가맹점 MID 는 SRA 로 시작합니다 (예: SRA1234567). 운영 모드 사용 전 필수 입력.", + "live_mid_hint": "이니시스 라이브 가맹점 MID 는 SRB 로 시작합니다 (예: SRB1234567). 운영 모드 사용 전 필수 입력.", "live_api_key": "라이브 API 키", "section": { "duplicate_field": "동일인 식별" diff --git a/plugins/_bundled/sirsoft-verification_kginicis/resources/layouts/admin/plugin_settings.json b/plugins/_bundled/sirsoft-verification_kginicis/resources/layouts/admin/plugin_settings.json index 3ef449dd..ebc1f22e 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/resources/layouts/admin/plugin_settings.json +++ b/plugins/_bundled/sirsoft-verification_kginicis/resources/layouts/admin/plugin_settings.json @@ -63,7 +63,7 @@ "name": "Icon", "props": { "name": "circle-info", - "className": "w-5 h-5 text-blue-600 dark:text-blue-400 flex-shrink-0 mt-0.5" + "className": "text-xl text-blue-600 dark:text-blue-400 flex-shrink-0 mt-0.5" } }, { @@ -98,7 +98,7 @@ "name": "Icon", "props": { "name": "triangle-exclamation", - "className": "w-5 h-5 text-red-600 dark:text-red-400 flex-shrink-0 mt-0.5" + "className": "text-xl text-red-600 dark:text-red-400 flex-shrink-0 mt-0.5" } }, { @@ -203,7 +203,7 @@ "name": "Icon", "props": { "name": "triangle-exclamation", - "className": "w-5 h-5 text-amber-600 dark:text-amber-400 flex-shrink-0 mt-0.5" + "className": "text-xl text-amber-600 dark:text-amber-400 flex-shrink-0 mt-0.5" } }, { @@ -297,7 +297,7 @@ "props": { "className": "inline-flex items-center px-3 bg-gray-100 dark:bg-gray-600 border-r border-gray-300 dark:border-gray-600 text-body font-mono font-bold select-none" }, - "text": "SRA" + "text": "SRB" }, { "type": "basic", @@ -305,6 +305,7 @@ "props": { "type": "text", "name": "live_mid", + "autoComplete": "one-time-code", "placeholder": "1234567", "className": "flex-1 font-mono outline-none border-0" } @@ -353,7 +354,7 @@ "props": { "type": "password", "name": "live_api_key", - "autoComplete": "off", + "autoComplete": "new-password", "placeholder": "••••••••••••••••", "className": "{{_local.errors?.live_api_key ? 'dark:focus:ring-red-400 font-mono border border-red-500 dark:border-red-500 focus:ring-red-500' : 'dark:focus:ring-blue-400 focus:border-transparent font-mono'}}" } diff --git a/plugins/_bundled/sirsoft-verification_kginicis/src/Identity/InicisIdentityProvider.php b/plugins/_bundled/sirsoft-verification_kginicis/src/Identity/InicisIdentityProvider.php index 414986ec..4234556f 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/src/Identity/InicisIdentityProvider.php +++ b/plugins/_bundled/sirsoft-verification_kginicis/src/Identity/InicisIdentityProvider.php @@ -36,6 +36,15 @@ class InicisIdentityProvider implements IdentityVerificationInterface /** Provider 식별자 (코어 표준) */ public const PROVIDER_ID = 'inicis'; + /** + * 라이브 가맹점 MID 프리픽스 (이니시스 정책값). + * + * 라이브 MID = 이 프리픽스 + 운영자 입력값 (예: SRB1234567). + * 이니시스 프리픽스 정책 변경 시 이 상수 1곳만 갱신하면 런타임 로직 전체에 반영된다. + * (UI Span·언어팩 힌트 같은 정적 표시 문자열은 상수 참조가 불가하므로 값만 함께 교체) + */ + public const LIVE_MID_PREFIX = 'SRB'; + /** * 성인인증 purpose 키 (Plugin::getIdentityPurposes 선언값과 동일 — 단일 출처). * @@ -143,7 +152,7 @@ class InicisIdentityProvider implements IdentityVerificationInterface } /** - * 운영 가능 여부 — 모드별 MID/API key + 라이브 모드의 SRA 프리픽스 검증. + * 운영 가능 여부 — 모드별 MID/API key + 라이브 모드의 프리픽스 검증. * * @return bool */ @@ -157,7 +166,7 @@ class InicisIdentityProvider implements IdentityVerificationInterface return $liveMid !== '' && ! empty($this->config['live_api_key']) - && str_starts_with($liveMid, 'SRA'); + && str_starts_with($liveMid, self::LIVE_MID_PREFIX); } /** @@ -500,7 +509,7 @@ class InicisIdentityProvider implements IdentityVerificationInterface 'default' => 'TGdxb2l3enJDWFRTbTgvREU3MGYwUT09', ], 'live_mid' => [ - 'label' => 'Live MID (SRA prefix)', + 'label' => 'Live MID (SRB prefix)', 'type' => 'text', 'default' => '', ], @@ -568,13 +577,13 @@ class InicisIdentityProvider implements IdentityVerificationInterface } /** - * 라이브 MID 에 SRA 프리픽스를 보장한다. + * 라이브 MID 에 프리픽스(self::LIVE_MID_PREFIX)를 보장한다. * - * 운영자가 settings UI 에서 SRA 분리형 input 으로 입력하므로 일반적으로 SRA 미포함 값이 - * 들어오지만, 직접 SRA 포함하여 입력한 경우에도 안전하게 처리한다. + * 운영자가 settings UI 에서 프리픽스 분리형 input 으로 입력하므로 일반적으로 프리픽스 + * 미포함 값이 들어오지만, 직접 프리픽스를 포함하여 입력한 경우에도 안전하게 처리한다. * * @param string $value 운영자 입력 값 - * @return string SRA 가 보장된 라이브 MID + * @return string 프리픽스가 보장된 라이브 MID */ protected function buildLiveMid(string $value): string { @@ -583,7 +592,7 @@ class InicisIdentityProvider implements IdentityVerificationInterface return ''; } - return str_starts_with($value, 'SRA') ? $value : 'SRA'.$value; + return str_starts_with($value, self::LIVE_MID_PREFIX) ? $value : self::LIVE_MID_PREFIX.$value; } /** diff --git a/plugins/_bundled/sirsoft-verification_kginicis/src/Listeners/ValidateInicisSettingsListener.php b/plugins/_bundled/sirsoft-verification_kginicis/src/Listeners/ValidateInicisSettingsListener.php index 2e3fa92d..5deca61a 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/src/Listeners/ValidateInicisSettingsListener.php +++ b/plugins/_bundled/sirsoft-verification_kginicis/src/Listeners/ValidateInicisSettingsListener.php @@ -14,7 +14,7 @@ use Illuminate\Support\Facades\Lang; * 자격증명에 required 규칙을 동적 부여한다. * * 검증 기준은 InicisIdentityProvider::isAvailable() 의 라이브 운영 가능 조건 - * (live_mid 비어있지 않음 + live_api_key 비어있지 않음) 과 일치시킨다. live_mid 의 SRA + * (live_mid 비어있지 않음 + live_api_key 비어있지 않음) 과 일치시킨다. live_mid 의 SRB * 프리픽스는 buildLiveMid() 가 자동 부착하므로 별도 형식 검증은 두지 않는다. * * @since 1.0.0-beta.1 diff --git a/plugins/_bundled/sirsoft-verification_kginicis/tests/Feature/Settings/InicisLiveModeSettingsValidationTest.php b/plugins/_bundled/sirsoft-verification_kginicis/tests/Feature/Settings/InicisLiveModeSettingsValidationTest.php index 51954366..182d9e54 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/tests/Feature/Settings/InicisLiveModeSettingsValidationTest.php +++ b/plugins/_bundled/sirsoft-verification_kginicis/tests/Feature/Settings/InicisLiveModeSettingsValidationTest.php @@ -8,6 +8,7 @@ use App\Models\Role; use App\Models\User; use App\Services\PluginSettingsService; use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Storage; use Plugins\Sirsoft\VerificationKginicis\Plugin; use Plugins\Sirsoft\VerificationKginicis\Tests\PluginTestCase; @@ -219,9 +220,11 @@ class InicisLiveModeSettingsValidationTest extends PluginTestCase ])->assertStatus(200); // 저장 파일에 평문이 남지 않아야 한다 (sensitive 암호화). - $settingsPath = storage_path('app/plugins/'.self::IDENTIFIER.'/settings/setting.json'); - $this->assertFileExists($settingsPath); - $raw = file_get_contents($settingsPath); + // PluginTestCase 가 'plugins' 디스크를 임시 디렉토리로 격리하므로 실제 storage_path 를 + // 하드코딩하지 않고 격리된 디스크를 통해 파일을 확인한다. + $settingsFile = self::IDENTIFIER.'/settings/setting.json'; + $this->assertTrue(Storage::disk('plugins')->exists($settingsFile)); + $raw = Storage::disk('plugins')->get($settingsFile); $this->assertStringNotContainsString('live-secret-key', $raw); // 복호화 왕복은 원문과 일치해야 한다. diff --git a/plugins/_bundled/sirsoft-verification_kginicis/tests/PluginTestCase.php b/plugins/_bundled/sirsoft-verification_kginicis/tests/PluginTestCase.php index 4ea1e383..57557913 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/tests/PluginTestCase.php +++ b/plugins/_bundled/sirsoft-verification_kginicis/tests/PluginTestCase.php @@ -4,7 +4,9 @@ namespace Plugins\Sirsoft\VerificationKginicis\Tests; use App\Extension\HookListenerRegistrar; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Route; +use Illuminate\Support\Facades\Storage; use Plugins\Sirsoft\VerificationKginicis\Listeners\AssertNoDuplicateInicisIdentity; use Plugins\Sirsoft\VerificationKginicis\Listeners\CleanInicisRecordOnUserDelete; use Plugins\Sirsoft\VerificationKginicis\Listeners\CleanInicisRecordOnUserWithdraw; @@ -25,6 +27,9 @@ abstract class PluginTestCase extends TestCase { use RefreshDatabase; + /** 테스트 격리용 임시 plugins 스토리지 루트 (setUp 에서 생성, tearDown 에서 제거). */ + private ?string $isolatedPluginsRoot = null; + protected function migrateFreshUsing(): array { return [ @@ -42,6 +47,8 @@ abstract class PluginTestCase extends TestCase { parent::setUp(); + $this->isolatePluginStorage(); + $this->registerPluginAutoload(); // 플러그인 lang 네임스페이스 등록 — 실 환경에서는 코어 TranslationServiceProvider::boot() @@ -84,6 +91,54 @@ abstract class PluginTestCase extends TestCase $this->registerPluginHookListeners(); } + protected function tearDown(): void + { + $this->restorePluginStorage(); + + parent::tearDown(); + } + + /** + * 플러그인 스토리지('plugins' 디스크)를 테스트 전용 임시 디렉토리로 격리한다. + * + * 설정 저장 테스트(PluginSettingsService::save)는 코어 'plugins' 디스크 + * (root = storage_path('app/plugins'))에 setting.json 을 쓴다. 격리하지 않으면 + * 테스트가 실제 로컬 런타임 설정 파일을 덮어써 라이브 모드/자격증명이 오염된다 + * (RefreshDatabase 는 DB 만 롤백하고 파일시스템은 되돌리지 않음). 디스크 root 를 + * 임시 경로로 바꾸고 resolved 인스턴스를 purge 하여 실제 파일을 원천적으로 못 + * 건드리게 한다. + */ + private function isolatePluginStorage(): void + { + // Laravel 이 테스트용 쓰기 공간으로 보장하는 storage/framework/testing 하위를 사용한다. + // sys_get_temp_dir() 은 CI/컨테이너/open_basedir 제약 환경에서 위치가 다르거나 + // 쓰기 불가일 수 있어 프로젝트 내부의 격리 경로를 쓴다 (Laravel 규약 준수). + $this->isolatedPluginsRoot = storage_path( + 'framework/testing/plugin-storage-'.uniqid('', true) + ); + + File::ensureDirectoryExists($this->isolatedPluginsRoot); + + config(['filesystems.disks.plugins.root' => $this->isolatedPluginsRoot]); + + // 이미 resolve 된 'plugins' 디스크 인스턴스를 폐기해 새 root 로 재생성되게 한다. + Storage::forgetDisk('plugins'); + } + + /** + * 격리 임시 디렉토리를 제거한다 (테스트 간 잔여 파일 격리). + */ + private function restorePluginStorage(): void + { + if ($this->isolatedPluginsRoot !== null && is_dir($this->isolatedPluginsRoot)) { + File::deleteDirectory($this->isolatedPluginsRoot); + } + + $this->isolatedPluginsRoot = null; + + Storage::forgetDisk('plugins'); + } + /** * Plugin 의 hook listener 들을 코어 HookManager 에 등록. * diff --git a/plugins/_bundled/sirsoft-verification_kginicis/tests/Unit/Identity/InicisIdentityProviderWithConfigTest.php b/plugins/_bundled/sirsoft-verification_kginicis/tests/Unit/Identity/InicisIdentityProviderWithConfigTest.php index 275a5c6b..fc3e735a 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/tests/Unit/Identity/InicisIdentityProviderWithConfigTest.php +++ b/plugins/_bundled/sirsoft-verification_kginicis/tests/Unit/Identity/InicisIdentityProviderWithConfigTest.php @@ -99,7 +99,7 @@ class InicisIdentityProviderWithConfigTest extends TestCase ['is_test_mode' => true, 'test_mid' => 'INIiasTest', 'duplicate_field' => 'di'], ); - $cloned = $provider->withConfig(['is_test_mode' => false, 'live_mid' => 'SRA1234567']); + $cloned = $provider->withConfig(['is_test_mode' => false, 'live_mid' => 'SRB1234567']); $reflection = new \ReflectionClass($cloned); foreach (['gateway', 'mappingRepository', 'recordRepository', 'cache', 'config'] as $prop) { @@ -113,7 +113,7 @@ class InicisIdentityProviderWithConfigTest extends TestCase $this->assertSame(false, $injectedConfig['is_test_mode']); $this->assertSame('INIiasTest', $injectedConfig['test_mid']); - $this->assertSame('SRA1234567', $injectedConfig['live_mid']); + $this->assertSame('SRB1234567', $injectedConfig['live_mid']); $this->assertSame('di', $injectedConfig['duplicate_field']); $gatewayProp = $reflection->getProperty('gateway'); diff --git a/plugins/_bundled/sirsoft-verification_kginicis/tests/Unit/Identity/InicisLiveMidPrefixTest.php b/plugins/_bundled/sirsoft-verification_kginicis/tests/Unit/Identity/InicisLiveMidPrefixTest.php new file mode 100644 index 00000000..1f161fde --- /dev/null +++ b/plugins/_bundled/sirsoft-verification_kginicis/tests/Unit/Identity/InicisLiveMidPrefixTest.php @@ -0,0 +1,139 @@ +assertSame('SRB', InicisIdentityProvider::LIVE_MID_PREFIX); + } + + /** + * buildLiveMid 는 프리픽스 미포함 입력값 앞에 상수 프리픽스를 부착해야 한다. + * + * @return void + */ + public function test_build_live_mid_prepends_prefix_when_absent(): void + { + $result = $this->invokeBuildLiveMid('1234567'); + + $this->assertSame(InicisIdentityProvider::LIVE_MID_PREFIX.'1234567', $result); + $this->assertSame('SRB1234567', $result); + } + + /** + * buildLiveMid 는 이미 프리픽스를 포함한 입력값에 중복 부착하지 않아야 한다. + * + * @return void + */ + public function test_build_live_mid_does_not_double_prepend_prefix(): void + { + $result = $this->invokeBuildLiveMid('SRB1234567'); + + $this->assertSame('SRB1234567', $result); + } + + /** + * buildLiveMid 는 빈 입력값(공백 포함)을 빈 문자열로 반환해야 한다. + * + * @return void + */ + public function test_build_live_mid_returns_empty_for_blank_input(): void + { + $this->assertSame('', $this->invokeBuildLiveMid('')); + $this->assertSame('', $this->invokeBuildLiveMid(' ')); + } + + /** + * 라이브 모드에서 프리픽스가 부착된 라이브 MID + API 키가 있으면 운영 가능해야 한다. + * + * @return void + */ + public function test_is_available_true_in_live_mode_with_prefixed_mid(): void + { + $provider = $this->makeProvider([ + 'is_test_mode' => false, + 'live_mid' => '1234567', + 'live_api_key' => 'live-api-key', + ]); + + $this->assertTrue($provider->isAvailable()); + } + + /** + * 라이브 모드에서 API 키가 비어 있으면 운영 불가여야 한다. + * + * @return void + */ + public function test_is_available_false_in_live_mode_without_api_key(): void + { + $provider = $this->makeProvider([ + 'is_test_mode' => false, + 'live_mid' => '1234567', + 'live_api_key' => '', + ]); + + $this->assertFalse($provider->isAvailable()); + } + + /** + * 라이브 MID 를 리플렉션으로 protected buildLiveMid() 에 통과시킨다. + * + * @param string $value + * @return string + */ + protected function invokeBuildLiveMid(string $value): string + { + $provider = $this->makeProvider(['is_test_mode' => true, 'test_mid' => 'INIiasTest']); + + $method = new \ReflectionMethod($provider, 'buildLiveMid'); + $method->setAccessible(true); + + return $method->invoke($provider, $value); + } + + /** + * @param array $config + * @return InicisIdentityProvider + */ + protected function makeProvider(array $config): InicisIdentityProvider + { + return new InicisIdentityProvider( + Mockery::mock(InicisGatewayInterface::class), + Mockery::mock(InicisChallengeMappingRepositoryInterface::class), + Mockery::mock(InicisIdentityRecordRepositoryInterface::class), + Mockery::mock(CacheInterface::class), + $config, + ); + } +} diff --git a/plugins/_bundled/sirsoft-verification_kginicis/tests/scenarios/live-mode-settings-validation.yaml b/plugins/_bundled/sirsoft-verification_kginicis/tests/scenarios/live-mode-settings-validation.yaml index 2c32efd7..e9ae6f89 100644 --- a/plugins/_bundled/sirsoft-verification_kginicis/tests/scenarios/live-mode-settings-validation.yaml +++ b/plugins/_bundled/sirsoft-verification_kginicis/tests/scenarios/live-mode-settings-validation.yaml @@ -59,7 +59,7 @@ design_rationale: | - 채택: (a) 스키마를 plugin.php 로 이전(결제 플러그인 동형 + sensitive) + (b) 라이브 조건부 required 는 코어가 이미 발행하는 core.plugin_settings.update_rules 필터로 주입. 코어 무수정. - 라이브 검증 기준은 InicisIdentityProvider::isAvailable()(live_mid + live_api_key 비어있지 않음) - 과 일치. live_mid 의 SRA 프리픽스는 buildLiveMid() 가 자동 부착하므로 별도 형식 검증 미도입. + 과 일치. live_mid 의 SRB 프리픽스는 buildLiveMid() 가 자동 부착하므로 별도 형식 검증 미도입. - (라벨 로케일 보강) ServiceProvider 의 validation.attributes 라벨 등록이 ['ko','en'] 하드코딩이라 ja 로케일에서 일본어 라벨이 노출되지 않던 결함을 config('app.supported_locales') 동적 처리로 정정. ja 번역(ライブ MID 등)은 이미 언어팩에 존재했으나 등록 로케일 누락으로 미사용 상태였다.