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:
parent
03d06676f8
commit
c3c3d85248
4 changed files with 53 additions and 28 deletions
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue