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

[IMPROVEMENT] Share credentials with Rocket.Chat.iOS #982

Merged
merged 20 commits into from
Jun 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7dadd7a
:sparkles: Create user table
djorkaeffalexandre Jun 12, 2019
92b022d
:sparkles: Introduce user table
djorkaeffalexandre Jun 12, 2019
053a72e
:fire: Remove unused table
djorkaeffalexandre Jun 12, 2019
c4cc3e2
:heavy_plus_sign: Add userdefaults to storage data
djorkaeffalexandre Jun 12, 2019
e3d2470
:green_heart: Fix android build
djorkaeffalexandre Jun 12, 2019
672099c
:sparkles: Get credentials from iOS native client
djorkaeffalexandre Jun 13, 2019
7368d87
Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.R…
djorkaeffalexandre Jun 13, 2019
02ff0e4
:fire: Remove unused code
djorkaeffalexandre Jun 13, 2019
5d51809
:rewind: Revert sign xcode
djorkaeffalexandre Jun 13, 2019
515f7ee
:bug: Fix first login-logout
djorkaeffalexandre Jun 13, 2019
7bf0c33
:art: Use constants to UserDefaults Keys
djorkaeffalexandre Jun 13, 2019
63bef4e
:bug: Fix clear server-user-info on logout
djorkaeffalexandre Jun 14, 2019
9e7a5f7
:bug: Fix filter null value
djorkaeffalexandre Jun 14, 2019
344556c
:ambulance: Remove user object in logout
djorkaeffalexandre Jun 14, 2019
5c93d49
:twisted_rightwards_arrows: Merge develop
djorkaeffalexandre Jun 17, 2019
4e029c1
Merge branch 'develop' into user-defaults-ios
diegolmello Jun 24, 2019
cd229f5
:sparkles: Fix get servers from native-client
djorkaeffalexandre Jun 26, 2019
56a734b
Merge branch 'user-defaults-ios' of https://github.com/djorkaeffalexa…
djorkaeffalexandre Jun 26, 2019
90842a3
:ambulance: Fix error on change server
djorkaeffalexandre Jun 26, 2019
86137c9
Merge branch 'develop' into user-defaults-ios
diegolmello Jun 26, 2019
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
6 changes: 6 additions & 0 deletions app/constants/userDefaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const SERVERS = 'kServers';
export const TOKEN = 'kAuthToken';
export const USER_ID = 'kUserId';
export const SERVER_URL = 'kAuthServerURL';
export const SERVER_NAME = 'kServerName';
export const SERVER_ICON = 'kServerIconURL';
15 changes: 15 additions & 0 deletions app/lib/realm.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ import Realm from 'realm';
// Realm.clearTestState();
// AsyncStorage.clear();

const userSchema = {
name: 'user',
primaryKey: 'id',
properties: {
id: 'string',
token: { type: 'string', optional: true },
username: { type: 'string', optional: true },
name: { type: 'string', optional: true },
language: { type: 'string', optional: true },
status: { type: 'string', optional: true },
roles: { type: 'string[]', optional: true }
}
};

