Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions app/lib/database/services/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ import { SERVERS_TABLE } from '../model';
const getCollection = (db: TServerDatabase) => db.get(SERVERS_TABLE);

export const getServerById = async (server: string): Promise<TServerModel | null> => {
const db = database.servers;
const serverCollection = getCollection(db);
try {
const result = await serverCollection.find(server);
return result;
return await getCollection(database.servers).find(server);
} catch {
return null;
}
};

export const getAllServers = (): Promise<TServerModel[]> => getCollection(database.servers).query().fetch();
13 changes: 5 additions & 8 deletions app/lib/methods/loggedInServer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { type TServerModel } from '../../definitions';
import { TOKEN_KEY } from '../constants/keys';
import database from '../database';
import { SERVERS_TABLE } from '../database/model';
import { getAllServers } from '../database/services/Server';
import UserPreferences from './userPreferences';

export const hasStoredLoginToken = (serverId: string): boolean => !!UserPreferences.getString(`${TOKEN_KEY}-${serverId}`);
export const isLoggedInServer = (serverId?: string | null): boolean =>
!!serverId && !!UserPreferences.getString(`${TOKEN_KEY}-${serverId}`);

export const findLoggedInServer = function* findLoggedInServer(): Generator<any, TServerModel | undefined> {
const serversCollection = database.servers.get(SERVERS_TABLE);
const servers = (yield serversCollection.query().fetch()) as TServerModel[];
return servers.find(({ id }) => hasStoredLoginToken(id));
};
export const findLoggedInServer = async (): Promise<TServerModel | undefined> =>
(await getAllServers()).find(({ id }) => isLoggedInServer(id));
27 changes: 18 additions & 9 deletions app/sagas/__tests__/init.fallbackServer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,9 @@ const FALLBACK_SERVER = 'https://fallback.rocket.chat';
const FALLBACK_VERSION = '7.0.0';
const LOGGED_OUT_SERVER = 'https://loggedout.rocket.chat';

