update local saved data

This commit is contained in:
PhilReact 2025-01-06 11:00:03 +02:00
parent 1040fd4018
commit 3e8af4a270
6 changed files with 62 additions and 27 deletions

View File

@ -13,6 +13,7 @@ dependencies {
implementation project(':capacitor-browser') implementation project(':capacitor-browser')
implementation project(':capacitor-filesystem') implementation project(':capacitor-filesystem')
implementation project(':capacitor-local-notifications') implementation project(':capacitor-local-notifications')
implementation project(':capacitor-preferences')
implementation project(':capacitor-splash-screen') implementation project(':capacitor-splash-screen')
implementation project(':capawesome-capacitor-file-picker') implementation project(':capawesome-capacitor-file-picker')
implementation project(':evva-capacitor-secure-storage-plugin') implementation project(':evva-capacitor-secure-storage-plugin')

View File

@ -14,6 +14,9 @@ project(':capacitor-filesystem').projectDir = new File('../node_modules/@capacit
include ':capacitor-local-notifications' include ':capacitor-local-notifications'
project(':capacitor-local-notifications').projectDir = new File('../node_modules/@capacitor/local-notifications/android') project(':capacitor-local-notifications').projectDir = new File('../node_modules/@capacitor/local-notifications/android')
include ':capacitor-preferences'
project(':capacitor-preferences').projectDir = new File('../node_modules/@capacitor/preferences/android')
include ':capacitor-splash-screen' include ':capacitor-splash-screen'
project(':capacitor-splash-screen').projectDir = new File('../node_modules/@capacitor/splash-screen/android') project(':capacitor-splash-screen').projectDir = new File('../node_modules/@capacitor/splash-screen/android')

9
package-lock.json generated
View File

@ -15,6 +15,7 @@
"@capacitor/core": "^6.1.2", "@capacitor/core": "^6.1.2",
"@capacitor/filesystem": "^6.0.1", "@capacitor/filesystem": "^6.0.1",
"@capacitor/local-notifications": "^6.1.0", "@capacitor/local-notifications": "^6.1.0",
"@capacitor/preferences": "^6.0.3",
"@capacitor/splash-screen": "^6.0.2", "@capacitor/splash-screen": "^6.0.2",
"@capawesome/capacitor-file-picker": "^6.1.0", "@capawesome/capacitor-file-picker": "^6.1.0",
"@chatscope/chat-ui-kit-react": "^2.0.3", "@chatscope/chat-ui-kit-react": "^2.0.3",
@ -1776,6 +1777,14 @@
"@capacitor/core": "^6.0.0" "@capacitor/core": "^6.0.0"
} }
}, },
"node_modules/@capacitor/preferences": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/@capacitor/preferences/-/preferences-6.0.3.tgz",
"integrity": "sha512-3I1BbhhCBTMBziVvr0fU7RCRXqGvhUW/apHLRJSaJAWonASya5rp6AWsHv1lW1tkF0avUOMwp6e7iNA4UUGu8g==",
"peerDependencies": {
"@capacitor/core": "^6.0.0"
}
},
"node_modules/@capacitor/splash-screen": { "node_modules/@capacitor/splash-screen": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/@capacitor/splash-screen/-/splash-screen-6.0.2.tgz", "resolved": "https://registry.npmjs.org/@capacitor/splash-screen/-/splash-screen-6.0.2.tgz",

View File

@ -19,6 +19,7 @@
"@capacitor/core": "^6.1.2", "@capacitor/core": "^6.1.2",
"@capacitor/filesystem": "^6.0.1", "@capacitor/filesystem": "^6.0.1",
"@capacitor/local-notifications": "^6.1.0", "@capacitor/local-notifications": "^6.1.0",
"@capacitor/preferences": "^6.0.3",
"@capacitor/splash-screen": "^6.0.2", "@capacitor/splash-screen": "^6.0.2",
"@capawesome/capacitor-file-picker": "^6.1.0", "@capawesome/capacitor-file-picker": "^6.1.0",
"@chatscope/chat-ui-kit-react": "^2.0.3", "@chatscope/chat-ui-kit-react": "^2.0.3",
@ -72,6 +73,7 @@
"react-frame-component": "^5.2.7", "react-frame-component": "^5.2.7",
"react-infinite-scroller": "^1.2.6", "react-infinite-scroller": "^1.2.6",
"react-intersection-observer": "^9.13.0", "react-intersection-observer": "^9.13.0",
"react-json-view-lite": "^2.0.1",
"react-loader-spinner": "^6.1.6", "react-loader-spinner": "^6.1.6",
"react-qr-code": "^2.0.15", "react-qr-code": "^2.0.15",
"react-quick-pinch-zoom": "^5.1.0", "react-quick-pinch-zoom": "^5.1.0",
@ -87,8 +89,7 @@
"tiptap-extension-resize-image": "^1.1.8", "tiptap-extension-resize-image": "^1.1.8",
"ts-key-enum": "^2.0.12", "ts-key-enum": "^2.0.12",
"vite-plugin-top-level-await": "^1.4.4", "vite-plugin-top-level-await": "^1.4.4",
"vite-plugin-wasm": "^3.3.0", "vite-plugin-wasm": "^3.3.0"
"react-json-view-lite": "^2.0.1"
}, },
"devDependencies": { "devDependencies": {
"@testing-library/dom": "^10.3.0", "@testing-library/dom": "^10.3.0",

View File

@ -533,6 +533,7 @@ export const Group = ({
}, [selectedGroup]); }, [selectedGroup]);
useEffect(() => { useEffect(() => {
selectedDirectRef.current = selectedDirect; selectedDirectRef.current = selectedDirect;
}, [selectedDirect]); }, [selectedDirect]);
@ -633,6 +634,13 @@ export const Group = ({
} catch (error) {} } catch (error) {}
}; };
useEffect(()=> {
if(myAddress){
getGroupAnnouncements()
getTimestampEnterChat()
}
}, [myAddress])
const getGroupOwner = async (groupId) => { const getGroupOwner = async (groupId) => {
try { try {
const url = `${getBaseApiReact()}/groups/${groupId}`; const url = `${getBaseApiReact()}/groups/${groupId}`;

View File

@ -1,13 +1,14 @@
import { SecureStoragePlugin } from '@evva/capacitor-secure-storage-plugin'; import { SecureStoragePlugin } from '@evva/capacitor-secure-storage-plugin';
import { Preferences } from '@capacitor/preferences';
let inMemoryKey: CryptoKey | null = null; let inMemoryKey: CryptoKey | null = null;
let inMemoryIV: Uint8Array | null = null;
const keysToEncrypt = ['keyPair']; const keysToEncrypt = ['keyPair'];
const keysToUseEvva = ['wallets'];
async function initializeKeyAndIV() { async function initializeKeyAndIV() {
if (!inMemoryKey) { if (!inMemoryKey) {
inMemoryKey = await generateKey(); // Generates the key in memory inMemoryKey = await generateKey(); // Generates the key in memory
} }
} }
@ -15,7 +16,7 @@ async function generateKey(): Promise<CryptoKey> {
return await crypto.subtle.generateKey( return await crypto.subtle.generateKey(
{ {
name: "AES-GCM", name: "AES-GCM",
length: 256 length: 256,
}, },
true, true,
["encrypt", "decrypt"] ["encrypt", "decrypt"]
@ -32,7 +33,7 @@ async function encryptData(data: string, key: CryptoKey): Promise<{ iv: Uint8Arr
const encryptedData = await crypto.subtle.encrypt( const encryptedData = await crypto.subtle.encrypt(
{ {
name: "AES-GCM", name: "AES-GCM",
iv: iv iv: iv,
}, },
key, key,
encodedData encodedData
@ -45,7 +46,7 @@ async function decryptData(encryptedData: ArrayBuffer, key: CryptoKey, iv: Uint8
const decryptedData = await crypto.subtle.decrypt( const decryptedData = await crypto.subtle.decrypt(
{ {
name: "AES-GCM", name: "AES-GCM",
iv: iv iv: iv,
}, },
key, key,
encryptedData encryptedData
@ -56,7 +57,7 @@ async function decryptData(encryptedData: ArrayBuffer, key: CryptoKey, iv: Uint8
} }
// Encode a JSON payload as Base64 // Encode a JSON payload as Base64
function jsonToBase64(payload) { function jsonToBase64(payload: any): string {
const utf8Array = new TextEncoder().encode(JSON.stringify(payload)); const utf8Array = new TextEncoder().encode(JSON.stringify(payload));
let binary = ''; let binary = '';
utf8Array.forEach((byte) => (binary += String.fromCharCode(byte))); utf8Array.forEach((byte) => (binary += String.fromCharCode(byte)));
@ -64,7 +65,7 @@ function jsonToBase64(payload) {
} }
// Decode a Base64 string back to JSON // Decode a Base64 string back to JSON
function base64ToJson(base64) { function base64ToJson(base64: string): any {
const binary = atob(base64); const binary = atob(base64);
const bytes = new Uint8Array(binary.length); const bytes = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) { for (let i = 0; i < binary.length; i++) {
@ -86,24 +87,25 @@ export const storeData = async (key: string, payload: any): Promise<string> => {
const combinedData = new Uint8Array([...iv, ...new Uint8Array(encryptedData)]); const combinedData = new Uint8Array([...iv, ...new Uint8Array(encryptedData)]);
const encryptedBase64Data = btoa(String.fromCharCode(...combinedData)); const encryptedBase64Data = btoa(String.fromCharCode(...combinedData));
await SecureStoragePlugin.set({ key, value: encryptedBase64Data }); await SecureStoragePlugin.set({ key, value: encryptedBase64Data });
} else { } else if (keysToUseEvva?.includes(key)){
// Store Base64-encoded data in plain text if not in keysToEncrypt
await SecureStoragePlugin.set({ key, value: base64Data }); await SecureStoragePlugin.set({ key, value: base64Data });
} else {
// Store Base64-encoded data in Capacitor Preferences for non-encrypted keys
await Preferences.set({ key, value: base64Data });
} }
return "Data saved successfully"; return "Data saved successfully";
}; };
export const getData = async <T = any>(key: string): Promise<T | null> => { export const getData = async <T = any>(key: string): Promise<T | null> => {
await initializeKeyAndIV(); await initializeKeyAndIV();
try { try {
const storedDataBase64 = await SecureStoragePlugin.get({ key }); if (keysToEncrypt.includes(key) && inMemoryKey) {
// Fetch encrypted data for sensitive keys
const storedDataBase64 = await SecureStoragePlugin.get({ key });
if (storedDataBase64.value) { if (storedDataBase64.value) {
if (keysToEncrypt.includes(key) && inMemoryKey) {
// Decode the Base64-encoded encrypted data
const combinedData = atob(storedDataBase64.value) const combinedData = atob(storedDataBase64.value)
.split("") .split("")
.map((c) => c.charCodeAt(0)); .map((c) => c.charCodeAt(0));
@ -113,28 +115,39 @@ export const getData = async <T = any>(key: string): Promise<T | null> => {
const decryptedBase64Data = await decryptData(encryptedData, inMemoryKey, iv); const decryptedBase64Data = await decryptData(encryptedData, inMemoryKey, iv);
return base64ToJson(decryptedBase64Data); return base64ToJson(decryptedBase64Data);
} else {
// Decode non-encrypted data
return base64ToJson(storedDataBase64.value);
} }
} else if (keysToUseEvva?.includes(key)){
const storedDataBase64 = await SecureStoragePlugin.get({ key });
if(storedDataBase64?.value){
return base64ToJson(storedDataBase64.value);
} else return null
} else { } else {
return null; // Fetch plain data for non-encrypted keys
const { value } = await Preferences.get({ key });
if (value) {
return base64ToJson(value);
}
} }
return null;
} catch (error) { } catch (error) {
return null console.error("Error fetching data:", error);
return null;
} }
}; };
// Remove keys from storage and log out
export async function removeKeysAndLogout(keys: string[], event: MessageEvent, request: any) { export async function removeKeysAndLogout(keys: string[], event: MessageEvent, request: any) {
try { try {
for (const key of keys) { for (const key of keys) {
try { try {
await SecureStoragePlugin.remove({ key }); if (keysToEncrypt.includes(key)) {
await SecureStoragePlugin.remove({ key: `${key}_iv` }); // Remove associated IV // Remove from Secure Storage for sensitive keys
await SecureStoragePlugin.remove({ key });
} else {
// Remove from Capacitor Preferences for non-sensitive keys
await Preferences.remove({ key });
}
} catch (error) { } catch (error) {
console.warn(`Key not found: ${key}`); console.warn(`Key not found: ${key}`);
} }