feat: obscure/remove auth headers from console logs

This commit is contained in:
Aliaksei Tratseuski 2024-06-13 21:53:06 +04:00
parent dfef56c25f
commit efd3dfbde5
4 changed files with 89 additions and 15 deletions

View file

@ -10,10 +10,6 @@ enum ConsoleLogSeverity {
}
/// Base entity for console logs.
///
/// TODO(misterfourtytwo): should we add?
///
/// * equality override
sealed class ConsoleLog {
ConsoleLog({
final String? customTitle,
@ -75,6 +71,8 @@ class RestApiRequestConsoleLog extends ConsoleLog {
super.severity,
});
static const blacklistedHeaders = ['Authorization'];
final String? method;
final Uri? uri;
final Map<String, dynamic>? headers;
@ -82,10 +80,18 @@ class RestApiRequestConsoleLog extends ConsoleLog {
@override
String get title => 'Rest API Request';
Map<String, dynamic> get filteredHeaders => Map.fromEntries(
headers?.entries.where(
(final entry) => !blacklistedHeaders.contains(entry.key),
) ??
const [],
);
@override
String get content => '"method": "$method",\n'
'"uri": "$uri",\n'
'"headers": ${jsonEncode(headers)},\n'
'"headers": ${jsonEncode(filteredHeaders)},\n' // censor header to not expose API keys
'"data": $data';
}

View file

@ -1,4 +1,5 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:selfprivacy/logic/models/console_log.dart';
import 'package:selfprivacy/utils/platform_adapter.dart';
@ -202,23 +203,81 @@ class _SectionRow extends StatelessWidget {
class _KeyValueRow extends StatelessWidget {
const _KeyValueRow(this.title, this.value);
static const List<String> hideList = ['Authorization'];
final String title;
final String? value;
@override
Widget build(final BuildContext context) => hideList.contains(title)
? _ObscuredKeyValueRow(title, value)
: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: SelectableText.rich(
TextSpan(
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: '$title: ',
style: const TextStyle(fontWeight: FontWeight.bold),
),
TextSpan(text: value ?? ''),
],
),
),
);
}
class _ObscuredKeyValueRow extends StatefulWidget {
const _ObscuredKeyValueRow(this.title, this.value);
final String title;
final String? value;
@override
State<_ObscuredKeyValueRow> createState() => _ObscuredKeyValueRowState();
}
class _ObscuredKeyValueRowState extends State<_ObscuredKeyValueRow> {
static const obscuringCharacter = '';
bool _obscureValue = true;
@override
Widget build(final BuildContext context) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: SelectableText.rich(
TextSpan(
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: '$title: ',
style: const TextStyle(fontWeight: FontWeight.bold),
child: Row(
children: [
Expanded(
child: SelectableText.rich(
TextSpan(
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: '${widget.title}: ',
style: const TextStyle(fontWeight: FontWeight.bold),
),
TextSpan(
text: _obscureValue
? obscuringCharacter * (widget.value?.length ?? 4)
: widget.value ?? '',
style: const TextStyle(
fontFeatures: [FontFeature.tabularFigures()],
),
),
],
),
),
TextSpan(text: value ?? ''),
],
),
),
IconButton(
icon: Icon(
_obscureValue ? CupertinoIcons.eye : CupertinoIcons.eye_slash,
),
onPressed: () {
_obscureValue ^= true; // toggle value
setState(() {});
},
),
],
),
);
}

View file

@ -257,6 +257,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.2"
cupertino_icons:
dependency: "direct dev"
description:
name: cupertino_icons
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.dev"
source: hosted
version: "1.0.8"
dart_style:
dependency: transitive
description:

View file

@ -55,6 +55,7 @@ dependencies:
dev_dependencies:
auto_route_generator: ^8.0.0
build_runner: ^2.4.9
cupertino_icons: ^1.0.8
flutter_launcher_icons: ^0.13.1
flutter_lints: ^3.0.2
flutter_test: