Harden published curriculum and student flows
This commit is contained in:
@@ -6,13 +6,57 @@ import 'package:flutter/foundation.dart';
|
||||
class AppLogger {
|
||||
AppLogger._();
|
||||
|
||||
static const _sensitiveKeyParts = [
|
||||
'authorization',
|
||||
'token',
|
||||
'secret',
|
||||
'password',
|
||||
'phone',
|
||||
'national',
|
||||
'identity',
|
||||
'otp',
|
||||
'ticket',
|
||||
'email',
|
||||
'fingerprint',
|
||||
'pin',
|
||||
'address',
|
||||
];
|
||||
|
||||
static bool _isSensitiveKey(String key) {
|
||||
final normalized = key.toLowerCase().replaceAll(RegExp(r'[^a-z0-9]'), '');
|
||||
return _sensitiveKeyParts.any(normalized.contains);
|
||||
}
|
||||
|
||||
static dynamic _safeLogValue(dynamic value, {String key = ''}) {
|
||||
if (_isSensitiveKey(key)) return '[REDACTED]';
|
||||
if (value is Map) {
|
||||
return value.map((k, v) => MapEntry(
|
||||
k.toString(),
|
||||
_safeLogValue(v, key: k.toString()),
|
||||
));
|
||||
}
|
||||
if (value is List) {
|
||||
return value.map((v) => _safeLogValue(v)).toList();
|
||||
}
|
||||
if (value is String && key.isEmpty) return '[TEXT OMITTED]';
|
||||
return value;
|
||||
}
|
||||
|
||||
static Uri _safeUri(Uri uri) {
|
||||
final safeQuery = Map<String, String>.fromEntries(
|
||||
uri.queryParameters.entries.where((entry) => !_isSensitiveKey(entry.key)),
|
||||
);
|
||||
return uri.replace(queryParameters: safeQuery.isEmpty ? null : safeQuery);
|
||||
}
|
||||
|
||||
static void log(String message, {String tag = 'SAQEL'}) {
|
||||
if (kDebugMode) {
|
||||
debugPrint('[$tag] $message');
|
||||
}
|
||||
}
|
||||
|
||||
static void event(String name, {Map<String, dynamic>? details, String tag = 'EVENT'}) {
|
||||
static void event(String name,
|
||||
{Map<String, dynamic>? details, String tag = 'EVENT'}) {
|
||||
if (!kDebugMode) return;
|
||||
final buffer = StringBuffer();
|
||||
buffer.write('⚡ [$tag] $name');
|
||||
@@ -35,21 +79,23 @@ class AppLogger {
|
||||
if (!kDebugMode) return;
|
||||
|
||||
final buffer = StringBuffer();
|
||||
buffer.writeln('\n🌐 ─── [HTTP REQUEST] ──────────────────────────────────────────');
|
||||
buffer.writeln(
|
||||
'\n🌐 ─── [HTTP REQUEST] ──────────────────────────────────────────');
|
||||
buffer.writeln('➡️ Method: $method');
|
||||
buffer.writeln('🔗 URL: $uri');
|
||||
buffer.writeln('🔗 URL: ${_safeUri(uri)}');
|
||||
if (headers != null && headers.isNotEmpty) {
|
||||
final safeHeaders = Map<String, String>.from(headers);
|
||||
if (safeHeaders.containsKey('Authorization')) {
|
||||
final auth = safeHeaders['Authorization']!;
|
||||
safeHeaders['Authorization'] = auth.length > 20 ? '${auth.substring(0, 15)}...' : 'Bearer [REDACTED]';
|
||||
safeHeaders['Authorization'] = '[REDACTED]';
|
||||
}
|
||||
safeHeaders.removeWhere((key, _) => _isSensitiveKey(key));
|
||||
buffer.writeln('📋 Headers: ${jsonEncode(safeHeaders)}');
|
||||
}
|
||||
if (body != null) {
|
||||
buffer.writeln('📦 Body: ${body is String ? body : jsonEncode(body)}');
|
||||
buffer.writeln('📦 Body: ${jsonEncode(_safeLogValue(body))}');
|
||||
}
|
||||
buffer.writeln('───────────────────────────────────────────────────────────────');
|
||||
buffer.writeln(
|
||||
'───────────────────────────────────────────────────────────────');
|
||||
debugPrint(buffer.toString());
|
||||
}
|
||||
|
||||
@@ -66,24 +112,28 @@ class AppLogger {
|
||||
final emoji = isSuccess ? '✅' : '⚠️';
|
||||
final buffer = StringBuffer();
|
||||
|
||||
buffer.writeln('\n$emoji ─── [HTTP RESPONSE $statusCode] ────────────────────────────────');
|
||||
buffer.writeln(
|
||||
'\n$emoji ─── [HTTP RESPONSE $statusCode] ────────────────────────────────');
|
||||
buffer.writeln('⬅️ Method: $method');
|
||||
buffer.writeln('🔗 URL: $uri');
|
||||
buffer.writeln('🔗 URL: ${_safeUri(uri)}');
|
||||
if (duration != null) {
|
||||
buffer.writeln('⏱️ Time: ${duration.inMilliseconds}ms');
|
||||
}
|
||||
if (responseBody != null) {
|
||||
buffer.writeln('📦 Data: ${responseBody is String ? responseBody : jsonEncode(responseBody)}');
|
||||
buffer.writeln('📦 Data: ${jsonEncode(_safeLogValue(responseBody))}');
|
||||
}
|
||||
buffer.writeln('───────────────────────────────────────────────────────────────');
|
||||
buffer.writeln(
|
||||
'───────────────────────────────────────────────────────────────');
|
||||
debugPrint(buffer.toString());
|
||||
}
|
||||
|
||||
static void error(String message, {dynamic error, StackTrace? stackTrace, String tag = 'ERROR'}) {
|
||||
static void error(String message,
|
||||
{dynamic error, StackTrace? stackTrace, String tag = 'ERROR'}) {
|
||||
if (!kDebugMode) return;
|
||||
|
||||
final buffer = StringBuffer();
|
||||
buffer.writeln('\n🚨 ─── [ERROR: $tag] ──────────────────────────────────────────');
|
||||
buffer.writeln(
|
||||
'\n🚨 ─── [ERROR: $tag] ──────────────────────────────────────────');
|
||||
buffer.writeln('❌ Message: $message');
|
||||
if (error != null) {
|
||||
buffer.writeln('⚠️ Error: $error');
|
||||
@@ -91,7 +141,8 @@ class AppLogger {
|
||||
if (stackTrace != null) {
|
||||
buffer.writeln('📍 Trace: \n$stackTrace');
|
||||
}
|
||||
buffer.writeln('───────────────────────────────────────────────────────────────');
|
||||
buffer.writeln(
|
||||
'───────────────────────────────────────────────────────────────');
|
||||
debugPrint(buffer.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user