MM-16095 Android share extension to use keychain for authentication (#2876)

* MM-16095 Android share extension to use keychain for authentication

* Remove unnecessary comment
This commit is contained in:
Elias Nahum 2019-06-15 14:13:54 -04:00 committed by GitHub
parent 03d06676f8
commit c3c3d85248
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 28 deletions

View file

@ -127,7 +127,6 @@
"mobile.account_notifications.threads_mentions": "Mentions in threads",
"mobile.account_notifications.threads_start": "Threads that I start",
"mobile.account_notifications.threads_start_participate": "Threads that I start or participate in",
"mobile.account.settings.cancel": "Cancel",
"mobile.account.settings.save": "Save",
"mobile.action_menu.select": "Select an option",
"mobile.advanced_settings.clockDisplay": "Clock display",
@ -401,6 +400,7 @@
"mobile.routes.thread": "{channelName} Thread",
"mobile.routes.thread_dm": "Direct Message Thread",
"mobile.routes.user_profile": "Profile",
"mobile.routes.user_profile.edit": "Edit",
"mobile.routes.user_profile.local_time": "LOCAL TIME",
"mobile.routes.user_profile.send_message": "Send Message",
"mobile.search.after_modifier_description": "to find posts after a specific date",

View file

@ -21,7 +21,9 @@ import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import Video from 'react-native-video';
import LocalAuth from 'react-native-local-auth';
import RNFetchBlob from 'rn-fetch-blob';
import {getGenericPassword} from 'react-native-keychain';
import {Client4} from 'mattermost-redux/client';
import {Preferences} from 'mattermost-redux/constants';
import {getFormattedFileSize, lookupMimeType} from 'mattermost-redux/utils/file_utils';
@ -29,8 +31,10 @@ import Loading from 'app/components/loading';
import PaperPlane from 'app/components/paper_plane';
import {MAX_FILE_COUNT} from 'app/constants/post_textbox';
import mattermostManaged from 'app/mattermost_managed';
import avoidNativeBridge from 'app/utils/avoid_native_bridge';
import {getExtensionFromMime} from 'app/utils/file';
import {emptyFunction} from 'app/utils/general';
import {setCSRFFromCookie} from 'app/utils/security';
import {preventDoubleTap} from 'app/utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
@ -45,6 +49,7 @@ import {
import ChannelButton from './channel_button';
import TeamButton from './team_button';
const {Initialization} = NativeModules;
const defaultTheme = Preferences.THEMES.default;
const extensionSvg = {
csv: ExcelSvg,
@ -70,8 +75,6 @@ export default class ExtensionPost extends PureComponent {
maxFileSize: PropTypes.number.isRequired,
navigation: PropTypes.object.isRequired,
teamId: PropTypes.string.isRequired,
token: PropTypes.string,
url: PropTypes.string,
};
static contextTypes = {
@ -227,6 +230,43 @@ export default class ExtensionPost extends PureComponent {
});
}
getAppCredentials = async () => {
try {
const credentials = await avoidNativeBridge(
() => {
return Initialization.credentialsExist;
},
() => {
return Initialization.credentials;
},
() => {
return getGenericPassword();
}
);
if (credentials) {
const passwordParsed = credentials.password.split(',');
// password == token, url
if (passwordParsed.length === 2) {
const [token, url] = passwordParsed;
if (url && url !== 'undefined' && token && token !== 'undefined') {
this.token = token;
this.url = url;
Client4.setUrl(url);
Client4.setToken(token);
await setCSRFFromCookie(url);
}
}
}
} catch (error) {
return null;
}
return null;
};
getInputRef = (ref) => {
this.input = ref;
};
@ -294,6 +334,8 @@ export default class ExtensionPost extends PureComponent {
};
initialize = async () => {
await this.getAppCredentials();
const hasPermission = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE);
let granted;
if (!hasPermission) {
@ -311,8 +353,8 @@ export default class ExtensionPost extends PureComponent {
};
loadData = async (items) => {
const {actions, maxFileSize, teamId, token, url} = this.props;
if (token && url) {
const {actions, maxFileSize, teamId} = this.props;
if (this.token && this.url) {
const text = [];
const files = [];
let totalSize = 0;
@ -379,14 +421,14 @@ export default class ExtensionPost extends PureComponent {
onPost = () => {
const {channelId, files, value} = this.state;
const {currentUserId, token, url} = this.props;
const {currentUserId} = this.props;
const data = {
channelId,
currentUserId,
files,
token,
url,
token: this.token,
url: this.url,
value,
};
@ -542,7 +584,7 @@ export default class ExtensionPost extends PureComponent {
render() {
const {formatMessage} = this.context.intl;
const {maxFileSize, token, url} = this.props;
const {maxFileSize} = this.props;
const {error, hasPermission, files, totalSize, loaded} = this.state;
if (!loaded) {
@ -555,7 +597,7 @@ export default class ExtensionPost extends PureComponent {
return this.renderErrorMessage(error);
}
if (token && url) {
if (this.token && this.url) {
if (hasPermission === false) {
const storage = formatMessage({
id: 'mobile.extension.permission',

View file

@ -16,8 +16,7 @@ import ExtensionPost from './extension_post';
function mapStateToProps(state) {
const config = getConfig(state);
const {credentials} = state.entities.general;
const {token, url} = credentials;
let channel = getCurrentChannel(state);
if (channel && channel.delete_at !== 0) {
channel = getDefaultChannel(state);
@ -29,8 +28,6 @@ function mapStateToProps(state) {
currentUserId: getCurrentUserId(state),
maxFileSize: getAllowedServerMaxFileSize(config),
teamId: getCurrentTeamId(state),
token,
url,
};
}

View file

@ -5,8 +5,6 @@ import React, {PureComponent} from 'react';
import {Provider} from 'react-redux';
import {IntlProvider} from 'react-intl';
import {Client4} from 'mattermost-redux/client';
import {getTranslations} from 'app/i18n';
import {getCurrentLocale} from 'app/selectors/i18n';
import {store} from 'app/mattermost';
@ -42,8 +40,6 @@ export default class ShareApp extends PureComponent {
this.unsubscribeFromStore();
}
this.setCredentialsForClient();
dispatch(extensionSelectTeamId(currentTeamId));
if (this.mounted) {
@ -52,16 +48,6 @@ export default class ShareApp extends PureComponent {
}
};
setCredentialsForClient() {
const state = store.getState();
const {credentials} = state.entities.general;
if (credentials.token && credentials.url) {
Client4.setToken(credentials.token);
Client4.setUrl(credentials.url);
}
}
render() {
if (!this.state.init) {
return null;