Merge branch 'master' into port-perm-checks

This commit is contained in:
Kiwi
2017-06-09 17:49:18 +07:00
committed by GitHub
4 changed files with 82 additions and 29 deletions
+9
View File
@@ -4,6 +4,7 @@ import * as actions from '../constants/auth';
import * as Storage from '../helpers/storage';
import coralApi, {base} from '../helpers/request';
import {resetWebsocket} from 'coral-framework/services/client';
import t from 'coral-framework/services/i18n';
export const showSignInDialog = () => (dispatch, getState) => {
@@ -117,6 +118,7 @@ const signInFailure = (error) => ({
export const handleAuthToken = (token) => (dispatch) => {
Storage.setItem('exp', jwtDecode(token).exp);
Storage.setItem('token', token);
dispatch({type: 'HANDLE_AUTH_TOKEN'});
};
@@ -277,6 +279,10 @@ export const logout = () => (dispatch) => {
if (!bowser.safari && !bowser.ios) {
Storage.removeItem('token');
}
// Reset the websocket.
resetWebsocket();
dispatch({type: actions.LOGOUT});
});
};
@@ -307,6 +313,9 @@ export const checkLogin = () => (dispatch) => {
dispatch(checkLoginSuccess(result.user));
// Reset the websocket.
resetWebsocket();
// Display create username dialog if necessary.
if (result.user.canEditName && result.user.status !== 'BANNED') {
dispatch(showCreateUsernameDialog());
+39 -3
View File
@@ -1,8 +1,31 @@
import ApolloClient, {addTypename} from 'apollo-client';
import {networkInterface} from './transport';
import {SubscriptionClient, addGraphQLSubscriptions} from 'subscriptions-transport-ws';
import {SUBSCRIPTION_END} from 'subscriptions-transport-ws/dist/messageTypes';
import {getAuthToken} from '../helpers/request';
let client;
let client, wsClient = null, wsClientToken = null;
export function resetWebsocket() {
if (wsClient === null) {
// Nothing to reset!
return;
}
// Unsubscribe from all the active subscriptions.
Object.keys(wsClient.subscriptions).forEach((id) => {
// Create the message.
let message = {id: parseInt(id), type: SUBSCRIPTION_END};
// Send the unsubscribe message.
wsClient.client.send(JSON.stringify(message));
});
// Close the client, this will trigger a reconnect.
wsClient.close();
}
export function getClient() {
if (client) {
@@ -10,8 +33,21 @@ export function getClient() {
}
const protocol = location.protocol === 'https:' ? 'wss' : 'ws';
const wsClient = new SubscriptionClient(`${protocol}://${location.host}/api/v1/live`, {
reconnect: true
wsClient = new SubscriptionClient(`${protocol}://${location.host}/api/v1/live`, {
reconnect: true,
connectionParams: {
get token() {
wsClientToken = getAuthToken();
// Try to get the token from localStorage. If it isn't here, it may
// be passed as a cookie.
// NOTE: THIS IS ONLY EVER EVALUATED ONCE, IN ORDER TO SEND A DIFFERNT
// TOKEN YOU MUST DISCONNECT AND RECONNECT THE WEBSOCKET CLIENT.
return wsClientToken;
}
}
});
const networkInterfaceWithSubscriptions = addGraphQLSubscriptions(
+23 -5
View File
@@ -41,16 +41,34 @@ const createSubscriptionManager = (server) => new SubscriptionServer({
pubsub,
setupFunctions,
}),
onConnect: ({token}, connection) => {
// Attach the token from the connection options if it was provided.
if (token) {
// Attach it to the upgrade request.
connection.upgradeReq.headers['authorization'] = `Bearer ${token}`;
}
},
onSubscribe: (parsedMessage, baseParams, connection) => {
// Cache the upgrade request.
let upgradeReq = connection.upgradeReq;
// Attach the context per request.
baseParams.context = () => deserializeUser(connection.upgradeReq)
.then((req) => new Context(req, pubsub))
.catch((err) => {
console.error(err);
baseParams.context = async () => {
let req;
try {
req = await deserializeUser(upgradeReq);
} catch (e) {
console.error(e);
return new Context({}, pubsub);
});
}
return new Context(req, pubsub);
};
return baseParams;
}
+11 -21
View File
@@ -1,4 +1,4 @@
const passport = require('./passport');
const cookieParser = require('cookie-parser')();
const authentication = require('../middleware/authentication');
// Session data does not automatically attach to websocket req objects.
@@ -7,32 +7,22 @@ const authentication = require('../middleware/authentication');
const deserializeUser = (req) => {
return new Promise((resolve, reject) => {
// This uses the authentication connect middleware to establish the session
// user details from the headers.
authentication(req, null, (err) => {
// Parse the cookies (if they exist?).
cookieParser(req, null, (err) => {
if (err) {
return reject(err);
}
if ('session' in req && 'passport' in req.session && 'user' in req.session.passport) {
passport.deserializeUser(req.session.passport.user, (err, user) => {
if (err) {
return reject(err);
}
req.user = user;
return resolve(req);
});
}
// Remove the user from the request (if there was one)
if (req.user) {
delete req.user;
}
// This uses the authentication connect middleware to establish the
// current user.
authentication(req, null, (err) => {
if (err) {
return reject(err);
}
// Resolve with the request (user removed possibly).
return resolve(req);
return resolve(req);
});
});
});
};