mirror of
https://github.com/haorendashu/nowser.git
synced 2025-12-17 09:54:19 +01:00
remote add nostrconnect url login
This commit is contained in:
83
lib/data/nostrconnect_remote_signing_info.dart
Normal file
83
lib/data/nostrconnect_remote_signing_info.dart
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import 'package:nostr_sdk/utils/string_util.dart';
|
||||||
|
import 'package:nowser/data/remote_signing_info.dart';
|
||||||
|
|
||||||
|
class NostrconnectRemoteSigningInfo extends RemoteSigningInfo {
|
||||||
|
String? perms;
|
||||||
|
|
||||||
|
String? name;
|
||||||
|
|
||||||
|
String? url;
|
||||||
|
|
||||||
|
String? image;
|
||||||
|
|
||||||
|
NostrconnectRemoteSigningInfo({
|
||||||
|
super.id,
|
||||||
|
super.appId,
|
||||||
|
super.localPubkey,
|
||||||
|
super.remotePubkey,
|
||||||
|
super.remoteSignerKey,
|
||||||
|
super.relays,
|
||||||
|
super.secret,
|
||||||
|
super.createdAt,
|
||||||
|
super.updatedAt,
|
||||||
|
this.perms,
|
||||||
|
this.name,
|
||||||
|
this.url,
|
||||||
|
this.image,
|
||||||
|
});
|
||||||
|
|
||||||
|
NostrconnectRemoteSigningInfo.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
appId = json['app_id'];
|
||||||
|
localPubkey = json['local_pubkey'];
|
||||||
|
remotePubkey = json['remote_pubkey'];
|
||||||
|
remoteSignerKey = json['remote_signer_key'];
|
||||||
|
relays = json['relays'];
|
||||||
|
secret = json['secret'];
|
||||||
|
createdAt = json['created_at'];
|
||||||
|
updatedAt = json['updated_at'];
|
||||||
|
perms = json['perms'];
|
||||||
|
name = json['name'];
|
||||||
|
url = json['url'];
|
||||||
|
image = json['image'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't implement toJson method and when saving data it only save the super.toJson data.
|
||||||
|
// @override
|
||||||
|
// Map<String, dynamic> toJson() {
|
||||||
|
// final data = super.toJson();
|
||||||
|
// data['perms'] = perms;
|
||||||
|
// data['name'] = name;
|
||||||
|
// data['url'] = url;
|
||||||
|
// data['image'] = image;
|
||||||
|
// return data;
|
||||||
|
// }
|
||||||
|
|
||||||
|
static NostrconnectRemoteSigningInfo? parseNostrConnectUrl(
|
||||||
|
String nostrconnectUrlText) {
|
||||||
|
var uri = Uri.parse(nostrconnectUrlText);
|
||||||
|
var parsList = uri.queryParametersAll;
|
||||||
|
var pars = uri.queryParameters;
|
||||||
|
var localPubkey = uri.host;
|
||||||
|
|
||||||
|
var relays = parsList['relay'];
|
||||||
|
var secret = pars['secret'];
|
||||||
|
var perms = pars['perms'];
|
||||||
|
var name = pars['name'];
|
||||||
|
var url = pars['url'];
|
||||||
|
var image = pars['image'];
|
||||||
|
if (relays == null || relays.isEmpty || StringUtil.isBlank(secret)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NostrconnectRemoteSigningInfo(
|
||||||
|
localPubkey: localPubkey,
|
||||||
|
relays: relays.join(","),
|
||||||
|
secret: secret,
|
||||||
|
perms: perms,
|
||||||
|
name: name,
|
||||||
|
url: url,
|
||||||
|
image: image,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,20 +45,4 @@ class RemoteSigningInfo {
|
|||||||
data['updated_at'] = this.updatedAt;
|
data['updated_at'] = this.updatedAt;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RemoteSigningInfo? parseNostrConnectUrl(String nostrconnectUrlText) {
|
|
||||||
var uri = Uri.parse(nostrconnectUrlText);
|
|
||||||
var pars = uri.queryParametersAll;
|
|
||||||
var localPubkey = uri.host;
|
|
||||||
|
|
||||||
var relays = pars["relay"];
|
|
||||||
if (relays == null || relays.isEmpty) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return RemoteSigningInfo(
|
|
||||||
localPubkey: localPubkey,
|
|
||||||
relays: relays.join(","),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:bot_toast/bot_toast.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:nostr_sdk/client_utils/keys.dart';
|
import 'package:nostr_sdk/client_utils/keys.dart';
|
||||||
@@ -9,6 +10,7 @@ import 'package:nostr_sdk/event_kind.dart';
|
|||||||
import 'package:nostr_sdk/filter.dart';
|
import 'package:nostr_sdk/filter.dart';
|
||||||
import 'package:nostr_sdk/nip46/nostr_remote_request.dart';
|
import 'package:nostr_sdk/nip46/nostr_remote_request.dart';
|
||||||
import 'package:nostr_sdk/nip46/nostr_remote_response.dart';
|
import 'package:nostr_sdk/nip46/nostr_remote_response.dart';
|
||||||
|
import 'package:nostr_sdk/relay/client_connected.dart';
|
||||||
import 'package:nostr_sdk/relay/relay.dart';
|
import 'package:nostr_sdk/relay/relay.dart';
|
||||||
import 'package:nostr_sdk/relay/relay_isolate.dart';
|
import 'package:nostr_sdk/relay/relay_isolate.dart';
|
||||||
import 'package:nostr_sdk/relay/relay_status.dart';
|
import 'package:nostr_sdk/relay/relay_status.dart';
|
||||||
@@ -19,6 +21,7 @@ import 'package:nostr_sdk/utils/string_util.dart';
|
|||||||
import 'package:nowser/const/app_type.dart';
|
import 'package:nowser/const/app_type.dart';
|
||||||
import 'package:nowser/const/auth_type.dart';
|
import 'package:nowser/const/auth_type.dart';
|
||||||
import 'package:nowser/data/app.dart';
|
import 'package:nowser/data/app.dart';
|
||||||
|
import 'package:nowser/data/nostrconnect_remote_signing_info.dart';
|
||||||
import 'package:nowser/provider/permission_check_mixin.dart';
|
import 'package:nowser/provider/permission_check_mixin.dart';
|
||||||
import 'package:relay_sdk/network/memory/mem_relay_client.dart';
|
import 'package:relay_sdk/network/memory/mem_relay_client.dart';
|
||||||
|
|
||||||
@@ -77,7 +80,7 @@ class RemoteSigningProvider extends ChangeNotifier with PermissionCheckMixin {
|
|||||||
return str!;
|
return str!;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> addRemoteApp(App remoteApp, String encryptKey) async {
|
Future<List<Relay>?> addRemoteApp(App remoteApp, String encryptKey) async {
|
||||||
var remoteSigningInfo =
|
var remoteSigningInfo =
|
||||||
await RemoteSigningInfoDB.getByAppId(remoteApp.id!, encryptKey);
|
await RemoteSigningInfoDB.getByAppId(remoteApp.id!, encryptKey);
|
||||||
if (remoteSigningInfo != null &&
|
if (remoteSigningInfo != null &&
|
||||||
@@ -91,6 +94,8 @@ class RemoteSigningProvider extends ChangeNotifier with PermissionCheckMixin {
|
|||||||
remoteSigningInfoMap[remoteSignerPubkey] = remoteSigningInfo;
|
remoteSigningInfoMap[remoteSignerPubkey] = remoteSigningInfo;
|
||||||
appMap[remoteSignerPubkey] = remoteApp;
|
appMap[remoteSignerPubkey] = remoteApp;
|
||||||
relayMap[remoteSignerPubkey] = relays;
|
relayMap[remoteSignerPubkey] = relays;
|
||||||
|
|
||||||
|
return relays;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,7 +318,12 @@ class RemoteSigningProvider extends ChangeNotifier with PermissionCheckMixin {
|
|||||||
|
|
||||||
if (event != null) {
|
if (event != null) {
|
||||||
for (var relay in relays) {
|
for (var relay in relays) {
|
||||||
relay.send(["EVENT", event.toJson()]);
|
if (relay.relayStatus.connected == ClientConneccted.CONNECTED) {
|
||||||
|
relay.send(["EVENT", event.toJson()]);
|
||||||
|
} else {
|
||||||
|
relay.pendingAuthedMessages.add(["EVENT", event.toJson()]);
|
||||||
|
relay.pendingMessages.add(["EVENT", event.toJson()]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -400,11 +410,49 @@ class RemoteSigningProvider extends ChangeNotifier with PermissionCheckMixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> addNostrconnectRemoteSigningInfo(
|
||||||
|
NostrconnectRemoteSigningInfo remoteSigningInfo) async {
|
||||||
|
NostrSigner signerSigner =
|
||||||
|
LocalNostrSigner(remoteSigningInfo.remoteSignerKey!);
|
||||||
|
var remoteSignerPubkey = getPublicKey(remoteSigningInfo.remoteSignerKey!);
|
||||||
|
var appType = AppType.REMOTE;
|
||||||
|
var code = remoteSignerPubkey;
|
||||||
|
|
||||||
|
App? app = await getApp(appType, code);
|
||||||
|
app.name = remoteSigningInfo.name;
|
||||||
|
if (StringUtil.isBlank(app.name)) {
|
||||||
|
app.name = remoteSigningInfo.url;
|
||||||
|
}
|
||||||
|
app.pubkey = remoteSigningInfo.remotePubkey;
|
||||||
|
app.image = remoteSigningInfo.image;
|
||||||
|
await AuthAppConnectDialog.show(context!, app);
|
||||||
|
app = appProvider.getApp(appType, code);
|
||||||
|
if (app == null) {
|
||||||
|
BotToast.showText(text: "Remote App connect fail.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteSigningInfo.appId = app.id;
|
||||||
|
remoteSigningInfo.updatedAt = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||||
|
|
||||||
|
await RemoteSigningInfoDB.insert(remoteSigningInfo, encryptKey);
|
||||||
|
|
||||||
|
var relays = await addRemoteApp(app, encryptKey);
|
||||||
|
if (relays != null) {
|
||||||
|
var response = NostrRemoteResponse(
|
||||||
|
StringUtil.rndNameStr(12), remoteSigningInfo.secret!);
|
||||||
|
await sendResponse(relays, response, signerSigner,
|
||||||
|
remoteSigningInfo.localPubkey!, remoteSignerPubkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
List<RemoteSigningInfo> _penddingRemoteApps = [];
|
List<RemoteSigningInfo> _penddingRemoteApps = [];
|
||||||
|
|
||||||
List<RemoteSigningInfo> get penddingRemoteApps => _penddingRemoteApps;
|
List<RemoteSigningInfo> get penddingRemoteApps => _penddingRemoteApps;
|
||||||
|
|
||||||
Future<void> saveRemoteSigningInfo(
|
Future<void> saveBunkerRemoteSigningInfo(
|
||||||
RemoteSigningInfo remoteSigningInfo) async {
|
RemoteSigningInfo remoteSigningInfo) async {
|
||||||
await RemoteSigningInfoDB.insert(remoteSigningInfo, encryptKey);
|
await RemoteSigningInfoDB.insert(remoteSigningInfo, encryptKey);
|
||||||
await reloadPenddingRemoteApps();
|
await reloadPenddingRemoteApps();
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:nostr_sdk/client_utils/keys.dart';
|
import 'package:nostr_sdk/client_utils/keys.dart';
|
||||||
import 'package:nostr_sdk/nip19/nip19.dart';
|
import 'package:nostr_sdk/nip19/nip19.dart';
|
||||||
import 'package:nostr_sdk/nip46/nostr_remote_signer_info.dart';
|
import 'package:nostr_sdk/nip46/nostr_remote_signer_info.dart';
|
||||||
|
import 'package:nostr_sdk/utils/platform_util.dart';
|
||||||
import 'package:nostr_sdk/utils/string_util.dart';
|
import 'package:nostr_sdk/utils/string_util.dart';
|
||||||
import 'package:nowser/component/cust_state.dart';
|
import 'package:nowser/component/cust_state.dart';
|
||||||
import 'package:nowser/component/qrscanner.dart';
|
import 'package:nowser/component/qrscanner.dart';
|
||||||
import 'package:nowser/component/simple_qrcode_dialog.dart';
|
import 'package:nowser/component/simple_qrcode_dialog.dart';
|
||||||
import 'package:nowser/component/user/user_name_component.dart';
|
import 'package:nowser/component/user/user_name_component.dart';
|
||||||
|
import 'package:nowser/data/nostrconnect_remote_signing_info.dart';
|
||||||
import 'package:nowser/data/remote_signing_info.dart';
|
import 'package:nowser/data/remote_signing_info.dart';
|
||||||
import 'package:nowser/data/remote_signing_info_db.dart';
|
import 'package:nowser/data/remote_signing_info_db.dart';
|
||||||
import 'package:nowser/main.dart';
|
import 'package:nowser/main.dart';
|
||||||
@@ -205,14 +207,9 @@ class _AddRemoteAppRouter extends CustState<AddRemoteAppRouter> {
|
|||||||
unselectedLabelColor: textColor,
|
unselectedLabelColor: textColor,
|
||||||
indicatorColor: mainColor,
|
indicatorColor: mainColor,
|
||||||
tabs: [
|
tabs: [
|
||||||
GestureDetector(
|
Text(
|
||||||
child: Text(
|
"${s.Connect_by}\nnostrconnect:// url",
|
||||||
"${s.Connect_by}\nnostrconnect:// url",
|
textAlign: TextAlign.center,
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
BotToast.showText(text: s.Comming_soon);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"${s.Connect_by}\nbunker:// url",
|
"${s.Connect_by}\nbunker:// url",
|
||||||
@@ -246,12 +243,14 @@ class _AddRemoteAppRouter extends CustState<AddRemoteAppRouter> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(child: Container()),
|
Expanded(child: Container()),
|
||||||
IconButton(
|
PlatformUtil.isAndroid() || PlatformUtil.isIOS()
|
||||||
onPressed: () {
|
? IconButton(
|
||||||
scanNostrConnectQRCode();
|
onPressed: () {
|
||||||
},
|
scanNostrConnectQRCode();
|
||||||
icon: const Icon(Icons.qr_code_scanner),
|
},
|
||||||
),
|
icon: const Icon(Icons.qr_code_scanner),
|
||||||
|
)
|
||||||
|
: Container(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -259,9 +258,7 @@ class _AddRemoteAppRouter extends CustState<AddRemoteAppRouter> {
|
|||||||
margin: const EdgeInsets.only(top: Base.BASE_PADDING),
|
margin: const EdgeInsets.only(top: Base.BASE_PADDING),
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: FilledButton(
|
child: FilledButton(
|
||||||
onPressed: () {
|
onPressed: confirmNostrConnect,
|
||||||
BotToast.showText(text: s.Comming_soon);
|
|
||||||
},
|
|
||||||
child: Text(s.Confirm),
|
child: Text(s.Confirm),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -347,19 +344,27 @@ class _AddRemoteAppRouter extends CustState<AddRemoteAppRouter> {
|
|||||||
|
|
||||||
String remoteSignerKey = generatePrivateKey();
|
String remoteSignerKey = generatePrivateKey();
|
||||||
|
|
||||||
void confirmNostrConnect() {
|
Future<void> confirmNostrConnect() async {
|
||||||
var remoteSigningInfo =
|
var remoteSigningInfo = NostrconnectRemoteSigningInfo.parseNostrConnectUrl(
|
||||||
RemoteSigningInfo.parseNostrConnectUrl(nostrconnectConn.text);
|
nostrconnectConn.text.trim());
|
||||||
if (remoteSigningInfo == null) {
|
if (remoteSigningInfo == null) {
|
||||||
// TODO
|
BotToast.showText(text: 'Invalid nostrconnect url');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remoteSigningInfo.remotePubkey = pubkey;
|
||||||
remoteSigningInfo.remoteSignerKey = remoteSignerKey;
|
remoteSigningInfo.remoteSignerKey = remoteSignerKey;
|
||||||
remoteSigningInfo.createdAt = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
remoteSigningInfo.createdAt = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||||
remoteSigningInfo.updatedAt = remoteSigningInfo.createdAt;
|
remoteSigningInfo.updatedAt = remoteSigningInfo.createdAt;
|
||||||
|
|
||||||
// TODO
|
var result = await remoteSigningProvider
|
||||||
|
.addNostrconnectRemoteSigningInfo(remoteSigningInfo);
|
||||||
|
if (result) {
|
||||||
|
BotToast.showText(text: 'Add remote app success');
|
||||||
|
RouterUtil.back(context);
|
||||||
|
} else {
|
||||||
|
BotToast.showText(text: 'Add remote app fail');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEditingController relayAddrController = TextEditingController();
|
TextEditingController relayAddrController = TextEditingController();
|
||||||
@@ -412,7 +417,7 @@ class _AddRemoteAppRouter extends CustState<AddRemoteAppRouter> {
|
|||||||
);
|
);
|
||||||
remoteSigningInfo.updatedAt = remoteSigningInfo.createdAt;
|
remoteSigningInfo.updatedAt = remoteSigningInfo.createdAt;
|
||||||
|
|
||||||
remoteSigningProvider.saveRemoteSigningInfo(remoteSigningInfo);
|
remoteSigningProvider.saveBunkerRemoteSigningInfo(remoteSigningInfo);
|
||||||
RouterUtil.back(context);
|
RouterUtil.back(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Submodule packages/nostr_sdk updated: af5304d08a...a900fb91d4
Reference in New Issue
Block a user