From eea95839680be8c55a9f48c1c08edc22f4b413bf Mon Sep 17 00:00:00 2001 From: balzack Date: Tue, 27 Aug 2024 18:52:56 -0700 Subject: [PATCH] implementing account module --- app/client/mobile/src/SessionStore.ts | 1 + .../mobile/src/context/useAppContext.hook.ts | 2 +- .../ios/Databag.xcodeproj/project.pbxproj | 54 ++- app/mobile/ios/Databag/AppDelegate.mm | 2 + app/mobile/ios/Podfile | 3 + app/mobile/ios/Podfile.lock | 412 ++++++++++++++++-- app/mobile/package.json | 4 +- app/mobile/yarn.lock | 8 +- app/sdk/src/account.ts | 75 +++- app/sdk/src/crypto.ts | 2 +- app/sdk/src/net/addAccountMFAuth.ts | 10 + app/sdk/src/net/clearAccountSeal.ts | 10 + app/sdk/src/net/removeAccountMFAuth.ts | 10 + app/sdk/src/net/setAccountLogin.ts | 9 + app/sdk/src/net/setAccountMFAuth.ts | 10 + app/sdk/src/net/setAccountNotifications.ts | 10 + app/sdk/src/net/setAccountSeal.ts | 11 + app/sdk/src/net/setAccountSearchable.ts | 10 + app/sdk/src/session.ts | 2 +- app/sdk/src/store.ts | 61 ++- 20 files changed, 631 insertions(+), 75 deletions(-) create mode 100644 app/sdk/src/net/addAccountMFAuth.ts create mode 100644 app/sdk/src/net/clearAccountSeal.ts create mode 100644 app/sdk/src/net/removeAccountMFAuth.ts create mode 100644 app/sdk/src/net/setAccountLogin.ts create mode 100644 app/sdk/src/net/setAccountMFAuth.ts create mode 100644 app/sdk/src/net/setAccountNotifications.ts create mode 100644 app/sdk/src/net/setAccountSeal.ts create mode 100644 app/sdk/src/net/setAccountSearchable.ts diff --git a/app/client/mobile/src/SessionStore.ts b/app/client/mobile/src/SessionStore.ts index 4b8aba5b..85a5c620 100644 --- a/app/client/mobile/src/SessionStore.ts +++ b/app/client/mobile/src/SessionStore.ts @@ -25,6 +25,7 @@ export class SessionStore implements SqlStore { stmt: string, params: (string | number | null)[], ): Promise { + console.log('GET: ', stmt); const res = await this.db.executeSql(stmt, params); const rows = []; if (res[0] && res[0].rows && res[0].rows.length > 0) { diff --git a/app/client/mobile/src/context/useAppContext.hook.ts b/app/client/mobile/src/context/useAppContext.hook.ts index e2140b2e..9af8e798 100644 --- a/app/client/mobile/src/context/useAppContext.hook.ts +++ b/app/client/mobile/src/context/useAppContext.hook.ts @@ -1,7 +1,7 @@ import {useState, useEffect, useRef} from 'react'; import {DatabagSDK, Session} from 'databag-client-sdk'; import {SessionStore} from '../SessionStore'; -const DATABAG_DB = 'db_v201.db'; +const DATABAG_DB = 'db_v202.db'; export function useAppContext() { const sdk = useRef(new DatabagSDK(null)); diff --git a/app/mobile/ios/Databag.xcodeproj/project.pbxproj b/app/mobile/ios/Databag.xcodeproj/project.pbxproj index e97fb077..4363765f 100644 --- a/app/mobile/ios/Databag.xcodeproj/project.pbxproj +++ b/app/mobile/ios/Databag.xcodeproj/project.pbxproj @@ -9,12 +9,12 @@ /* Begin PBXBuildFile section */ 00E356F31AD99517003FC87E /* DatabagTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* DatabagTests.m */; }; 054418A1394B8F74B2D5F56A /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EA9B975EA9789519AEC0AE47 /* PrivacyInfo.xcprivacy */; }; - 0C80B921A6F3F58F76C31292 /* libPods-Databag.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-Databag.a */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 7699B88040F8A987B510C191 /* libPods-Databag-DatabagTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-Databag-DatabagTests.a */; }; + 7129C222D8D21DBC6428E317 /* Pods_Databag.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCFB7DA873D4045CEFDFA64B /* Pods_Databag.framework */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; + 91DE1DEFA24D4F0D68C20D28 /* Pods_Databag_DatabagTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33AAD1177A93A7C77ED52C08 /* Pods_Databag_DatabagTests.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -38,14 +38,15 @@ 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Databag/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Databag/main.m; sourceTree = ""; }; 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = Databag/PrivacyInfo.xcprivacy; sourceTree = ""; }; - 19F6CBCC0A4E27FBF8BF4A61 /* libPods-Databag-DatabagTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Databag-DatabagTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33AAD1177A93A7C77ED52C08 /* Pods_Databag_DatabagTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Databag_DatabagTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B4392A12AC88292D35C810B /* Pods-Databag.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Databag.debug.xcconfig"; path = "Target Support Files/Pods-Databag/Pods-Databag.debug.xcconfig"; sourceTree = ""; }; 5709B34CF0A7D63546082F79 /* Pods-Databag.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Databag.release.xcconfig"; path = "Target Support Files/Pods-Databag/Pods-Databag.release.xcconfig"; sourceTree = ""; }; 5B7EB9410499542E8C5724F5 /* Pods-Databag-DatabagTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Databag-DatabagTests.debug.xcconfig"; path = "Target Support Files/Pods-Databag-DatabagTests/Pods-Databag-DatabagTests.debug.xcconfig"; sourceTree = ""; }; - 5DCACB8F33CDC322A6C60F78 /* libPods-Databag.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Databag.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 7B413FF92C6CFD4F0032D17C /* MaterialCommunityIcons.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = MaterialCommunityIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"; sourceTree = ""; }; + 7B466B912C7061BF00FE912E /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../GoogleService-Info.plist"; sourceTree = ""; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = Databag/LaunchScreen.storyboard; sourceTree = ""; }; 89C6BE57DB24E9ADA2F236DE /* Pods-Databag-DatabagTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Databag-DatabagTests.release.xcconfig"; path = "Target Support Files/Pods-Databag-DatabagTests/Pods-Databag-DatabagTests.release.xcconfig"; sourceTree = ""; }; + BCFB7DA873D4045CEFDFA64B /* Pods_Databag.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Databag.framework; sourceTree = BUILT_PRODUCTS_DIR; }; EA9B975EA9789519AEC0AE47 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = Databag/PrivacyInfo.xcprivacy; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -55,7 +56,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 7699B88040F8A987B510C191 /* libPods-Databag-DatabagTests.a in Frameworks */, + 91DE1DEFA24D4F0D68C20D28 /* Pods_Databag_DatabagTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -63,7 +64,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0C80B921A6F3F58F76C31292 /* libPods-Databag.a in Frameworks */, + 7129C222D8D21DBC6428E317 /* Pods_Databag.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -106,8 +107,8 @@ isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - 5DCACB8F33CDC322A6C60F78 /* libPods-Databag.a */, - 19F6CBCC0A4E27FBF8BF4A61 /* libPods-Databag-DatabagTests.a */, + BCFB7DA873D4045CEFDFA64B /* Pods_Databag.framework */, + 33AAD1177A93A7C77ED52C08 /* Pods_Databag_DatabagTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -122,6 +123,7 @@ 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( + 7B466B912C7061BF00FE912E /* GoogleService-Info.plist */, 7B413FF92C6CFD4F0032D17C /* MaterialCommunityIcons.ttf */, 13B07FAE1A68108700A75B9A /* Databag */, 832341AE1AAA6A7D00B99B32 /* Libraries */, @@ -190,6 +192,7 @@ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, + 94F72EC27A6C928516539705 /* [CP-User] [RNFB] Core Configuration */, ); buildRules = ( ); @@ -291,6 +294,19 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Databag/Pods-Databag-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; + 94F72EC27A6C928516539705 /* [CP-User] [RNFB] Core Configuration */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)", + ); + name = "[CP-User] [RNFB] Core Configuration"; + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#!/usr/bin/env bash\n#\n# Copyright (c) 2016-present Invertase Limited & Contributors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this library except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nset -e\n\n_MAX_LOOKUPS=2;\n_SEARCH_RESULT=''\n_RN_ROOT_EXISTS=''\n_CURRENT_LOOKUPS=1\n_JSON_ROOT=\"'react-native'\"\n_JSON_FILE_NAME='firebase.json'\n_JSON_OUTPUT_BASE64='e30=' # { }\n_CURRENT_SEARCH_DIR=${PROJECT_DIR}\n_PLIST_BUDDY=/usr/libexec/PlistBuddy\n_TARGET_PLIST=\"${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}\"\n_DSYM_PLIST=\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist\"\n\n# plist arrays\n_PLIST_ENTRY_KEYS=()\n_PLIST_ENTRY_TYPES=()\n_PLIST_ENTRY_VALUES=()\n\nfunction setPlistValue {\n echo \"info: setting plist entry '$1' of type '$2' in file '$4'\"\n ${_PLIST_BUDDY} -c \"Add :$1 $2 '$3'\" $4 || echo \"info: '$1' already exists\"\n}\n\nfunction getFirebaseJsonKeyValue () {\n if [[ ${_RN_ROOT_EXISTS} ]]; then\n ruby -Ku -e \"require 'rubygems';require 'json'; output=JSON.parse('$1'); puts output[$_JSON_ROOT]['$2']\"\n else\n echo \"\"\n fi;\n}\n\nfunction jsonBoolToYesNo () {\n if [[ $1 == \"false\" ]]; then\n echo \"NO\"\n elif [[ $1 == \"true\" ]]; then\n echo \"YES\"\n else echo \"NO\"\n fi\n}\n\necho \"info: -> RNFB build script started\"\necho \"info: 1) Locating ${_JSON_FILE_NAME} file:\"\n\nif [[ -z ${_CURRENT_SEARCH_DIR} ]]; then\n _CURRENT_SEARCH_DIR=$(pwd)\nfi;\n\nwhile true; do\n _CURRENT_SEARCH_DIR=$(dirname \"$_CURRENT_SEARCH_DIR\")\n if [[ \"$_CURRENT_SEARCH_DIR\" == \"/\" ]] || [[ ${_CURRENT_LOOKUPS} -gt ${_MAX_LOOKUPS} ]]; then break; fi;\n echo \"info: ($_CURRENT_LOOKUPS of $_MAX_LOOKUPS) Searching in '$_CURRENT_SEARCH_DIR' for a ${_JSON_FILE_NAME} file.\"\n _SEARCH_RESULT=$(find \"$_CURRENT_SEARCH_DIR\" -maxdepth 2 -name ${_JSON_FILE_NAME} -print | /usr/bin/head -n 1)\n if [[ ${_SEARCH_RESULT} ]]; then\n echo \"info: ${_JSON_FILE_NAME} found at $_SEARCH_RESULT\"\n break;\n fi;\n _CURRENT_LOOKUPS=$((_CURRENT_LOOKUPS+1))\ndone\n\nif [[ ${_SEARCH_RESULT} ]]; then\n _JSON_OUTPUT_RAW=$(cat \"${_SEARCH_RESULT}\")\n _RN_ROOT_EXISTS=$(ruby -Ku -e \"require 'rubygems';require 'json'; output=JSON.parse('$_JSON_OUTPUT_RAW'); puts output[$_JSON_ROOT]\" || echo '')\n\n if [[ ${_RN_ROOT_EXISTS} ]]; then\n if ! python3 --version >/dev/null 2>&1; then echo \"python3 not found, firebase.json file processing error.\" && exit 1; fi\n _JSON_OUTPUT_BASE64=$(python3 -c 'import json,sys,base64;print(base64.b64encode(bytes(json.dumps(json.loads(open('\"'${_SEARCH_RESULT}'\"', '\"'rb'\"').read())['${_JSON_ROOT}']), '\"'utf-8'\"')).decode())' || echo \"e30=\")\n fi\n\n _PLIST_ENTRY_KEYS+=(\"firebase_json_raw\")\n _PLIST_ENTRY_TYPES+=(\"string\")\n _PLIST_ENTRY_VALUES+=(\"$_JSON_OUTPUT_BASE64\")\n\n # config.app_data_collection_default_enabled\n _APP_DATA_COLLECTION_ENABLED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"app_data_collection_default_enabled\")\n if [[ $_APP_DATA_COLLECTION_ENABLED ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseDataCollectionDefaultEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_APP_DATA_COLLECTION_ENABLED\")\")\n fi\n\n # config.analytics_auto_collection_enabled\n _ANALYTICS_AUTO_COLLECTION=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_auto_collection_enabled\")\n if [[ $_ANALYTICS_AUTO_COLLECTION ]]; then\n _PLIST_ENTRY_KEYS+=(\"FIREBASE_ANALYTICS_COLLECTION_ENABLED\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_AUTO_COLLECTION\")\")\n fi\n\n # config.analytics_collection_deactivated\n _ANALYTICS_DEACTIVATED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_collection_deactivated\")\n if [[ $_ANALYTICS_DEACTIVATED ]]; then\n _PLIST_ENTRY_KEYS+=(\"FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_DEACTIVATED\")\")\n fi\n\n # config.analytics_idfv_collection_enabled\n _ANALYTICS_IDFV_COLLECTION=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_idfv_collection_enabled\")\n if [[ $_ANALYTICS_IDFV_COLLECTION ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_IDFV_COLLECTION_ENABLED\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_IDFV_COLLECTION\")\")\n fi\n\n # config.analytics_default_allow_ad_personalization_signals\n _ANALYTICS_PERSONALIZATION=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"analytics_default_allow_ad_personalization_signals\")\n if [[ $_ANALYTICS_PERSONALIZATION ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_DEFAULT_ALLOW_AD_PERSONALIZATION_SIGNALS\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_PERSONALIZATION\")\")\n fi\n\n # config.analytics_registration_with_ad_network_enabled\n _ANALYTICS_REGISTRATION_WITH_AD_NETWORK=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"google_analytics_registration_with_ad_network_enabled\")\n if [[ $_ANALYTICS_REGISTRATION_WITH_AD_NETWORK ]]; then\n _PLIST_ENTRY_KEYS+=(\"GOOGLE_ANALYTICS_REGISTRATION_WITH_AD_NETWORK_ENABLED\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_REGISTRATION_WITH_AD_NETWORK\")\")\n fi\n\n # config.google_analytics_automatic_screen_reporting_enabled\n _ANALYTICS_AUTO_SCREEN_REPORTING=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"google_analytics_automatic_screen_reporting_enabled\")\n if [[ $_ANALYTICS_AUTO_SCREEN_REPORTING ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseAutomaticScreenReportingEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_ANALYTICS_AUTO_SCREEN_REPORTING\")\")\n fi\n\n # config.perf_auto_collection_enabled\n _PERF_AUTO_COLLECTION=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"perf_auto_collection_enabled\")\n if [[ $_PERF_AUTO_COLLECTION ]]; then\n _PLIST_ENTRY_KEYS+=(\"firebase_performance_collection_enabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_PERF_AUTO_COLLECTION\")\")\n fi\n\n # config.perf_collection_deactivated\n _PERF_DEACTIVATED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"perf_collection_deactivated\")\n if [[ $_PERF_DEACTIVATED ]]; then\n _PLIST_ENTRY_KEYS+=(\"firebase_performance_collection_deactivated\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_PERF_DEACTIVATED\")\")\n fi\n\n # config.messaging_auto_init_enabled\n _MESSAGING_AUTO_INIT=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"messaging_auto_init_enabled\")\n if [[ $_MESSAGING_AUTO_INIT ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseMessagingAutoInitEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_MESSAGING_AUTO_INIT\")\")\n fi\n\n # config.in_app_messaging_auto_colllection_enabled\n _FIAM_AUTO_INIT=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"in_app_messaging_auto_collection_enabled\")\n if [[ $_FIAM_AUTO_INIT ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseInAppMessagingAutomaticDataCollectionEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_FIAM_AUTO_INIT\")\")\n fi\n\n # config.app_check_token_auto_refresh\n _APP_CHECK_TOKEN_AUTO_REFRESH=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"app_check_token_auto_refresh\")\n if [[ $_APP_CHECK_TOKEN_AUTO_REFRESH ]]; then\n _PLIST_ENTRY_KEYS+=(\"FirebaseAppCheckTokenAutoRefreshEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"$(jsonBoolToYesNo \"$_APP_CHECK_TOKEN_AUTO_REFRESH\")\")\n fi\n\n # config.crashlytics_disable_auto_disabler - undocumented for now - mainly for debugging, document if becomes useful\n _CRASHLYTICS_AUTO_DISABLE_ENABLED=$(getFirebaseJsonKeyValue \"$_JSON_OUTPUT_RAW\" \"crashlytics_disable_auto_disabler\")\n if [[ $_CRASHLYTICS_AUTO_DISABLE_ENABLED == \"true\" ]]; then\n echo \"Disabled Crashlytics auto disabler.\" # do nothing\n else\n _PLIST_ENTRY_KEYS+=(\"FirebaseCrashlyticsCollectionEnabled\")\n _PLIST_ENTRY_TYPES+=(\"bool\")\n _PLIST_ENTRY_VALUES+=(\"NO\")\n fi\nelse\n _PLIST_ENTRY_KEYS+=(\"firebase_json_raw\")\n _PLIST_ENTRY_TYPES+=(\"string\")\n _PLIST_ENTRY_VALUES+=(\"$_JSON_OUTPUT_BASE64\")\n echo \"warning: A firebase.json file was not found, whilst this file is optional it is recommended to include it to configure firebase services in React Native Firebase.\"\nfi;\n\necho \"info: 2) Injecting Info.plist entries: \"\n\n# Log out the keys we're adding\nfor i in \"${!_PLIST_ENTRY_KEYS[@]}\"; do\n echo \" -> $i) ${_PLIST_ENTRY_KEYS[$i]}\" \"${_PLIST_ENTRY_TYPES[$i]}\" \"${_PLIST_ENTRY_VALUES[$i]}\"\ndone\n\nfor plist in \"${_TARGET_PLIST}\" \"${_DSYM_PLIST}\" ; do\n if [[ -f \"${plist}\" ]]; then\n\n # paths with spaces break the call to setPlistValue. temporarily modify\n # the shell internal field separator variable (IFS), which normally\n # includes spaces, to consist only of line breaks\n oldifs=$IFS\n IFS=\"\n\"\n\n for i in \"${!_PLIST_ENTRY_KEYS[@]}\"; do\n setPlistValue \"${_PLIST_ENTRY_KEYS[$i]}\" \"${_PLIST_ENTRY_TYPES[$i]}\" \"${_PLIST_ENTRY_VALUES[$i]}\" \"${plist}\"\n done\n\n # restore the original internal field separator value\n IFS=$oldifs\n else\n echo \"warning: A Info.plist build output file was not found (${plist})\"\n fi\ndone\n\necho \"info: <- RNFB build script finished\"\n"; + }; A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -583,6 +599,17 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + ); IPHONEOS_DEPLOYMENT_TARGET = 13.4; LD = ""; LDPLUSPLUS = ""; @@ -659,6 +686,17 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + ); IPHONEOS_DEPLOYMENT_TARGET = 13.4; LD = ""; LDPLUSPLUS = ""; diff --git a/app/mobile/ios/Databag/AppDelegate.mm b/app/mobile/ios/Databag/AppDelegate.mm index b673f869..d912ae6e 100644 --- a/app/mobile/ios/Databag/AppDelegate.mm +++ b/app/mobile/ios/Databag/AppDelegate.mm @@ -1,10 +1,12 @@ #import "AppDelegate.h" +#import #import @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions + [FIRApp configure]; { self.moduleName = @"Databag"; // You can add your custom initial props in the dictionary below. diff --git a/app/mobile/ios/Podfile b/app/mobile/ios/Podfile index d573962b..ac129b44 100644 --- a/app/mobile/ios/Podfile +++ b/app/mobile/ios/Podfile @@ -17,6 +17,9 @@ end target 'Databag' do config = use_native_modules! + use_frameworks! :linkage => :static + $RNFirebaseAsStaticFramework = true + use_react_native!( :path => config[:reactNativePath], # An absolute path to your application root. diff --git a/app/mobile/ios/Podfile.lock b/app/mobile/ios/Podfile.lock index d7dd82eb..cbe77ee7 100644 --- a/app/mobile/ios/Podfile.lock +++ b/app/mobile/ios/Podfile.lock @@ -2,11 +2,86 @@ PODS: - boost (1.83.0) - DoubleConversion (1.1.6) - FBLazyVector (0.74.3) + - Firebase/CoreOnly (10.7.0): + - FirebaseCore (= 10.7.0) + - Firebase/Messaging (10.7.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 10.7.0) + - FirebaseCore (10.7.0): + - FirebaseCoreInternal (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/Logger (~> 7.8) + - FirebaseCoreExtension (10.7.0): + - FirebaseCore (~> 10.0) + - FirebaseCoreInternal (10.29.0): + - "GoogleUtilities/NSData+zlib (~> 7.8)" + - FirebaseInstallations (10.29.0): + - FirebaseCore (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - PromisesObjC (~> 2.1) + - FirebaseMessaging (10.7.0): + - FirebaseCore (~> 10.0) + - FirebaseInstallations (~> 10.0) + - GoogleDataTransport (~> 9.2) + - GoogleUtilities/AppDelegateSwizzler (~> 7.8) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/Reachability (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - nanopb (< 2.30910.0, >= 2.30908.0) - fmt (9.1.0) - glog (0.3.5) + - GoogleDataTransport (9.4.1): + - GoogleUtilities/Environment (~> 7.7) + - nanopb (< 2.30911.0, >= 2.30908.0) + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/AppDelegateSwizzler (7.13.3): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Privacy + - GoogleUtilities/Environment (7.13.3): + - GoogleUtilities/Privacy + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/Logger (7.13.3): + - GoogleUtilities/Environment + - GoogleUtilities/Privacy + - GoogleUtilities/Network (7.13.3): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Privacy + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (7.13.3)": + - GoogleUtilities/Privacy + - GoogleUtilities/Privacy (7.13.3) + - GoogleUtilities/Reachability (7.13.3): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - GoogleUtilities/UserDefaults (7.13.3): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy - hermes-engine (0.74.3): - hermes-engine/Pre-built (= 0.74.3) - hermes-engine/Pre-built (0.74.3) + - JitsiWebRTC (118.0.0) + - libwebp (1.3.2): + - libwebp/demux (= 1.3.2) + - libwebp/mux (= 1.3.2) + - libwebp/sharpyuv (= 1.3.2) + - libwebp/webp (= 1.3.2) + - libwebp/demux (1.3.2): + - libwebp/webp + - libwebp/mux (1.3.2): + - libwebp/demux + - libwebp/sharpyuv (1.3.2) + - libwebp/webp (1.3.2): + - libwebp/sharpyuv + - nanopb (2.30909.1): + - nanopb/decode (= 2.30909.1) + - nanopb/encode (= 2.30909.1) + - nanopb/decode (2.30909.1) + - nanopb/encode (2.30909.1) + - PromisesObjC (2.4.0) - RCT-Folly (2024.01.01.00): - boost - DoubleConversion @@ -956,10 +1031,32 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga + - react-native-create-thumbnail (1.6.4): + - React-Core + - react-native-document-picker (8.2.2): + - React-Core + - react-native-image-resizer (3.0.10): + - React-Core + - react-native-keep-awake (1.2.4): + - React-Core + - react-native-receive-sharing-intent (2.0.0): + - React-Core + - react-native-rsa-native (2.0.5): + - React - react-native-safe-area-context (4.10.9): - React-Core - react-native-sqlite-storage (6.0.1): - React-Core + - react-native-unifiedpush-connector (0.1.8): + - React-Core + - react-native-video (5.2.1): + - React-Core + - react-native-video/Video (= 5.2.1) + - react-native-video/Video (5.2.1): + - React-Core + - react-native-webrtc (118.0.7): + - JitsiWebRTC (~> 118.0.0) + - React-Core - React-nativeconfig (0.74.3) - React-NativeModulesApple (0.74.3): - glog @@ -1189,6 +1286,123 @@ PODS: - React-logger (= 0.74.3) - React-perflogger (= 0.74.3) - React-utils (= 0.74.3) + - ReactNativeIncallManager (4.2.0): + - React-Core + - rn-fetch-blob (0.12.0): + - React-Core + - RNCClipboard (1.14.1): + - React-Core + - RNDeviceInfo (10.14.0): + - React-Core + - RNFastImage (8.6.3): + - React-Core + - SDWebImage (~> 5.11.1) + - SDWebImageWebPCoder (~> 0.8.4) + - RNFBApp (17.5.0): + - Firebase/CoreOnly (= 10.7.0) + - React-Core + - RNFBMessaging (17.5.0): + - Firebase/Messaging (= 10.7.0) + - FirebaseCoreExtension (= 10.7.0) + - React-Core + - RNFBApp + - RNFS (2.20.0): + - React-Core + - RNGestureHandler (2.18.1): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Codegen + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - RNImageCropPicker (0.39.0): + - React-Core + - React-RCTImage + - RNImageCropPicker/QBImagePickerController (= 0.39.0) + - TOCropViewController + - RNImageCropPicker/QBImagePickerController (0.39.0): + - React-Core + - React-RCTImage + - TOCropViewController + - RNReanimated (3.15.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Codegen + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - RNReanimated/reanimated (= 3.15.0) + - RNReanimated/worklets (= 3.15.0) + - Yoga + - RNReanimated/reanimated (3.15.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Codegen + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - RNReanimated/worklets (3.15.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Codegen + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga - RNScreens (3.34.0): - DoubleConversion - glog @@ -1211,28 +1425,18 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - RNVectorIcons (10.1.0): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.01.01.00) - - RCTRequired - - RCTTypeSafety - - React-Codegen + - RNShare (8.2.2): - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga + - RNVectorIcons (9.2.0): + - React-Core + - SDWebImage (5.11.1): + - SDWebImage/Core (= 5.11.1) + - SDWebImage/Core (5.11.1) + - SDWebImageWebPCoder (0.8.5): + - libwebp (~> 1.0) + - SDWebImage/Core (~> 5.10) - SocketRocket (0.7.0) + - TOCropViewController (2.7.4) - Yoga (0.0.0) DEPENDENCIES: @@ -1269,8 +1473,17 @@ DEPENDENCIES: - React-logger (from `../node_modules/react-native/ReactCommon/logger`) - React-Mapbuffer (from `../node_modules/react-native/ReactCommon`) - "react-native-blur (from `../node_modules/@react-native-community/blur`)" + - react-native-create-thumbnail (from `../node_modules/react-native-create-thumbnail`) + - react-native-document-picker (from `../node_modules/react-native-document-picker`) + - "react-native-image-resizer (from `../node_modules/@bam.tech/react-native-image-resizer`)" + - "react-native-keep-awake (from `../node_modules/@sayem314/react-native-keep-awake`)" + - react-native-receive-sharing-intent (from `../node_modules/react-native-receive-sharing-intent`) + - react-native-rsa-native (from `../node_modules/react-native-rsa-native`) - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) - react-native-sqlite-storage (from `../node_modules/react-native-sqlite-storage`) + - react-native-unifiedpush-connector (from `../node_modules/react-native-unifiedpush-connector`) + - react-native-video (from `../node_modules/react-native-video`) + - react-native-webrtc (from `../node_modules/react-native-webrtc`) - React-nativeconfig (from `../node_modules/react-native/ReactCommon`) - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) @@ -1294,13 +1507,40 @@ DEPENDENCIES: - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - ReactNativeIncallManager (from `../node_modules/react-native-incall-manager`) + - rn-fetch-blob (from `../node_modules/rn-fetch-blob`) + - "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)" + - RNDeviceInfo (from `../node_modules/react-native-device-info`) + - RNFastImage (from `../node_modules/react-native-fast-image`) + - "RNFBApp (from `../node_modules/@react-native-firebase/app`)" + - "RNFBMessaging (from `../node_modules/@react-native-firebase/messaging`)" + - RNFS (from `../node_modules/react-native-fs`) + - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) + - RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`) + - RNReanimated (from `../node_modules/react-native-reanimated`) - RNScreens (from `../node_modules/react-native-screens`) + - RNShare (from `../node_modules/react-native-share`) - RNVectorIcons (from `../node_modules/react-native-vector-icons`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: trunk: + - Firebase + - FirebaseCore + - FirebaseCoreExtension + - FirebaseCoreInternal + - FirebaseInstallations + - FirebaseMessaging + - GoogleDataTransport + - GoogleUtilities + - JitsiWebRTC + - libwebp + - nanopb + - PromisesObjC + - SDWebImage + - SDWebImageWebPCoder - SocketRocket + - TOCropViewController EXTERNAL SOURCES: boost: @@ -1366,10 +1606,28 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon" react-native-blur: :path: "../node_modules/@react-native-community/blur" + react-native-create-thumbnail: + :path: "../node_modules/react-native-create-thumbnail" + react-native-document-picker: + :path: "../node_modules/react-native-document-picker" + react-native-image-resizer: + :path: "../node_modules/@bam.tech/react-native-image-resizer" + react-native-keep-awake: + :path: "../node_modules/@sayem314/react-native-keep-awake" + react-native-receive-sharing-intent: + :path: "../node_modules/react-native-receive-sharing-intent" + react-native-rsa-native: + :path: "../node_modules/react-native-rsa-native" react-native-safe-area-context: :path: "../node_modules/react-native-safe-area-context" react-native-sqlite-storage: :path: "../node_modules/react-native-sqlite-storage" + react-native-unifiedpush-connector: + :path: "../node_modules/react-native-unifiedpush-connector" + react-native-video: + :path: "../node_modules/react-native-video" + react-native-webrtc: + :path: "../node_modules/react-native-webrtc" React-nativeconfig: :path: "../node_modules/react-native/ReactCommon" React-NativeModulesApple: @@ -1416,8 +1674,32 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/react/utils" ReactCommon: :path: "../node_modules/react-native/ReactCommon" + ReactNativeIncallManager: + :path: "../node_modules/react-native-incall-manager" + rn-fetch-blob: + :path: "../node_modules/rn-fetch-blob" + RNCClipboard: + :path: "../node_modules/@react-native-clipboard/clipboard" + RNDeviceInfo: + :path: "../node_modules/react-native-device-info" + RNFastImage: + :path: "../node_modules/react-native-fast-image" + RNFBApp: + :path: "../node_modules/@react-native-firebase/app" + RNFBMessaging: + :path: "../node_modules/@react-native-firebase/messaging" + RNFS: + :path: "../node_modules/react-native-fs" + RNGestureHandler: + :path: "../node_modules/react-native-gesture-handler" + RNImageCropPicker: + :path: "../node_modules/react-native-image-crop-picker" + RNReanimated: + :path: "../node_modules/react-native-reanimated" RNScreens: :path: "../node_modules/react-native-screens" + RNShare: + :path: "../node_modules/react-native-share" RNVectorIcons: :path: "../node_modules/react-native-vector-icons" Yoga: @@ -1427,64 +1709,100 @@ SPEC CHECKSUMS: boost: d3f49c53809116a5d38da093a8aa78bf551aed09 DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5 FBLazyVector: 7e977dd099937dc5458851233141583abba49ff2 + Firebase: 0219acf760880eeec8ce479895bd7767466d9f81 + FirebaseCore: e317665b9d744727a97e623edbbed009320afdd7 + FirebaseCoreExtension: f17247ba8c61e4d3c8d136b5e2de3cb4ac6a85b6 + FirebaseCoreInternal: df84dd300b561c27d5571684f389bf60b0a5c934 + FirebaseInstallations: 913cf60d0400ebd5d6b63a28b290372ab44590dd + FirebaseMessaging: ac9062bcc35ed56e15a0241d8fd317022499baf8 fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120 glog: fdfdfe5479092de0c4bdbebedd9056951f092c4f + GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a + GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15 hermes-engine: 1f547997900dd0752dc0cc0ae6dd16173c49e09b + JitsiWebRTC: 3a41671ef65a51d7204323814b055a2690b921c7 + libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009 + nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5 + PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 RCT-Folly: 02617c592a293bd6d418e0a88ff4ee1f88329b47 RCTDeprecation: 4c7eeb42be0b2e95195563c49be08d0b839d22b4 RCTRequired: d530a0f489699c8500e944fde963102c42dcd0c2 RCTTypeSafety: b20878506b094fa3d9007d7b9e4be0faa3562499 React: 2f9da0177233f60fa3462d83fcccde245759f81a React-callinvoker: d0205f0dcebf72ec27263ab41e3a5ad827ed503f - React-Codegen: b4457c8557cb61a27508745f8b03f16afeb9ef59 + React-Codegen: 27212e14727ad7d6d9fd1b1967fbf21929e4ce29 React-Core: 690ebbbf8f8dcfba6686ce8927731d3f025c3114 React-CoreModules: 185da31f5eb2e6043c3d19b10c64c4661322ed6a React-cxxreact: c53d2ac9246235351086b8c588feaf775b4ec7f7 - React-debug: dd8f7c772fda4196814a3b12620863d1d98b3a53 - React-Fabric: 68935648d5c81e6b84445d9e726a79301f1fac8f - React-FabricImage: c92bd5ed4b553c800ca39aee305aaf8dd3e9f4b0 - React-featureflags: ead50fe0ee4ab9278b5fd9f3f2f0f63e316452f4 - React-graphics: 71c87b09041e45c61809cd357436e570dea5ed48 + React-debug: 40caf8ab4c0fd3afe831912e3d4d0e7303eecc5d + React-Fabric: 51ccb4f7e45df5837e796f339d602737063c463e + React-FabricImage: 376b7a81bfe64102e7da5fc85cd1775638584c92 + React-featureflags: 0d0576ae8306801a8a660b36afcdbda04dd7cc12 + React-graphics: e0e6b8fbb1c5968c70d3584dccec42544b769b60 React-hermes: 917b7ab4c3cb9204c2ad020d74f313830097148b - React-ImageManager: 1086d48d00fcb511ea119bfc58fb12a72c4dcb95 - React-jserrorhandler: 84d45913636750c2e620a8c8e049964967040405 + React-ImageManager: 5cebcc0136f3b309c7f5189b96e6c0ebd0ec8192 + React-jserrorhandler: 5dc7e036cba3b7d167380c02afabf818ad0b2f98 React-jsi: 024b933267079f80c30a5cae97bf5ce521217505 React-jsiexecutor: 45cb079c87db3f514da3acfc686387a0e01de5c5 - React-jsinspector: 1066f8b3da937daf8ced4cf3786eb29e1e4f9b30 - React-jsitracing: 6b3c8c98313642140530f93c46f5a6ca4530b446 + React-jsinspector: c9551971f1298163c93e2bfb082c2b4245618fc6 + React-jsitracing: 1aa5681c353b41573b03e0e480a5adf5fa1c56d8 React-logger: fa92ba4d3a5d39ac450f59be2a3cec7b099f0304 - React-Mapbuffer: 9f68550e7c6839d01411ac8896aea5c868eff63a - react-native-blur: a2acf22fd7bd13621df5e0b1c130b81adea7009c + React-Mapbuffer: 70da5955150a58732e9336a0c7e71cd49e909f25 + react-native-blur: b58f3155f534d975b7647593d93a2e907513addd + react-native-create-thumbnail: e022bcdcba8a0b4529a50d3fa1a832ec921be39d + react-native-document-picker: cd4d6b36a5207ad7a9e599ebb9eb0c2e84fa0b87 + react-native-image-resizer: fd0c333eca55147bd55c5e054cac95dcd0da6814 + react-native-keep-awake: a15b33cd9b94a2da9b0a1c50ac64ac2391d3e330 + react-native-receive-sharing-intent: 62ab28c50e6ae56d32b9e841d7452091312a0bc7 + react-native-rsa-native: 12132eb627797529fdb1f0d22fd0f8f9678df64a react-native-safe-area-context: ab8f4a3d8180913bd78ae75dd599c94cce3d5e9a react-native-sqlite-storage: f6d515e1c446d1e6d026aa5352908a25d4de3261 - React-nativeconfig: fa5de9d8f4dbd5917358f8ad3ad1e08762f01dcb - React-NativeModulesApple: 585d1b78e0597de364d259cb56007052d0bda5e5 + react-native-unifiedpush-connector: 4d60170e5eb46329f15e5da6c1171d3683480bf4 + react-native-video: c26780b224543c62d5e1b2a7244a5cd1b50e8253 + react-native-webrtc: 8b024c7bb9a005d2b9efeba4c691172dbd00268d + React-nativeconfig: 84806b820491db30175afbf027e99e8415dc63f0 + React-NativeModulesApple: 7b79212f8cf496ab554e0b7b09acbd4aa4690260 React-perflogger: 7bb9ba49435ff66b666e7966ee10082508a203e8 React-RCTActionSheet: a2816ae2b5c8523c2bc18a8f874a724a096e6d97 React-RCTAnimation: e78f52d7422bac13e1213e25e9bcbf99be872e1a React-RCTAppDelegate: 24f46de486cfa3a9f46e4b0786eaf17d92e1e0c6 React-RCTBlob: 9f9d6599d1b00690704dadc4a4bc33a7e76938be - React-RCTFabric: 609e66bb0371b9082c62ed677ee0614efe711bf2 + React-RCTFabric: 416d20a24b117a7ec7d32088fc8f359b5e558fa7 React-RCTImage: 39dd5aee6b92213845e1e7a7c41865801dc33493 React-RCTLinking: 35d742a982f901f9ea416d772763e2da65c2dc7d React-RCTNetwork: b078576c0c896c71905f841716b9f9f5922111dc React-RCTSettings: 900aab52b5b1212f247c2944d88f4defbf6146f2 React-RCTText: a3895ab4e5df4a5fd41b6f059eed484a0c7016d1 React-RCTVibration: ab4912e1427d8de00ef89e9e6582094c4c25dc05 - React-rendererdebug: 542934058708a643fa5743902eb2fedc0833770a - React-rncore: f6c23d9810c8de9e369781bb7b1d5511e9d9f4e7 - React-RuntimeApple: ce41ba7df744c7a6c2cc490a9b2e15fc58019508 - React-RuntimeCore: 350218ac9ee1412ddc9806f248141c8fb9bccd8b + React-rendererdebug: 8ea55aebb8cba804db2a8449a2f0c80ccfe0ce5a + React-rncore: 1f725aee4e00c317e51cb4d37aca7f6a47da9a11 + React-RuntimeApple: c1833d8e82f7c5314c001d61d289849c75217944 + React-RuntimeCore: 0a5b37b50737af3505b5801376ae5788532c013e React-runtimeexecutor: 69cab8ddf409de6d6a855a71c8af9e7290c4e55b - React-RuntimeHermes: 9d0812e3370111dd175aa1fa8bd4da93a9efc4fd - React-runtimescheduler: 0c80752bceb80924cb8a4babc2a8e3ed70d41e87 - React-utils: a06061b3887c702235d2dac92dacbd93e1ea079e - ReactCommon: f00e436b3925a7ae44dfa294b43ef360fbd8ccc4 - RNScreens: aa943ad421c3ced3ef5a47ede02b0cbfc43a012e - RNVectorIcons: 2a2f79274248390b80684ea3c4400bd374a15c90 + React-RuntimeHermes: 44847ba3e8a9394b9829d9a9abde7590624f32d0 + React-runtimescheduler: e4ad653e1d2f5ff40ba047446cacde009694f0ed + React-utils: 6f7ac39d9a0de447d4334bb25d144a28c0c5d8c9 + ReactCommon: 4a09c7d8a06e93c1e2e988a3b9f3db3d2449f2fc + ReactNativeIncallManager: bfc9c67358cd524882a7c4116dcb311ac2293d4b + rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba + RNCClipboard: 0a720adef5ec193aa0e3de24c3977222c7e52a37 + RNDeviceInfo: 59344c19152c4b2b32283005f9737c5c64b42fba + RNFastImage: 5c9c9fed9c076e521b3f509fe79e790418a544e8 + RNFBApp: d59efa0872fff4e27de03cca3c528c203a436ae5 + RNFBMessaging: 216693dd5ba4f18ba65fb39fc73a44a23c26190f + RNFS: 4ac0f0ea233904cb798630b3c077808c06931688 + RNGestureHandler: fc0d83b45872ee937ecc9814012d9b48586b4d7a + RNImageCropPicker: 14fe1c29298fb4018f3186f455c475ab107da332 + RNReanimated: 45f0fd1250364dffec9aabd4a0959f2956a5e78b + RNScreens: db442e7b8c7bc8befec2ce057927305ff8598cc8 + RNShare: d82e10f6b7677f4b0048c23709bd04098d5aee6c + RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8 + SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d + SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d - Yoga: 88480008ccacea6301ff7bf58726e27a72931c8d + TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654 + Yoga: bd92064a0d558be92786820514d74fc4dddd1233 -PODFILE CHECKSUM: 8461018d8deceb200962c829584af7c2eb345c80 +PODFILE CHECKSUM: 98a8566a28ef3705c6f2fdf1c3525e90e7ebfdfd COCOAPODS: 1.15.2 diff --git a/app/mobile/package.json b/app/mobile/package.json index 21ef97ae..7193a10a 100644 --- a/app/mobile/package.json +++ b/app/mobile/package.json @@ -15,8 +15,8 @@ "@braintree/sanitize-url": "^6.0.2", "@react-native-clipboard/clipboard": "^1.11.1", "@react-native-community/blur": "^4.3.2", - "@react-native-firebase/app": "^17.2.0", - "@react-native-firebase/messaging": "^17.2.0", + "@react-native-firebase/app": "^17.5.0", + "@react-native-firebase/messaging": "^17.5.0", "@react-navigation/bottom-tabs": "^6.5.5", "@react-navigation/drawer": "^6.6.0", "@react-navigation/native": "^6.1.4", diff --git a/app/mobile/yarn.lock b/app/mobile/yarn.lock index 53c128a6..e955ae4e 100644 --- a/app/mobile/yarn.lock +++ b/app/mobile/yarn.lock @@ -2387,7 +2387,7 @@ __metadata: languageName: node linkType: hard -"@react-native-firebase/app@npm:^17.2.0": +"@react-native-firebase/app@npm:^17.5.0": version: 17.5.0 resolution: "@react-native-firebase/app@npm:17.5.0" dependencies: @@ -2404,7 +2404,7 @@ __metadata: languageName: node linkType: hard -"@react-native-firebase/messaging@npm:^17.2.0": +"@react-native-firebase/messaging@npm:^17.5.0": version: 17.5.0 resolution: "@react-native-firebase/messaging@npm:17.5.0" peerDependencies: @@ -3241,8 +3241,8 @@ __metadata: "@braintree/sanitize-url": ^6.0.2 "@react-native-clipboard/clipboard": ^1.11.1 "@react-native-community/blur": ^4.3.2 - "@react-native-firebase/app": ^17.2.0 - "@react-native-firebase/messaging": ^17.2.0 + "@react-native-firebase/app": ^17.5.0 + "@react-native-firebase/messaging": ^17.5.0 "@react-native/babel-preset": 0.74.85 "@react-native/eslint-config": 0.74.85 "@react-native/metro-config": 0.74.85 diff --git a/app/sdk/src/account.ts b/app/sdk/src/account.ts index 26241d3d..a98094fc 100644 --- a/app/sdk/src/account.ts +++ b/app/sdk/src/account.ts @@ -4,6 +4,15 @@ import type { AccountStatus } from './types'; import { Store } from './store'; import { defaultAccountEntity, AccountEntity } from './entities'; import { getAccountStatus } from './net/getAccountStatus'; +import { addAccountMFAuth } from './net/addAccountMFAuth'; +import { setAccountMFAuth } from './net/setAccountMFAuth'; +import { removeAccountMFAuth } from './net/removeAccountMFAuth'; +import { setAccountLogin } from './net/setAccountLogin'; +import { setAccountNotifications } from './net/setAccountNotifications'; +import { setAccountSearchable } from './net/setAccountSearchable'; +import { setAccountSeal } from './net/setAccountSeal'; +import { clearAccountSeal } from './net/clearAccountSeal'; +import { Crypto } from './crypto'; const CLOSE_POLL_MS = 100; const RETRY_POLL_MS = 2000; @@ -16,18 +25,21 @@ export class AccountModule implements Account { private node: string; private secure: boolean; private log: Logging; + private crypto: Crypto | null; private syncing: boolean; private closing: boolean; private revision: number; private nextRevision: number | null; private entity: AccountEntity; + private sealKey: { privateKey: string, publicKey: string } | null; - constructor(log: Logging, store: Store, guid: string, token: string, node: string, secure: boolean) { + constructor(log: Logging, store: Store, crypto: Crypto | null, guid: string, token: string, node: string, secure: boolean) { this.log = log; this.emitter = new EventEmitter(); this.guid = guid; this.token = token; this.node = node; + this.seal = null; this.secure = secure; this.revision = 0; this.entity = defaultAccountEntity; @@ -40,6 +52,7 @@ export class AccountModule implements Account { private async init() { this.revision = await this.store.getAccountRevision(this.guid); this.entity = await this.store.getAccountData(this.guid); + this.seal = await this.store.getSeal(this.guid); this.syncing = false; await this.sync(); } @@ -72,12 +85,14 @@ export class AccountModule implements Account { } } } + this.syncing = false; } } public getStatus() { const { storageUsed, storageAvailable, forwardingAddress, searchable, allowUnseaed, pushEnabled, sealable, seal, enableIce, multiFactorAuth, webPushKey } = this.entity; - return { storageUsed, storageAvailable, forwardingAddress, searchable, allowUnsealed, pushEnabled, sealable, sealSet: Boolean(seal), enableIce, multiFactorAuth, webPushKey }; + const sealSet = this.seal && seal && this.seal.publicKey == seal.publicKey && this.seal.privateKey + return { storageUsed, storageAvailable, forwardingAddress, searchable, allowUnsealed, pushEnabled, sealable, sealSet, enableIce, multiFactorAuth, webPushKey }; } public addStatusListener(ev: (status: AccountStatus) => void): void { @@ -102,37 +117,91 @@ export class AccountModule implements Account { } public async enableNotifications(): Promise { + const { node, secure, token } = this; + await setAccountNotifications(node, secure, token, true); } public async disableNotifications(): Promise { + const { node, secure, token } = this; + await setAccountNotifications(node, secure, token, false); } public async enableRegistry(): Promise { + const { node, secure, token } = this; + await setAccountSearchable(node, secure, token, true); } public async disableRegistry(): Promise { + const { node, secure, token } = this; + await setAccountSearchable(node, secure, token, false); } public async enableMFA(): Promise<{ secretImage: string, secretText: string }> { - return { secretImage: '', secretText: '' }; + const { node, secure, token } = this; + const { image, text } = await addAccountMFAuth(node, secure, token); + return { secretImage: image, secretText: text }; } public async disableMFA(): Promise { + const { node, secure, token } = this; + await removeAccountMFAuth(node, secure, token); } public async confirmMFA(code: string): Promise { + const { node, secure, token } = this; + await setAccountMFAuth(node, secure, token, code); } public async setAccountSeal(password: string): Promise { + const { crypto, guid, node, secure, token } = this; + if (!crypto) { + throw new Error('crypto not enabled'); + } + const { saltHex } = crypto.pbkdfSalt(); + const { aesKeyHex } = crypto.pbkdfKey(saltHex, password); + const { publicKeyB64, privateKeyB64 } = crypto.rsaKey(); + const { ivHex } = crypto.aesIv(); + const { encryptedDataB64 } = crypto.aesEncrypt(privateKeyB64, ivHex, aesKeyHex); + + const entity = { passwordSalt: saltHex, privateKeyIv: ivHex, privateKeyEncrypted: encryptedDataB64, publicKey: publicKeyB64 }; + await setAccountSeal(node, secure, token, entity); + + const seal = { publicKey: publicKeyB64, privateKey: privateKeyB64 }; + this.store.setSeal(guid, seal); + this.seal = seal; + + this.emitter.emit('status', this.getStatus()); } public async clearAccountSeal(): Promise { + const { guid, node, secure, token } = this; + await this.store.clearAccountSeal(guid, node, secure, token); + this.seal = null; + this.emitter.emit('status', this.getStatus()); } public async unlockAccountSeal(password: string): Promise { + const { guid, entity, crypto } = this; + const { passwordSalt, privateKeyIv, privateKeyEncrypted, publicKey } = entity.seal; + if (!passwordSalt || !privateKeyIv || !privateKeyEncrypted || !publicKey) { + throw new Error('account seal not set'); + } + if (!crypto) { + throw new Error('crypto not set'); + } + const { aesKeyHex } = crypto.pbkdfKey(passwordSalt, password); + const { data } = crypto.aesDecrypt(privateKeyEncrypted, privateKeyIv, aesKeyHex); + + const seal = { publicKey: publicKey, privateKey: data }; + this.store.setSeal(guid, seal); + this.seal = seal; + + this.emitter.emit('status', this.getStatus()); } public async setLogin(username: string, password: string): Promise { + const { node, secure, token } = this; + await setAccountLogin(node, secure, token, username, password); } } diff --git a/app/sdk/src/crypto.ts b/app/sdk/src/crypto.ts index f35d2388..a8810cb0 100644 --- a/app/sdk/src/crypto.ts +++ b/app/sdk/src/crypto.ts @@ -1,7 +1,7 @@ export interface Crypto { // generate salt for pbk function - pkdkfSalt(): { saltHex: string }; + pbkdfSalt(): { saltHex: string }; // generate aes key with pbkdf2 pbkdfKey(saltHex: string, password: string): { aesKeyHex: string }; diff --git a/app/sdk/src/net/addAccountMFAuth.ts b/app/sdk/src/net/addAccountMFAuth.ts new file mode 100644 index 00000000..f6850d37 --- /dev/null +++ b/app/sdk/src/net/addAccountMFAuth.ts @@ -0,0 +1,10 @@ +import axios from 'redaxios'; + +export async function addAccountMFAuth(node: string, secure: boolean, token: string): { text: string, image: string } { + const endpoint = `http${secure ? 's' : ''}://${node}/account/mfauth=${token}`; + const response = await axios.post(endpoint); + if (response.status >= 400 && response.status < 600) { + throw new Error('setAccountMFAuth failed'); + } +} + diff --git a/app/sdk/src/net/clearAccountSeal.ts b/app/sdk/src/net/clearAccountSeal.ts new file mode 100644 index 00000000..c279c635 --- /dev/null +++ b/app/sdk/src/net/clearAccountSeal.ts @@ -0,0 +1,10 @@ +import axios from 'redaxios'; + +export async function setAccountSeal(node: string, secure: boolean, token: string) { + const endpoint = `http${secure ? 's' : ''}://${node}/account/seal?agent=${token}`; + const response = await axios.delete(endpoint); + if (response.status >= 400 && response.status < 600) { + throw new Error('setAccountSeal failed'); + } +} + diff --git a/app/sdk/src/net/removeAccountMFAuth.ts b/app/sdk/src/net/removeAccountMFAuth.ts new file mode 100644 index 00000000..9e35a898 --- /dev/null +++ b/app/sdk/src/net/removeAccountMFAuth.ts @@ -0,0 +1,10 @@ +import axios from 'redaxios'; + +export async function removeAccountMFAuth(node: string, secure: boolean, token: string) { + const endpoint = `http${secure ? 's' : ''}://${node}/account/mfauth=${token}`; + const response = await axios.delete(endpoint); + if (response.status >= 400 && response.status < 600) { + throw new Error('setAccountMFAuth failed'); + } +} + diff --git a/app/sdk/src/net/setAccountLogin.ts b/app/sdk/src/net/setAccountLogin.ts new file mode 100644 index 00000000..4d0ab9fe --- /dev/null +++ b/app/sdk/src/net/setAccountLogin.ts @@ -0,0 +1,9 @@ +import axios from 'redaxios'; +import { encode } from './base64'; + +export async function setAccountLogin(node: string, secure: boolean, token: string, username: string, password: string) { + const endpoint = `http${secure ? 's' : ''}://${node}/account/login?agent=${token}`; + const auth = encode(`${username}:${password}`); + const response = await axios.put(endpoint, null, { auth: `Basic ${auth}` }); + return response.data; +} diff --git a/app/sdk/src/net/setAccountMFAuth.ts b/app/sdk/src/net/setAccountMFAuth.ts new file mode 100644 index 00000000..f2a3f783 --- /dev/null +++ b/app/sdk/src/net/setAccountMFAuth.ts @@ -0,0 +1,10 @@ +import axios from 'redaxios'; + +export async function setAccountMFAuth(node: string, secure: boolean, token: string, code: string) { + const endpoint = `http${secure ? 's' : ''}://${node}/account/mfauth=${token}`; + const response = await axios.put(endpoint, code); + if (response.status >= 400 && response.status < 600) { + throw new Error('setAccountMFAuth failed'); + } +} + diff --git a/app/sdk/src/net/setAccountNotifications.ts b/app/sdk/src/net/setAccountNotifications.ts new file mode 100644 index 00000000..b89ad2a9 --- /dev/null +++ b/app/sdk/src/net/setAccountNotifications.ts @@ -0,0 +1,10 @@ +import axios from 'redaxios'; + +export async function setAccountNotifications(node: string, secure: boolean, token: string, flag: boolean) { + const endpoint = `http${secure ? 's' : ''}://${node}/account/notification?agent=${token}`; + const response = await axios.put(endpoint, flag); + if (response.status >= 400 && response.status < 600) { + throw new Error('setAccountNotification failed'); + } +} + diff --git a/app/sdk/src/net/setAccountSeal.ts b/app/sdk/src/net/setAccountSeal.ts new file mode 100644 index 00000000..e9d7742d --- /dev/null +++ b/app/sdk/src/net/setAccountSeal.ts @@ -0,0 +1,11 @@ +import axios from 'redaxios'; +import { SealEntity } from '../entities'; + +export async function setAccountSeal(node: string, secure: boolean, token: string, seal: SealEntity) { + const endpoint = `http${secure ? 's' : ''}://${node}/account/seal?agent=${token}`; + const response = await axios.put(endpoint, seal); + if (response.status >= 400 && response.status < 600) { + throw new Error('setAccountSeal failed'); + } +} + diff --git a/app/sdk/src/net/setAccountSearchable.ts b/app/sdk/src/net/setAccountSearchable.ts new file mode 100644 index 00000000..84ab5745 --- /dev/null +++ b/app/sdk/src/net/setAccountSearchable.ts @@ -0,0 +1,10 @@ +import axios from 'redaxios'; + +export async function setAccountSearchable(node: string, secure: boolean, token: string, flag: boolean) { + const endpoint = `http${secure ? 's' : ''}://${node}/account/searchable?agent=${token}`; + const response = await axios.put(endpoint, flag); + if (response.status >= 400 && response.status < 600) { + throw new Error('setAccountSearchable failed'); + } +} + diff --git a/app/sdk/src/session.ts b/app/sdk/src/session.ts index 94870f4b..5b056594 100644 --- a/app/sdk/src/session.ts +++ b/app/sdk/src/session.ts @@ -59,7 +59,7 @@ export class SessionModule implements Session { this.emitter = new EventEmitter(); this.identity = new IdentityModule(log, this.store, guid, token, node, secure); - this.account = new AccountModule(log, this.store, guid, token, node, secure); + this.account = new AccountModule(log, this.store, this.crypto, guid, token, node, secure); this.contact = new ContactModule(log, this.store, guid, token, node, secure); this.alias = new AliasModule(log, this.account, this.store, guid, token, node, secure); this.attribute = new AttributeModule(log, this.account, this.store, guid, token, node, secure); diff --git a/app/sdk/src/store.ts b/app/sdk/src/store.ts index 3cd8cc33..ff65b58f 100644 --- a/app/sdk/src/store.ts +++ b/app/sdk/src/store.ts @@ -6,6 +6,9 @@ export interface Store { init(): Promise; setLogin(login: Login): Promise; clearLogin(): Promise; + getSeal(guid: string): Promise<{ publicKey: string, privateKey: string } | null>; + setSeal(guid: string, seal: { publicKey: string, privateKey: string }): Promise; + clearSeal(guid: string): Promise; getProfileRevision(guid: string): Promise; setProfileRevision(guid: string, revision: number): Promise; @@ -41,8 +44,8 @@ export class OfflineStore implements Store { return unset; } - private async setAppValue(guid: string, id: string, value: string): Promise { - await this.sql.set('INSERT OR REPLACE INTO app (key, value) values (?, ?)', [`${guid}::${id}`, value]); + private async setAppValue(guid: string, id: string, value: any): Promise { + await this.sql.set('INSERT OR REPLACE INTO app (key, value) values (?, ?)', [`${guid}::${id}`, JSON.stringify(value)]); } private async clearAppValue(guid: string, id: string): Promise { @@ -64,13 +67,25 @@ export class OfflineStore implements Store { public async setLogin(login: Login): Promise { await this.initLogin(login.guid); - await this.setAppValue('', 'login', JSON.stringify(login)); + await this.setAppValue('', 'login', login); } public async clearLogin(): Promise { await this.clearAppValue('', 'login'); } + public async getSeal(guid: string): Promise<{ publicKey: string, privateKey: string } | null> { + return await this.getAppValue(guid, 'seal', null) as { publicKey: string, privateKey: string } | null; + } + + public async setSeal(guid: string, seal: { publicKey: string, privateKey: string }): Promise { + await this.setAppValue(guid, 'seal', seal); + } + + public async clearSeal(guid: string): Promise { + await this.clearAppValue(guid, 'seal'); + } + public async getProfileRevision(guid: string): Promise { return await this.getAppValue(guid, 'profile_revision', 0) as number; } @@ -115,24 +130,44 @@ export class OnlineStore implements Store { this.log = log; } - private async getAppValue(id: string, unset: any): Promise { - const value = await this.web.getValue(id); + private async getAppValue(guid: string, id: string, unset: any): Promise { + const value = await this.web.getValue(`${guid}::${id}`); if (value != null) { return JSON.parse(value); } return unset; } + private async setAppValue(guid: string, id: string, value: any): Promise { + await this.web.setValue(`${guid}::${id}`, JSON.stringify(value)); + } + + private async clearAppValue(guid: string, id: string): Promise { + await this.web.clearValue(`${guid}::${id}`); + } + public async init(): Promise { - return this.getAppValue('login', null); + return await this.getAppValue('', 'login', null) as Login | null; } public async setLogin(login: Login): Promise { - return await this.web.setValue('login', JSON.stringify(login)); + await this.setAppValue('', 'login', login); } public async clearLogin(): Promise { - return await this.web.clearValue('login'); + await this.clearAppValue('', 'login'); + } + + public async getSeal(guid: string): Promise<{ publicKey: string, privateKey: string } | null> { + return await this.getAppValue(guid, 'seal', null) as { publicKey: string, privateKey: string } | null; + } + + public async setSeal(guid: string, seal: { publicKey: string, privateKey: string }): Promise { + await this.setAppValue(guid, 'seal', seal); + } + + public async clearSeal(guid: string): Promise { + await this.clearAppValue(guid, 'seal'); } public async getProfileRevision(guid: string): Promise { @@ -179,6 +214,16 @@ export class NoStore implements Store { public async clearLogin(): Promise { } + public async getSeal(guid: string): Promise<{ publicKey: string, privateKey: string } | null> { + return null; + } + + public async setSeal(guid: string, seal: { publicKey: string, privateKey: string }): Promise { + } + + public async clearSeal(guid: string): Promise { + } + public async getProfileRevision(guid: string): Promise { return 0; }