@ethora/chat-component-rn 26.6.13 → 26.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/lib/commonjs/components/AuthForms/Login.js +2 -3
- package/lib/commonjs/components/AuthForms/Login.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js +9 -8
- package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
- package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js +2 -1
- package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js.map +1 -1
- package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js +8 -0
- package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js +7 -21
- package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +2 -3
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/helpers/ensureScopedChatCache.js +2 -2
- package/lib/commonjs/helpers/ensureScopedChatCache.js.map +1 -1
- package/lib/commonjs/helpers/persistCrypto.js +122 -0
- package/lib/commonjs/helpers/persistCrypto.js.map +1 -0
- package/lib/commonjs/helpers/pickImageAsset.js +68 -0
- package/lib/commonjs/helpers/pickImageAsset.js.map +1 -0
- package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js +5 -6
- package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js.map +1 -1
- package/lib/commonjs/helpers/secureKeyValue.js +83 -0
- package/lib/commonjs/helpers/secureKeyValue.js.map +1 -0
- package/lib/commonjs/helpers/secureStoreRuntime.js +59 -0
- package/lib/commonjs/helpers/secureStoreRuntime.js.map +1 -0
- package/lib/commonjs/helpers/secureUserStorage.js +75 -0
- package/lib/commonjs/helpers/secureUserStorage.js.map +1 -0
- package/lib/commonjs/hooks/useLogout.js +15 -7
- package/lib/commonjs/hooks/useLogout.js.map +1 -1
- package/lib/commonjs/networking/authRefresh.js +4 -5
- package/lib/commonjs/networking/authRefresh.js.map +1 -1
- package/lib/commonjs/roomStore/chatSettingsSlice.js +3 -4
- package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
- package/lib/commonjs/roomStore/persistence.js +29 -15
- package/lib/commonjs/roomStore/persistence.js.map +1 -1
- package/lib/commonjs/roomStore/roomsSlice.js +2 -0
- package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
- package/lib/module/components/AuthForms/Login.js +2 -3
- package/lib/module/components/AuthForms/Login.js.map +1 -1
- package/lib/module/components/MainComponents/ProfileImagePlaceholder.js +9 -8
- package/lib/module/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
- package/lib/module/components/Modals/NewChatModal/ModalContent.js +2 -1
- package/lib/module/components/Modals/NewChatModal/ModalContent.js.map +1 -1
- package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js +8 -0
- package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
- package/lib/module/components/Modals/UserProfileModal/EditUserModal.js +9 -23
- package/lib/module/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
- package/lib/module/context/xmppProvider.js +2 -3
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/helpers/ensureScopedChatCache.js +2 -2
- package/lib/module/helpers/ensureScopedChatCache.js.map +1 -1
- package/lib/module/helpers/persistCrypto.js +115 -0
- package/lib/module/helpers/persistCrypto.js.map +1 -0
- package/lib/module/helpers/pickImageAsset.js +63 -0
- package/lib/module/helpers/pickImageAsset.js.map +1 -0
- package/lib/module/helpers/resolveInitBeforeLoadUser.js +5 -6
- package/lib/module/helpers/resolveInitBeforeLoadUser.js.map +1 -1
- package/lib/module/helpers/secureKeyValue.js +75 -0
- package/lib/module/helpers/secureKeyValue.js.map +1 -0
- package/lib/module/helpers/secureStoreRuntime.js +52 -0
- package/lib/module/helpers/secureStoreRuntime.js.map +1 -0
- package/lib/module/helpers/secureUserStorage.js +72 -0
- package/lib/module/helpers/secureUserStorage.js.map +1 -0
- package/lib/module/hooks/useLogout.js +15 -7
- package/lib/module/hooks/useLogout.js.map +1 -1
- package/lib/module/networking/authRefresh.js +4 -5
- package/lib/module/networking/authRefresh.js.map +1 -1
- package/lib/module/roomStore/chatSettingsSlice.js +3 -4
- package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
- package/lib/module/roomStore/persistence.js +30 -15
- package/lib/module/roomStore/persistence.js.map +1 -1
- package/lib/module/roomStore/roomsSlice.js +2 -0
- package/lib/module/roomStore/roomsSlice.js.map +1 -1
- package/lib/typescript/components/AuthForms/Login.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ProfileImagePlaceholder.d.ts.map +1 -1
- package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts +4 -2
- package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts.map +1 -1
- package/lib/typescript/components/Modals/NewChatModal/UpdNewChatModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserProfileModal/EditUserModal.d.ts.map +1 -1
- package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
- package/lib/typescript/helpers/persistCrypto.d.ts +13 -0
- package/lib/typescript/helpers/persistCrypto.d.ts.map +1 -0
- package/lib/typescript/helpers/pickImageAsset.d.ts +27 -0
- package/lib/typescript/helpers/pickImageAsset.d.ts.map +1 -0
- package/lib/typescript/helpers/resolveInitBeforeLoadUser.d.ts.map +1 -1
- package/lib/typescript/helpers/secureKeyValue.d.ts +13 -0
- package/lib/typescript/helpers/secureKeyValue.d.ts.map +1 -0
- package/lib/typescript/helpers/secureStoreRuntime.d.ts +29 -0
- package/lib/typescript/helpers/secureStoreRuntime.d.ts.map +1 -0
- package/lib/typescript/helpers/secureUserStorage.d.ts +23 -0
- package/lib/typescript/helpers/secureUserStorage.d.ts.map +1 -0
- package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
- package/lib/typescript/networking/authRefresh.d.ts.map +1 -1
- package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
- package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
- package/package.json +8 -1
- package/src/components/AuthForms/Login.tsx +2 -3
- package/src/components/MainComponents/ProfileImagePlaceholder.tsx +16 -9
- package/src/components/Modals/NewChatModal/ModalContent.tsx +6 -3
- package/src/components/Modals/NewChatModal/UpdNewChatModal.tsx +12 -1
- package/src/components/Modals/UserProfileModal/EditUserModal.tsx +9 -25
- package/src/context/xmppProvider.tsx +2 -3
- package/src/helpers/ensureScopedChatCache.ts +2 -2
- package/src/helpers/persistCrypto.ts +127 -0
- package/src/helpers/pickImageAsset.ts +68 -0
- package/src/helpers/resolveInitBeforeLoadUser.ts +5 -10
- package/src/helpers/secureKeyValue.ts +80 -0
- package/src/helpers/secureStoreRuntime.ts +62 -0
- package/src/helpers/secureUserStorage.ts +80 -0
- package/src/hooks/useLogout.tsx +15 -9
- package/src/networking/authRefresh.ts +4 -9
- package/src/roomStore/chatSettingsSlice.ts +3 -6
- package/src/roomStore/persistence.ts +39 -19
- package/src/roomStore/roomsSlice.ts +2 -0
|
@@ -11,8 +11,7 @@ import {
|
|
|
11
11
|
} from '../types/types';
|
|
12
12
|
import { Iso639_1Codes } from '../types/models/language.model';
|
|
13
13
|
import type { TranslateMode } from '../utils/translateModePolicy';
|
|
14
|
-
import {
|
|
15
|
-
import { asyncLocalStorage } from '../hooks/useLocalStorage';
|
|
14
|
+
import { secureUserStorage } from '../helpers/secureUserStorage';
|
|
16
15
|
|
|
17
16
|
export interface ChatState {
|
|
18
17
|
user: User;
|
|
@@ -113,9 +112,7 @@ const initialState: ChatState = {
|
|
|
113
112
|
const reducers = {
|
|
114
113
|
setUser: (state: WritableDraft<ChatState>, action: PayloadAction<User>) => {
|
|
115
114
|
state.user = unpackAndTransform(action.payload);
|
|
116
|
-
|
|
117
|
-
unpackAndTransform(action.payload)
|
|
118
|
-
);
|
|
115
|
+
secureUserStorage().set(unpackAndTransform(action.payload));
|
|
119
116
|
},
|
|
120
117
|
updateUser(state: WritableDraft<ChatState>, action: PayloadAction<{ updates: Partial<User> }>) {
|
|
121
118
|
const { updates } = action.payload;
|
|
@@ -186,7 +183,7 @@ const reducers = {
|
|
|
186
183
|
state.client = undefined;
|
|
187
184
|
state.langSource = undefined;
|
|
188
185
|
state.translateMode = undefined;
|
|
189
|
-
|
|
186
|
+
secureUserStorage().remove();
|
|
190
187
|
},
|
|
191
188
|
setLangSource: (
|
|
192
189
|
state: WritableDraft<ChatState>,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
2
2
|
import { Middleware } from '@reduxjs/toolkit';
|
|
3
3
|
import { IMessage, IRoom, User } from '../types/types';
|
|
4
|
+
import { encryptForPersist, decryptFromPersist } from '../helpers/persistCrypto';
|
|
4
5
|
|
|
5
6
|
// -------------------------------------------------------------------
|
|
6
7
|
// Lightweight RN persistence layer. Mirrors what redux-persist gives
|
|
@@ -11,7 +12,11 @@ import { IMessage, IRoom, User } from '../types/types';
|
|
|
11
12
|
// - cap each room's messages to the most recent MESSAGE_LIMIT (100)
|
|
12
13
|
// - debounced writes (200ms) on relevant action types
|
|
13
14
|
//
|
|
14
|
-
//
|
|
15
|
+
// AES-256-CBC at rest (see `helpers/persistCrypto.ts`): the JSON blob
|
|
16
|
+
// under each key below is encrypted before it reaches AsyncStorage, with
|
|
17
|
+
// the symmetric key held in the platform Keychain/Keystore. `user` here
|
|
18
|
+
// is already secret-free (see `sanitizeUser`) — the encryption is for
|
|
19
|
+
// the message bodies in `rooms`, which aren't.
|
|
15
20
|
// -------------------------------------------------------------------
|
|
16
21
|
|
|
17
22
|
const KEY_CHAT = '@ethora/persist:chatSettingStore';
|
|
@@ -199,21 +204,27 @@ export const persistenceMiddleware: Middleware = (storeAPI) => (next) => (
|
|
|
199
204
|
|
|
200
205
|
if (writeTimer) {clearTimeout(writeTimer);}
|
|
201
206
|
writeTimer = setTimeout(() => {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
[
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
207
|
+
(async () => {
|
|
208
|
+
try {
|
|
209
|
+
const state = storeAPI.getState();
|
|
210
|
+
const chatPayload: PersistedChatState = {
|
|
211
|
+
user: sanitizeUser(state.chatSettingStore?.user) as User,
|
|
212
|
+
};
|
|
213
|
+
const roomsPayload: PersistedRoomsState = {
|
|
214
|
+
rooms: sanitizeRooms(state.rooms?.rooms || {}),
|
|
215
|
+
};
|
|
216
|
+
const [chatCipher, roomsCipher] = await Promise.all([
|
|
217
|
+
encryptForPersist(JSON.stringify(chatPayload)),
|
|
218
|
+
encryptForPersist(JSON.stringify(roomsPayload)),
|
|
219
|
+
]);
|
|
220
|
+
await AsyncStorage.multiSet([
|
|
221
|
+
[KEY_CHAT, chatCipher],
|
|
222
|
+
[KEY_ROOMS, roomsCipher],
|
|
223
|
+
]);
|
|
224
|
+
} catch (e) {
|
|
225
|
+
console.warn('persist write failed', e);
|
|
226
|
+
}
|
|
227
|
+
})();
|
|
217
228
|
}, 200);
|
|
218
229
|
|
|
219
230
|
return result;
|
|
@@ -233,9 +244,18 @@ export async function readPersistedState(): Promise<{
|
|
|
233
244
|
KEY_CHAT,
|
|
234
245
|
KEY_ROOMS,
|
|
235
246
|
]);
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
? (
|
|
247
|
+
const [chatPlain, roomsPlain] = await Promise.all([
|
|
248
|
+
chatRaw[1] ? decryptFromPersist(chatRaw[1]) : Promise.resolve(null),
|
|
249
|
+
roomsRaw[1] ? decryptFromPersist(roomsRaw[1]) : Promise.resolve(null),
|
|
250
|
+
]);
|
|
251
|
+
// `decryptFromPersist` returns null both for "nothing stored" and
|
|
252
|
+
// for "stored value isn't a valid envelope for the current key" —
|
|
253
|
+
// notably a plaintext blob left over from a pre-encryption install.
|
|
254
|
+
// Either way there is nothing safe to parse, so the caller treats it
|
|
255
|
+
// as a cold start and re-hydrates from the server.
|
|
256
|
+
const chat = chatPlain ? (JSON.parse(chatPlain) as PersistedChatState) : null;
|
|
257
|
+
const rooms = roomsPlain
|
|
258
|
+
? (JSON.parse(roomsPlain) as PersistedRoomsState)
|
|
239
259
|
: null;
|
|
240
260
|
return { chat, rooms };
|
|
241
261
|
} catch (e) {
|
|
@@ -317,6 +317,8 @@ const reducers = {
|
|
|
317
317
|
: [];
|
|
318
318
|
state.rooms[roomData.jid] = {
|
|
319
319
|
...roomData,
|
|
320
|
+
icon: roomData.icon !== undefined ? roomData.icon : existing?.icon,
|
|
321
|
+
roomBg: roomData.roomBg !== undefined ? roomData.roomBg : existing?.roomBg,
|
|
320
322
|
messages:
|
|
321
323
|
existingMessages.length > 0 ? existingMessages : incomingMessages,
|
|
322
324
|
lastViewedTimestamp: lastViewed,
|