const serversSchema = {
name: 'servers',
primaryKey: 'id',
Expand Down Expand Up @@ -370,6 +384,7 @@ class DB {
serversDB: new Realm({
path: 'default.realm',
schema: [
userSchema,
diegolmello marked this conversation as resolved.
Show resolved Hide resolved
serversSchema
],
schemaVersion: 8,
Expand Down
28 changes: 23 additions & 5 deletions app/lib/rocketchat.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AsyncStorage, InteractionManager } from 'react-native';
import semver from 'semver';
import { Rocketchat as RocketchatClient } from '@rocket.chat/sdk';
import RNUserDefaults from 'rn-user-defaults';

import reduxStore from './createStore';
import defaultSettings from '../constants/settings';
Expand Down Expand Up @@ -36,6 +37,7 @@ import sendMessage, { getMessage, sendMessageCall } from './methods/sendMessage'
import { sendFileMessage, cancelUpload, isUploadActive } from './methods/sendFileMessage';

import { getDeviceToken } from '../notifications/push';
import { SERVERS, SERVER_URL } from '../constants/userDefaults';

const TOKEN_KEY = 'reactnativemeteor_usertoken';
const SORT_PREFS_KEY = 'RC_SORT_PREFS_KEY';
Expand All @@ -58,9 +60,9 @@ const RocketChat = {
},
async getUserToken() {
try {
return await AsyncStorage.getItem(TOKEN_KEY);
return await RNUserDefaults.get(TOKEN_KEY);
} catch (error) {
console.warn(`AsyncStorage error: ${ error.message }`);
console.warn(`RNUserDefaults error: ${ error.message }`);
}
},
async getServerInfo(server) {
Expand Down Expand Up @@ -321,10 +323,26 @@ const RocketChat = {
}
this.sdk = null;

try {
const servers = await RNUserDefaults.objectForKey(SERVERS);
await RNUserDefaults.setObjectForKey(SERVERS, servers && servers.filter(srv => srv[SERVER_URL] !== server));
} catch (error) {
console.log('logout_rn_user_defaults', error);
}

const { serversDB } = database.databases;

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

serversDB.write(() => {
const user = serversDB.objectForPrimaryKey('user', userId);
serversDB.delete(user);
});

Promise.all([
AsyncStorage.removeItem('currentServer'),
AsyncStorage.removeItem(TOKEN_KEY),
AsyncStorage.removeItem(`${ TOKEN_KEY }-${ server }`)
RNUserDefaults.clear('currentServer'),
RNUserDefaults.clear(TOKEN_KEY),
RNUserDefaults.clear(`${ TOKEN_KEY }-${ server }`)
]).catch(error => console.log(error));

try {
Expand Down
6 changes: 3 additions & 3 deletions app/sagas/deepLinking.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { AsyncStorage } from 'react-native';
import { delay } from 'redux-saga';
import {
takeLatest, take, select, put, all
} from 'redux-saga/effects';
import RNUserDefaults from 'rn-user-defaults';

import Navigation from '../lib/Navigation';
import * as types from '../actions/actionsTypes';
Expand Down Expand Up @@ -43,8 +43,8 @@ const handleOpen = function* handleOpen({ params }) {
}

const [server, user] = yield all([
AsyncStorage.getItem('currentServer'),
AsyncStorage.getItem(`${ RocketChat.TOKEN_KEY }-${ host }`)
RNUserDefaults.get('currentServer'),
RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ host }`)
]);

// TODO: needs better test
Expand Down
44 changes: 38 additions & 6 deletions app/sagas/init.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AsyncStorage } from 'react-native';
import { put, takeLatest, all } from 'redux-saga/effects';
import SplashScreen from 'react-native-splash-screen';
import RNUserDefaults from 'rn-user-defaults';

import * as actions from '../actions';
import { selectServerRequest } from '../actions/server';
Expand All @@ -11,14 +11,46 @@ import RocketChat from '../lib/rocketchat';
import log from '../utils/log';
import Navigation from '../lib/Navigation';
import database from '../lib/realm';
import {
SERVERS, SERVER_ICON, SERVER_NAME, SERVER_URL, TOKEN, USER_ID
} from '../constants/userDefaults';

const restore = function* restore() {
try {
const { token, server } = yield all({
token: AsyncStorage.getItem(RocketChat.TOKEN_KEY),
server: AsyncStorage.getItem('currentServer')
yield RNUserDefaults.setName('group.ios.chat.rocket');

let { token, server } = yield all({
token: RNUserDefaults.get(RocketChat.TOKEN_KEY),
server: RNUserDefaults.get('currentServer')
});

// get native credentials
const { serversDB } = database.databases;
const servers = yield RNUserDefaults.objectForKey(SERVERS);
if (servers) {
serversDB.write(() => {
servers.forEach(async(serverItem) => {
const serverInfo = {
id: serverItem[SERVER_URL],
name: serverItem[SERVER_NAME],
iconURL: serverItem[SERVER_ICON]
};
try {
serversDB.create('servers', serverInfo, true);
await RNUserDefaults.set(`${ RocketChat.TOKEN_KEY }-${ serverInfo.id }`, serverItem[USER_ID]);
} catch (e) {
log('err_create_servers', e);
}
});
});
}

// if not have current
if (servers.length !== 0 && (!token || !server)) {
server = servers[0][SERVER_URL];
token = servers[0][TOKEN];
}

const sortPreferences = yield RocketChat.getSortPreferences();
yield put(setAllPreferences(sortPreferences));

Expand All @@ -27,8 +59,8 @@ const restore = function* restore() {

if (!token || !server) {
yield all([
AsyncStorage.removeItem(RocketChat.TOKEN_KEY),
AsyncStorage.removeItem('currentServer')
RNUserDefaults.clear(RocketChat.TOKEN_KEY),
RNUserDefaults.clear('currentServer')
]);
yield put(actions.appStart('outside'));
} else if (server) {
Expand Down
18 changes: 14 additions & 4 deletions app/sagas/login.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AsyncStorage } from 'react-native';
import {
put, call, takeLatest, select, take, fork, cancel
} from 'redux-saga/effects';
import RNUserDefaults from 'rn-user-defaults';

import * as types from '../actions/actionsTypes';
import { appStart } from '../actions';
Expand Down Expand Up @@ -60,7 +60,7 @@ const fetchUserPresence = function* fetchUserPresence() {
const handleLoginSuccess = function* handleLoginSuccess({ user }) {
try {
const adding = yield select(state => state.server.adding);
yield AsyncStorage.setItem(RocketChat.TOKEN_KEY, user.token);
yield RNUserDefaults.set(RocketChat.TOKEN_KEY, user.token);

const server = yield select(getServer);
yield put(roomsRequest());
Expand All @@ -72,7 +72,17 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) {
yield fork(fetchUserPresence);

I18n.locale = user.language;
yield AsyncStorage.setItem(`${ RocketChat.TOKEN_KEY }-${ server }`, JSON.stringify(user));

const { serversDB } = database.databases;
serversDB.write(() => {
try {
serversDB.create('user', user, true);
} catch (e) {
log('err_set_user_token', e);
}
});

yield RNUserDefaults.set(`${ RocketChat.TOKEN_KEY }-${ server }`, user.id);
yield put(setUser(user));
EventEmitter.emit('connected');

Expand Down Expand Up @@ -105,7 +115,7 @@ const handleLogout = function* handleLogout() {
// see if there's other logged in servers and selects first one
if (servers.length > 0) {
const newServer = servers[0].id;
const token = yield AsyncStorage.getItem(`${ RocketChat.TOKEN_KEY }-${ newServer }`);
const token = yield RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ newServer }`);
if (token) {
return yield put(selectServerRequest(newServer));
}
Expand Down
24 changes: 17 additions & 7 deletions app/sagas/selectServer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {
put, take, takeLatest, fork, cancel, race
} from 'redux-saga/effects';
import { AsyncStorage, Alert } from 'react-native';
import { Alert } from 'react-native';
import RNUserDefaults from 'rn-user-defaults';

import Navigation from '../lib/Navigation';
import { SERVER } from '../actions/actionsTypes';
Expand All @@ -14,6 +15,7 @@ import RocketChat from '../lib/rocketchat';
import database from '../lib/realm';
import log from '../utils/log';
import I18n from '../i18n';
import { SERVERS, TOKEN, SERVER_URL } from '../constants/userDefaults';

const getServerInfo = function* getServerInfo({ server, raiseError = true }) {
try {
Expand All @@ -38,13 +40,21 @@ const getServerInfo = function* getServerInfo({ server, raiseError = true }) {

const handleSelectServer = function* handleSelectServer({ server, version, fetchVersion }) {
try {
yield AsyncStorage.setItem('currentServer', server);
const userStringified = yield AsyncStorage.getItem(`${ RocketChat.TOKEN_KEY }-${ server }`);
const { serversDB } = database.databases;

if (userStringified) {
const user = JSON.parse(userStringified);
yield RocketChat.connect({ server, user });
yield put(setUser(user));
yield RNUserDefaults.set('currentServer', server);
const userId = yield RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ server }`);
const user = userId && serversDB.objectForPrimaryKey('user', userId);

const servers = yield RNUserDefaults.objectForKey(SERVERS);
const userCredentials = servers && servers.find(srv => srv[SERVER_URL] === server);
const userLogin = userCredentials && {
token: userCredentials[TOKEN]
};

if (user || userLogin) {
yield RocketChat.connect({ server, user: user || userLogin });
yield put(setUser(user || userLogin));
yield put(actions.appStart('inside'));
} else {
yield RocketChat.connect({ server });
Expand Down
7 changes: 4 additions & 3 deletions app/views/RoomsListView/ServerDropdown.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, { Component } from 'react';
import {
View, Text, Animated, Easing, TouchableWithoutFeedback, TouchableOpacity, FlatList, Image, AsyncStorage
View, Text, Animated, Easing, TouchableWithoutFeedback, TouchableOpacity, FlatList, Image
} from 'react-native';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import equal from 'deep-equal';
import { withNavigation } from 'react-navigation';
import RNUserDefaults from 'rn-user-defaults';

import { toggleServerDropdown as toggleServerDropdownAction } from '../../actions/rooms';
import { selectServerRequest as selectServerRequestAction } from '../../actions/server';
Expand Down Expand Up @@ -124,8 +125,8 @@ class ServerDropdown extends Component {

this.close();
if (currentServer !== server) {
const token = await AsyncStorage.getItem(`${ RocketChat.TOKEN_KEY }-${ server }`);
if (!token) {
const userId = await RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ server }`);
if (!userId) {
appStart();
this.newServerTimeout = setTimeout(() => {
EventEmitter.emit('NewServer', { server });
Expand Down
8 changes: 5 additions & 3 deletions app/views/RoomsListView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const keyExtractor = item => item.rid;

@connect(state => ({
userId: state.login.user && state.login.user.id,
isAuthenticated: state.login.isAuthenticated,
server: state.server.server,
baseUrl: state.settings.baseUrl || state.server ? state.server.server : '',
searchText: state.rooms.searchText,
Expand Down Expand Up @@ -111,7 +112,8 @@ export default class RoomsListView extends React.Component {
openSearchHeader: PropTypes.func,
closeSearchHeader: PropTypes.func,
appStart: PropTypes.func,
roomsRequest: PropTypes.func
roomsRequest: PropTypes.func,
isAuthenticated: PropTypes.bool
}

constructor(props) {
Expand Down Expand Up @@ -187,7 +189,7 @@ export default class RoomsListView extends React.Component {

componentDidUpdate(prevProps) {
const {
sortBy, groupByType, showFavorites, showUnread, appState, roomsRequest
sortBy, groupByType, showFavorites, showUnread, appState, roomsRequest, isAuthenticated
} = this.props;

if (!(
Expand All @@ -197,7 +199,7 @@ export default class RoomsListView extends React.Component {
&& (prevProps.showUnread === showUnread)
)) {
this.getSubscriptions();
} else if (appState === 'foreground' && appState !== prevProps.appState) {
} else if (appState === 'foreground' && appState !== prevProps.appState && isAuthenticated) {
roomsRequest();
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/views/SidebarView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export default class Sidebar extends Component {
const permissionsFiltered = database.objects('permissions')
.filter(permission => permissions.includes(permission._id));
return permissionsFiltered.reduce((result, permission) => (
result || permission.roles.some(r => roles.includes(r))),
result || permission.roles.some(r => roles.indexOf(r) !== -1)),
false);
}
return false;
Expand Down
Loading