Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add AtServerEvent interface and AtSignPKChangedEvent class. Enables better reset handling #773

Merged
merged 11 commits into from
Feb 25, 2025
Merged
1 change: 1 addition & 0 deletions packages/at_commons/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 5.2.0
- feat: add Atsign string extensions
- feat: add AtServerEvent interface and AtSignPKChangedEvent class
## 5.1.2
- fix: remove isPaginated check in SyncVerbBuilder and always set from: and limit: since sync:from verb
expects these params to be set.
Expand Down
2 changes: 1 addition & 1 deletion packages/at_commons/lib/at_builders.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
library at_builders;
library;

export 'package:at_commons/src/verb/config_verb_builder.dart';
export 'package:at_commons/src/verb/delete_verb_builder.dart';
Expand Down
3 changes: 2 additions & 1 deletion packages/at_commons/lib/at_commons.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
library at_commons;
library;

import 'package:meta/meta.dart';

Expand Down Expand Up @@ -35,3 +35,4 @@ export 'package:at_commons/src/utils/at_key_regex_utils.dart';
export 'package:at_commons/src/telemetry/at_telemetry.dart';
export 'package:at_commons/src/utils/string_utils.dart';
export 'package:at_commons/src/keystore/public_key_hash.dart';
export 'package:at_commons/src/atserver/atserver_events.dart';
1 change: 1 addition & 0 deletions packages/at_commons/lib/src/at_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,5 @@ class AtConstants {
static const String defaultEncryptionPrivateKey = 'default_enc_private_key';
static const String defaultSelfEncryptionKey = 'default_self_enc_key';
static const String enrollParams = 'enrollParams';
static const String atServerReservedNamespace = '__atserver';
}
1 change: 1 addition & 0 deletions packages/at_commons/lib/src/at_message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ extension AtMessageExtension on AtMessage {
return noAtSign;
case AtMessage.controlCharacter:
return controlCharacter;
// ignore: unreachable_switch_default
default:
return notFoundMsg;
}
Expand Down
55 changes: 55 additions & 0 deletions packages/at_commons/lib/src/atserver/atserver_events.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import 'dart:convert';

import 'package:at_commons/atsign.dart';

const JsonEncoder jsonPrettyPrinter = JsonEncoder.withIndent(' ');

/// Events which are generated by an atServer. Initial example is the
/// [AtSignPKChangedEvent] but we want to allow for others in future.
abstract interface class AtServerEvent {
static const String atProtocolCategory = 'atProtocol';
static const String atSignPKChangedEventName = 'atsign_pk_changed';

/// The category of event. Events which are part of the atProtocol will
/// have a category of 'atProtocol'. Events which are specific to particular
/// AtServer implementations should have a different category (e.g. the name
/// of the implementation)
String get category;

/// The name of the event
String get name;

/// The event's data (JSON map)
Map<String, dynamic> get data;

Map<String, dynamic> toJson() => {
'category': category,
'name': name,
'data': data,
};
}

