Skip to content

Commit

Permalink
MM-45027 - Fix: Cloud plugin causing crash on webapp (#101)
Browse files Browse the repository at this point in the history
* prevent future webapp crashes; display server error in UI

* fix goarch for arm64
  • Loading branch information
cpoile authored Jun 13, 2022
1 parent 4f504da commit 6100ae8
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 63 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ ifneq ($(HAS_SERVER),)
mkdir -p server/dist;
cd server && env GOOS=linux GOARCH=amd64 $(GO) build $(GO_BUILD_FLAGS) -ldflags '$(LDFLAGS)' -o dist/plugin-linux-amd64;
cd server && env GOOS=darwin GOARCH=amd64 $(GO) build $(GO_BUILD_FLAGS) -ldflags '$(LDFLAGS)' -o dist/plugin-darwin-amd64;
cd server && env GOOS=darwin GOARCH=arm64 $(GO) build $(GO_BUILD_FLAGS) -ldflags '$(LDFLAGS)' -o dist/plugin-darwin-arm64;
cd server && env GOOS=windows GOARCH=amd64 $(GO) build $(GO_BUILD_FLAGS) -ldflags '$(LDFLAGS)' -o dist/plugin-windows-amd64.exe;
endif

Expand Down
1 change: 1 addition & 0 deletions plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"executables": {
"linux-amd64": "server/dist/plugin-linux-amd64",
"darwin-amd64": "server/dist/plugin-darwin-amd64",
"darwin-arm64": "server/dist/plugin-darwin-arm64",
"windows-amd64": "server/dist/plugin-windows-amd64.exe"
}
},
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/action_types/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import {id as pluginId} from '../manifest';

export const RECEIVED_USER_INSTALLS = pluginId + '_received_user_installs';
export const RECEIVED_SHOW_RHS_ACTION = pluginId + '_show_rhs';
export const UPDATE_RHS_STATE = pluginId + '_update_rhs_state';
export const SET_RHS_VISIBLE = pluginId + '_set_rhs_visible';
export const SET_SERVER_ERROR = pluginId + '_set_server_error';
37 changes: 21 additions & 16 deletions webapp/src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,24 @@ import Client from '../client';

import {id as pluginId} from '../manifest';

import {installsForUser} from 'selectors';
import {installsForUser, serverError} from 'selectors';

import {
RECEIVED_USER_INSTALLS,
RECEIVED_SHOW_RHS_ACTION,
UPDATE_RHS_STATE,
SET_RHS_VISIBLE,
SET_SERVER_ERROR,
} from '../action_types';

const CLOUD_USER_GET_TIMEOUT_MILLISECONDS = 1000 * 60; // 1 minute

export function setServerError(errorString) {
return {
type: SET_SERVER_ERROR,
error: errorString,
};
}

