Packages
This commit is contained in:
1
mobile/packages/.gitignore
vendored
1
mobile/packages/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
.dart_tool/
|
||||
.flutter-plugins-dependencies
|
||||
|
||||
10
mobile/packages/base/analysis_options.yaml
Normal file
10
mobile/packages/base/analysis_options.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- always_declare_return_types
|
||||
- always_put_required_named_parameters_first
|
||||
- avoid_print
|
||||
- prefer_const_constructors
|
||||
- prefer_const_literals_to_create_immutables
|
||||
- use_key_in_widget_constructors
|
||||
6
mobile/packages/base/lib/ente_base.dart
Normal file
6
mobile/packages/base/lib/ente_base.dart
Normal file
@@ -0,0 +1,6 @@
|
||||
library ente_base;
|
||||
|
||||
export 'models/database.dart';
|
||||
export 'models/key_attributes.dart';
|
||||
export 'models/key_gen_result.dart';
|
||||
export 'models/private_key_attributes.dart';
|
||||
3
mobile/packages/base/lib/models/database.dart
Normal file
3
mobile/packages/base/lib/models/database.dart
Normal file
@@ -0,0 +1,3 @@
|
||||
abstract class EnteBaseDatabase {
|
||||
Future<void> clearTable();
|
||||
}
|
||||
102
mobile/packages/base/lib/models/key_attributes.dart
Normal file
102
mobile/packages/base/lib/models/key_attributes.dart
Normal file
@@ -0,0 +1,102 @@
|
||||
import 'dart:convert';
|
||||
|
||||
class KeyAttributes {
|
||||
final String kekSalt;
|
||||
final String encryptedKey;
|
||||
final String keyDecryptionNonce;
|
||||
final String publicKey;
|
||||
final String encryptedSecretKey;
|
||||
final String secretKeyDecryptionNonce;
|
||||
final int memLimit;
|
||||
final int opsLimit;
|
||||
final String masterKeyEncryptedWithRecoveryKey;
|
||||
final String masterKeyDecryptionNonce;
|
||||
final String recoveryKeyEncryptedWithMasterKey;
|
||||
final String recoveryKeyDecryptionNonce;
|
||||
|
||||
KeyAttributes(
|
||||
this.kekSalt,
|
||||
this.encryptedKey,
|
||||
this.keyDecryptionNonce,
|
||||
this.publicKey,
|
||||
this.encryptedSecretKey,
|
||||
this.secretKeyDecryptionNonce,
|
||||
this.memLimit,
|
||||
this.opsLimit,
|
||||
this.masterKeyEncryptedWithRecoveryKey,
|
||||
this.masterKeyDecryptionNonce,
|
||||
this.recoveryKeyEncryptedWithMasterKey,
|
||||
this.recoveryKeyDecryptionNonce,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'kekSalt': kekSalt,
|
||||
'encryptedKey': encryptedKey,
|
||||
'keyDecryptionNonce': keyDecryptionNonce,
|
||||
'publicKey': publicKey,
|
||||
'encryptedSecretKey': encryptedSecretKey,
|
||||
'secretKeyDecryptionNonce': secretKeyDecryptionNonce,
|
||||
'memLimit': memLimit,
|
||||
'opsLimit': opsLimit,
|
||||
'masterKeyEncryptedWithRecoveryKey': masterKeyEncryptedWithRecoveryKey,
|
||||
'masterKeyDecryptionNonce': masterKeyDecryptionNonce,
|
||||
'recoveryKeyEncryptedWithMasterKey': recoveryKeyEncryptedWithMasterKey,
|
||||
'recoveryKeyDecryptionNonce': recoveryKeyDecryptionNonce,
|
||||
};
|
||||
}
|
||||
|
||||
factory KeyAttributes.fromMap(Map<String, dynamic> map) {
|
||||
return KeyAttributes(
|
||||
map['kekSalt'],
|
||||
map['encryptedKey'],
|
||||
map['keyDecryptionNonce'],
|
||||
map['publicKey'],
|
||||
map['encryptedSecretKey'],
|
||||
map['secretKeyDecryptionNonce'],
|
||||
map['memLimit'],
|
||||
map['opsLimit'],
|
||||
map['masterKeyEncryptedWithRecoveryKey'],
|
||||
map['masterKeyDecryptionNonce'],
|
||||
map['recoveryKeyEncryptedWithMasterKey'],
|
||||
map['recoveryKeyDecryptionNonce'],
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory KeyAttributes.fromJson(String source) =>
|
||||
KeyAttributes.fromMap(json.decode(source));
|
||||
|
||||
KeyAttributes copyWith({
|
||||
String? kekSalt,
|
||||
String? encryptedKey,
|
||||
String? keyDecryptionNonce,
|
||||
String? publicKey,
|
||||
String? encryptedSecretKey,
|
||||
String? secretKeyDecryptionNonce,
|
||||
int? memLimit,
|
||||
int? opsLimit,
|
||||
String? masterKeyEncryptedWithRecoveryKey,
|
||||
String? masterKeyDecryptionNonce,
|
||||
String? recoveryKeyEncryptedWithMasterKey,
|
||||
String? recoveryKeyDecryptionNonce,
|
||||
}) {
|
||||
return KeyAttributes(
|
||||
kekSalt ?? this.kekSalt,
|
||||
encryptedKey ?? this.encryptedKey,
|
||||
keyDecryptionNonce ?? this.keyDecryptionNonce,
|
||||
publicKey ?? this.publicKey,
|
||||
encryptedSecretKey ?? this.encryptedSecretKey,
|
||||
secretKeyDecryptionNonce ?? this.secretKeyDecryptionNonce,
|
||||
memLimit ?? this.memLimit,
|
||||
opsLimit ?? this.opsLimit,
|
||||
masterKeyEncryptedWithRecoveryKey ??
|
||||
this.masterKeyEncryptedWithRecoveryKey,
|
||||
masterKeyDecryptionNonce ?? this.masterKeyDecryptionNonce,
|
||||
recoveryKeyEncryptedWithMasterKey ??
|
||||
this.recoveryKeyEncryptedWithMasterKey,
|
||||
recoveryKeyDecryptionNonce ?? this.recoveryKeyDecryptionNonce,
|
||||
);
|
||||
}
|
||||
}
|
||||
12
mobile/packages/base/lib/models/key_gen_result.dart
Normal file
12
mobile/packages/base/lib/models/key_gen_result.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
import "dart:typed_data";
|
||||
|
||||
import 'key_attributes.dart';
|
||||
import 'private_key_attributes.dart';
|
||||
|
||||
class KeyGenResult {
|
||||
final KeyAttributes keyAttributes;
|
||||
final PrivateKeyAttributes privateKeyAttributes;
|
||||
final Uint8List loginKey;
|
||||
|
||||
KeyGenResult(this.keyAttributes, this.privateKeyAttributes, this.loginKey);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class PrivateKeyAttributes {
|
||||
final String key;
|
||||
final String recoveryKey;
|
||||
final String secretKey;
|
||||
|
||||
PrivateKeyAttributes(this.key, this.recoveryKey, this.secretKey);
|
||||
}
|
||||
205
mobile/packages/base/pubspec.lock
Normal file
205
mobile/packages/base/pubspec.lock
Normal file
@@ -0,0 +1,205 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.13.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.9"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.9"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.17"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.11.1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.12.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.2"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.4"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "15.0.0"
|
||||
sdks:
|
||||
dart: ">=3.7.0-0 <4.0.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
18
mobile/packages/base/pubspec.yaml
Normal file
18
mobile/packages/base/pubspec.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
name: ente_base
|
||||
description: A base Flutter package containing shared models and types for ente apps
|
||||
version: 1.0.0
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^5.0.0
|
||||
|
||||
flutter:
|
||||
@@ -1,7 +1,406 @@
|
||||
library configuration;
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io' as io;
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:configuration/constants.dart';
|
||||
import 'package:ente_base/models/database.dart';
|
||||
import 'package:ente_base/models/key_attributes.dart';
|
||||
import 'package:ente_base/models/key_gen_result.dart';
|
||||
import 'package:ente_base/models/private_key_attributes.dart';
|
||||
import 'package:ente_crypto_dart/ente_crypto_dart.dart';
|
||||
import 'package:ente_events/event_bus.dart';
|
||||
import 'package:ente_events/models/endpoint_updated_event.dart';
|
||||
import 'package:ente_events/models/signed_in_event.dart';
|
||||
import 'package:ente_events/models/signed_out_event.dart';
|
||||
import 'package:ente_logging/logging.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class Configuration {
|
||||
static Future<void> init() async {
|
||||
// TODO
|
||||
Configuration._privateConstructor();
|
||||
|
||||
static final Configuration instance = Configuration._privateConstructor();
|
||||
static const endpoint = String.fromEnvironment(
|
||||
"endpoint",
|
||||
defaultValue: kDefaultProductionEndpoint,
|
||||
);
|
||||
static const emailKey = "email";
|
||||
static const keyAttributesKey = "key_attributes";
|
||||
|
||||
static const lastTempFolderClearTimeKey = "last_temp_folder_clear_time";
|
||||
static const keyKey = "key";
|
||||
static const secretKeyKey = "secret_key";
|
||||
static const authSecretKeyKey = "auth_secret_key";
|
||||
static const offlineAuthSecretKey = "offline_auth_secret_key";
|
||||
static const tokenKey = "token";
|
||||
static const encryptedTokenKey = "encrypted_token";
|
||||
static const userIDKey = "user_id";
|
||||
static const endPointKey = "endpoint";
|
||||
|
||||
final kTempFolderDeletionTimeBuffer = const Duration(days: 1).inMicroseconds;
|
||||
|
||||
static final _logger = Logger("Configuration");
|
||||
|
||||
String? _cachedToken;
|
||||
late SharedPreferences _preferences;
|
||||
String? _key;
|
||||
String? _secretKey;
|
||||
late FlutterSecureStorage _secureStorage;
|
||||
late String _documentsDirectory;
|
||||
late String _cacheDirectory;
|
||||
late String _tempDocumentsDirPath;
|
||||
late List<EnteBaseDatabase> _databases;
|
||||
|
||||
String? _volatilePassword;
|
||||
|
||||
Future<void> init(List<EnteBaseDatabase> dbs) async {
|
||||
_databases = dbs;
|
||||
_documentsDirectory = (await getApplicationDocumentsDirectory()).path;
|
||||
_tempDocumentsDirPath = "$_documentsDirectory/temp/";
|
||||
_preferences = await SharedPreferences.getInstance();
|
||||
_secureStorage = const FlutterSecureStorage(
|
||||
iOptions: IOSOptions(
|
||||
accessibility: KeychainAccessibility.first_unlock_this_device,
|
||||
),
|
||||
);
|
||||
final tempDirectory = io.Directory(_tempDocumentsDirPath);
|
||||
try {
|
||||
final currentTime = DateTime.now().microsecondsSinceEpoch;
|
||||
if (tempDirectory.existsSync() &&
|
||||
(_preferences.getInt(lastTempFolderClearTimeKey) ?? 0) <
|
||||
(currentTime - kTempFolderDeletionTimeBuffer)) {
|
||||
await tempDirectory.delete(recursive: true);
|
||||
await _preferences.setInt(lastTempFolderClearTimeKey, currentTime);
|
||||
_logger.info("Cleared temp folder");
|
||||
} else {
|
||||
_logger.info("Skipping temp folder clear");
|
||||
}
|
||||
} catch (e) {
|
||||
_logger.warning(e);
|
||||
}
|
||||
tempDirectory.createSync(recursive: true);
|
||||
|
||||
_cacheDirectory = "$_documentsDirectory/cache/";
|
||||
if (!io.Directory(_cacheDirectory).existsSync()) {
|
||||
io.Directory(_cacheDirectory).createSync(recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> logout({bool autoLogout = false}) async {
|
||||
await _preferences.clear();
|
||||
_secureStorage.deleteAll();
|
||||
for (final db in _databases) {
|
||||
await db.clearTable();
|
||||
}
|
||||
_key = null;
|
||||
_cachedToken = null;
|
||||
_secretKey = null;
|
||||
Bus.instance.fire(SignedOutEvent());
|
||||
}
|
||||
|
||||
Future<KeyGenResult> generateKey(String password) async {
|
||||
// Create a master key
|
||||
final masterKey = CryptoUtil.generateKey();
|
||||
|
||||
// Create a recovery key
|
||||
final recoveryKey = CryptoUtil.generateKey();
|
||||
|
||||
// Encrypt master key and recovery key with each other
|
||||
final encryptedMasterKey = CryptoUtil.encryptSync(masterKey, recoveryKey);
|
||||
final encryptedRecoveryKey = CryptoUtil.encryptSync(recoveryKey, masterKey);
|
||||
|
||||
// Derive a key from the password that will be used to encrypt and
|
||||
// decrypt the master key
|
||||
final kekSalt = CryptoUtil.getSaltToDeriveKey();
|
||||
final derivedKeyResult = await CryptoUtil.deriveSensitiveKey(
|
||||
utf8.encode(password),
|
||||
kekSalt,
|
||||
);
|
||||
final loginKey = await CryptoUtil.deriveLoginKey(derivedKeyResult.key);
|
||||
|
||||
// Encrypt the key with this derived key
|
||||
final encryptedKeyData =
|
||||
CryptoUtil.encryptSync(masterKey, derivedKeyResult.key);
|
||||
|
||||
// Generate a public-private keypair and encrypt the latter
|
||||
final keyPair = CryptoUtil.generateKeyPair();
|
||||
final encryptedSecretKeyData =
|
||||
CryptoUtil.encryptSync(keyPair.secretKey.extractBytes(), masterKey);
|
||||
|
||||
final attributes = KeyAttributes(
|
||||
CryptoUtil.bin2base64(kekSalt),
|
||||
CryptoUtil.bin2base64(encryptedKeyData.encryptedData!),
|
||||
CryptoUtil.bin2base64(encryptedKeyData.nonce!),
|
||||
CryptoUtil.bin2base64(keyPair.publicKey),
|
||||
CryptoUtil.bin2base64(encryptedSecretKeyData.encryptedData!),
|
||||
CryptoUtil.bin2base64(encryptedSecretKeyData.nonce!),
|
||||
derivedKeyResult.memLimit,
|
||||
derivedKeyResult.opsLimit,
|
||||
CryptoUtil.bin2base64(encryptedMasterKey.encryptedData!),
|
||||
CryptoUtil.bin2base64(encryptedMasterKey.nonce!),
|
||||
CryptoUtil.bin2base64(encryptedRecoveryKey.encryptedData!),
|
||||
CryptoUtil.bin2base64(encryptedRecoveryKey.nonce!),
|
||||
);
|
||||
final privateAttributes = PrivateKeyAttributes(
|
||||
CryptoUtil.bin2base64(masterKey),
|
||||
CryptoUtil.bin2hex(recoveryKey),
|
||||
CryptoUtil.bin2base64(keyPair.secretKey.extractBytes()),
|
||||
);
|
||||
return KeyGenResult(attributes, privateAttributes, loginKey);
|
||||
}
|
||||
|
||||
Future<Tuple2<KeyAttributes, Uint8List>> getAttributesForNewPassword(
|
||||
String password,
|
||||
) async {
|
||||
// Get master key
|
||||
final masterKey = getKey();
|
||||
|
||||
// Derive a key from the password that will be used to encrypt and
|
||||
// decrypt the master key
|
||||
final kekSalt = CryptoUtil.getSaltToDeriveKey();
|
||||
final derivedKeyResult = await CryptoUtil.deriveSensitiveKey(
|
||||
utf8.encode(password),
|
||||
kekSalt,
|
||||
);
|
||||
final loginKey = await CryptoUtil.deriveLoginKey(derivedKeyResult.key);
|
||||
|
||||
// Encrypt the key with this derived key
|
||||
final encryptedKeyData =
|
||||
CryptoUtil.encryptSync(masterKey!, derivedKeyResult.key);
|
||||
|
||||
final existingAttributes = getKeyAttributes();
|
||||
|
||||
final updatedAttributes = existingAttributes!.copyWith(
|
||||
kekSalt: CryptoUtil.bin2base64(kekSalt),
|
||||
encryptedKey: CryptoUtil.bin2base64(encryptedKeyData.encryptedData!),
|
||||
keyDecryptionNonce: CryptoUtil.bin2base64(encryptedKeyData.nonce!),
|
||||
memLimit: derivedKeyResult.memLimit,
|
||||
opsLimit: derivedKeyResult.opsLimit,
|
||||
);
|
||||
return Tuple2(updatedAttributes, loginKey);
|
||||
}
|
||||
|
||||
// decryptSecretsAndGetLoginKey decrypts the master key and recovery key
|
||||
// with the given password and save them in local secure storage.
|
||||
// This method also returns the keyEncKey that can be used for performing
|
||||
// SRP setup for existing users.
|
||||
Future<Uint8List> decryptSecretsAndGetKeyEncKey(
|
||||
String password,
|
||||
KeyAttributes attributes, {
|
||||
Uint8List? keyEncryptionKey,
|
||||
}) async {
|
||||
_logger.info('Start decryptAndSaveSecrets');
|
||||
keyEncryptionKey ??= await CryptoUtil.deriveKey(
|
||||
utf8.encode(password),
|
||||
CryptoUtil.base642bin(attributes.kekSalt),
|
||||
attributes.memLimit,
|
||||
attributes.opsLimit,
|
||||
);
|
||||
|
||||
_logger.info('user-key done');
|
||||
Uint8List key;
|
||||
try {
|
||||
key = CryptoUtil.decryptSync(
|
||||
CryptoUtil.base642bin(attributes.encryptedKey),
|
||||
keyEncryptionKey,
|
||||
CryptoUtil.base642bin(attributes.keyDecryptionNonce),
|
||||
);
|
||||
} catch (e) {
|
||||
_logger.severe('master-key failed, incorrect password?', e);
|
||||
throw Exception("Incorrect password");
|
||||
}
|
||||
_logger.info("master-key done");
|
||||
await setKey(CryptoUtil.bin2base64(key));
|
||||
final secretKey = CryptoUtil.decryptSync(
|
||||
CryptoUtil.base642bin(attributes.encryptedSecretKey),
|
||||
key,
|
||||
CryptoUtil.base642bin(attributes.secretKeyDecryptionNonce),
|
||||
);
|
||||
_logger.info("secret-key done");
|
||||
await setSecretKey(CryptoUtil.bin2base64(secretKey));
|
||||
final token = CryptoUtil.openSealSync(
|
||||
CryptoUtil.base642bin(getEncryptedToken()!),
|
||||
CryptoUtil.base642bin(attributes.publicKey),
|
||||
secretKey,
|
||||
);
|
||||
_logger.info('appToken done');
|
||||
await setToken(
|
||||
CryptoUtil.bin2base64(token, urlSafe: true),
|
||||
);
|
||||
return keyEncryptionKey;
|
||||
}
|
||||
|
||||
Future<void> recover(String recoveryKey) async {
|
||||
// check if user has entered mnemonic code
|
||||
if (recoveryKey.contains(' ')) {
|
||||
final split = recoveryKey.split(' ');
|
||||
if (split.length != mnemonicKeyWordCount) {
|
||||
String wordThatIsFollowedByEmptySpaceInSplit = '';
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
String word = split[i];
|
||||
if (word.isEmpty) {
|
||||
wordThatIsFollowedByEmptySpaceInSplit =
|
||||
'\n\nExtra space after word at position $i';
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw AssertionError(
|
||||
'\nRecovery code should have $mnemonicKeyWordCount words, '
|
||||
'found ${split.length} words instead.$wordThatIsFollowedByEmptySpaceInSplit',
|
||||
);
|
||||
}
|
||||
recoveryKey = bip39.mnemonicToEntropy(recoveryKey);
|
||||
}
|
||||
final attributes = getKeyAttributes();
|
||||
Uint8List masterKey;
|
||||
try {
|
||||
masterKey = await CryptoUtil.decrypt(
|
||||
CryptoUtil.base642bin(attributes!.masterKeyEncryptedWithRecoveryKey),
|
||||
CryptoUtil.hex2bin(recoveryKey),
|
||||
CryptoUtil.base642bin(attributes.masterKeyDecryptionNonce),
|
||||
);
|
||||
} catch (e) {
|
||||
_logger.severe(e);
|
||||
rethrow;
|
||||
}
|
||||
await setKey(CryptoUtil.bin2base64(masterKey));
|
||||
final secretKey = CryptoUtil.decryptSync(
|
||||
CryptoUtil.base642bin(attributes.encryptedSecretKey),
|
||||
masterKey,
|
||||
CryptoUtil.base642bin(attributes.secretKeyDecryptionNonce),
|
||||
);
|
||||
await setSecretKey(CryptoUtil.bin2base64(secretKey));
|
||||
final token = CryptoUtil.openSealSync(
|
||||
CryptoUtil.base642bin(getEncryptedToken()!),
|
||||
CryptoUtil.base642bin(attributes.publicKey),
|
||||
secretKey,
|
||||
);
|
||||
await setToken(
|
||||
CryptoUtil.bin2base64(token, urlSafe: true),
|
||||
);
|
||||
}
|
||||
|
||||
String getHttpEndpoint() {
|
||||
return _preferences.getString(endPointKey) ?? endpoint;
|
||||
}
|
||||
|
||||
Future<void> setHttpEndpoint(String endpoint) async {
|
||||
await _preferences.setString(endPointKey, endpoint);
|
||||
Bus.instance.fire(EndpointUpdatedEvent());
|
||||
}
|
||||
|
||||
String? getToken() {
|
||||
_cachedToken ??= _preferences.getString(tokenKey);
|
||||
return _cachedToken;
|
||||
}
|
||||
|
||||
bool isLoggedIn() {
|
||||
return getToken() != null;
|
||||
}
|
||||
|
||||
Future<void> setToken(String token) async {
|
||||
_cachedToken = token;
|
||||
await _preferences.setString(tokenKey, token);
|
||||
Bus.instance.fire(SignedInEvent());
|
||||
}
|
||||
|
||||
Future<void> setEncryptedToken(String encryptedToken) async {
|
||||
await _preferences.setString(encryptedTokenKey, encryptedToken);
|
||||
}
|
||||
|
||||
String? getEncryptedToken() {
|
||||
return _preferences.getString(encryptedTokenKey);
|
||||
}
|
||||
|
||||
String? getEmail() {
|
||||
return _preferences.getString(emailKey);
|
||||
}
|
||||
|
||||
Future<void> setEmail(String email) async {
|
||||
await _preferences.setString(emailKey, email);
|
||||
}
|
||||
|
||||
int? getUserID() {
|
||||
return _preferences.getInt(userIDKey);
|
||||
}
|
||||
|
||||
Future<void> setUserID(int userID) async {
|
||||
await _preferences.setInt(userIDKey, userID);
|
||||
}
|
||||
|
||||
Future<void> setKeyAttributes(KeyAttributes attributes) async {
|
||||
await _preferences.setString(keyAttributesKey, attributes.toJson());
|
||||
}
|
||||
|
||||
KeyAttributes? getKeyAttributes() {
|
||||
final jsonValue = _preferences.getString(keyAttributesKey);
|
||||
if (jsonValue == null) {
|
||||
return null;
|
||||
} else {
|
||||
return KeyAttributes.fromJson(jsonValue);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setKey(String key) async {
|
||||
_key = key;
|
||||
await _secureStorage.write(
|
||||
key: keyKey,
|
||||
value: key,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> setSecretKey(String? secretKey) async {
|
||||
_secretKey = secretKey;
|
||||
await _secureStorage.write(
|
||||
key: secretKeyKey,
|
||||
value: secretKey,
|
||||
);
|
||||
}
|
||||
|
||||
Uint8List? getKey() {
|
||||
return _key == null ? null : CryptoUtil.base642bin(_key!);
|
||||
}
|
||||
|
||||
Uint8List? getSecretKey() {
|
||||
return _secretKey == null ? null : CryptoUtil.base642bin(_secretKey!);
|
||||
}
|
||||
|
||||
Uint8List getRecoveryKey() {
|
||||
final keyAttributes = getKeyAttributes()!;
|
||||
return CryptoUtil.decryptSync(
|
||||
CryptoUtil.base642bin(keyAttributes.recoveryKeyEncryptedWithMasterKey),
|
||||
getKey()!,
|
||||
CryptoUtil.base642bin(keyAttributes.recoveryKeyDecryptionNonce),
|
||||
);
|
||||
}
|
||||
|
||||
// Caution: This directory is cleared on app start
|
||||
String getTempDirectory() {
|
||||
return _tempDocumentsDirPath;
|
||||
}
|
||||
|
||||
String getCacheDirectory() {
|
||||
return _cacheDirectory;
|
||||
}
|
||||
|
||||
bool hasConfiguredAccount() {
|
||||
return getToken() != null && _key != null;
|
||||
}
|
||||
|
||||
void setVolatilePassword(String volatilePassword) {
|
||||
_volatilePassword = volatilePassword;
|
||||
}
|
||||
|
||||
void resetVolatilePassword() {
|
||||
_volatilePassword = null;
|
||||
}
|
||||
|
||||
String? getVolatilePassword() {
|
||||
return _volatilePassword;
|
||||
}
|
||||
}
|
||||
|
||||
5
mobile/packages/configuration/lib/constants.dart
Normal file
5
mobile/packages/configuration/lib/constants.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
const kDefaultProductionEndpoint = 'https://api.ente.io';
|
||||
|
||||
// 256 bit key maps to 24 words
|
||||
// https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#Generating_the_mnemonic
|
||||
const mnemonicKeyWordCount = 24;
|
||||
@@ -1,6 +1,14 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.7.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -9,6 +17,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.13.0"
|
||||
bip39:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: bip39
|
||||
sha256: de1ee27ebe7d96b84bb3a04a4132a0a3007dcdd5ad27dd14aa87a29d97c45edc
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.6"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -41,6 +57,84 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.6"
|
||||
csslib:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: csslib
|
||||
sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
device_info_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus
|
||||
sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.1.2"
|
||||
device_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus_platform_interface
|
||||
sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.3"
|
||||
ente_base:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "../base"
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.0.0"
|
||||
ente_crypto_dart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: HEAD
|
||||
resolved-ref: f91e1545f8263df127762240c4da54a0c42835b2
|
||||
url: "https://github.com/ente-io/ente_crypto_dart.git"
|
||||
source: git
|
||||
version: "1.0.0"
|
||||
ente_events:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "../events"
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.0.0"
|
||||
ente_logging:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "../logging"
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.0.0"
|
||||
event_bus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: event_bus
|
||||
sha256: "1a55e97923769c286d295240048fc180e7b0768902c3c2e869fe059aafa15304"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -49,6 +143,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum
|
||||
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@@ -62,11 +180,128 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
flutter_secure_storage:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_secure_storage
|
||||
sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.2.4"
|
||||
flutter_secure_storage_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_linux
|
||||
sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.3"
|
||||
flutter_secure_storage_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_macos
|
||||
sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
flutter_secure_storage_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_platform_interface
|
||||
sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
flutter_secure_storage_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_web
|
||||
sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
flutter_secure_storage_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_windows
|
||||
sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
freezed_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: freezed_annotation
|
||||
sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.4"
|
||||
hex:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: hex
|
||||
sha256: "4e7cd54e4b59ba026432a6be2dd9d96e4c5205725194997193bf871703b82c4a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: html
|
||||
sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.15.6"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.2"
|
||||
intl:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.20.2"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.9.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -99,6 +334,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -123,6 +366,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
package_info_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.3.0"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -131,11 +390,171 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.17"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.6"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.9.1"
|
||||
sentry:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sentry
|
||||
sha256: "599701ca0693a74da361bc780b0752e1abc98226cf5095f6b069648116c896bb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.14.2"
|
||||
sentry_flutter:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sentry_flutter
|
||||
sha256: "5ba2cf40646a77d113b37a07bd69f61bb3ec8a73cbabe5537b05a7c89d2656f8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.14.2"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.3"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.10"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_foundation
|
||||
sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.4"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_linux
|
||||
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
shared_preferences_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_platform_interface
|
||||
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
shared_preferences_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_web
|
||||
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.3"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_windows
|
||||
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
sodium:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sodium
|
||||
sha256: d9830a388e37c82891888e64cfd4c6764fa3ac716bed80ac6eab89ee42c3cd76
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1+1"
|
||||
sodium_libs:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sodium_libs
|
||||
sha256: aa764acd6ccc6113e119c2d99471aeeb4637a9a501639549b297d3a143ff49b3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1+6"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -144,6 +563,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.1"
|
||||
sprintf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sprintf
|
||||
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -168,6 +595,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: synchronized
|
||||
sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -184,6 +619,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.4"
|
||||
tuple:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: tuple
|
||||
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
uuid:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: uuid
|
||||
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.1"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -200,6 +659,38 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "15.0.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.14.0"
|
||||
win32_registry:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32_registry
|
||||
sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.5"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
sdks:
|
||||
dart: ">=3.7.0-0 <4.0.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
dart: ">=3.8.0 <4.0.0"
|
||||
flutter: ">=3.29.0"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
name: configuration
|
||||
description: A Flutter package for shared configuration across ente apps
|
||||
version: 1.0.0
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
@@ -9,6 +10,20 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
bip39: ^1.0.6
|
||||
ente_base:
|
||||
path: ../../packages/base
|
||||
ente_crypto_dart:
|
||||
git:
|
||||
url: https://github.com/ente-io/ente_crypto_dart.git
|
||||
ente_events:
|
||||
path: ../../packages/events
|
||||
ente_logging:
|
||||
path: ../../packages/logging
|
||||
flutter_secure_storage: ^9.0.0
|
||||
path_provider: ^2.1.5
|
||||
shared_preferences: ^2.5.3
|
||||
tuple: ^2.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
10
mobile/packages/events/analysis_options.yaml
Normal file
10
mobile/packages/events/analysis_options.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- always_declare_return_types
|
||||
- always_put_required_named_parameters_first
|
||||
- avoid_print
|
||||
- prefer_const_constructors
|
||||
- prefer_const_literals_to_create_immutables
|
||||
- use_key_in_widget_constructors
|
||||
13
mobile/packages/events/lib/ente_events.dart
Normal file
13
mobile/packages/events/lib/ente_events.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
library ente_events;
|
||||
|
||||
// Export the event bus
|
||||
export 'event_bus.dart';
|
||||
|
||||
// Export all event models
|
||||
export 'models/event.dart';
|
||||
export 'models/signed_in_event.dart';
|
||||
export 'models/signed_out_event.dart';
|
||||
export 'models/trigger_logout_event.dart';
|
||||
export 'models/user_details_changed_event.dart';
|
||||
export 'models/endpoint_updated_event.dart';
|
||||
export 'models/collections_updated_event.dart';
|
||||
5
mobile/packages/events/lib/event_bus.dart
Normal file
5
mobile/packages/events/lib/event_bus.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
import 'package:event_bus/event_bus.dart';
|
||||
|
||||
class Bus {
|
||||
static final EventBus instance = EventBus();
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import 'event.dart';
|
||||
|
||||
class CollectionsUpdatedEvent extends Event {}
|
||||
@@ -0,0 +1,3 @@
|
||||
import 'event.dart';
|
||||
|
||||
class EndpointUpdatedEvent extends Event {}
|
||||
1
mobile/packages/events/lib/models/event.dart
Normal file
1
mobile/packages/events/lib/models/event.dart
Normal file
@@ -0,0 +1 @@
|
||||
class Event {}
|
||||
3
mobile/packages/events/lib/models/signed_in_event.dart
Normal file
3
mobile/packages/events/lib/models/signed_in_event.dart
Normal file
@@ -0,0 +1,3 @@
|
||||
import 'event.dart';
|
||||
|
||||
class SignedInEvent extends Event {}
|
||||
3
mobile/packages/events/lib/models/signed_out_event.dart
Normal file
3
mobile/packages/events/lib/models/signed_out_event.dart
Normal file
@@ -0,0 +1,3 @@
|
||||
import 'event.dart';
|
||||
|
||||
class SignedOutEvent extends Event {}
|
||||
@@ -0,0 +1,3 @@
|
||||
import 'event.dart';
|
||||
|
||||
class TriggerLogoutEvent extends Event {}
|
||||
@@ -0,0 +1,3 @@
|
||||
import 'event.dart';
|
||||
|
||||
class UserDetailsChangedEvent extends Event {}
|
||||
213
mobile/packages/events/pubspec.lock
Normal file
213
mobile/packages/events/pubspec.lock
Normal file
@@ -0,0 +1,213 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.13.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
event_bus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: event_bus
|
||||
sha256: "1a55e97923769c286d295240048fc180e7b0768902c3c2e869fe059aafa15304"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.9"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.9"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.17"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.11.1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.12.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.2"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.4"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "15.0.0"
|
||||
sdks:
|
||||
dart: ">=3.7.0-0 <4.0.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
19
mobile/packages/events/pubspec.yaml
Normal file
19
mobile/packages/events/pubspec.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
name: ente_events
|
||||
description: A Flutter package for event management using event_bus, extracted from the surprise app
|
||||
version: 1.0.0
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
event_bus: ^2.0.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^5.0.0
|
||||
|
||||
flutter:
|
||||
10
mobile/packages/logging/analysis_options.yaml
Normal file
10
mobile/packages/logging/analysis_options.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- always_declare_return_types
|
||||
- always_put_required_named_parameters_first
|
||||
- avoid_print
|
||||
- prefer_const_constructors
|
||||
- prefer_const_literals_to_create_immutables
|
||||
- use_key_in_widget_constructors
|
||||
3
mobile/packages/logging/lib/logging.dart
Normal file
3
mobile/packages/logging/lib/logging.dart
Normal file
@@ -0,0 +1,3 @@
|
||||
export 'src/super_logging.dart';
|
||||
export 'src/tunneled_transport.dart';
|
||||
export 'package:logging/logging.dart';
|
||||
402
mobile/packages/logging/lib/src/super_logging.dart
Normal file
402
mobile/packages/logging/lib/src/super_logging.dart
Normal file
@@ -0,0 +1,402 @@
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'dart:core';
|
||||
import 'dart:io';
|
||||
|
||||
import 'tunneled_transport.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:logging/logging.dart' as log;
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
/// Type definition for functions that may return a value or Future
|
||||
typedef FutureOrVoidCallback = dynamic Function();
|
||||
|
||||
extension SuperString on String {
|
||||
Iterable<String> chunked(int chunkSize) sync* {
|
||||
var start = 0;
|
||||
|
||||
while (true) {
|
||||
final stop = start + chunkSize;
|
||||
if (stop > length) break;
|
||||
yield substring(start, stop);
|
||||
start = stop;
|
||||
}
|
||||
|
||||
if (start < length) {
|
||||
yield substring(start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension SuperLogRecord on log.LogRecord {
|
||||
String toPrettyString([String? extraLines]) {
|
||||
final header = "[$loggerName] [$level] [$time]";
|
||||
|
||||
var msg = "$header $message";
|
||||
|
||||
if (error != null) {
|
||||
msg += "\n⤷ type: ${error.runtimeType}\n⤷ error: $error";
|
||||
}
|
||||
if (stackTrace != null) {
|
||||
msg += "\n⤷ trace: $stackTrace";
|
||||
}
|
||||
|
||||
for (var line in extraLines?.split('\n') ?? []) {
|
||||
msg += '\n$header $line';
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
class LogConfig {
|
||||
/// The DSN for a Sentry app.
|
||||
/// This can be obtained from the Sentry apps's "settings > Client Keys (DSN)" page.
|
||||
///
|
||||
/// Only logs containing errors are sent to sentry.
|
||||
/// Errors can be caught using a try-catch block, like so:
|
||||
///
|
||||
/// ```
|
||||
/// final logger = Logger("main");
|
||||
///
|
||||
/// try {
|
||||
/// // do something dangerous here
|
||||
/// } catch(e, trace) {
|
||||
/// logger.info("Huston, we have a problem", e, trace);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// If this is [null], Sentry logger is completely disabled (default).
|
||||
String? sentryDsn;
|
||||
|
||||
String? tunnel;
|
||||
|
||||
/// A built-in retry mechanism for sending errors to sentry.
|
||||
///
|
||||
/// This parameter defines the time to wait for, before retrying.
|
||||
Duration sentryRetryDelay;
|
||||
|
||||
/// Path of the directory where log files will be stored.
|
||||
///
|
||||
/// If this is [null], file logging is completely disabled (default).
|
||||
///
|
||||
/// If this is an empty string (['']),
|
||||
/// then a 'logs' directory will be created in [getTemporaryDirectory()].
|
||||
///
|
||||
/// A non-empty string will be treated as an explicit path to a directory.
|
||||
///
|
||||
/// The chosen directory can be accessed using [SuperLogging.logFile.parent].
|
||||
String? logDirPath;
|
||||
|
||||
/// The maximum number of log files inside [logDirPath].
|
||||
///
|
||||
/// One log file is created per day.
|
||||
/// Older log files are deleted automatically.
|
||||
int maxLogFiles;
|
||||
|
||||
/// Whether to enable super logging features in debug mode.
|
||||
///
|
||||
/// Sentry and file logging are typically not needed in debug mode,
|
||||
/// where a complete logcat is available.
|
||||
bool enableInDebugMode;
|
||||
|
||||
/// If provided, super logging will invoke this function, and
|
||||
/// any uncaught errors during its execution will be reported.
|
||||
///
|
||||
/// Works by using [FlutterError.onError] and [runZoned].
|
||||
FutureOrVoidCallback? body;
|
||||
|
||||
/// The date format for storing log files.
|
||||
///
|
||||
/// `DateFormat('y-M-d')` by default.
|
||||
DateFormat? dateFmt;
|
||||
|
||||
String prefix;
|
||||
|
||||
LogConfig({
|
||||
this.sentryDsn,
|
||||
this.tunnel,
|
||||
this.sentryRetryDelay = const Duration(seconds: 30),
|
||||
this.logDirPath,
|
||||
this.maxLogFiles = 10,
|
||||
this.enableInDebugMode = false,
|
||||
this.body,
|
||||
this.dateFmt,
|
||||
this.prefix = "",
|
||||
}) {
|
||||
dateFmt ??= DateFormat("y-M-d");
|
||||
}
|
||||
}
|
||||
|
||||
class SuperLogging {
|
||||
/// The logger for SuperLogging
|
||||
static final $ = log.Logger('ente_logging');
|
||||
|
||||
/// The current super logging configuration
|
||||
static late LogConfig config;
|
||||
|
||||
static late SharedPreferences _preferences;
|
||||
|
||||
static const keyShouldReportErrors = "should_report_errors";
|
||||
|
||||
static const keyAnonymousUserID = "anonymous_user_id";
|
||||
|
||||
static Future<void> main([LogConfig? appConfig]) async {
|
||||
appConfig ??= LogConfig();
|
||||
SuperLogging.config = appConfig;
|
||||
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
_preferences = await SharedPreferences.getInstance();
|
||||
|
||||
appVersion ??= await getAppVersion();
|
||||
|
||||
final enable = appConfig.enableInDebugMode || kReleaseMode;
|
||||
sentryIsEnabled =
|
||||
enable && appConfig.sentryDsn != null && shouldReportErrors();
|
||||
fileIsEnabled = enable && appConfig.logDirPath != null;
|
||||
|
||||
if (fileIsEnabled) {
|
||||
await setupLogDir();
|
||||
}
|
||||
if (sentryIsEnabled) {
|
||||
setupSentry().ignore();
|
||||
}
|
||||
|
||||
log.Logger.root.level = log.Level.ALL;
|
||||
log.Logger.root.onRecord.listen(onLogRecord);
|
||||
|
||||
if (!enable) {
|
||||
$.info("detected debug mode; sentry & file logging disabled.");
|
||||
}
|
||||
if (fileIsEnabled) {
|
||||
$.info("log file for today: $logFile with prefix ${appConfig.prefix}");
|
||||
}
|
||||
if (sentryIsEnabled) {
|
||||
$.info("sentry uploader started");
|
||||
}
|
||||
|
||||
if (appConfig.body == null) return;
|
||||
|
||||
if (enable && sentryIsEnabled) {
|
||||
await SentryFlutter.init(
|
||||
(options) {
|
||||
options.dsn = appConfig!.sentryDsn;
|
||||
options.httpClient = http.Client();
|
||||
if (appConfig.tunnel != null) {
|
||||
options.transport =
|
||||
TunneledTransport(Uri.parse(appConfig.tunnel!), options);
|
||||
}
|
||||
},
|
||||
appRunner: () => appConfig!.body!(),
|
||||
);
|
||||
} else {
|
||||
await appConfig.body!();
|
||||
}
|
||||
}
|
||||
|
||||
static void setUserID(String userID) async {
|
||||
if (config.sentryDsn != null) {
|
||||
Sentry.configureScope((scope) => scope.setUser(SentryUser(id: userID)));
|
||||
$.info("setting sentry user ID to: $userID");
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> _sendErrorToSentry(
|
||||
Object error,
|
||||
StackTrace? stack,
|
||||
) async {
|
||||
try {
|
||||
await Sentry.captureException(
|
||||
error,
|
||||
stackTrace: stack,
|
||||
);
|
||||
} catch (e) {
|
||||
$.info('Sending report to sentry.io failed: $e');
|
||||
$.info('Original error: $error');
|
||||
}
|
||||
}
|
||||
|
||||
static String _lastExtraLines = '';
|
||||
|
||||
static Future onLogRecord(log.LogRecord rec) async {
|
||||
// log misc info if it changed
|
||||
String? extraLines = "app version: '$appVersion'\n";
|
||||
if (extraLines != _lastExtraLines) {
|
||||
_lastExtraLines = extraLines;
|
||||
} else {
|
||||
extraLines = null;
|
||||
}
|
||||
|
||||
final str = "${config.prefix} ${rec.toPrettyString(extraLines)}";
|
||||
|
||||
// write to stdout
|
||||
printLog(str);
|
||||
|
||||
// push to log queue
|
||||
if (fileIsEnabled) {
|
||||
fileQueueEntries.add('$str\n');
|
||||
if (fileQueueEntries.length == 1) {
|
||||
flushQueue();
|
||||
}
|
||||
}
|
||||
|
||||
// add error to sentry queue
|
||||
if (sentryIsEnabled && rec.error != null) {
|
||||
_sendErrorToSentry(rec.error!, null).ignore();
|
||||
}
|
||||
}
|
||||
|
||||
static final Queue<String> fileQueueEntries = Queue();
|
||||
static bool isFlushing = false;
|
||||
|
||||
static void flushQueue() async {
|
||||
if (isFlushing || logFile == null) {
|
||||
return;
|
||||
}
|
||||
isFlushing = true;
|
||||
final entry = fileQueueEntries.removeFirst();
|
||||
await logFile!.writeAsString(entry, mode: FileMode.append, flush: true);
|
||||
isFlushing = false;
|
||||
if (fileQueueEntries.isNotEmpty) {
|
||||
flushQueue();
|
||||
}
|
||||
}
|
||||
|
||||
// Logs on must be chunked or they get truncated otherwise
|
||||
// See https://github.com/flutter/flutter/issues/22665
|
||||
static var logChunkSize = 800;
|
||||
|
||||
static void printLog(String text) {
|
||||
text.chunked(logChunkSize).forEach(debugPrint);
|
||||
}
|
||||
|
||||
/// A queue to be consumed by [setupSentry].
|
||||
static final sentryQueueControl = StreamController<Error>();
|
||||
|
||||
/// Whether sentry logging is currently enabled or not.
|
||||
static bool sentryIsEnabled = false;
|
||||
|
||||
static Future<void> setupSentry() async {
|
||||
$.info("Setting up sentry");
|
||||
SuperLogging.setUserID(await _getOrCreateAnonymousUserID());
|
||||
await for (final error in sentryQueueControl.stream.asBroadcastStream()) {
|
||||
try {
|
||||
await Sentry.captureException(
|
||||
error,
|
||||
);
|
||||
} catch (e) {
|
||||
$.fine(
|
||||
"sentry upload failed; will retry after ${config.sentryRetryDelay}",
|
||||
);
|
||||
doSentryRetry(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doSentryRetry(Error error) async {
|
||||
await Future.delayed(config.sentryRetryDelay);
|
||||
sentryQueueControl.add(error);
|
||||
}
|
||||
|
||||
static bool shouldReportErrors() {
|
||||
if (_preferences.containsKey(keyShouldReportErrors)) {
|
||||
return _preferences.getBool(keyShouldReportErrors)!;
|
||||
} else {
|
||||
return kDebugMode;
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> setShouldReportErrors(bool value) {
|
||||
return _preferences.setBool(keyShouldReportErrors, value);
|
||||
}
|
||||
|
||||
static Future<String> _getOrCreateAnonymousUserID() async {
|
||||
if (!_preferences.containsKey(keyAnonymousUserID)) {
|
||||
//ignore: prefer_const_constructors
|
||||
await _preferences.setString(keyAnonymousUserID, Uuid().v4());
|
||||
}
|
||||
return _preferences.getString(keyAnonymousUserID)!;
|
||||
}
|
||||
|
||||
/// The log file currently in use.
|
||||
static File? logFile;
|
||||
|
||||
/// Whether file logging is currently enabled or not.
|
||||
static bool fileIsEnabled = false;
|
||||
|
||||
static Future<void> setupLogDir() async {
|
||||
var dirPath = config.logDirPath;
|
||||
|
||||
// choose [logDir]
|
||||
if (dirPath == null || dirPath.isEmpty) {
|
||||
final root = await getExternalStorageDirectory();
|
||||
dirPath = '${root!.path}/logs';
|
||||
}
|
||||
|
||||
// create [logDir]
|
||||
final dir = Directory(dirPath);
|
||||
await dir.create(recursive: true);
|
||||
|
||||
final files = <File>[];
|
||||
final dates = <File, DateTime>{};
|
||||
|
||||
// collect all log files with valid names
|
||||
await for (final file in dir.list()) {
|
||||
try {
|
||||
final date = config.dateFmt!.parse(basename(file.path));
|
||||
dates[file as File] = date;
|
||||
files.add(file);
|
||||
} on Exception catch (_) {}
|
||||
}
|
||||
final nowTime = DateTime.now();
|
||||
|
||||
// delete old log files, if [maxLogFiles] is exceeded.
|
||||
if (files.length > config.maxLogFiles) {
|
||||
// sort files based on ascending order of date (older first)
|
||||
files.sort(
|
||||
(a, b) => (dates[a] ?? nowTime).compareTo((dates[b] ?? nowTime)),
|
||||
);
|
||||
|
||||
final extra = files.length - config.maxLogFiles;
|
||||
final toDelete = files.sublist(0, extra);
|
||||
|
||||
for (final file in toDelete) {
|
||||
try {
|
||||
$.fine(
|
||||
"deleting log file ${file.path}",
|
||||
);
|
||||
await file.delete();
|
||||
} on Exception catch (_) {}
|
||||
}
|
||||
}
|
||||
|
||||
logFile = File("$dirPath/${config.dateFmt!.format(DateTime.now())}.txt");
|
||||
}
|
||||
|
||||
/// Current app version, obtained from package_info plugin.
|
||||
///
|
||||
/// See: [getAppVersion]
|
||||
static String? appVersion;
|
||||
|
||||
static Future<String> getAppVersion() async {
|
||||
final pkgInfo = await PackageInfo.fromPlatform();
|
||||
return "${pkgInfo.version}+${pkgInfo.buildNumber}";
|
||||
}
|
||||
|
||||
// disable sentry on f-droid. We need to make it opt-in preference
|
||||
static Future<bool> isFDroidBuild() async {
|
||||
if (!Platform.isAndroid) {
|
||||
return false;
|
||||
}
|
||||
final pkgName = (await PackageInfo.fromPlatform()).packageName;
|
||||
return pkgName.endsWith("fdroid");
|
||||
}
|
||||
}
|
||||
140
mobile/packages/logging/lib/src/tunneled_transport.dart
Normal file
140
mobile/packages/logging/lib/src/tunneled_transport.dart
Normal file
@@ -0,0 +1,140 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:http/http.dart';
|
||||
import 'package:sentry/sentry.dart';
|
||||
|
||||
/// A transport is in charge of sending the event to the Sentry server.
|
||||
class TunneledTransport implements Transport {
|
||||
final Uri _tunnel;
|
||||
final SentryOptions _options;
|
||||
|
||||
final Dsn? _dsn;
|
||||
|
||||
_CredentialBuilder? _credentialBuilder;
|
||||
|
||||
final Map<String, String> _headers;
|
||||
|
||||
factory TunneledTransport(Uri tunnel, SentryOptions options) {
|
||||
return TunneledTransport._(tunnel, options);
|
||||
}
|
||||
|
||||
TunneledTransport._(this._tunnel, this._options)
|
||||
: _dsn = _options.dsn != null ? Dsn.parse(_options.dsn!) : null,
|
||||
_headers = _buildHeaders(
|
||||
_options.platformChecker.isWeb,
|
||||
_options.sentryClientName,
|
||||
) {
|
||||
_credentialBuilder = _CredentialBuilder(
|
||||
_dsn,
|
||||
_options.sentryClientName,
|
||||
// ignore: invalid_use_of_internal_member
|
||||
_options.clock,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SentryId?> send(SentryEnvelope envelope) async {
|
||||
final streamedRequest = await _createStreamedRequest(envelope);
|
||||
final response = await _options.httpClient
|
||||
.send(streamedRequest)
|
||||
.then(Response.fromStream);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
// body guard to not log the error as it has performance impact to allocate
|
||||
// the body String.
|
||||
if (_options.debug) {
|
||||
_options.logger(
|
||||
SentryLevel.error,
|
||||
'API returned an error, statusCode = ${response.statusCode}, '
|
||||
'body = ${response.body}',
|
||||
);
|
||||
}
|
||||
return const SentryId.empty();
|
||||
} else {
|
||||
_options.logger(
|
||||
SentryLevel.debug,
|
||||
'Envelope ${envelope.header.eventId ?? "--"} was sent successfully.',
|
||||
);
|
||||
}
|
||||
|
||||
final eventId = json.decode(response.body)['id'];
|
||||
if (eventId == null) {
|
||||
return null;
|
||||
}
|
||||
return SentryId.fromId(eventId);
|
||||
}
|
||||
|
||||
Future<StreamedRequest> _createStreamedRequest(
|
||||
SentryEnvelope envelope,
|
||||
) async {
|
||||
final streamedRequest = StreamedRequest('POST', _tunnel);
|
||||
envelope
|
||||
.envelopeStream(_options)
|
||||
.listen(streamedRequest.sink.add)
|
||||
.onDone(streamedRequest.sink.close);
|
||||
|
||||
streamedRequest.headers.addAll(_credentialBuilder!.configure(_headers));
|
||||
|
||||
return streamedRequest;
|
||||
}
|
||||
}
|
||||
|
||||
class _CredentialBuilder {
|
||||
final String _authHeader;
|
||||
|
||||
final ClockProvider _clock;
|
||||
|
||||
int get timestamp => _clock().millisecondsSinceEpoch;
|
||||
|
||||
_CredentialBuilder._(String authHeader, ClockProvider clock)
|
||||
: _authHeader = authHeader,
|
||||
_clock = clock;
|
||||
|
||||
factory _CredentialBuilder(
|
||||
Dsn? dsn,
|
||||
String sdkIdentifier,
|
||||
ClockProvider clock,
|
||||
) {
|
||||
final authHeader = _buildAuthHeader(
|
||||
publicKey: dsn?.publicKey,
|
||||
secretKey: dsn?.secretKey,
|
||||
sdkIdentifier: sdkIdentifier,
|
||||
);
|
||||
|
||||
return _CredentialBuilder._(authHeader, clock);
|
||||
}
|
||||
|
||||
static String _buildAuthHeader({
|
||||
String? publicKey,
|
||||
String? secretKey,
|
||||
String? sdkIdentifier,
|
||||
}) {
|
||||
var header = 'Sentry sentry_version=7, sentry_client=$sdkIdentifier, '
|
||||
'sentry_key=$publicKey';
|
||||
|
||||
if (secretKey != null) {
|
||||
header += ', sentry_secret=$secretKey';
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
Map<String, String> configure(Map<String, String> headers) {
|
||||
return headers
|
||||
..addAll(
|
||||
<String, String>{
|
||||
'X-Sentry-Auth': '$_authHeader, sentry_timestamp=$timestamp',
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, String> _buildHeaders(bool isWeb, String sdkIdentifier) {
|
||||
final headers = {'Content-Type': 'application/x-sentry-envelope'};
|
||||
// NOTE(lejard_h) overriding user agent on VM and Flutter not sure why
|
||||
// for web it use browser user agent
|
||||
if (!isWeb) {
|
||||
headers['User-Agent'] = sdkIdentifier;
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
474
mobile/packages/logging/pubspec.lock
Normal file
474
mobile/packages/logging/pubspec.lock
Normal file
@@ -0,0 +1,474 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.13.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.6"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum
|
||||
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.2"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.20.2"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.9"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.9"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
logging:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: logging
|
||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.17"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.11.1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
package_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.3.0"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
path:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path
|
||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.5"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.17"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.6"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
sentry:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sentry
|
||||
sha256: "599701ca0693a74da361bc780b0752e1abc98226cf5095f6b069648116c896bb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.14.2"
|
||||
sentry_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sentry_flutter
|
||||
sha256: "5ba2cf40646a77d113b37a07bd69f61bb3ec8a73cbabe5537b05a7c89d2656f8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.14.2"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.3"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.10"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_foundation
|
||||
sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.4"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_linux
|
||||
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
shared_preferences_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_platform_interface
|
||||
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
shared_preferences_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_web
|
||||
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.3"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_windows
|
||||
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.1"
|
||||
sprintf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sprintf
|
||||
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.12.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.2"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.4"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
uuid:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: uuid
|
||||
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.1"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "15.0.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.14.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
sdks:
|
||||
dart: ">=3.8.0 <4.0.0"
|
||||
flutter: ">=3.27.0"
|
||||
28
mobile/packages/logging/pubspec.yaml
Normal file
28
mobile/packages/logging/pubspec.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
name: ente_logging
|
||||
description: A Flutter package for logging functionality across ente apps
|
||||
version: 1.0.0
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
http: ^1.4.0
|
||||
intl: ^0.20.2
|
||||
logging: ^1.3.0
|
||||
package_info_plus: ^8.3.0
|
||||
path: ^1.9.0
|
||||
path_provider: ^2.1.5
|
||||
sentry: ^8.14.2
|
||||
sentry_flutter: ^8.14.2
|
||||
shared_preferences: ^2.5.3
|
||||
uuid: ^4.5.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^5.0.0
|
||||
|
||||
flutter:
|
||||
Reference in New Issue
Block a user