Diagnose-Logs werden zentral bereinigt, bevor sie an logs.baka-net.de gehen. Lokaler debugPrint bleibt vollständig. - Freitext-Scrubber (LoggerService.scrubText) für message + stackTrace: maskiert user=/pw=/password=/token=/secret=/url= sowie Datei-Pfade, nackte URLs, Bearer-Token, JWTs und lange Hex-IDs. - stackTrace auf 8 Zeilen gekürzt (capFrames). - deviceModel nur noch grobe Plattform (android/ios) statt Hersteller+Modell; device_info_plus im Logger entfernt. - Quelle entschärft: settings_screen loggte Navidrome-Login mit Klartext user=/url= — jetzt nur neutraler Status inkl. pwLeer-Flag. - Neue Tests: test/logger_service_test.dart (9). 79/79 grün, analyze sauber. Opt-in/Einwilligung bleibt separater Folgeschritt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tr2UwurtxyJUpWpBSeVmBm
68 lines
2.6 KiB
Dart
68 lines
2.6 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
||
import 'package:melo/services/logger_service.dart';
|
||
|
||
/// Sicherheits-Tests für die Log-Bereinigung vor dem Server-Upload
|
||
/// (logs.baka-net.de). Der Logger ist freitextbasiert, daher wird der
|
||
/// message-/stackTrace-Text zentral maskiert, bevor er das Gerät verlässt.
|
||
void main() {
|
||
group('LoggerService.scrubText – sensible Fragmente', () {
|
||
test('Benutzername (user=) wird redigiert', () {
|
||
expect(LoggerService.scrubText('Login user=Dustin ok'),
|
||
'Login user=<redacted> ok');
|
||
});
|
||
|
||
test('Server-URL (url=) wird redigiert', () {
|
||
expect(LoggerService.scrubText('verbinde url=https://musik.baka-net.de'),
|
||
contains('url=<redacted>'));
|
||
});
|
||
|
||
test('Passwort/Token/Secret werden redigiert', () {
|
||
expect(LoggerService.scrubText('password=geheim123'), 'password=<redacted>');
|
||
expect(LoggerService.scrubText('token=abc.def'), 'token=<redacted>');
|
||
expect(LoggerService.scrubText('secret=xyz'), 'secret=<redacted>');
|
||
});
|
||
|
||
test('pwLeer=false (bool-Flag) bleibt erhalten', () {
|
||
expect(LoggerService.scrubText('Login pwLeer=false'), 'Login pwLeer=false');
|
||
});
|
||
});
|
||
|
||
group('LoggerService.scrubText – Pfade/URLs/Token', () {
|
||
test('Datei-Pfade werden maskiert', () {
|
||
expect(LoggerService.scrubText('lese /storage/emulated/0/m.mp3 ok'),
|
||
'lese <path> ok');
|
||
expect(LoggerService.scrubText('crash /home/dustin/secret/x.dart'),
|
||
'crash <path>');
|
||
});
|
||
|
||
test('Nackte URLs werden maskiert', () {
|
||
expect(LoggerService.scrubText('GET https://logs.baka-net.de/api/logs'),
|
||
'GET <url>');
|
||
});
|
||
|
||
test('Bearer-Token, JWT und lange Hex-IDs werden maskiert', () {
|
||
expect(LoggerService.scrubText('Authorization: Bearer abc.def-ghi'),
|
||
'Authorization: Bearer <token>');
|
||
expect(LoggerService.scrubText('t=eyJhbGciOiJIUzI1NiIsdummydummy'),
|
||
contains('<jwt>'));
|
||
final s = LoggerService.scrubText('id deadbeefdeadbeef12');
|
||
expect(s.contains('deadbeefdeadbeef12'), isFalse);
|
||
expect(s.contains('<hex>'), isTrue);
|
||
});
|
||
});
|
||
|
||
group('LoggerService.capFrames', () {
|
||
test('kürzt lange Stack-Traces auf wenige Zeilen', () {
|
||
final viele = List.generate(20, (i) => 'frame $i').join('\n');
|
||
final s = LoggerService.capFrames(viele);
|
||
expect(s.contains('weitere Zeilen entfernt'), isTrue);
|
||
expect(s.contains('frame 19'), isFalse);
|
||
});
|
||
|
||
test('kurze Traces bleiben unverändert', () {
|
||
const kurz = 'a\nb\nc';
|
||
expect(LoggerService.capFrames(kurz), kurz);
|
||
});
|
||
});
|
||
}
|