Skip to content

Commit

Permalink
[NEW] Remove server
Browse files Browse the repository at this point in the history
Co-authored-by: Bruno Dantas <oliveiradantas96@gmail.com>
Co-authored-by: Calebe Rios <calebersmendes@gmail.com>

[NEW] Remove push token & logout

[NEW] Remove server database

[FIX] Superfluous trailing arguments
  • Loading branch information
djorkaeffalexandre committed Apr 2, 2020
1 parent df0a385 commit cff6e34
Show file tree
Hide file tree
Showing 9 changed files with 278 additions and 170 deletions.
1 change: 1 addition & 0 deletions app/i18n/locales/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,7 @@ export default {
You_will_be_logged_out_of_this_application: 'You will be logged out of this application.',
Clear: 'Clear',
This_will_clear_all_your_offline_data: 'This will clear all your offline data.',
This_will_remove_all_data_of_this_server: 'This will remove all data of this server.',
Mark_unread: 'Mark Unread',
Wait_activation_warning: 'Before you can login, your account must be manually activated by an administrator.'
};
1 change: 1 addition & 0 deletions app/i18n/locales/pt-BR.js
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ export default {
You_will_be_logged_out_of_this_application: 'Você sairá deste aplicativo.',
Clear: 'Limpar',
This_will_clear_all_your_offline_data: 'Isto limpará todos os seus dados offline.',
This_will_remove_all_data_of_this_server: 'Isto removerá todos os dados desse servidor.',
Mark_unread: 'Marcar como não Lida',
Wait_activation_warning: 'Antes que você possa fazer o login, sua conta deve ser manualmente ativada por um administrador.'
};
60 changes: 32 additions & 28 deletions app/lib/database/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,36 @@ if (__DEV__ && isIOS) {
console.log(appGroupPath);
}

