Files
Melo/test/logger_service_test.dart
T
Hermes (Server)andClaude Opus 4.8 d83f8c8c54 Datenschutz: Log-Bereinigung vor Server-Upload (Scrubber + Quelle)
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
2026-08-20 01:38:56 +02:00

68 lines
2.6 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
});
});
}