From 7bbd689f83833acb3656c6001016e03c8efb9ce6 Mon Sep 17 00:00:00 2001 From: Barry Low Date: Fri, 26 Oct 2018 08:54:44 -0700 Subject: [PATCH] Switch authId to userId --- api/src/auth/middleware/getMember.js | 60 +++++++++++++++++++--- api/src/directives/index.js | 76 +++++++++------------------- api/src/index.js | 67 +++++------------------- 3 files changed, 89 insertions(+), 114 deletions(-) diff --git a/api/src/auth/middleware/getMember.js b/api/src/auth/middleware/getMember.js index 7d19b2d6c..611dce9f7 100644 --- a/api/src/auth/middleware/getMember.js +++ b/api/src/auth/middleware/getMember.js @@ -1,10 +1,54 @@ -const getMember = async (req, res, next, db) => { - if (!req.user) return next() - const member = await db.query.member({ - where: { authId: req.user.sub } - }) - req.user = { user: member } - next() +import { logger } from '../../logger' + +export const getMember = async (req, res, next, db) => { + if (!req.headers.userId) return next() + try { + const member = await getUser(req.headers.userId) + req.user = await member + next() + } catch (err) { + next() + } + } -module.exports = { getMember } +export const getUser = authId => { + logger.info('getUser') + logger.info(authId) + const API_URL = 'https://app-api.advancedalgos.net/graphql' + return new Promise(resolve => { + try { + const result = axios.post(API_URL, { + query: `query users_User($userId: String!) { + users_User(id: $userId){ + id + alias + email + } + }`, + variables: { + userId: authId + } + }, { + headers: { + 'Content-Type': 'application/json' + } + }) + .then(result => { + logger.info('getUser result') + logger.info(result.data) + resolve(result.data) + }) + .catch(err => { + logger.info('getUser err') + logger.info(err) + throw new Error(err) + }) + + } catch (error) { + resolve(error) + } + }) +} + +export default getUser diff --git a/api/src/directives/index.js b/api/src/directives/index.js index 8e6b925ae..b686e7bae 100644 --- a/api/src/directives/index.js +++ b/api/src/directives/index.js @@ -6,6 +6,7 @@ import { AuthenticationError, ForbiddenError } from '../errors' import { validateIdToken } from '../auth/validateIdToken' const memberLocationOnContext = 'request.user' +const userIdOnContext = 'req.userid' const bearerAccessToken = 'request.headers.authorization' const ctxMember = ctx => _get(ctx, memberLocationOnContext) @@ -29,48 +30,18 @@ const createMember = async (ctx, idToken, info) => { return member } -const isLoggedIn = async ctx => { - logger.info(`isLoggedIn 0: ${JSON.stringify(ctx.request.headers)}`) - let member = ctxMember(ctx, memberLocationOnContext) - let token = ctxToken(ctx, bearerAccessToken) - let memberToken - logger.info('isLoggedIn: ', member, token) - if (!member && token) { - let scheme, credentials - const tokenParts = token.split(' ') - if (tokenParts.length === 2) { - scheme = tokenParts[0] - credentials = tokenParts[1] - } - - if (/^Bearer$/i.test(scheme)) { - token = credentials - //verify token - try { - memberToken = await validateIdToken(token) - const authId = memberToken.sub - exists = await ctx.db.query.member({ where: { authId: authId } }) - if (!member && exists === null) { - member = await createMember(ctx, memberToken).then(res => { - return res - }) - - return member - } - return member - } catch (err) { - memberToken = false - } - } - } - if (!member) { - throw new AuthenticationError('Access token is missing or expired') - } +const isUserId = async ctx => { + logger.info(`isUserId 0: ${ctx.userId}`) + let member = ctxMember(ctx, userIdOnContext) + if (!member) { + throw new AuthenticationError('Access token is missing or expired') + } else { return member + } } -const isRequestingMemberAlsoOwner = ({ ctx, memberId, type, typeId }) => - ctx.db.exists[type]({ slug: typeId, owner: memberId }) +const isRequestingMemberAlsoOwner = ({ ctx, memberId, type, teamSlug }) => + ctx.db.exists[type]({ slug: teamSlug, owner: memberId }) const isRequestingMember = ({ ctx, memberId }) => ctx.db.exists.Member({ authId: memberId }) @@ -89,12 +60,12 @@ const assertAuth = ctx => { // Directive resolvers (apollo v1 syntax) export const directiveResolvers = { isAuthenticated: async (next, source, args, ctx) => { - let result = await isLoggedIn(ctx) + let result = await isUserId(ctx) logger.info('directive isAuthenticated: ', result) return next(result) }, hasRole: (next, source, { roles }, ctx) => { - const { role } = isLoggedIn(ctx) + const { role } = isUserId(ctx) logger.info('directive hasRole: ', role) if (roles.includes(role)) { return next() @@ -107,42 +78,41 @@ export const directiveResolvers = { source && source.id ? source : ctx.request.body.variables ? ctx.request.body.variables : { id: null } - const user = await isLoggedIn(ctx) - const memberId = user.sub + const userId = await isUserId(ctx) const isOwner = type === `Member` ? memberId === typeId - : await isRequestingMemberAlsoOwner({ ctx, memberId, type, typeId }) + : await isRequestingMemberAlsoOwner({ ctx, userId, type, typeId }) if (isOwner) { return next() } throw new ForbiddenError('Insufficient permissions') }, isOwnerOrHasRole: async (next, source, { roles, type }, ctx, ...p) => { - const { authId: memberId } = await isLoggedIn(ctx) - logger.info('directive isOwnerOrHasRole 1: ', memberId, roles, type) - if(memberId === undefined && role=== undefined) throw new Error(`Not logged in`) + const userId = await isUserId(ctx) + logger.info('directive isOwnerOrHasRole 1: ', userId, roles, type) + if(userId === undefined && role=== undefined) throw new Error(`Not logged in`) if (roles.includes(role)) { return next() } - const { authId: typeId } = ctx.request.body.variables + const { teamSlug } = ctx.request.body.variables const isOwner = await isRequestingMemberAlsoOwner({ ctx, - memberId, + userId, type, - typeId + teamSlug }) - logger.info('directive isOwnerOrHasRole 2: ', typeId, memberId, role, isOwner) + logger.info('directive isOwnerOrHasRole 2: ', teamSlug, userId, role, isOwner) if (isOwner) { return next() } const hasRole = await isRequestingMember({ ctx, - memberId, + userId, type, - typeId + teamSlug }) if(hasRole){ return next() diff --git a/api/src/index.js b/api/src/index.js index 47bb9435e..faa7c62f0 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -14,7 +14,7 @@ import parser from 'fast-xml-parser' import axios from 'axios' import checkJwt from './auth/middleware/jwt' -import { getMember } from './auth/middleware/getMember' +import { getMember, getUser } from './auth/middleware/getMember' import { validateIdToken } from './auth/validateIdToken' import { schemaDirectives } from './directives' @@ -32,25 +32,25 @@ const GRAPHQL_SUBSCRIPTIONS = '/graphql' const PORT = 4001 const NODE_ENV = 'development' -const createMember = async function (ctx, info, idToken) { - logger.info('createMember', idToken) +const createMember = async function (ctx, info, authId) { + logger.info('createMember', authId) const member = await ctx.db.mutation.upsertMember({ where: { - authId: idToken.sub, + authId: authId, }, create: { - authId: idToken.sub, + authId: authId, alias: idToken.nickname }, update: { - authId: idToken.sub, + authId: authId, alias: idToken.nickname } }, info) return member } -const ctxMember = ctx => ctx.request.user +const ctxMember = ctx => ctx.user const resolvers = { Query: { @@ -124,12 +124,12 @@ const resolvers = { logger.debug('authenticat.validateIdToken err: ', err) throw new Error(err.message) } - const authId = memberToken.sub + const authId = ctx.userId let member = await ctx.db.query.member({ where: { authId } }, info) if (!member) { try { - return createMember(ctx, info, memberToken) + return createMember(ctx, info, authId) } catch (error) { throw new Error(error.message) } @@ -168,18 +168,15 @@ const resolvers = { logger.info('createTeam ctx.request.user:') logger.info(ctx.request.user) - const authId = ctx.request.user.sub + const authId = ctx.userId - const encodedAuthId = encodeURI(authId) - const encodedURL = `https://users-api.advancedalgos.net/graphql?query=%7B%0A%20%20userByAuthId(authId:%20%22${authId}%22)%20%7B%0A%20%20%20%20id%0A%20%20%20%20email%0A%20%20%20%20alias%0A%20%20%7D%0A%7D%0A` - const decodedURL = decodeURI(encodedURL) return getUser(authId) .then(async result => { logger.info('axios:') logger.info(result) - const alias = result.data.users_UserByAuthId.alias - const email = result.data.users_UserByAuthId.email + const alias = result.data.users_User.alias + const email = result.data.users_User.email const avatar = 'https://aadevelop.blob.core.windows.net/module-teams/module-default/aa-avatar-default.png' const banner = 'https://aadevelop.blob.core.windows.net/module-teams/module-default/aa-banner-default.png' @@ -273,44 +270,7 @@ const resolvers = { } } -const getUser = authId => { - logger.info('getUser') - logger.info(authId) - const API_URL = 'https://app-api.advancedalgos.net/graphql' - return new Promise(resolve => { - try { - const result = axios.post(API_URL, { - query: `query users_UserByAuthId($authId: String!) { - users_UserByAuthId(authId: $authId){ - id - alias - email - } - }`, - variables: { - authId: authId - } - }, { - headers: { - 'Content-Type': 'application/json' - } - }) - .then(result => { - logger.info('getUser result') - logger.info(result.data) - resolve(result.data) - }) - .catch(err => { - logger.info('getUser err') - logger.info(err) - throw new Error(err) - }) - } catch (error) { - resolve(error) - } - }) -} const db = new Prisma({ fragmentReplacements: extractFragmentReplacements(resolvers), @@ -332,7 +292,7 @@ const connectionMiddlewares = [ next() } }, - // (req, res, done) => getMember(req, res, done, db) + (req, res, done) => getUser(req, res, done, db) ] app.post(GRAPHQL_ENDPOINT, ...connectionMiddlewares) @@ -365,6 +325,7 @@ const server = createApolloServer(app, { ...req , token: req.headers, user: req.user, + userId: req.headers.userid, db, pubsub })