/// This event is specific to when the 'public:publickey@alice' key changes.
class AtSignPKChangedEvent extends AtServerEvent {
@override
final String category = AtServerEvent.atProtocolCategory;

@override
final String name = AtServerEvent.atSignPKChangedEventName;

/// The atSign whose PK has changed
final Atsign atSign;

AtSignPKChangedEvent(String atSign) : atSign = atSign.toAtsign();

@override
Map<String, dynamic> get data => {
'atSign': atSign,
};

static AtSignPKChangedEvent fromJson(Map<String, dynamic> json) =>
AtSignPKChangedEvent(json['data']['atSign']);

@override
String toString() => jsonPrettyPrinter.convert(toJson());
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore_for_file: use_super_parameters

import 'package:at_commons/src/exception/at_exceptions.dart';

class AtClientException extends AtException {
Expand Down
2 changes: 2 additions & 0 deletions packages/at_commons/lib/src/exception/at_exceptions.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore_for_file: use_super_parameters

import 'package:at_commons/at_commons.dart';

/// The class [AtException] and its subclasses represents various exceptions that can arise
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// ignore_for_file: use_super_parameters

import 'package:at_commons/src/exception/at_exceptions.dart';

class AtServerException extends AtException {
Expand Down
2 changes: 1 addition & 1 deletion packages/at_commons/lib/src/keystore/at_key.dart
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ class Metadata {
/// * When multiple asymmetric keypairs are in use, @bob will need to know which of them was used to
/// encrypt [sharedKeyEnc]. [skeEncKeyName] will only be null when the legacy default public key
/// was used; conversely if the legacy default public key was used then [skeEncKeyName] must be
/// null. Non-null values _must_ look like this "<keyName>.__public_keys.<namespace>" - i.e. must not include
/// null. Non-null values _must_ look like this: `<keyName>.__public_keys.<namespace>` - i.e. must not include
/// either the visibility prefix, which is always `public:`, nor the ownership suffix, which is always
/// the receiving atSign (in this case `@bob`)
String? skeEncKeyName;
Expand Down
6 changes: 2 additions & 4 deletions packages/at_commons/lib/src/telemetry/at_telemetry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,12 @@ abstract class AtTelemetryItem {

/// Concrete [AtTelemetryItem] subclass for Events - e.g. SyncStarted, NetworkUnavailable, MonitorUnavailable
class AtTelemetryEvent extends AtTelemetryItem {
AtTelemetryEvent(String name, value, {DateTime? time})
: super(name, value, time: time);
AtTelemetryEvent(super.name, super.value, {super.time});
}

@experimental

/// Concrete [AtTelemetryItem] subclass for Samples - e.g. KeyStoreSize, DataReceived, DataTransmitted
class AtTelemetrySample extends AtTelemetryItem {
AtTelemetrySample(String name, value, {DateTime? time})
: super(name, value, time: time);
AtTelemetrySample(super.name, super.value, {super.time});
}
2 changes: 1 addition & 1 deletion packages/at_commons/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ repository: https://github.com/atsign-foundation/at_libraries
homepage: https://atsign.dev

environment:
sdk: ">=2.15.0 <4.0.0"
sdk: '>=3.0.0 <4.0.0'

dependencies:
json_annotation: ^4.9.0
Expand Down
43 changes: 43 additions & 0 deletions packages/at_commons/test/atserver_events_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'package:at_commons/at_commons.dart';
import 'package:test/test.dart';

void main() {
test('Test atSignPKChangedEvent toJson', () {
AtSignPKChangedEvent e = AtSignPKChangedEvent('@alice');
expect(e.toJson(), {
'category': AtServerEvent.atProtocolCategory,
'name': AtServerEvent.atSignPKChangedEventName,
'data': {'atSign': '@alice'}
});
});

test('Test atSignPKChangedEvent fromJson', () {
AtSignPKChangedEvent e1 = AtSignPKChangedEvent('@alice');
AtSignPKChangedEvent e2 = AtSignPKChangedEvent.fromJson(e1.toJson());
expect(e2.toJson(), e1.toJson());
expect(e2.atSign, e1.atSign);
});

test('Test atSignPKChangedEvent makes all latin chars lowercase', () {
final e = AtSignPKChangedEvent('@ALICE');
expect(e.atSign, '@alice');
});

test('Test atSignPKChangedEvent rejects invalid atSigns', () {
expect(() => AtSignPKChangedEvent('@al@ice'),
throwsA(isA<InvalidAtSignException>()));
expect(() => AtSignPKChangedEvent('al@ice'),
throwsA(isA<InvalidAtSignException>()));
expect(() => AtSignPKChangedEvent('@@alice'),
throwsA(isA<InvalidAtSignException>()));
expect(() => AtSignPKChangedEvent('alice@'),
throwsA(isA<InvalidAtSignException>()));
expect(() => AtSignPKChangedEvent('@alice@'),
throwsA(isA<InvalidAtSignException>()));
});

test('Test atSignPKChangedEvent prepends with @ if missing', () {
final e = AtSignPKChangedEvent('alice');
expect(e.atSign, '@alice');
});
}
4 changes: 0 additions & 4 deletions packages/at_commons/test/sync_verb_builder_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ void main() {
var syncVerbBuilder = SyncVerbBuilder()
..commitId = 3
..regex = '.buzz'
..isPaginated = true
..limit = 10;
var command = syncVerbBuilder.buildCommand();
expect(command, 'sync:from:3:limit:10:.buzz\n');
Expand All @@ -49,7 +48,6 @@ void main() {
test('build sync stream verb command', () {
var syncVerbBuilder = SyncVerbBuilder()
..commitId = 3
..isPaginated = true
..limit = 10;
var command = syncVerbBuilder.buildCommand();
expect(command, 'sync:from:3:limit:10\n');
Expand All @@ -61,7 +59,6 @@ void main() {
test('build sync stream verb command', () {
var syncVerbBuilder = SyncVerbBuilder()
..commitId = -1
..isPaginated = true
..limit = 5;
var command = syncVerbBuilder.buildCommand();
expect(command, 'sync:from:-1:limit:5\n');
Expand All @@ -73,7 +70,6 @@ void main() {
test('build sync stream verb command with skipDeletes', () {
var syncVerbBuilder = SyncVerbBuilder()
..commitId = -1
..isPaginated = true
..limit = 5
..skipDeletesUntil = 20;
var command = syncVerbBuilder.buildCommand();
Expand Down