WIP 최상 · 마스터 초기화 "저장된 비밀번호 · API 키" 가 AI 서비스 API 키도 지우게 (버그, 관리자 결정) (검토 대기)

관리자 결정 (10/17): 문구는 "비밀번호 · API 키" 인데 AI 서비스 API 키 (ai.*) 는 남았다 (예전부터) → 함께 지운다.
SFTP 비밀 값 (비밀번호 · 개인 키 · 키 암호) 은 88 1/3 에서 이미 넣음. 목록 · 아이디 · 주소 · 믿은 서버 키는 남김.
시험: 실제 SettingsStore + 메모리 안전 저장소로 os. · dav. · sftp. · ai. 값 7개를 넣고 지운 뒤 하나도 없음.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
묶음7_88
RyuJongJin 2026-10-17 22:32:14 +09:00
parent 9a786f3496
commit d00df74257
2 changed files with 28 additions and 0 deletions

View File

@ -142,6 +142,8 @@ Future<void> 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 = '');

View File

@ -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<int> 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);