Skip to content

Commit

Permalink
use new graphql based enkra api
Browse files Browse the repository at this point in the history
  • Loading branch information
harryfei committed Feb 28, 2023
1 parent de232c4 commit cd49c5b
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 37 deletions.
91 changes: 91 additions & 0 deletions lib/models/api.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import 'dart:convert';

import 'package:http/http.dart' as http;

const String ENKRA_API_URL = String.fromEnvironment('ENKRA_API_URL');

Uri convertToWebSocket(Uri uri) {
String scheme = uri.scheme == "https" ? "wss" : "ws";
return uri.replace(scheme: scheme, path: "/send-ws");
}

final String apiUrl = '$ENKRA_API_URL/graphql';
final String wsUrl = convertToWebSocket(Uri.parse(ENKRA_API_URL)).toString();

Future<dynamic?> requestChannel() async {
final response = await http.post(
Uri.parse(apiUrl),
headers: {
'Content-Type': 'application/json',
},
body: jsonEncode({
'query': '''mutation {
requestSendChannel {
channelId
hostToken
}
}
''',
}),
);

if (response.statusCode == 200) {
final res = jsonDecode(response.body);

return res["data"]["requestSendChannel"];
}

return null;
}

Future<dynamic?> joinChannel(channelId, encappedKey) async {
final response = await http.post(
Uri.parse(apiUrl),
headers: {
'Content-Type': 'application/json',
},
body: jsonEncode({
'query': '''mutation {
joinSendChannel(
channelId: "$channelId",
encappedKey: "$encappedKey",
)
}
''',
}),
);

if (response.statusCode == 200) {
final res = jsonDecode(response.body);

return res["data"]["joinSendChannel"];
}

return null;
}

Future<String?> approvePairing(channelId, deviceToken) async {
final response = await http.post(
Uri.parse(apiUrl),
headers: {
'Content-Type': 'application/json',
},
body: jsonEncode({
'query': '''mutation {
approveSendChannelPairing(
channelId: "$channelId",
deviceToken: "$deviceToken",
)
}
''',
}),
);

if (response.statusCode == 200) {
final res = jsonDecode(response.body);

return res["data"]["approveSendChannelPairing"];
}

return null;
}
7 changes: 2 additions & 5 deletions lib/models/paired.dart
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,8 @@ class PairedState extends AppState {

_sendMessage(Message msg) async {
final content = await _encryptContent(msg.toJson());
final message = jsonEncode({
"event": "message",
"content": content,
});
_channel.sink.add(message);

_channel.sink.add(content);

_addNewMessage(msg);
}
Expand Down
64 changes: 32 additions & 32 deletions lib/models/wait_to_pair.dart
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import 'dart:convert';
import 'dart:typed_data';

import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:nanoid/nanoid.dart';

import 'app_state.dart';
import 'ws_client.dart';
import 'api.dart';

import '../native/native.dart';

const String WS_API_URL = String.fromEnvironment('WS_API_URL');
const String ENKRA_SEND_APP_URL = String.fromEnvironment('SEND_APP_URL');

class WaitToPairState extends AppState {
final WsClient _channel;

final String _sessionKey;
final String _channelId;
final String _deviceToken;

final SecureChannelCipher _cipher;

Expand All @@ -26,10 +24,11 @@ class WaitToPairState extends AppState {

WaitToPairState._internal(
WebSocketChannel channel,
this._sessionKey,
this._channelId,
this._cipher,
this._isSender,
this._senderAeadCipher,
this._deviceToken,
) : _channel = WsClient(channel) {
if (_isSender) {
_senderListen(_channel);
Expand All @@ -39,51 +38,62 @@ class WaitToPairState extends AppState {
}

static create() async {
final sessionKey = nanoid();
final wsUrl = Uri.parse('$WS_API_URL/$sessionKey');
final channel = WebSocketChannel.connect(wsUrl);
final result = await Future.wait([
requestChannel(),
SecureChannelCipher.newRandom(bridge: api),
]);

final channelCipher = await SecureChannelCipher.newRandom(bridge: api);
final requestChannelResult = result[0];
final channelCipher = result[1];

final channelId = requestChannelResult["channelId"]!;
final deviceToken = requestChannelResult["hostToken"]!;

final wsChannelUrl = Uri.parse('$wsUrl/$channelId/$deviceToken');
final channel = WebSocketChannel.connect(wsChannelUrl);

return WaitToPairState._internal(
channel,
sessionKey,
channelId,
channelCipher,
false,
null,
deviceToken,
);
}

static connect(List<String> keys) async {
final sessionKey = keys[0];
final publicKey = base64Url.decode(keys[1]);
static connect(List<String> tokens) async {
final channelId = tokens[0];
final publicKey = base64Url.decode(tokens[1]);

final channelCipher = await SecureChannelCipher.newRandom(bridge: api);
final encapKeys = await channelCipher.encapKey(public: publicKey);

final wsUrl = Uri.parse('$WS_API_URL/$sessionKey');
final channel = WebSocketChannel.connect(wsUrl);
final deviceToken = await joinChannel(
channelId, base64Url.encode(encapKeys.encapsulatedKey));

_sendPairingMessage(encapKeys.encapsulatedKey, channel);
final wsChannelUrl = Uri.parse('$wsUrl/$channelId/$deviceToken');
final channel = WebSocketChannel.connect(wsChannelUrl);

return WaitToPairState._internal(
channel,
sessionKey,
channelId,
channelCipher,
true,
encapKeys.sharedSecret,
deviceToken,
);
}

String sesssionKey() {
return _sessionKey;
return _channelId;
}

Future<String> pairingUrl() async {
final key = await _cipher.public();
final publicKey = base64Url.encode(key);

return '$ENKRA_SEND_APP_URL/#/$_sessionKey/$publicKey';
return '$ENKRA_SEND_APP_URL/#/$_channelId/$publicKey';
}

_receiverListen(channel) async {
Expand All @@ -102,9 +112,7 @@ class WaitToPairState extends AppState {
final cipherKey =
await _cipher.sharedSecret(encapsulatedKey: encappedKey);

_channel.sink.add(jsonEncode({
"event": "paired",
}));
final result = await approvePairing(_channelId, _deviceToken);

_onPaired?.call(cipherKey);
}
Expand All @@ -125,19 +133,11 @@ class WaitToPairState extends AppState {
});
}

static _sendPairingMessage(encappedKey, wsChannel) async {
final msg = jsonEncode({
"event": "pairing",
"encappedKey": base64Url.encode(encappedKey),
});

wsChannel.sink.add(msg);
}

setOnPaired(Function(AeadCipher) onPaired) {
_onPaired = onPaired;
}

@override
void dispose() {
_cipher.key.dispose();
_cipher.csprng.dispose();
Expand Down

0 comments on commit cd49c5b

Please sign in to comment.