import 'package:flutter/material.dart'; import 'package:nostr_sdk/utils/string_util.dart'; import 'package:nowser/const/app_type.dart'; import 'package:nowser/const/auth_type.dart'; import 'package:nowser/const/connect_type.dart'; import 'package:nowser/data/app_db.dart'; import 'package:nowser/data/auth_log_db.dart'; import '../const/auth_result.dart'; import '../data/app.dart'; import '../data/remote_signing_info.dart'; import '../data/remote_signing_info_db.dart'; class AppProvider extends ChangeNotifier { List _list = []; List get appList => _list; List remoteAppList() { List apps = []; for (var app in _list) { if (app.appType == AppType.REMOTE) { apps.add(app); } } return apps; } Map _appMap = {}; Map> appPermissions = {}; Future reload() async { _appMap = {}; appPermissions = {}; var allApp = await AppDB.all(); _list = allApp; for (var app in allApp) { _appMap[app.id!] = app; } notifyListeners(); } Future update(App app) async { app.updatedAt = DateTime.now().millisecondsSinceEpoch ~/ 1000; AppDB.update(app); reload(); notifyListeners(); } Future add(App app) async { if (await AppDB.insert(app) > 0) { _list.add(app); notifyListeners(); } } String getAppCode(int appType, String code) { return "${appType}_$code"; } int checkPermission(int appType, String code, int authType, {int? eventKind}) { var app = getApp(appType, code); if (app != null) { if (app.connectType == ConnectType.FULLY_TRUST) { return AuthResult.OK; } else if (app.connectType == ConnectType.ALWAY_REJECT) { return AuthResult.REJECT; } else { var appCode = getAppCode(appType, code); var permissionsMap = appPermissions[appCode]; if (permissionsMap == null) { permissionsMap = _getPermissionMap(app); appPermissions[appCode] = permissionsMap; } var key = "$authType"; if (eventKind != null) { key = "$key-$eventKind"; } var value = permissionsMap[key]; if (value != null) { return value; } } } return AuthResult.ASK; } Map _getPermissionMap(App app) { Map m = {}; _putPermissionMapValue(m, app.alwaysAllow, AuthResult.OK); _putPermissionMapValue(m, app.alwaysReject, AuthResult.REJECT); return m; } void _putPermissionMapValue( Map m, String? permissionText, int value) { if (StringUtil.isNotBlank(permissionText)) { var permissionStrs = permissionText!.split(";"); for (var permissionStr in permissionStrs) { var strs = permissionStr.split("-"); var kindStr = strs[0]; if (strs.length == 1) { m[kindStr] = value; } else if (strs.length > 1) { var eventKindsStr = strs[1]; var eventKindStrs = eventKindsStr.split(","); for (var eventKindStr in eventKindStrs) { var key = "$kindStr-$eventKindStr"; m[key] = value; } } } } } Future deleteApp(App app) async { await AppDB.delete(app.id!); try { await AuthLogDB.deleteByAppId(app.id!); } catch (e) { print(e.toString()); } reload(); } App? getAppById(int appId) { return _appMap[appId]; } // try to find app depend on pubkey. App? getAppByUser(int appType, String pubkey) { List findedList = []; for (var app in _list) { if (app.appType == appType && app.pubkey == pubkey) { findedList.add(app); } } if (findedList.length == 1) { return findedList.first; } return null; } App? getApp(int appType, String code) { for (var app in _list) { if (app.appType == appType && app.code == code) { return app; } } return null; } void alwaysAllow(int appType, String code, int authType, int? eventKind) { _addAlways(appType, code, authType, eventKind, AuthResult.OK); } void alwaysReject(int appType, String code, int authType, int? eventKind) { _addAlways(appType, code, authType, eventKind, AuthResult.REJECT); } void _addAlways( int appType, String code, int authType, int? eventKind, int authResult) { var app = getApp(appType, code); if (app != null) { var permissionMap = _getPermissionMap(app); var key = "$authType"; if (eventKind != null) { key = "$key-$eventKind"; } permissionMap[key] = authResult; List allowAuthTypeStrs = []; List rejectAuthTypeStrs = []; List allowEventKindStrs = []; List rejectEventKindStrs = []; var entries = permissionMap.entries; for (var entry in entries) { var key = entry.key; var value = entry.value; if (key.contains("-")) { var strs = key.split("-"); var eventKindStr = strs[1]; if (value > 0) { allowEventKindStrs.add(eventKindStr); } else { rejectEventKindStrs.add(eventKindStr); } } else { var authTypeStr = key; if (value > 0) { allowAuthTypeStrs.add(authTypeStr); } else { rejectAuthTypeStrs.add(authTypeStr); } } } if (allowEventKindStrs.isNotEmpty) { allowAuthTypeStrs .add("${AuthType.SIGN_EVENT}-${allowEventKindStrs.join(",")}"); } if (rejectEventKindStrs.isNotEmpty) { rejectAuthTypeStrs .add("${AuthType.SIGN_EVENT}-${rejectEventKindStrs.join(",")}"); } app.alwaysAllow = allowAuthTypeStrs.join(";"); app.alwaysReject = rejectAuthTypeStrs.join(";"); var appCode = getAppCode(appType, code); appPermissions.remove(appCode); update(app); } } }