[MM-14887] Allow only jpeg, png, and bmp profile image uploads (#2715)
* Allow only for jpeg, png, and bmp profile image uploads * Add file type if missing and update error id * Update mattermost-redux commit hash * Point mattermost-redux to latest master commit
This commit is contained in:
parent
dc554bdfa7
commit
cb0e4e225a
9 changed files with 158 additions and 41 deletions
28
app/components/__snapshots__/attachment_button.test.js.snap
Normal file
28
app/components/__snapshots__/attachment_button.test.js.snap
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`AttachmentButton should match snapshot 1`] = `
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.2}
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"alignItems": "center",
|
||||
"height": 34,
|
||||
"justifyContent": "center",
|
||||
"width": 45,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Icon
|
||||
allowFontScaling={false}
|
||||
color="rgba(61,60,64,0.9)"
|
||||
name="md-add"
|
||||
size={30}
|
||||
style={
|
||||
Object {
|
||||
"marginTop": 2,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
`;
|
||||
|
|
@ -53,5 +53,6 @@ exports[`profile_picture_button should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
uploadFiles={[MockFunction]}
|
||||
validMimeTypes={Array []}
|
||||
/>
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ import {DocumentPicker} from 'react-native-document-picker';
|
|||
import ImagePicker from 'react-native-image-picker';
|
||||
import Permissions from 'react-native-permissions';
|
||||
|
||||
import {lookupMimeType} from 'mattermost-redux/utils/file_utils';
|
||||
|
||||
import {PermissionTypes} from 'app/constants';
|
||||
import {changeOpacity} from 'app/utils/theme';
|
||||
import {t} from 'app/utils/i18n';
|
||||
|
|
@ -27,6 +29,7 @@ export default class AttachmentButton extends PureComponent {
|
|||
static propTypes = {
|
||||
blurTextBox: PropTypes.func.isRequired,
|
||||
browseFileTypes: PropTypes.string,
|
||||
validMimeTypes: PropTypes.array,
|
||||
canBrowseFiles: PropTypes.bool,
|
||||
canBrowsePhotoLibrary: PropTypes.bool,
|
||||
canBrowseVideoLibrary: PropTypes.bool,
|
||||
|
|
@ -39,6 +42,7 @@ export default class AttachmentButton extends PureComponent {
|
|||
navigator: PropTypes.object.isRequired,
|
||||
onShowFileMaxWarning: PropTypes.func,
|
||||
onShowFileSizeWarning: PropTypes.func,
|
||||
onShowUnsupportedMimeTypeWarning: PropTypes.func,
|
||||
theme: PropTypes.object.isRequired,
|
||||
uploadFiles: PropTypes.func.isRequired,
|
||||
wrapper: PropTypes.bool,
|
||||
|
|
@ -47,6 +51,7 @@ export default class AttachmentButton extends PureComponent {
|
|||
|
||||
static defaultProps = {
|
||||
browseFileTypes: Platform.OS === 'ios' ? 'public.item' : '*/*',
|
||||
validMimeTypes: [],
|
||||
canBrowseFiles: true,
|
||||
canBrowsePhotoLibrary: true,
|
||||
canBrowseVideoLibrary: true,
|
||||
|
|
@ -321,7 +326,14 @@ export default class AttachmentButton extends PureComponent {
|
|||
file.fileName = fileInfo.filename;
|
||||
}
|
||||
|
||||
if (file.fileSize > this.props.maxFileSize) {
|
||||
if (!file.type) {
|
||||
file.type = lookupMimeType(file.fileName);
|
||||
}
|
||||
|
||||
const {validMimeTypes} = this.props;
|
||||
if (validMimeTypes.length && !validMimeTypes.includes(file.type)) {
|
||||
this.props.onShowUnsupportedMimeTypeWarning();
|
||||
} else if (file.fileSize > this.props.maxFileSize) {
|
||||
this.props.onShowFileSizeWarning(file.fileName);
|
||||
} else {
|
||||
this.props.uploadFiles(files);
|
||||
|
|
|
|||
71
app/components/attachment_button.test.js
Normal file
71
app/components/attachment_button.test.js
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {shallow} from 'enzyme';
|
||||
|
||||
import Preferences from 'mattermost-redux/constants/preferences';
|
||||
|
||||
import AttachmentButton from './attachment_button';
|
||||
|
||||
jest.mock('react-intl');
|
||||
|
||||
describe('AttachmentButton', () => {
|
||||
const baseProps = {
|
||||
theme: Preferences.THEMES.default,
|
||||
navigator: {},
|
||||
blurTextBox: jest.fn(),
|
||||
maxFileSize: 10,
|
||||
uploadFiles: jest.fn(),
|
||||
};
|
||||
|
||||
test('should match snapshot', () => {
|
||||
const wrapper = shallow(
|
||||
<AttachmentButton {...baseProps}/>
|
||||
);
|
||||
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should not upload file with invalid MIME type', () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
validMimeTypes: ['image/jpeg'],
|
||||
onShowUnsupportedMimeTypeWarning: jest.fn(),
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<AttachmentButton {...props}/>
|
||||
);
|
||||
|
||||
const file = {
|
||||
type: 'image/gif',
|
||||
fileSize: 10,
|
||||
fileName: 'test',
|
||||
};
|
||||
wrapper.instance().uploadFiles([file]);
|
||||
expect(props.onShowUnsupportedMimeTypeWarning).toHaveBeenCalled();
|
||||
expect(props.uploadFiles).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should upload file with valid MIME type', () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
validMimeTypes: ['image/jpeg'],
|
||||
onShowUnsupportedMimeTypeWarning: jest.fn(),
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<AttachmentButton {...props}/>
|
||||
);
|
||||
|
||||
const file = {
|
||||
type: 'image/jpeg',
|
||||
fileSize: 10,
|
||||
fileName: 'test',
|
||||
};
|
||||
wrapper.instance().uploadFiles([file]);
|
||||
expect(props.onShowUnsupportedMimeTypeWarning).not.toHaveBeenCalled();
|
||||
expect(props.uploadFiles).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
@ -74,6 +74,7 @@ exports[`edit_profile should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
onShowFileSizeWarning={[Function]}
|
||||
onShowUnsupportedMimeTypeWarning={[Function]}
|
||||
removeProfileImage={[Function]}
|
||||
theme={
|
||||
Object {
|
||||
|
|
@ -104,6 +105,13 @@ exports[`edit_profile should match snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
uploadFiles={[Function]}
|
||||
validMimeTypes={
|
||||
Array [
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/bmp",
|
||||
]
|
||||
}
|
||||
wrapper={true}
|
||||
>
|
||||
<Connect(ProfilePicture)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ import mattermostBucket from 'app/mattermost_bucket';
|
|||
import {getFormattedFileSize} from 'mattermost-redux/utils/file_utils';
|
||||
|
||||
const MAX_SIZE = 20 * 1024 * 1024;
|
||||
const VALID_MIME_TYPES = [
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'image/bmp',
|
||||
];
|
||||
const holders = {
|
||||
firstName: {
|
||||
id: t('user.settings.general.firstName'),
|
||||
|
|
@ -278,6 +283,18 @@ export default class EditProfile extends PureComponent {
|
|||
Alert.alert(fileSizeWarning);
|
||||
};
|
||||
|
||||
onShowUnsupportedMimeTypeWarning = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const fileTypeWarning = formatMessage({
|
||||
id: 'mobile.file_upload.unsupportedMimeType',
|
||||
defaultMessage: 'Only files of the following MIME type can be uploaded: {mimeTypes}',
|
||||
}, {
|
||||
mimeTypes: VALID_MIME_TYPES.join('\n'),
|
||||
});
|
||||
|
||||
Alert.alert('', fileTypeWarning);
|
||||
};
|
||||
|
||||
renderFirstNameSettings = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {config, currentUser, theme} = this.props;
|
||||
|
|
@ -500,6 +517,8 @@ export default class EditProfile extends PureComponent {
|
|||
uploadFiles={this.handleUploadProfileImage}
|
||||
removeProfileImage={this.handleRemoveProfileImage}
|
||||
onShowFileSizeWarning={this.onShowFileSizeWarning}
|
||||
onShowUnsupportedMimeTypeWarning={this.onShowUnsupportedMimeTypeWarning}
|
||||
validMimeTypes={VALID_MIME_TYPES}
|
||||
>
|
||||
<ProfilePicture
|
||||
userId={currentUser.id}
|
||||
|
|
|
|||
|
|
@ -252,6 +252,7 @@
|
|||
"mobile.file_upload.library": "Photo Library",
|
||||
"mobile.file_upload.max_warning": "Uploads limited to 5 files maximum.",
|
||||
"mobile.file_upload.video": "Video Library",
|
||||
"mobile.file_upload.unsupportedMimeType": "Only files of the following MIME type can be uploaded:\n{mimeTypes}",
|
||||
"mobile.flagged_posts.empty_description": "Flags are a way to mark messages for follow up. Your flags are personal, and cannot be seen by other users.",
|
||||
"mobile.flagged_posts.empty_title": "No Flagged Posts",
|
||||
"mobile.help.title": "Help",
|
||||
|
|
|
|||
55
package-lock.json
generated
55
package-lock.json
generated
|
|
@ -2700,7 +2700,6 @@
|
|||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"is-extendable": "^0.1.0"
|
||||
}
|
||||
|
|
@ -2745,8 +2744,7 @@
|
|||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "4.0.0",
|
||||
|
|
@ -4786,8 +4784,7 @@
|
|||
},
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
|
@ -4805,13 +4802,11 @@
|
|||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
|
@ -4824,18 +4819,15 @@
|
|||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
|
@ -4938,8 +4930,7 @@
|
|||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
|
@ -4949,7 +4940,6 @@
|
|||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
|
@ -4962,20 +4952,17 @@
|
|||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
|
@ -4992,7 +4979,6 @@
|
|||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
|
@ -5065,8 +5051,7 @@
|
|||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
|
@ -5076,7 +5061,6 @@
|
|||
"once": {
|
||||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
|
@ -5152,8 +5136,7 @@
|
|||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
|
|
@ -5183,7 +5166,6 @@
|
|||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
|
@ -5201,7 +5183,6 @@
|
|||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
|
@ -5240,13 +5221,11 @@
|
|||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -9751,8 +9730,8 @@
|
|||
"integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A=="
|
||||
},
|
||||
"mattermost-redux": {
|
||||
"version": "github:mattermost/mattermost-redux#16a39c671193db23006d848c7866adbb5cae6901",
|
||||
"from": "github:mattermost/mattermost-redux#16a39c671193db23006d848c7866adbb5cae6901",
|
||||
"version": "github:mattermost/mattermost-redux#10399546e5cd0cb2b874ebe95436a2cdefd78eb8",
|
||||
"from": "github:mattermost/mattermost-redux#10399546e5cd0cb2b874ebe95436a2cdefd78eb8",
|
||||
"requires": {
|
||||
"deep-equal": "1.0.1",
|
||||
"eslint-plugin-header": "3.0.0",
|
||||
|
|
@ -13046,8 +13025,7 @@
|
|||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
|
||||
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"braces": {
|
||||
"version": "2.3.2",
|
||||
|
|
@ -13333,8 +13311,7 @@
|
|||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
|
||||
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "3.1.10",
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
"intl": "1.2.5",
|
||||
"jail-monkey": "2.0.0",
|
||||
"jsc-android": "236355.1.1",
|
||||
"mattermost-redux": "github:mattermost/mattermost-redux#16a39c671193db23006d848c7866adbb5cae6901",
|
||||
"mattermost-redux": "github:mattermost/mattermost-redux#10399546e5cd0cb2b874ebe95436a2cdefd78eb8",
|
||||
"mime-db": "1.38.0",
|
||||
"moment-timezone": "0.5.23",
|
||||
"prop-types": "15.7.2",
|
||||
|
|
|
|||
Loading…
Reference in a new issue