Skip to content

Commit

Permalink
fixes #260
Browse files Browse the repository at this point in the history
  • Loading branch information
mattkrick committed Sep 11, 2016
1 parent 1c90e9e commit 37814d6
Show file tree
Hide file tree
Showing 11 changed files with 50 additions and 55 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
"babel-runtime": "6.11.6",
"bcrypt": "^0.8.7",
"body-parser": "1.15.2",
"cashay": "^0.20.1",
"cashay": "^0.20.3",
"cheerio": "^0.20.0",
"compression": "1.6.2",
"cors": "2.7.1",
Expand Down
5 changes: 1 addition & 4 deletions src/universal/components/NotificationBar/NotificationBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,7 @@ const NotificationBar = (props) => {


NotificationBar.propTypes = {
activeMeetings: PropTypes.arrayOf({
link: PropTypes.string,
name: PropTypes.string
})
activeMeetings: PropTypes.array
};

styles = StyleSheet.create({
Expand Down
2 changes: 2 additions & 0 deletions src/universal/containers/Logout/LogoutContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {removeAuthToken} from 'universal/redux/authDuck';
import {reset as resetAppState} from 'universal/redux/rootDuck';
import {withRouter} from 'react-router';
import {segmentEvent} from 'universal/redux/segmentActions';
import {cashay} from 'cashay';

const logoutSuccess = {
title: 'Tootles!',
Expand All @@ -28,6 +29,7 @@ export default class LogoutContainer extends Component {
dispatch(resetAppState());
dispatch(showSuccess(logoutSuccess));
dispatch(segmentEvent('User Logout'));
cashay.clear();
if (typeof window !== 'undefined' && typeof window.analytics !== 'undefined') {
// inform segment of the logout, wipe state:
window.analytics.reset();
Expand Down
8 changes: 5 additions & 3 deletions src/universal/containers/StandardHub/StandardHubContainer.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React, {PropTypes} from 'react';
import {cashay} from 'cashay';
import {getAuthQueryString, authedOptions} from 'universal/redux/getAuthedUser';
import {getAuthQueryString, getAuthedOptions} from 'universal/redux/getAuthedUser';
import {connect} from 'react-redux';
import StandardHub from 'universal/components/StandardHub/StandardHub';

const mapStateToProps = () => {
const mapStateToProps = (state) => {
const userId = state.auth.obj.sub;
const {user} = cashay.query(getAuthQueryString, getAuthedOptions(userId)).data;
return {
user: cashay.query(getAuthQueryString, authedOptions).data.user
user
};
};

Expand Down
15 changes: 5 additions & 10 deletions src/universal/decorators/loginWithToken/loginWithToken.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import React, {PropTypes} from 'react';
import {getAuthQueryString, authedOptions} from 'universal/redux/getAuthedUser';
import {getAuthQueryString, getAuthedOptions} from 'universal/redux/getAuthedUser';
import {cashay} from 'cashay';
import {connect} from 'react-redux';
import {withRouter} from 'react-router';

const mapStateToProps = state => {
const auth = state.auth.obj;
return {
auth: state.auth.obj,
user: cashay.query(getAuthQueryString, authedOptions).data.user
user: cashay.query(getAuthQueryString, getAuthedOptions(auth.sub)).data.user
};
};

export default ComposedComponent => {
const TokenizedComp = (props) => {
const {auth, user, router} = props;
if (auth.sub && user) {
const {auth, router} = props;
if (auth.sub) {
// note if you join a team & leave it, tms will be an empty array
const isNew = !auth.hasOwnProperty('tms');
if (isNew) {
Expand All @@ -28,12 +29,6 @@ export default ComposedComponent => {

TokenizedComp.propTypes = {
auth: PropTypes.object,
user: PropTypes.shape({
email: PropTypes.string,
id: PropTypes.string,
picture: PropTypes.string,
preferredName: PropTypes.string
}),
router: PropTypes.object.isRequired
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {Component, PropTypes} from 'react';
import {showError} from 'universal/modules/notifications/ducks/notifications';
import {getAuthQueryString, authedOptions} from 'universal/redux/getAuthedUser';
import {getAuthQueryString, getAuthedOptions} from 'universal/redux/getAuthedUser';
import {cashay} from 'cashay';
import {connect} from 'react-redux';
import {withRouter} from 'react-router';
Expand All @@ -16,10 +16,10 @@ const unauthenticated = {
};

const mapStateToProps = state => {
const user = cashay.query(getAuthQueryString, authedOptions).data.user;
const userId = state.auth.obj.sub;
return {
auth: state.auth.obj,
user
user: cashay.query(getAuthQueryString, getAuthedOptions(userId)).data.user
};
};

Expand Down
20 changes: 12 additions & 8 deletions src/universal/decorators/socketWithPresence/socketWithPresence.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,18 @@ export default ComposedComponent => {

constructor(props) {
super(props);
const socket = socketCluster.connect();
socket.on('subscribe', channelName => {
const {teamId} = props.params;
if (channelName === `${PRESENCE}/${teamId}`) {
const options = {variables: {teamId}};
cashay.mutate('soundOff', options);
}
});
const {teamId} = props.params;
if (teamId) {
const socket = socketCluster.connect();
socket.on('subscribe', channelName => {
if (channelName === `${PRESENCE}/${teamId}`) {
const options = {variables: {teamId}};
cashay.mutate('soundOff', options);
}
});
} else {
// TODO add a presence listener for the /me route
}
}

render() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import LoadingView from 'universal/components/LoadingView/LoadingView';
import {withRouter} from 'react-router';
import {showError, showSuccess, showWarning} from 'universal/modules/notifications/ducks/notifications';
import {setAuthToken} from 'universal/redux/authDuck';
import {getAuthQueryString, authedOptions} from 'universal/redux/getAuthedUser';
import {getAuthQueryString, getAuthedOptions} from 'universal/redux/getAuthedUser';
import {setWelcomeActivity} from 'universal/modules/userDashboard/ducks/settingsDuck';
import jwtDecode from 'jwt-decode';
import {
Expand All @@ -18,10 +18,11 @@ import {

const mapStateToProps = (state, props) => {
const {params: {id}} = props;
const auth = state.auth.obj;
return {
auth: state.auth.obj,
auth,
inviteToken: id,
user: cashay.query(getAuthQueryString, authedOptions).data.user
user: cashay.query(getAuthQueryString, getAuthedOptions(auth.sub))
};
};

Expand Down
10 changes: 5 additions & 5 deletions src/universal/redux/getAuthedUser.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const getAuthQueryString = `
query {
user: getCurrentUser {
user @cached(type: "User") {
email,
id,
picture,
Expand Down Expand Up @@ -37,9 +37,9 @@ const updateTokenMutationHandlers = {
},
};

export const authedOptions = {
export const getAuthedOptions = (userId) => ({
op: 'getAuthedUser',
resolveCached: {user: () => userId},
mutationHandlers: updateTokenMutationHandlers,
customMutations,
localOnly: true
};
customMutations
});
2 changes: 1 addition & 1 deletion src/universal/redux/reduxSocketOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ const onConnect = (options, hocOptions, socket) => {
const onDisconnect = () => {
cashay.create({priorityTransport: null});
};
export default ({AuthEngine, socketCluster, onConnect, onDisconnect, keepAlive: Infinity});
export default ({AuthEngine, socketCluster, onConnect, onDisconnect, keepAlive: 3000});
28 changes: 11 additions & 17 deletions src/universal/redux/storageMerger.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import jwtDecode from 'jwt-decode';

export default function merger(initialState, persistedState) {
// Update this list for each new duck written
const whitelist = new Set(['auth', 'cashay', 'notifications']);
Expand All @@ -9,26 +7,22 @@ export default function merger(initialState, persistedState) {
const reducerName = persistedStateKeys[i];
if (!whitelist.has(reducerName)) continue;
const value = persistedState[reducerName];
if (reducerName === 'auth' && value) {
// Always perform a fresh decode for security's sake:
let authTokenObj = null;
try {
authTokenObj = jwtDecode(value.token);
} catch (e) {
console.warn(`unable to decode jwt: ${e}`);
continue;
}
if (authTokenObj.exp < Date.now() / 1000) {
if (reducerName === 'auth' && value && value.obj) {
if (value.obj.exp < Date.now() / 1000) {
continue;
}
}
if (reducerName === 'cashay') {
if (value && value.entities) {
// cashay now supports rehydrating sub data
if (value) {
const {User} = value.entities || {};
value.entities = User ? {User} : {};
value.result = {};

// cashay now supports rehydrating sub data, but this can't account for removed items
// remove items with unbounded growth in production
value.result.presence = undefined;
value.entities.Presence = undefined;
value.entities.Task = undefined;
// value.result.presence = undefined;
// value.entities.Presence = undefined;
// value.entities.Task = undefined;
}
}
result[reducerName] = value;
Expand Down

0 comments on commit 37814d6

Please sign in to comment.