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

View file

@ -1,4 +1,5 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:selfprivacy/logic/models/console_log.dart'; import 'package:selfprivacy/logic/models/console_log.dart';
import 'package:selfprivacy/utils/platform_adapter.dart'; import 'package:selfprivacy/utils/platform_adapter.dart';
@ -202,11 +203,15 @@ class _SectionRow extends StatelessWidget {
class _KeyValueRow extends StatelessWidget { class _KeyValueRow extends StatelessWidget {
const _KeyValueRow(this.title, this.value); const _KeyValueRow(this.title, this.value);
static const List<String> hideList = ['Authorization'];
final String title; final String title;
final String? value; final String? value;
@override @override
Widget build(final BuildContext context) => Padding( Widget build(final BuildContext context) => hideList.contains(title)
? _ObscuredKeyValueRow(title, value)
: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.symmetric(horizontal: 12),
child: SelectableText.rich( child: SelectableText.rich(
TextSpan( TextSpan(
@ -223,6 +228,60 @@ class _KeyValueRow extends StatelessWidget {
); );
} }
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: 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()],
),
),
],
),
),
),
IconButton(
icon: Icon(
_obscureValue ? CupertinoIcons.eye : CupertinoIcons.eye_slash,
),
onPressed: () {
_obscureValue ^= true; // toggle value
setState(() {});
},
),
],
),
);
}
/// data row with only text /// data row with only text
class _DataRow extends StatelessWidget { class _DataRow extends StatelessWidget {
const _DataRow(this.data); const _DataRow(this.data);

View file

@ -257,6 +257,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.2" 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: dart_style:
dependency: transitive dependency: transitive
description: description:

View file

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