Skip to content

Commit

Permalink
Merge pull request #657 from atsign-foundation/consume_enroll_verb_bu…
Browse files Browse the repository at this point in the history
…ilder

feat: Consume enroll verb builder in AtLookup.executeVerb()
  • Loading branch information
murali-shris authored Sep 12, 2024
2 parents 1584b2a + 786e3c9 commit 2845575
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 10 deletions.
3 changes: 3 additions & 0 deletions packages/at_lookup/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 3.0.48
- feat: consume EnrollVerbBuilder in AtLookup.executeVerb()
- chore: upgrade at_commons to v4.1.1 and at_utils to v3.0.18
## 3.0.47
- fix: Fixed legacy error handling so error message isn't truncated if it
contains a hyphen
Expand Down
12 changes: 8 additions & 4 deletions packages/at_lookup/example/bin/example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ void main() async {
/// To update a key into secondary server
//Build update verb builder
var updateVerbBuilder = UpdateVerbBuilder()
..atKey = (AtKey.shared('phone', sharedBy: '@alice')..sharedWith('@bob')).build()
..atKey =
(AtKey.shared('phone', sharedBy: '@alice')..sharedWith('@bob')).build()
..value = '+1 889 886 7879';

// Sends update command to secondary server
Expand All @@ -38,12 +39,14 @@ void main() async {

/// To retrieve the value of key created by self.
var lLookupVerbBuilder = LLookupVerbBuilder()
..atKey = (AtKey.shared('phone', sharedBy: '@alice')..sharedWith('@bob')).build();
..atKey =
(AtKey.shared('phone', sharedBy: '@alice')..sharedWith('@bob')).build();
await atLookupImpl.executeVerb(lLookupVerbBuilder);

///To remove a key from secondary server
var deleteVerbBuilder = DeleteVerbBuilder()
..atKey = (AtKey.shared('phone', sharedBy: '@alice')..sharedWith('@bob')).build();
..atKey =
(AtKey.shared('phone', sharedBy: '@alice')..sharedWith('@bob')).build();
await atLookupImpl.executeVerb(deleteVerbBuilder, sync: true);

/// To retrieve keys from the secondary server
Expand All @@ -52,7 +55,8 @@ void main() async {

///To notify key to another atSign
var notifyVerbBuilder = NotifyVerbBuilder()
..atKey = (AtKey.shared('phone', sharedBy: '@alice')..sharedWith('@bob')).build();
..atKey =
(AtKey.shared('phone', sharedBy: '@alice')..sharedWith('@bob')).build();
await atLookupImpl.executeVerb(notifyVerbBuilder);

///To retrieve the notifications received
Expand Down
15 changes: 13 additions & 2 deletions packages/at_lookup/lib/src/at_lookup_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ class AtLookupImpl implements AtLookUp {
logger.finer('value: $value dataSignature:$dataSignature');
var isDataValid = publicKey.verifySHA256Signature(
// ignore: unnecessary_cast
utf8.encode(value) as Uint8List, base64Decode(dataSignature));
utf8.encode(value) as Uint8List,
base64Decode(dataSignature));
logger.finer('data verify result: $isDataValid');
return 'data:$value';
} on Exception catch (e) {
Expand Down Expand Up @@ -296,6 +297,8 @@ class AtLookupImpl implements AtLookUp {
verbResult = await _notifyRemove(builder);
} else if (builder is NotifyFetchVerbBuilder) {
verbResult = await _notifyFetch(builder);
} else if (builder is EnrollVerbBuilder) {
verbResult = await _enroll(builder);
}
} on Exception catch (e) {
logger.severe('Error in remote verb execution ${e.toString()}');
Expand Down Expand Up @@ -336,7 +339,7 @@ class AtLookupImpl implements AtLookUp {
// TODO: Can we remove the below catch block in next release once all the servers are migrated to new version.
if (verbResult.contains('-')) {
errorCode = verbResult.substring(0, verbResult.indexOf('-'));
errorDescription = verbResult.substring(verbResult.indexOf('-')+1);
errorDescription = verbResult.substring(verbResult.indexOf('-') + 1);
} else {
errorDescription += ": $verbResult";
}
Expand Down Expand Up @@ -407,6 +410,14 @@ class AtLookupImpl implements AtLookUp {
return await _process(atCommand, auth: true);
}

Future<String> _enroll(EnrollVerbBuilder builder) async {
var atCommand = builder.buildCommand();
if (builder.operation == EnrollOperationEnum.request) {
return _process(atCommand, auth: false);
}
return await _process(atCommand, auth: true);
}

@override
Future<String?> executeCommand(String atCommand, {bool auth = false}) async {
String verbResponse = await _process(atCommand, auth: auth);
Expand Down
6 changes: 3 additions & 3 deletions packages/at_lookup/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: at_lookup
description: A Dart library that contains the core commands that can be used with a secondary server (scan, update, lookup, llookup, plookup, etc.)
version: 3.0.47
version: 3.0.48
repository: https://github.com/atsign-foundation/at_libraries
homepage: https://atsign.com
documentation: https://docs.atsign.com/
Expand All @@ -12,8 +12,8 @@ dependencies:
path: ^1.8.0
crypton: ^2.0.1
crypto: ^3.0.1
at_utils: ^3.0.16
at_commons: ^4.0.0
at_utils: ^3.0.18
at_commons: ^4.1.1
mutex: ^3.0.0
meta: ^1.8.0
at_chops: ^2.0.0
Expand Down
150 changes: 149 additions & 1 deletion packages/at_lookup/test/at_lookup_test.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import 'dart:async';
import 'dart:io';

import 'package:at_chops/at_chops.dart';
import 'package:at_commons/at_builders.dart';
import 'package:at_commons/at_commons.dart';
import 'package:at_lookup/at_lookup.dart';
import 'package:at_lookup/src/connection/at_connection.dart';
import 'package:at_lookup/src/connection/outbound_message_listener.dart';
import 'package:test/test.dart';
import 'package:mocktail/mocktail.dart';
Expand Down Expand Up @@ -212,6 +215,7 @@ void main() {
e is UnAuthenticatedException && e.message.contains('AT0401'))));
});
});