export const getDatabase = (database = '') => {
const path = database.replace(/(^\w+:|^)\/\//, '').replace(/\//g, '.');
const dbName = `${ appGroupPath }${ path }.db`;

const adapter = new SQLiteAdapter({
dbName,
schema: appSchema,
migrations
});

return new Database({
adapter,
modelClasses: [
Subscription,
Room,
Message,
Thread,
ThreadMessage,
CustomEmoji,
FrequentlyUsedEmoji,
Upload,
Setting,
Role,
Permission,
SlashCommand
],
actionsEnabled: true
});
};

class DB {
databases = {
serversDB: new Database({
Expand Down Expand Up @@ -85,34 +115,8 @@ class DB {
});
}

setActiveDB(database = '') {
const path = database.replace(/(^\w+:|^)\/\//, '').replace(/\//g, '.');
const dbName = `${ appGroupPath }${ path }.db`;

const adapter = new SQLiteAdapter({
dbName,
schema: appSchema,
migrations
});

this.databases.activeDB = new Database({
adapter,
modelClasses: [
Subscription,
Room,
Message,
Thread,
ThreadMessage,
CustomEmoji,
FrequentlyUsedEmoji,
Upload,
Setting,
Role,
Permission,
SlashCommand
],
actionsEnabled: true
});
setActiveDB(database) {
this.databases.activeDB = getDatabase(database);
}
}

Expand Down
126 changes: 126 additions & 0 deletions app/lib/methods/logout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import RNUserDefaults from 'rn-user-defaults';
import * as FileSystem from 'expo-file-system';
import { Rocketchat as RocketchatClient } from '@rocket.chat/sdk';

import { SERVERS, SERVER_URL } from '../../constants/userDefaults';
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';

async function removeServerKeys({ server, userId }) {
await RNUserDefaults.clear(`${ RocketChat.TOKEN_KEY }-${ server }`);
await RNUserDefaults.clear(`${ RocketChat.TOKEN_KEY }-${ userId }`);
await RNUserDefaults.clear(`${ BASIC_AUTH_KEY }-${ server }`);
}

async function removeSharedCredentials({ server }) {
try {
const servers = await RNUserDefaults.objectForKey(SERVERS);
await RNUserDefaults.setObjectForKey(SERVERS, servers && servers.filter(srv => srv[SERVER_URL] !== server));

// clear certificate for server - SSL Pinning
const certificate = await RNUserDefaults.objectForKey(extractHostname(server));
if (certificate && certificate.path) {
await RNUserDefaults.clear(extractHostname(server));
await FileSystem.deleteAsync(certificate.path);
}
} catch (e) {
console.log('removeSharedCredentials', e);
}
}

async function removeServerData({ server }) {
try {
const batch = [];
const serversDB = database.servers;
const userId = await RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ server }`);

const usersCollection = serversDB.collections.get('users');
if (userId) {
const userRecord = await usersCollection.find(userId);
batch.push(userRecord.prepareDestroyPermanently());
}
const serverCollection = serversDB.collections.get('servers');
const serverRecord = await serverCollection.find(server);
batch.push(serverRecord.prepareDestroyPermanently());

await serversDB.action(() => serversDB.batch(...batch));
await removeSharedCredentials({ server });
await removeServerKeys({ server });
} catch (e) {
console.log('removeServerData', e);
}
}

async function removeCurrentServer() {
await RNUserDefaults.clear('currentServer');
await RNUserDefaults.clear(RocketChat.TOKEN_KEY);
}

async function removeServerDatabase({ server }) {
try {
const db = getDatabase(server);
await db.action(() => db.unsafeResetDatabase());
} catch (e) {
console.log(e);
}
}

export async function removeServer({ server }) {
try {
const userId = await RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ server }`);
if (userId) {
const resume = await RNUserDefaults.get(`${ 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) {
console.log('removePush', e);
}
}

export default async function logout({ server }) {
if (this.roomsSub) {
this.roomsSub.stop();
}

if (this.activeUsersSubTimeout) {
clearTimeout(this.activeUsersSubTimeout);
this.activeUsersSubTimeout = false;
}

try {
await this.removePushToken();
} catch (e) {
console.log('removePushToken', e);
}

try {
// RC 0.60.0
await this.sdk.logout();
} catch (e) {
console.log('logout', e);
}

if (this.sdk) {
this.sdk = null;
}

await removeServerData({ server });
await removeCurrentServer();
await removeServerDatabase({ server });
}
90 changes: 8 additions & 82 deletions app/lib/rocketchat.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@ import semver from 'semver';
import { Rocketchat as RocketchatClient } from '@rocket.chat/sdk';
import RNUserDefaults from 'rn-user-defaults';
import { Q } from '@nozbe/watermelondb';
import * as FileSystem from 'expo-file-system';

import reduxStore from './createStore';
import defaultSettings from '../constants/settings';
import messagesStatus from '../constants/messagesStatus';
import database from './database';
import log from '../utils/log';
import { isIOS, getBundleId } from '../utils/deviceInfo';
import { extractHostname } from '../utils/server';
import fetch, { BASIC_AUTH_KEY } from '../utils/fetch';
import fetch from '../utils/fetch';

import { setUser, setLoginServices, loginRequest } from '../actions/login';
import { disconnect, connectSuccess, connectRequest } from '../actions/connect';
Expand Down Expand Up @@ -43,12 +41,13 @@ import sendMessage, { sendMessageCall } from './methods/sendMessage';
import { sendFileMessage, cancelUpload, isUploadActive } from './methods/sendFileMessage';

import callJitsi from './methods/callJitsi';
import logout, { removeServer } from './methods/logout';

import { getDeviceToken } from '../notifications/push';
import { SERVERS, SERVER_URL } from '../constants/userDefaults';
import { setActiveUsers } from '../actions/activeUsers';
import I18n from '../i18n';
import { twoFactor } from '../utils/twoFactor';
import { useSsl } from '../utils/url';

const TOKEN_KEY = 'reactnativemeteor_usertoken';
const SORT_PREFS_KEY = 'RC_SORT_PREFS_KEY';
Expand Down Expand Up @@ -87,10 +86,7 @@ const RocketChat = {
}
},
async getWebsocketInfo({ server }) {
// Use useSsl: false only if server url starts with http://
const useSsl = !/http:\/\//.test(server);

const sdk = new RocketchatClient({ host: server, protocol: 'ddp', useSsl });
const sdk = new RocketchatClient({ host: server, protocol: 'ddp', useSsl: useSsl(server) });

try {
await sdk.connect();
Expand Down Expand Up @@ -200,10 +196,7 @@ const RocketChat = {
this.code = null;
}

// Use useSsl: false only if server url starts with http://
const useSsl = !/http:\/\//.test(server);

this.sdk = new RocketchatClient({ host: server, protocol: 'ddp', useSsl });
this.sdk = new RocketchatClient({ host: server, protocol: 'ddp', useSsl: useSsl(server) });
this.getSettings();

this.sdk.connect()
Expand Down Expand Up @@ -268,10 +261,7 @@ const RocketChat = {
this.shareSDK = null;
}

// Use useSsl: false only if server url starts with http://
const useSsl = !/http:\/\//.test(server);

this.shareSDK = new RocketchatClient({ host: server, protocol: 'ddp', useSsl });
this.shareSDK = new RocketchatClient({ host: server, protocol: 'ddp', useSsl: useSsl(server) });

// set Server
const serversDB = database.servers;
Expand Down Expand Up @@ -407,72 +397,8 @@ const RocketChat = {
throw e;
}
},
async logout({ server }) {
if (this.roomsSub) {
this.roomsSub.stop();
}

if (this.activeUsersSubTimeout) {
clearTimeout(this.activeUsersSubTimeout);
this.activeUsersSubTimeout = false;
}

try {
await this.removePushToken();
} catch (error) {
console.log('logout -> removePushToken -> catch -> error', error);
}
try {
// RC 0.60.0
await this.sdk.logout();
} catch (error) {
console.log('​logout -> api logout -> catch -> error', error);
}
this.sdk = null;

try {
const servers = await RNUserDefaults.objectForKey(SERVERS);
await RNUserDefaults.setObjectForKey(SERVERS, servers && servers.filter(srv => srv[SERVER_URL] !== server));
// clear certificate for server - SSL Pinning
const certificate = await RNUserDefaults.objectForKey(extractHostname(server));
if (certificate && certificate.path) {
await RNUserDefaults.clear(extractHostname(server));
await FileSystem.deleteAsync(certificate.path);
}
} catch (error) {
console.log('logout_rn_user_defaults', error);
}

const userId = await RNUserDefaults.get(`${ TOKEN_KEY }-${ server }`);

try {
const serversDB = database.servers;
await serversDB.action(async() => {
const usersCollection = serversDB.collections.get('users');
const userRecord = await usersCollection.find(userId);
const serverCollection = serversDB.collections.get('servers');
const serverRecord = await serverCollection.find(server);
await serversDB.batch(
userRecord.prepareDestroyPermanently(),
serverRecord.prepareDestroyPermanently()
);
});
} catch (error) {
// Do nothing
}

await RNUserDefaults.clear('currentServer');
await RNUserDefaults.clear(TOKEN_KEY);
await RNUserDefaults.clear(`${ TOKEN_KEY }-${ server }`);
await RNUserDefaults.clear(`${ BASIC_AUTH_KEY }-${ server }`);

try {
const db = database.active;
await db.action(() => db.unsafeResetDatabase());
} catch (error) {
console.log(error);
}
},
logout,
removeServer,
async clearCache({ server }) {
try {
const serversDB = database.servers;
Expand Down
Loading

0 comments on commit cff6e34

Please sign in to comment.