Files
Client/lib/storage/keychain_write.dart
T

35 lines
1.3 KiB
Dart

import 'package:flutter/services.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
/// `errSecDuplicateItem`: the iOS keychain refused to add an item that is
/// already there.
const int kErrSecDuplicateItem = -25299;
/// Whether [error] is the iOS keychain's "item already exists" failure.
/// flutter_secure_storage surfaces it as a PlatformException whose details
/// (and message) carry the OSStatus.
bool isKeychainDuplicateItem(Object error) {
if (error is! PlatformException) return false;
if (error.details == kErrSecDuplicateItem) return true;
return error.message?.contains('$kErrSecDuplicateItem') ?? false;
}
extension KeychainWrite on FlutterSecureStorage {
/// [write] that survives `errSecDuplicateItem`. The plugin's iOS write is
/// check-then-add/update and not atomic: a concurrent write to the same key
/// — or an existence check that itself failed (seen with the disk full) —
/// ends in SecItemAdd on an existing item. The second attempt finds the
/// item and updates it.
Future<void> writeRetrying({
required String key,
required String value,
}) async {
try {
await write(key: key, value: value);
} on PlatformException catch (e) {
if (!isKeychainDuplicateItem(e)) rethrow;
await write(key: key, value: value);
}
}
}