Rocket.Chat.ReactNative/app/lib/methods/logout.ts

132 lines
3.9 KiB
TypeScript
Raw Normal View History

import * as FileSystem from 'expo-file-system';
import { Rocketchat as RocketchatClient } from '@rocket.chat/sdk';
import Model from '@nozbe/watermelondb/Model';
import { getDeviceToken } from '../../notifications/push';
import { extractHostname } from '../../utils/server';
import { BASIC_AUTH_KEY } from '../../utils/fetch';
import database, { getDatabase } from '../database';
import RocketChat from '../rocketchat';
import { useSsl } from '../../utils/url';
import log from '../../utils/log';
import { E2E_PRIVATE_KEY, E2E_PUBLIC_KEY, E2E_RANDOM_PASSWORD_KEY } from '../encryption/constants';
[NEW] Encrypt user credentials and preferences (#2247) * install react-native-mmkv-storage * wip ios migration * change all js rn-user-defaults -> react-native-mmkv-storage * remove all rn-user-defaults native references (iOS) * android migration from rn-user-defaults to react-native-mmkv-storage * ios app group accessible mmkv * handle get errors * remove access of credentials from legacy native apps * remove data of user defaults * remove no longer necessary import * js mmkv encryption * run migration only once * reply from notification android * fix app group key access at native level ios * encrypt user credentials using a specific key * ios encrypt with random key * use a random key at the first encryption * encrypt migrated data on js land * remove unused function * reply notifications ios should be working * use fix instanceID * android ejson retrieve encrypted data * remove encryption migrated data for a while * encryption working between app and share extension * fix patch react-native-notifications * ssl pinning working using mmkv encrypted data * improve react-native-notifications * run encrypt migration data only once * fix build * fix patches magic string * fix mmkv id * mmkv -> userPreferences * fix instance id on android migration * cast our oldest sharedPreferences string into an object * revert log remove * create currentServer Rocket.Chat key * wrap mmkv api class * change the get logic * move userPreferences to lib * move encrypt migrated data to userPreferences class * check if the new object is new before insert * invalidate ci yarn cache * fix sort migration from android shared preferences * fix splashscreen forever * invalidate yarn cache * invalidate yarn cache * fix patch * Minor change * fix android notifications looking for wrong mmkv instance * Fix some issues on iOS mmkv native access * Remove unnecessary code * Fix notification reply and ssl pinning * WIP NotificationService use MMKV credentials * Add KeychainGroup * Notification idOnly get credentials from mmkv * Some fixes * Invalidate yarn cache * Pods * Use MMKVAppExtension on NotificationService Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-08-19 17:14:22 +00:00
import UserPreferences from '../userPreferences';
import { ICertificate, IRocketChat } from '../../definitions';
async function removeServerKeys({ server, userId }: { server: string; userId: string | null }) {
await UserPreferences.removeItem(`${RocketChat.TOKEN_KEY}-${server}`);
if (userId) {
await UserPreferences.removeItem(`${RocketChat.TOKEN_KEY}-${userId}`);
}
await UserPreferences.removeItem(`${BASIC_AUTH_KEY}-${server}`);
await UserPreferences.removeItem(`${server}-${E2E_PUBLIC_KEY}`);
await UserPreferences.removeItem(`${server}-${E2E_PRIVATE_KEY}`);
await UserPreferences.removeItem(`${server}-${E2E_RANDOM_PASSWORD_KEY}`);
}
async function removeSharedCredentials({ server }: { server: string }) {
[NEW] Encrypt user credentials and preferences (#2247) * install react-native-mmkv-storage * wip ios migration * change all js rn-user-defaults -> react-native-mmkv-storage * remove all rn-user-defaults native references (iOS) * android migration from rn-user-defaults to react-native-mmkv-storage * ios app group accessible mmkv * handle get errors * remove access of credentials from legacy native apps * remove data of user defaults * remove no longer necessary import * js mmkv encryption * run migration only once * reply from notification android * fix app group key access at native level ios * encrypt user credentials using a specific key * ios encrypt with random key * use a random key at the first encryption * encrypt migrated data on js land * remove unused function * reply notifications ios should be working * use fix instanceID * android ejson retrieve encrypted data * remove encryption migrated data for a while * encryption working between app and share extension * fix patch react-native-notifications * ssl pinning working using mmkv encrypted data * improve react-native-notifications * run encrypt migration data only once * fix build * fix patches magic string * fix mmkv id * mmkv -> userPreferences * fix instance id on android migration * cast our oldest sharedPreferences string into an object * revert log remove * create currentServer Rocket.Chat key * wrap mmkv api class * change the get logic * move userPreferences to lib * move encrypt migrated data to userPreferences class * check if the new object is new before insert * invalidate ci yarn cache * fix sort migration from android shared preferences * fix splashscreen forever * invalidate yarn cache * invalidate yarn cache * fix patch * Minor change * fix android notifications looking for wrong mmkv instance * Fix some issues on iOS mmkv native access * Remove unnecessary code * Fix notification reply and ssl pinning * WIP NotificationService use MMKV credentials * Add KeychainGroup * Notification idOnly get credentials from mmkv * Some fixes * Invalidate yarn cache * Pods * Use MMKVAppExtension on NotificationService Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-08-19 17:14:22 +00:00
// clear certificate for server - SSL Pinning
try {
const certificate = (await UserPreferences.getMapAsync(extractHostname(server))) as ICertificate | null;
if (certificate?.path) {
[NEW] Encrypt user credentials and preferences (#2247) * install react-native-mmkv-storage * wip ios migration * change all js rn-user-defaults -> react-native-mmkv-storage * remove all rn-user-defaults native references (iOS) * android migration from rn-user-defaults to react-native-mmkv-storage * ios app group accessible mmkv * handle get errors * remove access of credentials from legacy native apps * remove data of user defaults * remove no longer necessary import * js mmkv encryption * run migration only once * reply from notification android * fix app group key access at native level ios * encrypt user credentials using a specific key * ios encrypt with random key * use a random key at the first encryption * encrypt migrated data on js land * remove unused function * reply notifications ios should be working * use fix instanceID * android ejson retrieve encrypted data * remove encryption migrated data for a while * encryption working between app and share extension * fix patch react-native-notifications * ssl pinning working using mmkv encrypted data * improve react-native-notifications * run encrypt migration data only once * fix build * fix patches magic string * fix mmkv id * mmkv -> userPreferences * fix instance id on android migration * cast our oldest sharedPreferences string into an object * revert log remove * create currentServer Rocket.Chat key * wrap mmkv api class * change the get logic * move userPreferences to lib * move encrypt migrated data to userPreferences class * check if the new object is new before insert * invalidate ci yarn cache * fix sort migration from android shared preferences * fix splashscreen forever * invalidate yarn cache * invalidate yarn cache * fix patch * Minor change * fix android notifications looking for wrong mmkv instance * Fix some issues on iOS mmkv native access * Remove unnecessary code * Fix notification reply and ssl pinning * WIP NotificationService use MMKV credentials * Add KeychainGroup * Notification idOnly get credentials from mmkv * Some fixes * Invalidate yarn cache * Pods * Use MMKVAppExtension on NotificationService Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-08-19 17:14:22 +00:00
await UserPreferences.removeItem(extractHostname(server));
await FileSystem.deleteAsync(certificate.path);
}
} catch (e) {
log(e);
}
}
async function removeServerData({ server }: { server: string }) {
try {
const batch: Model[] = [];
const serversDB = database.servers;
const userId = await UserPreferences.getStringAsync(`${RocketChat.TOKEN_KEY}-${server}`);
const usersCollection = serversDB.get('users');
if (userId) {
const userRecord = await usersCollection.find(userId);
batch.push(userRecord.prepareDestroyPermanently());
}
const serverCollection = serversDB.get('servers');
const serverRecord = await serverCollection.find(server);
batch.push(serverRecord.prepareDestroyPermanently());
await serversDB.write(() => serversDB.batch(...batch));
await removeSharedCredentials({ server });
await removeServerKeys({ server, userId });
} catch (e) {
log(e);
}
}
async function removeCurrentServer() {
[NEW] Encrypt user credentials and preferences (#2247) * install react-native-mmkv-storage * wip ios migration * change all js rn-user-defaults -> react-native-mmkv-storage * remove all rn-user-defaults native references (iOS) * android migration from rn-user-defaults to react-native-mmkv-storage * ios app group accessible mmkv * handle get errors * remove access of credentials from legacy native apps * remove data of user defaults * remove no longer necessary import * js mmkv encryption * run migration only once * reply from notification android * fix app group key access at native level ios * encrypt user credentials using a specific key * ios encrypt with random key * use a random key at the first encryption * encrypt migrated data on js land * remove unused function * reply notifications ios should be working * use fix instanceID * android ejson retrieve encrypted data * remove encryption migrated data for a while * encryption working between app and share extension * fix patch react-native-notifications * ssl pinning working using mmkv encrypted data * improve react-native-notifications * run encrypt migration data only once * fix build * fix patches magic string * fix mmkv id * mmkv -> userPreferences * fix instance id on android migration * cast our oldest sharedPreferences string into an object * revert log remove * create currentServer Rocket.Chat key * wrap mmkv api class * change the get logic * move userPreferences to lib * move encrypt migrated data to userPreferences class * check if the new object is new before insert * invalidate ci yarn cache * fix sort migration from android shared preferences * fix splashscreen forever * invalidate yarn cache * invalidate yarn cache * fix patch * Minor change * fix android notifications looking for wrong mmkv instance * Fix some issues on iOS mmkv native access * Remove unnecessary code * Fix notification reply and ssl pinning * WIP NotificationService use MMKV credentials * Add KeychainGroup * Notification idOnly get credentials from mmkv * Some fixes * Invalidate yarn cache * Pods * Use MMKVAppExtension on NotificationService Co-authored-by: Diego Mello <diegolmello@gmail.com>
2020-08-19 17:14:22 +00:00
await UserPreferences.removeItem(RocketChat.CURRENT_SERVER);
}
async function removeServerDatabase({ server }: { server: string }) {
try {
const db = getDatabase(server);
await db.write(() => db.unsafeResetDatabase());
} catch (e) {
log(e);
}
}
export async function removeServer({ server }: { server: string }): Promise<void> {
try {
const userId = await UserPreferences.getStringAsync(`${RocketChat.TOKEN_KEY}-${server}`);
if (userId) {
const resume = await UserPreferences.getStringAsync(`${RocketChat.TOKEN_KEY}-${userId}`);
const sdk = new RocketchatClient({ host: server, protocol: 'ddp', useSsl: useSsl(server) });
await sdk.login({ resume });
const token = getDeviceToken();
if (token) {
await sdk.del('push.token', { token });
}
await sdk.logout();
}
await removeServerData({ server });
await removeServerDatabase({ server });
} catch (e) {
log(e);
}
}
export default async function logout(this: IRocketChat, { server }: { server: string }): Promise<void> {
if (this.roomsSub) {
this.roomsSub.stop();
this.roomsSub = null;
}
if (this.activeUsersSubTimeout) {
clearTimeout(this.activeUsersSubTimeout);
this.activeUsersSubTimeout = false;
}
try {
await this.removePushToken();
} catch (e) {
log(e);
}
try {
// RC 0.60.0
await this.sdk.logout();
} catch (e) {
log(e);
}
if (this.sdk) {
this.sdk = null;
}
await removeServerData({ server });
await removeCurrentServer();
await removeServerDatabase({ server });
}