Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REGRESSION] Auth via deep linking not working #3015

Merged
merged 10 commits into from
Mar 31, 2021
19 changes: 14 additions & 5 deletions app/sagas/deepLinking.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from '../actions/app';
import { localAuthenticate } from '../utils/localAuthentication';
import { goRoom } from '../utils/goRoom';
import { loginRequest } from '../actions/login';

const roomTypes = {
channel: 'c', direct: 'd', group: 'p', channels: 'l'
Expand All @@ -41,9 +42,13 @@ const popToRoot = function popToRoot({ isMasterDetail }) {

const navigate = function* navigate({ params }) {
yield put(appStart({ root: ROOT_INSIDE }));
if (params.path) {
const [type, name] = params.path.split('/');
if (type !== 'invite') {
if (params.path || params.rid) {
let type;
let name;
if (params.path) {
[type, name] = params.path.split('/');
}
if (type !== 'invite' || params.rid) {
const room = yield RocketChat.canOpenRoom(params);
if (room) {
const item = {
Expand Down Expand Up @@ -110,7 +115,11 @@ const handleOpen = function* handleOpen({ params }) {

// If there's host, continue
if (!/^(http|https)/.test(host)) {
host = `https://${ host }`;
if (/^localhost(:\d+)?/.test(host)) {
host = `http://${ host }`;
} else {
host = `https://${ host }`;
}
} else {
// Notification should always come from https
host = host.replace('http://', 'https://');
Expand Down Expand Up @@ -163,7 +172,7 @@ const handleOpen = function* handleOpen({ params }) {

if (params.token) {
yield take(types.SERVER.SELECT_SUCCESS);
yield RocketChat.connect({ server: host, user: { token: params.token } });
yield put(loginRequest({ resume: params.token }, true));
yield take(types.LOGIN.SUCCESS);
yield navigate({ params });
} else {
Expand Down
2 changes: 1 addition & 1 deletion e2e/data/data.docker.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const random = require('./helpers/random');
const value = random(20);
const data = {
server: 'http://127.0.0.1:3000',
server: 'http://localhost:3000',
adminUser: 'admin',
adminPassword: 'password',
alternateServer: 'https://stable.rocket.chat',
Expand Down
24 changes: 16 additions & 8 deletions e2e/helpers/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,29 @@ const {
} = require('detox');
const data = require('../data');

async function navigateToWorkspace() {
async function navigateToWorkspace(server = data.server) {
await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(10000);
await element(by.id('join-workspace')).tap();
await waitFor(element(by.id('new-server-view'))).toBeVisible().withTimeout(60000);
await element(by.id('new-server-view-input')).replaceText(data.server);
await element(by.id('new-server-view-input')).replaceText(server);
await element(by.id('new-server-view-button')).tap();
await waitFor(element(by.id('workspace-view'))).toBeVisible().withTimeout(60000);
await expect(element(by.id('workspace-view'))).toBeVisible();
}

async function navigateToLogin() {
async function navigateToLogin(server) {
await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(20000);
await navigateToWorkspace();
await navigateToWorkspace(server);
await element(by.id('workspace-view-login')).tap();
await waitFor(element(by.id('login-view'))).toBeVisible().withTimeout(2000);
await expect(element(by.id('login-view'))).toBeVisible();
}

async function navigateToRegister() {
async function navigateToRegister(server) {
await waitFor(element(by.id('onboarding-view'))).toBeVisible().withTimeout(20000);
await navigateToWorkspace();
await navigateToWorkspace(server);
await element(by.id('workspace-view-register')).tap();
await waitFor(element(by.id('register-view'))).toBeVisible().withTimeout(2000);
await expect(element(by.id('register-view'))).toBeVisible();
}

async function login(username, password) {
Expand Down Expand Up @@ -120,6 +119,14 @@ async function tryTapping(theElement, timeout, longtap = false){
}
}

const checkServer = async(server) => {
const label = `Connected to ${ server }`;
await element(by.id('rooms-list-view-sidebar')).tap();
await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000);
await waitFor(element(by.label(label))).toBeVisible().withTimeout(10000);
await element(by.id('sidebar-close-drawer')).tap();
}

module.exports = {
navigateToWorkspace,
navigateToLogin,
Expand All @@ -133,5 +140,6 @@ module.exports = {
tapBack,
sleep,
searchRoom,
tryTapping
tryTapping,
checkServer
};
12 changes: 11 additions & 1 deletion e2e/helpers/data_setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,16 @@ const setup = async () => {
return
}

const get = (endpoint) => {
console.log(`GET /${ endpoint }`)
return rocketchat.get(endpoint);
}

const post = (endpoint, body) => {
console.log(`POST /${ endpoint } ${ JSON.stringify(body) }`)
return rocketchat.post(endpoint, body);
}

module.exports = {
setup, sendMessage
setup, sendMessage, get, post
}
10 changes: 1 addition & 9 deletions e2e/tests/assorted/07-changeserver.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@ const {
device, expect, element, by, waitFor
} = require('detox');
const data = require('../../data');
const { sleep, navigateToLogin, login } = require('../../helpers/app');

const checkServer = async(server) => {
const label = `Connected to ${ server }`;
await element(by.id('rooms-list-view-sidebar')).tap();
await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000);
await waitFor(element(by.label(label))).toBeVisible().withTimeout(60000);
await element(by.id('sidebar-close-drawer')).tap();
}
const { navigateToLogin, login, checkServer } = require('../../helpers/app');

const reopenAndCheckServer = async(server) => {
await device.launchApp({ permissions: { notifications: 'YES' } });
Expand Down
10 changes: 1 addition & 9 deletions e2e/tests/assorted/10-deleteserver.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@ const {
device, element, by, waitFor
} = require('detox');
const data = require('../../data');
const { sleep, navigateToLogin, login } = require('../../helpers/app');

const checkServer = async(server) => {
const label = `Connected to ${ server }`;
await element(by.id('rooms-list-view-sidebar')).tap();
await waitFor(element(by.id('sidebar-view'))).toBeVisible().withTimeout(2000);
await waitFor(element(by.label(label))).toBeVisible().withTimeout(10000);
await element(by.id('sidebar-close-drawer')).tap();
}
const { sleep, navigateToLogin, login, checkServer } = require('../../helpers/app');

describe('Delete server', () => {
before(async() => {
Expand Down
123 changes: 123 additions & 0 deletions e2e/tests/assorted/11-deeplinking.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
const {
device, element, by, waitFor
} = require('detox');
const data = require('../../data');
const { tapBack, checkServer, navigateToRegister, login } = require('../../helpers/app');
const { post, get } = require('../../helpers/data_setup');

const DEEPLINK_METHODS = { AUTH: 'auth', ROOM: 'room' };
const getDeepLink = (method, server, params) => {
const deeplink = `rocketchat://${ method }?host=${ server.replace(/^(http:\/\/|https:\/\/)/, '') }&${params}`;
console.log(`Deeplinking to: ${ deeplink }`);
return deeplink;
};

describe('Deep linking', () => {
let userId;
let token;
before(async() => {
const loginResult = await post('login', {
user: data.users.regular.username,
password: data.users.regular.password
})
userId = loginResult.data.data.userId
token = loginResult.data.data.authToken
});

describe('Authentication', () => {
it('should run a deep link to an invalid account and raise error', async() => {
await device.launchApp({
permissions: { notifications: 'YES' },
newInstance: true,
url: getDeepLink(DEEPLINK_METHODS.AUTH, data.server, 'userId=123&token=abc'),
sourceApp: 'com.apple.mobilesafari'
});
await waitFor(element(by.text('You\'ve been logged out by the server. Please log in again.'))).toExist().withTimeout(5000); // TODO: we need to improve this message
});

const authAndNavigate = async() => {
await device.launchApp({
permissions: { notifications: 'YES' },
newInstance: true,
url: getDeepLink(DEEPLINK_METHODS.AUTH, data.server, `userId=${ userId }&token=${ token }&path=group/${ data.groups.private.name }`),
sourceApp: 'com.apple.mobilesafari'
});
await waitFor(element(by.id(`room-view-title-${ data.groups.private.name }`))).toExist().withTimeout(10000);
await tapBack();
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
await checkServer(data.server);
await waitFor(element(by.id(`rooms-list-view-item-${ data.groups.private.name }`))).toBeVisible().withTimeout(2000);
}

it('should authenticate and navigate', async() => {
await authAndNavigate();
});

it('should authenticate while logged in another server', async() => {
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
await navigateToRegister(data.alternateServer);
await element(by.id('register-view-name')).replaceText(data.registeringUser.username);
await element(by.id('register-view-username')).replaceText(data.registeringUser.username);
await element(by.id('register-view-email')).replaceText(data.registeringUser.email);
await element(by.id('register-view-password')).replaceText(data.registeringUser.password);
await element(by.id('register-view-submit')).tap();
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
await authAndNavigate();
});
});

describe('Room', () => {
describe('While logged in', async() => {
it('should navigate to the room using path', async() => {
await device.launchApp({
permissions: { notifications: 'YES' },
newInstance: true,
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `path=group/${ data.groups.private.name }`),
sourceApp: 'com.apple.mobilesafari'
});
await waitFor(element(by.id(`room-view-title-${ data.groups.private.name }`))).toExist().withTimeout(10000);
});

it('should navigate to the room using rid', async() => {
const roomResult = await get(`groups.info?roomName=${ data.groups.private.name }`)
await device.launchApp({
permissions: { notifications: 'YES' },
newInstance: true,
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `rid=${ roomResult.data.group._id }`),
sourceApp: 'com.apple.mobilesafari'
});
await waitFor(element(by.id(`room-view-title-${ data.groups.private.name }`))).toExist().withTimeout(10000);
await tapBack();
});
});

describe('Others', async() => {
it('should change server', async() => {
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
await element(by.id('rooms-list-header-server-dropdown-button')).tap();
await waitFor(element(by.id('rooms-list-header-server-dropdown'))).toBeVisible().withTimeout(5000);
await element(by.id(`rooms-list-header-server-${ data.alternateServer }`)).tap();
await checkServer(data.alternateServer);

await device.launchApp({
permissions: { notifications: 'YES' },
newInstance: true,
url: getDeepLink(DEEPLINK_METHODS.ROOM, data.server, `path=group/${ data.groups.private.name }`),
sourceApp: 'com.apple.mobilesafari'
});
await waitFor(element(by.id(`room-view-title-${ data.groups.private.name }`))).toExist().withTimeout(10000);
});

it('should add a not existing server and fallback to the previous one', async() => {
await device.launchApp({
permissions: { notifications: 'YES' },
newInstance: true,
url: getDeepLink(DEEPLINK_METHODS.ROOM, 'https://google.com'),
sourceApp: 'com.apple.mobilesafari'
});
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(10000);
await checkServer(data.server);
});
});
});
});