jest.mock('../../lib/database', () => ({
__esModule: true,
default: {
servers: {
get: () => ({
query: () => ({ fetch: () => Promise.resolve([{ id: FALLBACK_SERVER, version: FALLBACK_VERSION }]) })
})
}
}
jest.mock('../../lib/database/services/Server', () => ({
getServerById: jest.fn(),
getAllServers: jest.fn(() => Promise.resolve([{ id: FALLBACK_SERVER, version: FALLBACK_VERSION }]))
}));

jest.mock('../../lib/methods/helpers/localAuthentication', () => ({
Expand All @@ -22,10 +16,12 @@ import { SERVER } from '../../actions/actionsTypes';
import { CURRENT_SERVER, TOKEN_KEY } from '../../lib/constants/keys';
import UserPreferences from '../../lib/methods/userPreferences';
import { cancelSagaTasks, createRecordingStore, flushSagaMicrotasks } from '../../lib/testUtils/sagaStore';
import { localAuthenticate } from '../../lib/methods/helpers/localAuthentication';
import initRoot from '../init';

describe('init saga — fallback workspace', () => {
beforeEach(() => {
jest.mocked(localAuthenticate).mockClear();
UserPreferences.setString(CURRENT_SERVER, LOGGED_OUT_SERVER);
UserPreferences.removeItem(`${TOKEN_KEY}-${LOGGED_OUT_SERVER}`);
UserPreferences.setString(`${TOKEN_KEY}-${FALLBACK_SERVER}`, 'userId');
Expand All @@ -43,6 +39,19 @@ describe('init saga — fallback workspace', () => {
store.dispatch(appInit());
await flushSagaMicrotasks();

expect(dispatchedActions.find(action => action.type === SERVER.SELECT_REQUEST)).toEqual(
expect.objectContaining({ server: FALLBACK_SERVER, version: FALLBACK_VERSION })
);
expect(jest.mocked(localAuthenticate)).toHaveBeenCalledWith(FALLBACK_SERVER);
});

it('requests the fallback workspace when the current server was cleared by a logout', async () => {
UserPreferences.removeItem(CURRENT_SERVER);
const { store, dispatchedActions } = createRecordingStore(initRoot);

store.dispatch(appInit());
await flushSagaMicrotasks();

expect(dispatchedActions.find(action => action.type === SERVER.SELECT_REQUEST)).toEqual(
expect.objectContaining({ server: FALLBACK_SERVER, version: FALLBACK_VERSION })
);
Expand Down
25 changes: 6 additions & 19 deletions app/sagas/__tests__/init.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ jest.mock('../../lib/methods/userPreferences', () => ({
}));

jest.mock('../../lib/database/services/Server', () => ({
getServerById: jest.fn()
getServerById: jest.fn(),
getAllServers: jest.fn()
}));

jest.mock('../../lib/methods/helpers/localAuthentication', () => ({
Expand All @@ -30,26 +31,16 @@ jest.mock('@react-native-async-storage/async-storage', () => ({
}
}));

jest.mock('../../lib/database', () => ({
__esModule: true,
default: {
servers: {
get: jest.fn()
}
}
}));

import RNBootSplash from 'react-native-bootsplash';

import { appInit, appStart } from '../../actions/app';
import { RootEnum } from '../../definitions';
import initRoot from '../init';
import UserPreferences from '../../lib/methods/userPreferences';
import { getServerById } from '../../lib/database/services/Server';
import { getAllServers, getServerById } from '../../lib/database/services/Server';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { DEEP_LINKING } from '../../actions/actionsTypes';
import { TOKEN_KEY } from '../../lib/constants/keys';
import database from '../../lib/database';
import { cancelSagaTasks, createRecordingStore, flushSagaMicrotasks } from '../../lib/testUtils/sagaStore';
import type { RecordingStore } from '../../lib/testUtils/sagaStore';

Expand All @@ -65,7 +56,7 @@ describe('init saga — restore user-facing roots', () => {
jest.mocked(RNBootSplash.hide).mockClear();
jest.mocked(AsyncStorage.getItem).mockResolvedValue(null as any);
jest.mocked(AsyncStorage.removeItem).mockClear();
jest.mocked(database.servers.get).mockReset();
jest.mocked(getAllServers).mockResolvedValue([]);
jest.mocked(UserPreferences.getString).mockImplementation(() => HOST);
});

Expand Down Expand Up @@ -107,9 +98,7 @@ describe('init saga — restore user-facing roots', () => {

it('lands on ROOT_OUTSIDE when neither the stored server nor any other has a token', async () => {
jest.mocked(UserPreferences.getString).mockImplementation(key => (key.startsWith(`${TOKEN_KEY}-`) ? null : HOST));
jest.mocked(database.servers.get).mockReturnValue({
query: () => ({ fetch: () => Promise.resolve([{ id: OTHER_HOST, version: '7.0.0' }]) })
} as any);
jest.mocked(getAllServers).mockResolvedValue([{ id: OTHER_HOST, version: '7.0.0' }] as any);
const { store } = setupStore();

store.dispatch(appInit());
Expand All @@ -125,9 +114,7 @@ describe('init saga — restore user-facing roots', () => {
if (key.startsWith(`${TOKEN_KEY}-`)) return null;
return HOST;
});
jest.mocked(database.servers.get).mockReturnValue({
query: () => ({ fetch: () => Promise.resolve([{ id: OTHER_HOST, version: '7.0.0' }]) })
} as any);
jest.mocked(getAllServers).mockResolvedValue([{ id: OTHER_HOST, version: '7.0.0' }] as any);
const { store } = setupStore();

store.dispatch(appInit());
Expand Down
25 changes: 13 additions & 12 deletions app/sagas/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage';

import { CURRENT_SERVER } from '../lib/constants/keys';
import UserPreferences from '../lib/methods/userPreferences';
import { findLoggedInServer, hasStoredLoginToken } from '../lib/methods/loggedInServer';
import { findLoggedInServer, isLoggedInServer } from '../lib/methods/loggedInServer';
import { selectServerRequest } from '../actions/server';
import { setAllPreferences } from '../actions/sortPreferences';
import { APP } from '../actions/actionsTypes';
Expand All @@ -23,19 +23,20 @@ export const initLocalSettings = function* initLocalSettings() {
yield put(setAllPreferences(sortPreferences));
};

const serverToRestore = function* serverToRestore() {
try {
const server = UserPreferences.getString(CURRENT_SERVER);
if (!server) {
return null;
}
const findServerToRestore = async () => {
const server = UserPreferences.getString(CURRENT_SERVER);
const restoredServer = isLoggedInServer(server) ? await getServerById(server) : await findLoggedInServer();

if (!hasStoredLoginToken(server)) {
return (yield* findLoggedInServer()) || null;
}
if (restoredServer) {
await localAuthenticate(restoredServer.id);
}

return restoredServer;
};

yield localAuthenticate(server);
return (yield getServerById(server)) || null;
const serverToRestore = function* serverToRestore() {
try {
return (yield call(findServerToRestore)) || null;
} catch (e) {
log(e);
return null;
Expand Down