Skip to content

Commit

Permalink
feat: (Breaking; new major version 4.0.0) Take up new major version 3…
Browse files Browse the repository at this point in the history
….0.0 of at_persistence_spec, update and simplify the HiveKeyStore implementation accordingly.

feat: (non-breaking) Add support for the new `immutable` flag
  • Loading branch information
gkc committed Mar 10, 2025
1 parent 1522d14 commit 7f28374
Show file tree
Hide file tree
Showing 20 changed files with 185 additions and 381 deletions.
3 changes: 3 additions & 0 deletions packages/at_persistence_secondary_server/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 4.0.0
- refactor: Take up new major version 3.0.0 of at_persistence_spec, update and
simplify the HiveKeyStore implementation accordingly
## 3.1.0
- feat: commit log changes for sync skipDeletesUntil feature
- build[deps]: Upgraded the following package:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export 'package:at_persistence_secondary_server/src/notification/at_notification
export 'package:at_persistence_secondary_server/src/notification/at_notification_keystore.dart';
export 'package:at_persistence_secondary_server/src/notification/at_notification_manager.dart';
export 'package:at_persistence_secondary_server/src/notification/at_notification_strategy.dart';
export 'package:at_persistence_secondary_server/src/utils/at_metadata_adapter.dart';
export 'package:at_persistence_secondary_server/src/utils/date_time_extensions.dart';
export 'package:at_persistence_spec/at_persistence_spec.dart';
export 'package:at_persistence_secondary_server/src/compaction/at_compaction_service.dart';
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,11 @@ class AtConfig {
var newData = AtData();
newData.data = jsonEncode(config);

newData = HiveKeyStoreHelper.getInstance()
.prepareDataForKeystoreOperation(newData, existingAtData: existingData);
newData = HiveKeyStoreHelper.getInstance().prepareDataForKeystoreOperation(
newData,
existingAtData: existingData,
atSign: persistenceManager.atsign!,
);

logger.finest('Storing the config key:$configKey | Value: $newData');
await persistenceManager.getBox().put(configKey, newData);
Expand Down Expand Up @@ -168,7 +171,8 @@ class AtConfig {
AtData newAtData = AtData()..data = existingData.data;
HiveKeyStoreHelper.getInstance().prepareDataForKeystoreOperation(
newAtData,
existingAtData: existingData);
existingAtData: existingData,
atSign: persistenceManager.atsign!);
// store the existing data with the new key
await persistenceManager.getBox().put(configKey, newAtData);
logger.info('Successfully migrated configKey data to new key format');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ mixin HiveBase<E> {
}
}
if (getBox().isOpen) {
_logger.info('$boxName initialized successfully');
_logger.finer('$boxName initialized successfully');
} else {
_logger.shout('$boxName was apparently initialized, but is not open');
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,25 +90,11 @@ class HiveKeystore implements SecondaryKeyStore<String, AtData?, AtMetaData?> {
return value;
}

/// hive does not support directly storing emoji characters. So keys are encoded in [HiveKeyStoreHelper.prepareKey] using utf7 before storing.
/// hive does not support directly storing emoji characters, therefore keys
/// are encoded in [HiveKeyStoreHelper.prepareKey] using utf7 before storing.
@override
Future<dynamic> put(String key, AtData? value,
{int? time_to_live,
int? time_to_born,
int? time_to_refresh,
bool? isCascade,
bool? isBinary,
bool? isEncrypted,
String? dataSignature,
String? sharedKeyEncrypted,
String? publicKeyChecksum,
String? encoding,
String? encKeyName,
String? encAlgo,
String? ivNonce,
String? skeEncKeyName,
String? skeEncAlgo,
bool skipCommit = false}) async {
{bool skipCommit = false}) async {
key = key.toLowerCase();
final atKey = AtKey.getKeyType(key, enforceNameSpace: false);
if (atKey == KeyType.invalidKey) {
Expand All @@ -117,77 +103,19 @@ class HiveKeystore implements SecondaryKeyStore<String, AtData?, AtMetaData?> {
}
// ignore: prefer_typing_uninitialized_variables
var result;
// Default the commit op to just the value update
CommitOp commitOp = CommitOp.UPDATE;

// Set CommitOp to UPDATE_META if any of the metadata args are not null
var hasNonNullMetadata = ObjectsUtil.anyNotNull({
time_to_live,
time_to_born,
time_to_refresh,
isCascade,
isBinary,
isEncrypted,
dataSignature,
sharedKeyEncrypted,
publicKeyChecksum,
encoding,
encKeyName,
encAlgo,
ivNonce,
skeEncKeyName,
skeEncAlgo
});
if (hasNonNullMetadata) {
commitOp = CommitOp.UPDATE_META;
}
// But if the value is not null, the CommitOp will always be UPDATE_ALL
if (value != null) {
commitOp = CommitOp.UPDATE_ALL;
}

CommitOp commitOp = CommitOp.UPDATE_ALL;

try {
// If does not exist, create a new key,
// else update existing key.
if (!isKeyExists(key)) {
result = await create(key, value,
time_to_live: time_to_live,
time_to_born: time_to_born,
time_to_refresh: time_to_refresh,
isCascade: isCascade,
isBinary: isBinary,
isEncrypted: isEncrypted,
dataSignature: dataSignature,
sharedKeyEncrypted: sharedKeyEncrypted,
publicKeyChecksum: publicKeyChecksum,
encoding: encoding,
encKeyName: encKeyName,
encAlgo: encAlgo,
ivNonce: ivNonce,
skeEncKeyName: skeEncKeyName,
skeEncAlgo: skeEncAlgo,
skipCommit: skipCommit);
result = await create(key, value, skipCommit: skipCommit);
} else {
AtData? existingData = await get(key);
String hive_key = keyStoreHelper.prepareKey(key);
var hive_value = keyStoreHelper.prepareDataForKeystoreOperation(value!,
existingAtData: existingData!,
ttl: time_to_live,
ttb: time_to_born,
ttr: time_to_refresh,
isCascade: isCascade,
isBinary: isBinary,
isEncrypted: isEncrypted,
dataSignature: dataSignature,
sharedKeyEncrypted: sharedKeyEncrypted,
publicKeyChecksum: publicKeyChecksum,
encoding: encoding,
encKeyName: encKeyName,
encAlgo: encAlgo,
ivNonce: ivNonce,
skeEncKeyName: skeEncKeyName,
skeEncAlgo: skeEncAlgo,
atSign: persistenceManager?.atsign);
existingAtData: existingData!, atSign: persistenceManager!.atsign!);
logger.finest('hive key:$hive_key');
logger.finest('hive value:$hive_value');
await persistenceManager!.getBox().put(hive_key, hive_value);
Expand All @@ -211,26 +139,12 @@ class HiveKeystore implements SecondaryKeyStore<String, AtData?, AtMetaData?> {
return result;
}

/// hive does not support directly storing emoji characters. So keys are encoded in [HiveKeyStoreHelper.prepareKey] using utf7 before storing.
/// hive does not support directly storing emoji characters, therefore keys
/// are encoded in [HiveKeyStoreHelper.prepareKey] using utf7 before storing.
@override
@server
Future<dynamic> create(String key, AtData? value,
{int? time_to_live,
int? time_to_born,
int? time_to_refresh,
bool? isCascade,
bool? isBinary,
bool? isEncrypted,
String? dataSignature,
String? sharedKeyEncrypted,
String? publicKeyChecksum,
String? encoding,
String? encKeyName,
String? encAlgo,
String? ivNonce,
String? skeEncKeyName,
String? skeEncAlgo,
bool skipCommit = false}) async {
{bool skipCommit = false}) async {
key = key.toLowerCase();
final atKey = AtKey.getKeyType(key, enforceNameSpace: false);
if (atKey == KeyType.invalidKey) {
Expand All @@ -241,62 +155,32 @@ class HiveKeystore implements SecondaryKeyStore<String, AtData?, AtMetaData?> {
CommitOp commitOp;
String hive_key = keyStoreHelper.prepareKey(key);
_checkMaxLength(hive_key);
var hive_data = keyStoreHelper.prepareDataForKeystoreOperation(value!,
atSign: persistenceManager?.atsign,
ttl: time_to_live,
ttb: time_to_born,
ttr: time_to_refresh,
isCascade: isCascade,
isBinary: isBinary,
isEncrypted: isEncrypted,
dataSignature: dataSignature,
sharedKeyEncrypted: sharedKeyEncrypted,
publicKeyChecksum: publicKeyChecksum,
encoding: encoding,
encKeyName: encKeyName,
encAlgo: encAlgo,
ivNonce: ivNonce,
skeEncKeyName: skeEncKeyName,
skeEncAlgo: skeEncAlgo);
var hive_data = keyStoreHelper.prepareDataForKeystoreOperation(
value!,
atSign: persistenceManager!.atsign!,
);
// Default commitOp to Update.
commitOp = CommitOp.UPDATE;

// Setting metadata defined in values
if (value.metaData != null) {
time_to_live ??= value.metaData!.ttl;
time_to_born ??= value.metaData!.ttb;
time_to_refresh ??= value.metaData!.ttr;
isCascade ??= value.metaData!.isCascade;
isBinary ??= value.metaData!.isBinary;
isEncrypted ??= value.metaData!.isEncrypted;
dataSignature ??= value.metaData!.dataSignature;
sharedKeyEncrypted ??= value.metaData!.sharedKeyEnc;
publicKeyChecksum ??= value.metaData!.pubKeyCS;
encoding ??= value.metaData!.encoding;
encKeyName ??= value.metaData!.encKeyName;
encAlgo ??= value.metaData!.encAlgo;
ivNonce ??= value.metaData!.ivNonce;
skeEncKeyName ??= value.metaData!.skeEncKeyName;
skeEncAlgo ??= value.metaData!.skeEncAlgo;
}

// Set CommitOp to UPDATE_ALL if any of the metadata args are not null
if (ObjectsUtil.anyNotNull({
time_to_live,
time_to_born,
time_to_refresh,
isCascade,
isBinary,
isEncrypted,
dataSignature,
sharedKeyEncrypted,
publicKeyChecksum,
encoding,
encKeyName,
encAlgo,
ivNonce,
skeEncKeyName,
skeEncAlgo
value.metaData?.ttl,
value.metaData?.ttb,
value.metaData?.ttr,
value.metaData?.isCascade,
value.metaData?.isBinary,
value.metaData?.isEncrypted,
value.metaData?.dataSignature,
value.metaData?.sharedKeyEnc,
value.metaData?.pubKeyCS,
value.metaData?.encoding,
value.metaData?.encKeyName,
value.metaData?.encAlgo,
value.metaData?.ivNonce,
value.metaData?.skeEncKeyName,
value.metaData?.skeEncAlgo,
value.metaData?.pubKeyHash,
value.metaData?.immutable,
})) {
commitOp = CommitOp.UPDATE_ALL;
}
Expand Down Expand Up @@ -398,7 +282,7 @@ class HiveKeystore implements SecondaryKeyStore<String, AtData?, AtMetaData?> {

/// Returns list of keys from the secondary storage.
/// @param - regex : Optional parameter to filter keys on regular expression.
/// @return - List<String> : List of keys from secondary storage.
/// @return - `List<String>` : List of keys from secondary storage.
@override
List<String> getKeys({String? regex}) {
if (persistenceManager == null ||
Expand Down Expand Up @@ -467,9 +351,9 @@ class HiveKeystore implements SecondaryKeyStore<String, AtData?, AtMetaData?> {
existingData = await get(key);
}
value!.metaData = AtMetadataBuilder(
newAtMetaData: metadata,
newAtMetaData: metadata!,
existingMetaData: existingData?.metaData,
atSign: persistenceManager?.atsign)
atSign: persistenceManager!.atsign!)
.build();
await persistenceManager!.getBox().put(hive_key, value);
_updateMetadataCache(key, value.metaData);
Expand All @@ -495,9 +379,9 @@ class HiveKeystore implements SecondaryKeyStore<String, AtData?, AtMetaData?> {
// So, fetch the value from the existing key and set the same value.
AtData newData = existingData ?? AtData();
newData.metaData = AtMetadataBuilder(
newAtMetaData: metadata,
newAtMetaData: metadata!,
existingMetaData: existingData?.metaData,
atSign: persistenceManager?.atsign)
atSign: persistenceManager!.atsign!)
.build();

await persistenceManager!.getBox().put(hive_key, newData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,45 +17,14 @@ class HiveKeyStoreHelper {
}

AtData prepareDataForKeystoreOperation(AtData newAtData,
{AtData? existingAtData,
int? ttl,
int? ttb,
int? ttr,
bool? isCascade,
bool? isBinary,
bool? isEncrypted,
String? dataSignature,
String? sharedKeyEncrypted,
String? publicKeyChecksum,
String? encoding,
String? encKeyName,
String? encAlgo,
String? ivNonce,
String? skeEncKeyName,
String? skeEncAlgo,
String? atSign}) {
{AtData? existingAtData, required String atSign}) {
var atData = AtData();
atData.data = newAtData.data;
atData.metaData = AtMetadataBuilder(
atSign: atSign,
newAtMetaData: newAtData.metaData,
existingMetaData: existingAtData?.metaData,
ttl: ttl,
ttb: ttb,
ttr: ttr,
ccd: isCascade,
isBinary: isBinary,
isEncrypted: isEncrypted,
dataSignature: dataSignature,
sharedKeyEncrypted: sharedKeyEncrypted,
publicKeyChecksum: publicKeyChecksum,
encoding: encoding,
encKeyName: encKeyName,
encAlgo: encAlgo,
ivNonce: ivNonce,
skeEncKeyName: skeEncKeyName,
skeEncAlgo: skeEncAlgo)
.build();
atSign: atSign,
newAtMetaData: newAtData.metaData,
existingMetaData: existingAtData?.metaData,
).build();
return atData;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class HivePersistenceManager with HiveBase {
if (!Hive.isAdapterRegistered(AtMetaDataAdapter().typeId)) {
Hive.registerAdapter(AtMetaDataAdapter());
}
if (!Hive.isAdapterRegistered(PublicKeyHashAdapater().typeId)) {
Hive.registerAdapter(PublicKeyHashAdapater());
if (!Hive.isAdapterRegistered(PublicKeyHashAdapter().typeId)) {
Hive.registerAdapter(PublicKeyHashAdapter());
}

var secret = await _getHiveSecretFromFile(_atsign!, storagePath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class AccessLogKeyStore

/// Returns the list of expired keys.
/// @param expiryInDays - The count of days after which the keys expires
/// @return List<dynamic> - The list of expired keys.
/// @return `List<dynamic>` - The list of expired keys.
@override
Future<List<dynamic>> getExpired(int expiryInDays) async {
var expiredKeys = <dynamic>[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ class CommitLogCache {
if (existingCommitId != null &&
commitEntry.commitId != null &&
existingCommitId > commitEntry.commitId!) {
_logger.shout(
_logger.info(
'Ignoring commit entry update to cache. existingCommitId: $existingCommitId | toUpdateWithCommitId: ${commitEntry.commitId}');
return;
}
Expand Down
Loading

0 comments on commit 7f28374

Please sign in to comment.