group('A group of tests to verify executeCommand method', () {
test('executeCommand - from verb - auth false', () async {
final atLookup = AtLookupImpl('@alice', atServerHost, 64,
Expand All @@ -226,6 +230,7 @@ void main() {
var result = await atLookup.executeCommand('from:@alice\n');
expect(result, fromResponse);
});

test('executeCommand -llookup verb - auth true - auth key not set',
() async {
final atLookup = AtLookupImpl('@alice', atServerHost, 64,
Expand Down Expand Up @@ -292,7 +297,8 @@ void main() {
outboundConnectionFactory: mockOutboundConnectionFactory);
atLookup.atChops = mockAtChops;
final llookupCommand = 'llookup:phone@alice\n';
final llookupResponse = 'error:{"errorCode":"AT0015","errorDescription":"Exception: fubar"}';
final llookupResponse =
'error:{"errorCode":"AT0015","errorDescription":"Exception: fubar"}';
when(() => mockOutBoundConnection.write(llookupCommand))
.thenAnswer((invocation) {
mockSecureSocket.write(llookupCommand);
Expand All @@ -306,4 +312,146 @@ void main() {
e is AtLookUpException && e.errorMessage == 'Exception: fubar')));
});
});

group('Validate executeVerb() behaviour', () {
test('validate EnrollVerbHandler behaviour - request', () async {
final atLookup = AtLookupImpl('@alice', atServerHost, 64,
secondaryAddressFinder: mockSecondaryAddressFinder,
secureSocketFactory: mockSocketFactory,
socketListenerFactory: mockSecureSocketListenerFactory,
outboundConnectionFactory: mockOutboundConnectionFactory);

String appName = 'unit_test_1';
String deviceName = 'test_device';
String otp = 'ABCDEF';

EnrollVerbBuilder enrollVerbBuilder = EnrollVerbBuilder()
..operation = EnrollOperationEnum.request
..appName = appName
..deviceName = deviceName
..otp = otp;
String enrollCommand =
'enroll:request:{"appName":"$appName","deviceName":"$deviceName","otp":"$otp"}\n';
final enrollResponse =
'data:{"enrollmentId":"1234567890","status":"pending"}';

when(() => mockOutBoundConnection.write(enrollCommand))
.thenAnswer((invocation) {
mockSecureSocket.write(enrollCommand);
return Future.value();
});
when(() => mockOutboundListener.read())
.thenAnswer((_) => Future.value(enrollResponse));
AtConnectionMetaData? atConnectionMetaData = OutboundConnectionMetadata()
..isAuthenticated = false;
when(() => mockOutBoundConnection.getMetaData())
.thenReturn(atConnectionMetaData);
when(() => mockOutBoundConnection.isInValid()).thenReturn(false);

var result = await atLookup.executeVerb(enrollVerbBuilder);
expect(result, enrollResponse);
});

test('validate behaviour with EnrollVerbHandler - approve', () async {
final atLookup = AtLookupImpl('@alice', atServerHost, 64,
secondaryAddressFinder: mockSecondaryAddressFinder,
secureSocketFactory: mockSocketFactory,
socketListenerFactory: mockSecureSocketListenerFactory,
outboundConnectionFactory: mockOutboundConnectionFactory);
atLookup.atChops = mockAtChops;

String appName = 'unit_test_2';
String deviceName = 'test_device';
String enrollmentId = '1357913579';

EnrollVerbBuilder enrollVerbBuilder = EnrollVerbBuilder()
..operation = EnrollOperationEnum.approve
..enrollmentId = '1357913579'
..appName = appName
..deviceName = deviceName;
String enrollCommand =
'enroll:approve:{"enrollmentId":"$enrollmentId","appName":"$appName","deviceName":"$deviceName"}\n';
final enrollResponse =
'data:{"enrollmentId":"1357913579","status":"approved"}';

when(() => mockOutBoundConnection.write(enrollCommand))
.thenAnswer((invocation) {
mockSecureSocket.write(enrollCommand);
return Future.value();
});
when(() => mockOutboundListener.read())
.thenAnswer((_) => Future.value(enrollResponse));
AtConnectionMetaData? atConnectionMetaData = OutboundConnectionMetadata()
..isAuthenticated = true;
when(() => mockOutBoundConnection.getMetaData())
.thenReturn(atConnectionMetaData);
when(() => mockOutBoundConnection.isInValid()).thenReturn(false);

expect(await atLookup.executeVerb(enrollVerbBuilder), enrollResponse);
});

test('validate behaviour with EnrollVerbHandler - revoke', () async {
final atLookup = AtLookupImpl('@alice', atServerHost, 64,
secondaryAddressFinder: mockSecondaryAddressFinder,
secureSocketFactory: mockSocketFactory,
socketListenerFactory: mockSecureSocketListenerFactory,
outboundConnectionFactory: mockOutboundConnectionFactory);
atLookup.atChops = mockAtChops;
String enrollmentId = '89213647826348';

EnrollVerbBuilder enrollVerbBuilder = EnrollVerbBuilder()
..operation = EnrollOperationEnum.revoke
..enrollmentId = enrollmentId;
String enrollCommand = 'enroll:revoke:{"enrollmentId":"$enrollmentId"}\n';
String enrollResponse =
'data:{"enrollmentId":"$enrollmentId","status":"revoked"}';

when(() => mockOutBoundConnection.write(enrollCommand))
.thenAnswer((invocation) {
mockSecureSocket.write(enrollCommand);
return Future.value();
});
when(() => mockOutboundListener.read())
.thenAnswer((_) => Future.value(enrollResponse));
AtConnectionMetaData? atConnectionMetaData = OutboundConnectionMetadata()
..isAuthenticated = true;
when(() => mockOutBoundConnection.getMetaData())
.thenReturn(atConnectionMetaData);
when(() => mockOutBoundConnection.isInValid()).thenReturn(false);

expect(await atLookup.executeVerb(enrollVerbBuilder), enrollResponse);
});

test('validate behaviour with EnrollVerbHandler - deny', () async {
final atLookup = AtLookupImpl('@alice', atServerHost, 64,
secondaryAddressFinder: mockSecondaryAddressFinder,
secureSocketFactory: mockSocketFactory,
socketListenerFactory: mockSecureSocketListenerFactory,
outboundConnectionFactory: mockOutboundConnectionFactory);
atLookup.atChops = mockAtChops;
String enrollmentId = '5754765754';

EnrollVerbBuilder enrollVerbBuilder = EnrollVerbBuilder()
..operation = EnrollOperationEnum.deny
..enrollmentId = enrollmentId;
String enrollCommand = 'enroll:deny:{"enrollmentId":"$enrollmentId"}\n';
String enrollResponse =
'data:{"enrollmentId":"$enrollmentId","status":"denied"}';

when(() => mockOutBoundConnection.write(enrollCommand))
.thenAnswer((invocation) {
mockSecureSocket.write(enrollCommand);
return Future.value();
});
when(() => mockOutboundListener.read())
.thenAnswer((_) => Future.value(enrollResponse));
AtConnectionMetaData? atConnectionMetaData = OutboundConnectionMetadata()
..isAuthenticated = true;
when(() => mockOutBoundConnection.getMetaData())
.thenReturn(atConnectionMetaData);
when(() => mockOutBoundConnection.isInValid()).thenReturn(false);

expect(await atLookup.executeVerb(enrollVerbBuilder), enrollResponse);
});
});
}

0 comments on commit 2845575

Please sign in to comment.