export function getCloudUserData(userID) {
return async (dispatch, getState) => {
if (!userID) {
Expand All @@ -28,20 +35,23 @@ export function getCloudUserData(userID) {
return {};
}

let data;
try {
data = await Client.getUserInstalls(userID);
console.log('<><> received data from /userinstalls:', data); // eslint-disable-line no-console
} catch (error) {
console.log('<><> received error from /userinstalls:', error); // eslint-disable-line no-console
if (error.status === 404) {
const data = await Client.getUserInstalls(userID);

if (data.error) {
if (data.error.status === 404) {
dispatch({
type: RECEIVED_USER_INSTALLS,
userID,
data: {last_try: Date.now()},
});
}
return {error};
dispatch(setServerError(`Status: ${data.error.status}, Message: ${data.error.message}`));
return data;
}

// Clear server error
if (serverError(getState())) {
dispatch(setServerError(''));
}

dispatch({
Expand All @@ -53,6 +63,7 @@ export function getCloudUserData(userID) {
return {data};
};
}

export function setShowRHSAction(showRHSPluginAction) {
return {
type: RECEIVED_SHOW_RHS_ACTION,
Expand All @@ -67,12 +78,6 @@ export function setRhsVisible(payload) {
};
}

export function updateRhsState(rhsState) {
return {
type: UPDATE_RHS_STATE,
state: rhsState,
};
}
export const getPluginServerRoute = (state) => {
const config = getConfig(state);

Expand Down
8 changes: 4 additions & 4 deletions webapp/src/components/sidebar_right/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import {getCurrentUserId} from 'mattermost-redux/selectors/entities/common';

import {telemetry, setRhsVisible, getCloudUserData} from '../../actions';

import {installsForUser} from '../../selectors';
import {installsForUser, serverError} from '../../selectors';

import SidebarRight from './sidebar_right.jsx';

function mapStateToProps(state) {
const id = getCurrentUserId(state);
const installs = installsForUser(state, id);
return {
id,
installs,
installs: installsForUser(state, id),
serverError: serverError(state),
};
}

Expand All @@ -30,4 +30,4 @@ function mapDispatchToProps(dispatch) {
};
}

export default connect(mapStateToProps, mapDispatchToProps)(SidebarRight);
export default connect(mapStateToProps, mapDispatchToProps)(SidebarRight);
52 changes: 28 additions & 24 deletions webapp/src/components/sidebar_right/sidebar_right.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ export function renderThumbVertical(props) {

export default class SidebarRight extends React.PureComponent {
static propTypes = {
rhsState: PropTypes.string,
id: PropTypes.string.isRequired,
installs: PropTypes.array.isRequired,
serverError: PropTypes.string.isRequired,
actions: PropTypes.shape({
setVisible: PropTypes.func.isRequired,
telemetry: PropTypes.func.isRequired,
Expand All @@ -55,16 +55,30 @@ export default class SidebarRight extends React.PureComponent {
}

render() {
let installs = this.props.installs;
console.log('<><> sidebar_right installs:', installs); // eslint-disable-line no-console
if (!installs) {
installs = [];
}
if (this.props.serverError) {
return (
<div style={style.message}>
<p>{'Received a server error'}</p>
<p>{this.props.serverError}</p>
<div style={style.serverIcon}>
<i className='fa fa-server fa-4x'/>
</div>

var noInstalls = false;
</div>
);
}

const installs = this.props.installs;
if (installs.length === 0) {
noInstalls = true;
return (
<div style={style.message}>
<p>{'There are no installations, use the /cloud create command to add an installation.'}</p>
<div style={style.serverIcon}>
<i className='fa fa-server fa-4x'/>
</div>

</div>
);
}

const entries = installs.map((install) => (
Expand Down Expand Up @@ -148,21 +162,11 @@ export default class SidebarRight extends React.PureComponent {
renderView={renderView}
className='SidebarRight'
>
{noInstalls ?
<div style={style.noInstalls}>

<p>There are no installations, use the /cloud create command to add an installation.</p>

<div style={style.serverIcon}>
<i className='fa fa-server fa-4x'/>
</div>

</div> :
<div style={style.container}>
<ul style={style.ul}>
{entries}
</ul>
</div>}
<div style={style.container}>
<ul style={style.ul}>
{entries}
</ul>
</div>
</Scrollbars>
</React.Fragment>
);
Expand Down Expand Up @@ -204,7 +208,7 @@ const style = {
display: 'inline',
backgroundColor: '#FF8C00',
},
noInstalls: {
message: {
margin: 'auto',
width: '50%',
marginTop: '50px',
Expand Down
6 changes: 3 additions & 3 deletions webapp/src/components/user_attribute/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import {bindActionCreators} from 'redux';

import {getCloudUserData} from '../../actions';

import {installsForUser} from 'selectors';
import {installsForUser, serverError} from 'selectors';

import UserAttribute from './user_attribute.jsx';

function mapStateToProps(state, ownProps) {
const id = ownProps.user ? ownProps.user.id : '';
const installs = installsForUser(state, id);

return {
id,
installs,
installs: installsForUser(state, id),
serverError: serverError(state),
};
}

Expand Down
9 changes: 3 additions & 6 deletions webapp/src/components/user_attribute/user_attribute.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export default class UserAttribute extends React.PureComponent {
static propTypes = {
id: PropTypes.string.isRequired,
installs: PropTypes.array.isRequired,
serverError: PropTypes.string.isRequired,
actions: PropTypes.shape({
getCloudUserData: PropTypes.func.isRequired,
}).isRequired,
Expand All @@ -15,13 +16,9 @@ export default class UserAttribute extends React.PureComponent {
}

render() {
let installs = this.props.installs;
console.log('<><> user_attribute installs:', installs); // eslint-disable-line no-console
if (!installs) {
installs = [];
}
const installs = this.props.installs;

if (installs.length === 0) {
if (installs.length === 0 || this.props.serverError) {
return null;
}

Expand Down
17 changes: 9 additions & 8 deletions webapp/src/reducers/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {combineReducers} from 'redux';

import {RECEIVED_USER_INSTALLS, RECEIVED_SHOW_RHS_ACTION, UPDATE_RHS_STATE, SET_RHS_VISIBLE} from '../action_types';
import {RECEIVED_USER_INSTALLS, RECEIVED_SHOW_RHS_ACTION, SET_RHS_VISIBLE, SET_SERVER_ERROR} from '../action_types';

function cloudUserInstalls(state = {}, action) {
switch (action.type) {
Expand All @@ -13,6 +13,7 @@ function cloudUserInstalls(state = {}, action) {
return state;
}
}

function rhsPluginAction(state = null, action) {
switch (action.type) {
case RECEIVED_SHOW_RHS_ACTION:
Expand All @@ -22,19 +23,19 @@ function rhsPluginAction(state = null, action) {
}
}

function rhsState(state = '', action) {
function isRhsVisible(state = false, action) {
switch (action.type) {
case UPDATE_RHS_STATE:
return action.state;
case SET_RHS_VISIBLE:
return action.payload;
default:
return state;
}
}

function isRhsVisible(state = false, action) {
function serverError(state = '', action) {
switch (action.type) {
case SET_RHS_VISIBLE:
return action.payload;
case SET_SERVER_ERROR:
return action.error;
default:
return state;
}
Expand All @@ -43,6 +44,6 @@ function isRhsVisible(state = false, action) {
export default combineReducers({
cloudUserInstalls,
rhsPluginAction,
rhsState,
isRhsVisible,
serverError,
});
3 changes: 2 additions & 1 deletion webapp/src/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ const getPluginState = (state) => state['plugins-' + pluginId] || {};
export const installsForUser = (state, id) => getPluginState(state).cloudUserInstalls[id] || [];
export const getShowRHSAction = (state) => getPluginState(state).rhsPluginAction;

export const isRhsVisible = (state) => getPluginState(state).isRhsVisible;
export const isRhsVisible = (state) => getPluginState(state).isRhsVisible;
export const serverError = (state) => getPluginState(state).serverError;

0 comments on commit 6100ae8

Please sign in to comment.