mirror of
https://github.com/haorendashu/nowser.git
synced 2025-12-18 10:04:20 +01:00
simple support for android signer
This commit is contained in:
@@ -37,10 +37,16 @@ class _AuthAppInfoComponent extends State<AuthAppInfoComponent> {
|
|||||||
rightList.add(Text(
|
rightList.add(Text(
|
||||||
name!,
|
name!,
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if (StringUtil.isNotBlank(des)) {
|
if (StringUtil.isNotBlank(des)) {
|
||||||
rightList.add(Text(des!));
|
rightList.add(Text(
|
||||||
|
des!,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Stack(
|
return Stack(
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import 'package:nowser/component/webview/web_info.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/main.dart';
|
import 'package:nowser/main.dart';
|
||||||
import 'package:nowser/util/permission_check_mixin.dart';
|
import 'package:nowser/provider/permission_check_mixin.dart';
|
||||||
|
|
||||||
import '../../const/auth_result.dart';
|
import '../../const/auth_result.dart';
|
||||||
import '../../data/app.dart';
|
import '../../data/app.dart';
|
||||||
@@ -248,7 +248,8 @@ class _WebViewComponent extends State<WebViewComponent>
|
|||||||
}, (app, signer) async {
|
}, (app, signer) async {
|
||||||
var tags = eventObj["tags"];
|
var tags = eventObj["tags"];
|
||||||
Event? event = Event(app.pubkey!, eventObj["kind"], tags ?? [],
|
Event? event = Event(app.pubkey!, eventObj["kind"], tags ?? [],
|
||||||
eventObj["content"]);
|
eventObj["content"],
|
||||||
|
publishAt: eventObj["created_at"]);
|
||||||
event = await signer.signEvent(event);
|
event = await signer.signEvent(event);
|
||||||
if (event == null) {
|
if (event == null) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
|||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:nostr_sdk/utils/string_util.dart';
|
import 'package:nostr_sdk/utils/string_util.dart';
|
||||||
import 'package:nowser/data/db.dart';
|
import 'package:nowser/data/db.dart';
|
||||||
|
import 'package:nowser/provider/android_signer_mixin.dart';
|
||||||
import 'package:nowser/provider/app_provider.dart';
|
import 'package:nowser/provider/app_provider.dart';
|
||||||
import 'package:nowser/provider/key_provider.dart';
|
import 'package:nowser/provider/key_provider.dart';
|
||||||
|
import 'package:nowser/provider/permission_check_mixin.dart';
|
||||||
import 'package:nowser/provider/web_provider.dart';
|
import 'package:nowser/provider/web_provider.dart';
|
||||||
import 'package:nowser/router/index/index_router.dart';
|
import 'package:nowser/router/index/index_router.dart';
|
||||||
import 'package:nowser/router/keys/keys_router.dart';
|
import 'package:nowser/router/keys/keys_router.dart';
|
||||||
@@ -68,6 +70,11 @@ class _MyApp extends State<MyApp> {
|
|||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Locale? _locale;
|
Locale? _locale;
|
||||||
@@ -78,7 +85,6 @@ class _MyApp extends State<MyApp> {
|
|||||||
ThemeData? defaultDarkTheme;
|
ThemeData? defaultDarkTheme;
|
||||||
defaultTheme = lightTheme;
|
defaultTheme = lightTheme;
|
||||||
defaultDarkTheme = darkTheme;
|
defaultDarkTheme = darkTheme;
|
||||||
|
|
||||||
routes = {
|
routes = {
|
||||||
RouterPath.INDEX: (context) => IndexRouter(),
|
RouterPath.INDEX: (context) => IndexRouter(),
|
||||||
RouterPath.WEB_TABS: (context) => WebTabsSelectRouter(),
|
RouterPath.WEB_TABS: (context) => WebTabsSelectRouter(),
|
||||||
|
|||||||
160
lib/provider/android_signer_mixin.dart
Normal file
160
lib/provider/android_signer_mixin.dart
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:nostr_sdk/event.dart';
|
||||||
|
import 'package:nostr_sdk/utils/string_util.dart';
|
||||||
|
import 'package:nowser/const/app_type.dart';
|
||||||
|
import 'package:nowser/const/auth_result.dart';
|
||||||
|
import 'package:nowser/const/auth_type.dart';
|
||||||
|
import 'package:nowser/provider/permission_check_mixin.dart';
|
||||||
|
import 'package:receive_intent/receive_intent.dart' as receiveIntent;
|
||||||
|
|
||||||
|
mixin AndroidSignerMixin on PermissionCheckMixin {
|
||||||
|
// StreamSubscription? _sub;
|
||||||
|
// void listenIntent() {
|
||||||
|
// print("listenIntent call");
|
||||||
|
// _sub = receiveIntent.ReceiveIntent.receivedIntentStream.listen(
|
||||||
|
// (receiveIntent.Intent? intent) {
|
||||||
|
// log("receive intent!!!!!");
|
||||||
|
// if (intent != null) {
|
||||||
|
// log(intent.toString());
|
||||||
|
// log("from ${intent.fromPackageName}");
|
||||||
|
// log("action ${intent.action}");
|
||||||
|
// log("data ${intent.data}");
|
||||||
|
// log("categories ${intent.categories}");
|
||||||
|
// log("extra ${intent.extra}");
|
||||||
|
// }
|
||||||
|
// }, onError: (err) {
|
||||||
|
// print("listen error ");
|
||||||
|
// print(err);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
static const String PREFIX = "nostrsigner:";
|
||||||
|
|
||||||
|
Future<void> handleInitialIntent(BuildContext context) async {
|
||||||
|
final intent = await receiveIntent.ReceiveIntent.getInitialIntent();
|
||||||
|
if (intent != null) {
|
||||||
|
log(intent.toString());
|
||||||
|
log("from ${intent.fromPackageName}");
|
||||||
|
log("action ${intent.action}");
|
||||||
|
log("data ${intent.data}");
|
||||||
|
log("categories ${intent.categories}");
|
||||||
|
log("extra ${intent.extra}");
|
||||||
|
|
||||||
|
if (StringUtil.isNotBlank(intent.data) &&
|
||||||
|
intent.data!.startsWith(PREFIX)) {
|
||||||
|
// This is an android signer intent
|
||||||
|
var code = intent.fromPackageName;
|
||||||
|
// Maybe it should check this signature
|
||||||
|
// intent.fromSignatures;
|
||||||
|
var extra = intent.extra;
|
||||||
|
|
||||||
|
if (intent.extra != null) {
|
||||||
|
var callId = extra!["id"];
|
||||||
|
var authTypeStr = extra["type"];
|
||||||
|
var currentUser = extra["current_user"];
|
||||||
|
var pubkey = extra["pubKey"];
|
||||||
|
pubkey ??= extra["pubkey"];
|
||||||
|
|
||||||
|
if (StringUtil.isNotBlank(callId) &&
|
||||||
|
StringUtil.isNotBlank(authTypeStr) &&
|
||||||
|
StringUtil.isNotBlank(code)) {
|
||||||
|
var authType = AuthType.GET_PUBLIC_KEY;
|
||||||
|
if (authTypeStr == "get_public_key") {
|
||||||
|
authType = AuthType.GET_PUBLIC_KEY;
|
||||||
|
} else if (authTypeStr == "sign_event") {
|
||||||
|
authType = AuthType.SIGN_EVENT;
|
||||||
|
} else if (authTypeStr == "get_relays") {
|
||||||
|
authType = AuthType.GET_RELAYS;
|
||||||
|
} else if (authTypeStr == "nip04_encrypt") {
|
||||||
|
authType = AuthType.NIP04_ENCRYPT;
|
||||||
|
} else if (authTypeStr == "nip04_decrypt") {
|
||||||
|
authType = AuthType.NIP04_DECRYPT;
|
||||||
|
} else if (authTypeStr == "nip44_encrypt") {
|
||||||
|
authType = AuthType.NIP44_ENCRYPT;
|
||||||
|
} else if (authTypeStr == "nip44_decrypt") {
|
||||||
|
authType = AuthType.NIP44_DECRYPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
var playload = intent.data!.replaceFirst(PREFIX, "");
|
||||||
|
int? eventKind;
|
||||||
|
dynamic eventObj;
|
||||||
|
if (authType == AuthType.SIGN_EVENT) {
|
||||||
|
print(playload);
|
||||||
|
eventObj = jsonDecode(playload);
|
||||||
|
if (eventObj != null) {
|
||||||
|
eventKind = eventObj["kind"];
|
||||||
|
print("eventKind $eventKind");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPermission(context, AppType.ANDROID_APP, code!, authType,
|
||||||
|
eventKind: eventKind, authDetail: playload, () {
|
||||||
|
// this place should do some about reject
|
||||||
|
// saveAuthLog(app, authType, eventKind, playload, AuthResult.OK);
|
||||||
|
}, (app, signer) async {
|
||||||
|
print("checkPermission confrim $code");
|
||||||
|
// confirm
|
||||||
|
Map<String, Object?> data = {};
|
||||||
|
data["id"] = callId;
|
||||||
|
|
||||||
|
if (authType == AuthType.GET_PUBLIC_KEY) {
|
||||||
|
// TODO should handle permissions
|
||||||
|
// var permissions = extra["permissions"];
|
||||||
|
data["signature"] = await signer.getPublicKey();
|
||||||
|
data["package"] = "com.github.haorendashu.nowser";
|
||||||
|
} else if (authType == AuthType.SIGN_EVENT) {
|
||||||
|
var tags = eventObj["tags"];
|
||||||
|
Event? event = Event(app.pubkey!, eventObj["kind"], tags ?? [],
|
||||||
|
eventObj["content"],
|
||||||
|
publishAt: eventObj["created_at"]);
|
||||||
|
event = await signer.signEvent(event);
|
||||||
|
if (event == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data["signature"] = event.sig;
|
||||||
|
data["event"] = jsonEncode(event.toJson());
|
||||||
|
print("sig ${event.sig}");
|
||||||
|
} else if (authType == AuthType.GET_RELAYS) {
|
||||||
|
// TODO
|
||||||
|
} else if (authType == AuthType.NIP04_ENCRYPT) {
|
||||||
|
var result = await signer.encrypt(pubkey, playload);
|
||||||
|
if (StringUtil.isNotBlank(result)) {
|
||||||
|
data["signature"] = result;
|
||||||
|
}
|
||||||
|
} else if (authType == AuthType.NIP04_DECRYPT) {
|
||||||
|
var result = await signer.decrypt(pubkey, playload);
|
||||||
|
if (StringUtil.isNotBlank(result)) {
|
||||||
|
data["signature"] = result;
|
||||||
|
}
|
||||||
|
} else if (authType == AuthType.NIP44_ENCRYPT) {
|
||||||
|
var result = await signer.nip44Encrypt(pubkey, playload);
|
||||||
|
if (StringUtil.isNotBlank(result)) {
|
||||||
|
data["signature"] = result;
|
||||||
|
}
|
||||||
|
} else if (authType == AuthType.NIP44_DECRYPT) {
|
||||||
|
var result = await signer.nip44Decrypt(pubkey, playload);
|
||||||
|
if (StringUtil.isNotBlank(result)) {
|
||||||
|
data["signature"] = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saveAuthLog(app, authType, eventKind, playload, AuthResult.OK);
|
||||||
|
|
||||||
|
print("setResult ok");
|
||||||
|
print(data);
|
||||||
|
|
||||||
|
receiveIntent.ReceiveIntent.setResult(
|
||||||
|
receiveIntent.kActivityResultOk,
|
||||||
|
data: data,
|
||||||
|
shouldFinish: true,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@ import 'package:nowser/router/index/index_web_component.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import '../../component/webview/webview_component.dart';
|
import '../../component/webview/webview_component.dart';
|
||||||
|
import '../../provider/android_signer_mixin.dart';
|
||||||
|
import '../../provider/permission_check_mixin.dart';
|
||||||
|
|
||||||
class IndexRouter extends StatefulWidget {
|
class IndexRouter extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
@@ -13,11 +15,16 @@ class IndexRouter extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _IndexRouter extends State<IndexRouter> {
|
class _IndexRouter extends State<IndexRouter>
|
||||||
|
with PermissionCheckMixin, AndroidSignerMixin {
|
||||||
Map<String, WebViewComponent> webViewComponentMap = {};
|
Map<String, WebViewComponent> webViewComponentMap = {};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
handleInitialIntent(context);
|
||||||
|
});
|
||||||
|
|
||||||
webProvider.checkBlank();
|
webProvider.checkBlank();
|
||||||
|
|
||||||
var main = Selector<WebProvider, WebNumInfo>(
|
var main = Selector<WebProvider, WebNumInfo>(
|
||||||
|
|||||||
Reference in New Issue
Block a user