Merge branch 'bug/api-delete-member'

This commit is contained in:
Barry Low committed 2018-09-04 00:57:46 -07:00
commit 2aec42485c
6 files changed
+54 -20

No files matched your search

+14 -9
View File
@@ -73,7 +73,7 @@ const isLoggedIn = async ctx => {
console.log('member: ', await member)
if (!token && !member) {
if (!member) {
throw new Error(`Not logged in`)
}
return member
@@ -81,17 +81,18 @@ const isLoggedIn = async ctx => {
const isRequestingMemberAlsoOwner = ({ ctx, memberId, type, typeId }) =>
ctx.db.exists[type]({ id: typeId, member: { id: memberId } })
const isRequestingMember = ({ ctx, memberId }) => ctx.db.exists.Member({ id: memberId })
ctx.db.exists[type]({ id: typeId, owner: { auth0id: memberId } })
const isRequestingMember = ({ ctx, memberId }) => ctx.db.exists.Member({ auth0id: memberId })
const directiveResolvers = {
isAuthenticated: async (next, source, args, ctx) => {
let result = await isLoggedIn(ctx)
console.log('isAuthenticated: ', result)
return next()
console.log('directive isAuthenticated: ', result)
return next(result)
},
hasRole: (next, source, { roles }, ctx) => {
const { role } = isLoggedIn(ctx)
console.log('directive hasRole: ', role)
if (roles.includes(role)) {
return next()
}
@@ -102,30 +103,34 @@ const directiveResolvers = {
source && source.id
? source
: ctx.request.body.variables ? ctx.request.body.variables : { id: null }
const { id: memberId } = isLoggedIn(ctx)
const { auth0id: memberId } = await isLoggedIn(ctx)
console.log('directive isOwner 0: ', type, typeId, memberId)
const isOwner =
type === `Member`
? memberId === typeId
: await isRequestingMemberAlsoOwner({ ctx, memberId, type, typeId })
console.log('directive isOwner 1: ', source, isOwner, type, typeId, memberId)
if (isOwner) {
return next()
}
throw new Error(`Unauthorized, must be owner`)
},
isOwnerOrHasRole: async (next, source, { roles, type }, ctx, ...p) => {
const { id: memberId, role } = isLoggedIn(ctx)
const { auth0id: memberId } = await isLoggedIn(ctx)
console.log('directive isOwnerOrHasRole 1: ', memberId, roles, type)
if(memberId === undefined && role=== undefined) throw new Error(`Not logged in`)
if (roles.includes(role)) {
return next()
}
const { id: typeId } = ctx.request.body.variables
const { auth0id: typeId } = ctx.request.body.variables
const isOwner = await isRequestingMemberAlsoOwner({
ctx,
memberId,
type,
typeId
})
console.log('directive isOwnerOrHasRole 2: ', typeId, memberId, role, isOwner)
if (isOwner) {
return next()
}
+21 -3
View File
@@ -125,6 +125,12 @@ const resolvers = {
async owner(parent, args, ctx, info) {
console.log('resolver.query.owner ctx: ', ctxMember(ctx))
return ctx.db.query.member({ where: { id: ctxMember(ctx).auth0id } }, info)
.catch((res) => {
console.log('createTeam error: ', res)
const errors = res.graphQLErrors.map((error) => {
return error.message
})
})
},
members: forwardTo('db')
},
@@ -155,7 +161,7 @@ const resolvers = {
return member
},
async createTeam(parent, { name, slug, owner }, ctx, info) {
ctx.db.mutation.createTeam({
return ctx.db.mutation.createTeam({
data: {
name: name,
slug: slug,
@@ -163,9 +169,21 @@ const resolvers = {
members: {create: {role: 'OWNER', member: {connect: {auth0id: owner}}}}
}
}, info)
.catch((res) => {
console.log('createTeam error: ', res)
const errors = res.graphQLErrors.map((error) => {
return error.message
})
})
},
async deleteTeam(parent, { id, owner }, ctx, info) {
ctx.db.mutation.deleteTeam({ where: { id } }, info)
async deleteTeam(parent, { id }, ctx, info) {
return ctx.db.mutation.deleteTeam({ where: { id } }, info)
.catch((res) => {
console.log('deleteTeam error: ', res)
const errors = res.graphQLErrors.map((error) => {
return error.message
})
})
}
}
}
+1 -1
View File
@@ -18,7 +18,7 @@ type Query {
type Mutation {
authenticate(idToken: String!): Member
createTeam(name: String!, slug: String, owner: String): Team @isAuthenticated
deleteTeam(id: ID!): Team @isOwnerOrHasRole(type: "Member", roles: ["OWNER"])
deleteTeam(id: ID!): Team @isAuthenticated @isOwner(type: "Team")
updateProfile(data: MemberProfileInput): Member @isAuthenticated
}
+14 -3
View File
@@ -8,6 +8,7 @@ import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { ApolloLink, concat, split, Observable } from 'apollo-link'
import { onError } from 'apollo-link-error'
import { setContext } from 'apollo-link-context'
import { WebSocketLink } from 'apollo-link-ws'
import { SubscriptionClient } from 'subscriptions-transport-ws'
import { getMainDefinition } from 'apollo-utilities'
@@ -65,7 +66,7 @@ const link = split(
httpLink
)
const authLink = onError(({ graphQLErrors, networkError, operation, forward }) => {
const authRetryLink = onError(({ graphQLErrors, networkError, operation, forward }) => {
if (graphQLErrors) {
// User access token has expired
// console.log('authLink: ', graphQLErrors) // check for error message to intercept and resend with Auth0 access token
@@ -103,14 +104,24 @@ const authLink = onError(({ graphQLErrors, networkError, operation, forward }) =
}
})
const linkWithAuth = concat(authLink, link)
const authLink = setContext((_, { headers }) => {
// get the authentication token from local storage if it exists
const token = window.localStorage.getItem('access_token')
// return the headers to the context so httpLink can read them
return {
headers: {
...headers,
Authorization: token ? `Bearer ${token}` : ``
}
}
})
let apolloClient
const cache = new InMemoryCache().restore(window.__APOLLO_STATE__)
export const client = new ApolloClient({
link: linkWithAuth,
link: ApolloLink.from([authRetryLink, authLink, link]),
cache,
connectToDevTools: true
})
@@ -7,7 +7,7 @@ import { DeleteTeamMutation } from '../graphql/DeleteTeamMutation'
import { client } from '../../../index'
import { mergeDeep } from '../../../utils/js-helpers'
import { mergeDeep, validObject } from '../../../utils/js-helpers'
export const team = {
form: ({ form, message }) => state => {
@@ -203,10 +203,10 @@ export const team = {
return actions.form({ form: 'deleteTeamError', message: errors })
})
if (result.data.deleteTeam.id !== null) {
if (validObject(result, 'data') && result.data.deleteTeam !== null) {
return actions.deleteTeamSuccess({ name: '' })
} else {
return actions.form({ form: 'deleteTeamError', message: 'No team found' })
return actions.form({ form: 'deleteTeamError', message: result })
}
},
deleteTeamSuccess: profile => [
@@ -26,7 +26,7 @@ export const TeamPanel = props => (state, actions) => {
if (team[0].node.name !== '' && team[0].node.name !== null) {
const initial = team[0].node.name.substring(0, 1)
return (
<div class='section' key='teamList' class='is-marginless is-paddingless'>
<div class='section' key='teamPanel' class='is-marginless is-paddingless'>
<h2 class='title is-size-4 m-t-1'>Team</h2>
{team[0].node.profile !== null && team[0].node.profile.avatar !== '' ? (
<div class='image is-32x32 avatar'>