Skip to content

Instantly share code, notes, and snippets.

@smooJitter
Created July 11, 2017 08:03
Show Gist options
  • Save smooJitter/f9d4216183e71e70ab1258626844219b to your computer and use it in GitHub Desktop.
Save smooJitter/f9d4216183e71e70ab1258626844219b to your computer and use it in GitHub Desktop.
A proposal to add meteor user to the guru context object. This is based on the apollo-meteor-integration
/*
* GraphQL rourte
*/
'use strict';
import { Meteor } from 'meteor/meteor';
import { WebApp } from 'meteor/webapp';
import { Accounts } from 'meteor/accounts-base';
import { check } from 'meteor/check';
import { graphqlExpress } from 'graphql-server-express';
export default function graphqlRoute({ app, context }) {
app.use(
'/graphql',
graphqlExpress(req => {
// get the login token from the headers request, given by the Meteor's
// network interface middleware if enabled
const loginToken = req.headers['meteor-login-token'];
// get the current user & the user id for the context
const userContext = await getUserForContext(loginToken);
// context can accept a function returning the context object
const context = typeof context === 'function'
? context(userContext)
: { ...context, ...userContext };
return {
context: {
...context,
},
};
})
);
}
export const getUserForContext = async loginToken => {
// there is a possible current user connected!
if (loginToken) {
// throw an error if the token is not a string
check(loginToken, String);
// the hashed token is the key to find the possible current user in the db
const hashedToken = Accounts._hashLoginToken(loginToken);
// get the possible current user from the database
// note: no need of a fiber aware findOne + a fiber aware call break tests
// runned with practicalmeteor:mocha if eslint is enabled
const currentUser = await Meteor.users.rawCollection().findOne({
'services.resume.loginTokens.hashedToken': hashedToken,
});
// the current user exists
if (currentUser) {
// find the right login token corresponding, the current user may have
// several sessions logged on different browsers / computers
const tokenInformation = currentUser.services.resume.loginTokens.find(
tokenInfo => tokenInfo.hashedToken === hashedToken
);
// get an exploitable token expiration date
const expiresAt = Accounts._tokenExpiration(tokenInformation.when);
// true if the token is expired
const isExpired = expiresAt < new Date();
// if the token is still valid, give access to the current user
// information in the resolvers context
if (!isExpired) {
// return a new context object with the current user & her id
return {
user: currentUser,
userId: currentUser._id,
};
}
}
}
return {};
};
// take the existing context and return a new extended context with the current
// user if relevant (i.e. valid login token)
export const addCurrentUserToContext = async (context, loginToken) => {
const userContext = await getUserForContext(loginToken);
return {
...context,
...userContext,
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment