diff --git a/lib/ui/master_prompt.dart b/lib/ui/master_prompt.dart index dca8318..e4388dc 100644 --- a/lib/ui/master_prompt.dart +++ b/lib/ui/master_prompt.dart @@ -142,6 +142,8 @@ Future clearStoredSecrets(AppController c) => c.updateSettings((s) => s ..webdavServers = [for (final x in s.webdavServers) x.copyWith(password: '')] // 88: SFTP 의 비밀번호 · 개인 키 · 키 암호도 (믿은 호스트 키는 비밀이 아니라 남김) ..sftpServers = [for (final x in s.sftpServers) x.copyWith(password: '', privateKey: '', keyPassphrase: '')] + // AI 서비스 API 키도 (문구 "비밀번호 · API 키" 와 같게 - 예전에는 남았다, 관리자 결정 10/17) + ..aiServices = [for (final x in s.aiServices) x.copyWith(apiKey: '')] ..openSubtitlesKey = '' ..openSubtitlesPassword = ''); diff --git a/test/master_lock_test.dart b/test/master_lock_test.dart index 193a96c..b1dd73a 100644 --- a/test/master_lock_test.dart +++ b/test/master_lock_test.dart @@ -7,13 +7,16 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:jj_mkvmaker/app/app_controller.dart'; import 'package:jj_mkvmaker/app/master_lock.dart'; import 'package:jj_mkvmaker/app/settings.dart'; +import 'package:jj_mkvmaker/core/sftp.dart'; import 'package:jj_mkvmaker/core/webdav.dart'; import 'package:jj_mkvmaker/platform/windows/desktop_storage_service.dart'; import 'package:jj_mkvmaker/platform/windows/process_media_tool.dart'; import 'package:jj_mkvmaker/services/platform_services.dart'; +import 'package:jj_mkvmaker/services/image_ai.dart' show AiService; import 'package:jj_mkvmaker/services/secret_store.dart'; import 'package:jj_mkvmaker/ui/master_prompt.dart'; import 'package:jj_mkvmaker/ui/settings_page.dart'; +import 'package:path/path.dart' as p; String hex(List b) => b.map((x) => x.toRadixString(16).padLeft(2, '0')).join(); @@ -272,6 +275,29 @@ void main() { expect(lock.unlocked, isFalse); }); + test('"저장된 비밀번호 · API 키" 지우기: 안전 저장소의 os. · dav. · sftp. · ai. 값이 모두 없어진다 (AI 키가 남던 것 - 관리자 10/17)', () async { + final tmp = Directory.systemTemp.createTempSync('jj_master_clear_'); + addTearDown(() => tmp.deleteSync(recursive: true)); + final secrets = MemorySecretStore(); + final store = SettingsStore(p.join(tmp.path, 'settings.json'), secrets); + final c = AppController(PlatformServices(mediaTool: ProcessMediaTool('x', 'y'), storage: DesktopStorageService()), + settingsStore: store); + await c.updateSettings((s) => s + ..openSubtitlesKey = 'k' + ..openSubtitlesPassword = 'op' + ..webdavServers = [const DavServer(id: 'd1', name: 'n', url: 'https://x', user: 'u', password: 'dp')] + ..sftpServers = [const SftpServer(id: 's1', name: 'n', host: 'h', user: 'u', password: 'sp', privateKey: 'PRIVATE KEY', keyPassphrase: 'kp')] + ..aiServices = [const AiService(id: 'a1', name: 'n', url: 'https://ai', kind: 'openai', apiKey: 'ak')]); + await store.save(c.settings); + bool secret(String k) => k.startsWith('os.') || k.startsWith('dav.pw.') || k.startsWith('sftp.') || k.startsWith('ai.'); + expect(secrets.values.keys.where(secret).length, 7, reason: '넣은 비밀 값이 저장소에 있다 (os 2 · dav 1 · sftp 3 · ai 1)'); + await clearStoredSecrets(c); + await store.save(c.settings); + expect(secrets.values.keys.where(secret), isEmpty); + // 목록 · 아이디 · 믿은 서버 키는 남김 + expect((c.settings.webdavServers.single.user, c.settings.sftpServers.single.user, c.settings.aiServices.single.url), ('u', 'u', 'https://ai')); + }); + test('최상으로 "앱 설정 전체" 를 지우면 처음 상태', () async { final c = controller()..settings.explorerLayout = 'single'; await resetAllSettings(c);