refactor resolvers
This commit is contained in:
1 parent
4ae50ab3f2
commit
2449c642d2
21 files changed
+336
-325
No files matched your search
+5
-1
@@ -1,3 +1,7 @@
|
||||
{
|
||||
"presets": ["@babel/preset-env"]
|
||||
"presets": ["@babel/preset-env"],
|
||||
"plugins": [
|
||||
"@babel/plugin-proposal-throw-expressions",
|
||||
["@babel/plugin-proposal-class-properties", { "loose": true }]
|
||||
]
|
||||
}
|
||||
Generated
+42
@@ -575,6 +575,20 @@
|
||||
"@babel/plugin-syntax-async-generators": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-proposal-class-properties": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.1.0.tgz",
|
||||
"integrity": "sha512-/PCJWN+CKt5v1xcGn4vnuu13QDoV+P7NcICP44BoonAJoPSGwVkgrXihFIQGiEjjPlUDBIw1cM7wYFLARS2/hw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-function-name": "^7.1.0",
|
||||
"@babel/helper-member-expression-to-functions": "^7.0.0",
|
||||
"@babel/helper-optimise-call-expression": "^7.0.0",
|
||||
"@babel/helper-plugin-utils": "^7.0.0",
|
||||
"@babel/helper-replace-supers": "^7.1.0",
|
||||
"@babel/plugin-syntax-class-properties": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-proposal-json-strings": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.0.0.tgz",
|
||||
@@ -602,6 +616,16 @@
|
||||
"@babel/plugin-syntax-optional-catch-binding": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-proposal-throw-expressions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-throw-expressions/-/plugin-proposal-throw-expressions-7.0.0.tgz",
|
||||
"integrity": "sha512-CA2EUiwnbXrsdV4hy3jYghm91WaL7zL7xYfu628dyItRr6gylbRxshghGEK/Hhm//rR58N3PBmEeuYqSW57IUQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-plugin-utils": "^7.0.0",
|
||||
"@babel/plugin-syntax-throw-expressions": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-proposal-unicode-property-regex": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0.tgz",
|
||||
@@ -620,6 +644,15 @@
|
||||
"@babel/helper-plugin-utils": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-syntax-class-properties": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.0.0.tgz",
|
||||
"integrity": "sha512-cR12g0Qzn4sgkjrbrzWy2GE7m9vMl/sFkqZ3gIpAQdrvPDnLM8180i+ANDFIXfjHo9aqp0ccJlQ0QNZcFUbf9w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-plugin-utils": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-syntax-json-strings": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.0.0.tgz",
|
||||
@@ -644,6 +677,15 @@
|
||||
"@babel/helper-plugin-utils": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-syntax-throw-expressions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-throw-expressions/-/plugin-syntax-throw-expressions-7.0.0.tgz",
|
||||
"integrity": "sha512-/5uORdWlPta/ALhI5zKtm0Y9vAYOa7HJMML0OnCGk9XZA4hpGjb0Xjt/OVDCJVawC/4FrlAGCHOaj9BtWeVDvg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/helper-plugin-utils": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/plugin-transform-arrow-functions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0.tgz",
|
||||
|
||||
@@ -37,7 +37,10 @@
|
||||
"winston": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-class-properties": "^7.1.0",
|
||||
"@babel/plugin-proposal-throw-expressions": "^7.0.0",
|
||||
"graphql-cli": "^2.16.5",
|
||||
"lodash.merge": "^4.6.1",
|
||||
"npm-run-all": "4.1.3",
|
||||
"prisma": "^1.18.1"
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
const jwksClient = require('jwks-rsa')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const jwks = jwksClient({
|
||||
cache: true,
|
||||
rateLimit: true,
|
||||
jwksRequestsPerMinute: 1,
|
||||
jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json`
|
||||
})
|
||||
|
||||
const validateIdToken = idToken =>
|
||||
new Promise((resolve, reject) => {
|
||||
const { header, payload } = jwt.decode(idToken, { complete: true })
|
||||
if (!header || !header.kid || !payload) reject(new Error('Invalid Token'))
|
||||
jwks.getSigningKey(header.kid, (err, key) => {
|
||||
if (err) reject({ error: `Error getting signing key: ${err.message}` })
|
||||
jwt.verify(
|
||||
idToken,
|
||||
key.publicKey,
|
||||
{ algorithms: ['RS256'] },
|
||||
(err, decoded) => {
|
||||
if (err) reject('jwt verify error: ' + err.message)
|
||||
resolve(decoded)
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
module.exports = { validateIdToken }
|
||||
@@ -1,9 +1,6 @@
|
||||
import { SchemaDirectiveVisitor } from 'apollo-server-express'
|
||||
import _get from 'lodash.get'
|
||||
import { logger } from '../logger'
|
||||
|
||||
import { AuthenticationError, ForbiddenError } from '../errors'
|
||||
import { validateIdToken } from '../auth/validateIdToken'
|
||||
import { logger, AuthenticationError } from '../logger'
|
||||
|
||||
const memberLocationOnContext = 'request.user'
|
||||
const userIdOnContext = 'req.userid'
|
||||
@@ -70,7 +67,7 @@ export const directiveResolvers = {
|
||||
if (roles.includes(role)) {
|
||||
return next()
|
||||
}
|
||||
throw new ForbiddenError('Insufficient permissions')
|
||||
throw new AuthenticationError('Insufficient permissions')
|
||||
},
|
||||
isOwner: async (next, source, { type }, ctx) => {
|
||||
logger.info('directive isOwner: ', source, type, ctx)
|
||||
@@ -86,7 +83,7 @@ export const directiveResolvers = {
|
||||
if (isOwner) {
|
||||
return next()
|
||||
}
|
||||
throw new ForbiddenError('Insufficient permissions')
|
||||
throw new AuthenticationError('Insufficient permissions')
|
||||
},
|
||||
isOwnerOrHasRole: async (next, source, { roles, type }, ctx, ...p) => {
|
||||
const userId = await isUserId(ctx)
|
||||
@@ -117,7 +114,7 @@ export const directiveResolvers = {
|
||||
if(hasRole){
|
||||
return next()
|
||||
}
|
||||
throw new ForbiddenError('Insufficient permissions')
|
||||
throw new AuthenticationError('Insufficient permissions')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,17 @@
|
||||
export const createMember = async function (ctx, info, authId) {
|
||||
logger.info('createMember', authId)
|
||||
const member = await ctx.db.mutation.upsertMember({
|
||||
where: {
|
||||
authId: authId,
|
||||
},
|
||||
create: {
|
||||
authId: authId,
|
||||
alias: idToken.nickname
|
||||
},
|
||||
update: {
|
||||
authId: authId,
|
||||
alias: idToken.nickname
|
||||
}
|
||||
}, info)
|
||||
return member
|
||||
}
|
||||
Whitespace-only changes.
Whitespace-only changes.
@@ -0,0 +1,143 @@
|
||||
import { getUser } from '../../../middleware/getMember'
|
||||
|
||||
import { sendTeamMemberInvite, sendTeamCreateConfirmation, verifyInviteToken } from '../../..//email/sendgrid'
|
||||
|
||||
import TEAM_FB_FRAGMENT from '../../fragments/TeamFBFragment'
|
||||
|
||||
import { logger } from '../../../logger'
|
||||
|
||||
export const resolvers = {
|
||||
Mutation: {
|
||||
async sendMemberInviteSG(parent, { email, teamId }, ctx, info) {
|
||||
const team = await ctx.db.query.team({ where: { id: teamId } }, TEAMS_FRAGMENT)
|
||||
const addMember = await ctx.db.mutation.upsertTeamMembers({
|
||||
where:{email: email},
|
||||
create:{role:'MEMBER', email:email, team: {connect: {id: teamId}}, status:{create:{status: 'INVITED', reason: `Invited by ${team.members[0].member.alias}`}}},
|
||||
update:{role: 'MEMBER', email: email, team: {connect: {id: teamId}}, status:{create:{status: 'INVITED', reason: `Invite resent by ${team.members[0].member.alias}`}}}},
|
||||
`{ id }`)
|
||||
const sendInvite = await sendTeamMemberInvite(email, team)
|
||||
return sendInvite
|
||||
},
|
||||
async verifyTeamInvite(parent, { token }, ctx, info) {
|
||||
let verifiedToken = null
|
||||
let team = null
|
||||
try {
|
||||
verifiedToken = await verifyInviteToken(token)
|
||||
team = {
|
||||
email: verifiedToken.email,
|
||||
team: {
|
||||
slug: verifiedToken.team
|
||||
}
|
||||
}
|
||||
logger.info('verifyTeamInvite.token: ', await verifiedToken)
|
||||
} catch (err) {
|
||||
logger.debug('verifyTeamInvite. err: ', err)
|
||||
throw new Error(err.message)
|
||||
}
|
||||
return team
|
||||
},
|
||||
async createTeam(parent, { name, slug, botName, botSlug }, ctx, info) {
|
||||
logger.info('createTeam ctx.request.user:')
|
||||
logger.info(ctx.request.user)
|
||||
|
||||
const authId = ctx.userId
|
||||
|
||||
return getUser(authId)
|
||||
.then(async result => {
|
||||
logger.info('axios:')
|
||||
logger.info(result)
|
||||
|
||||
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'
|
||||
|
||||
const createTeamUrl = encodeURI(`${slug}/${name}/${alias}/${botSlug}/${botName}`)
|
||||
logger.info('createTeamUrl:')
|
||||
logger.info(JSON.stringify(await createTeamUrl))
|
||||
|
||||
const platformUrl = 'https://develop.advancedalgos.net/AABrowserAPI/teamSetup/'
|
||||
// const platformUrl = 'http://localhost:1337/AABrowserAPI/teamSetup/'
|
||||
|
||||
logger.info(`${platformUrl}${createTeamUrl}/${authId}`)
|
||||
const createPlatformTeam = await axios.get(`${platformUrl}${createTeamUrl}/${authId}`)
|
||||
.then((result) => {
|
||||
console.log('createPlatformTeam result:', result.data)
|
||||
if(result.data.message === 'Team Name already taken'){
|
||||
return result.data.message
|
||||
}
|
||||
if(result.data.result === 'Fail'){
|
||||
return result.data.message
|
||||
}
|
||||
return result
|
||||
})
|
||||
.catch(err =>{
|
||||
logger.debug('createPlatformTeam err:')
|
||||
logger.debug(err)
|
||||
throw new Error(err)
|
||||
})
|
||||
console.log('createPlatformTeam returned: ', await createPlatformTeam)
|
||||
if(await createPlatformTeam === 'Team Name already taken'){
|
||||
return createPlatformTeam
|
||||
}
|
||||
|
||||
const existingMember = await ctx.db.query.member({ where: { authId } }, `{id}`)
|
||||
.catch((err) => {
|
||||
logger.debug(err, 'existingMember error: ')
|
||||
return err
|
||||
})
|
||||
|
||||
logger.info('existingMember:')
|
||||
logger.info(await existingMember)
|
||||
|
||||
let createTeam
|
||||
if(existingMember.id !== null){
|
||||
logger.info('createTeam with existingMember:')
|
||||
createTeam = await ctx.db.mutation.createTeam({ data: {name: name, slug: slug, owner: authId, members: {create: {member: {connect: {authId: authId}}, role: 'OWNER', status: { create: { status: 'ACTIVE', reason: `Connected to Team ${name}`}}}}, profile: {create: {avatar: avatar, banner: banner}}, fb: {create: {name: botName, slug: botSlug, kind:'TRADER', avatar: avatar, status: {create: {status: 'ACTIVE', reason: "Cloned on team creation"}}}}, status: {create: {status: 'ACTIVE', reason:"Team created"}}} }, TEAMS_FRAGMENT)
|
||||
.catch((err) => {
|
||||
logger.debug(err, 'createTeamMutation error: ')
|
||||
return err
|
||||
})
|
||||
} else {
|
||||
logger.info('createTeam without existingMember:')
|
||||
createTeam = await ctx.db.mutation.createTeam({ data: {name: name, slug: slug, owner: authId, members: {create: {member: {create: {authId: authId, alias: alias, visible:'true', status: { create: { status: 'ACTIVE', reason: `Created team ${name}`}}}}, role: 'OWNER', status: { create: { status: 'ACTIVE', reason: `Created with Team ${name}`}}}}, profile: {create: {avatar: avatar, banner: banner}}, fb: {create: {name: botName, slug: botSlug, kind:'TRADER', avatar: avatar, status: {create: {status: 'ACTIVE', reason: "Cloned on team creation"}}}}, status: {create: {status: 'ACTIVE', reason:"Team created"}}} }, TEAMS_FRAGMENT)
|
||||
.catch((err) => {
|
||||
logger.debug(err, 'createTeamMutation error: ')
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// sendTeamCreateConfirmation(email, name, botName)
|
||||
|
||||
return createTeam
|
||||
})
|
||||
.catch((err) => {
|
||||
logger.debug('createTeam error: ')
|
||||
return err
|
||||
})
|
||||
},
|
||||
async updateTeamProfile(parent, { slug, owner, description, motto, avatar, banner }, ctx, info) {
|
||||
return ctx.db.mutation.updateTeam({data:{profile: {update: {description: description, motto: motto, avatar: avatar, banner: banner}}}, where:{slug: slug}}, TEAMS_FRAGMENT)
|
||||
.catch((err) => {
|
||||
logger.debug('createTeam error: ', err)
|
||||
return err
|
||||
})
|
||||
},
|
||||
async updateFB(parent, { fbId, avatar}, ctx, info) {
|
||||
return ctx.db.mutation.updateFinancialBeings({data:{avatar:avatar}, where:{id:fbId}}, info)
|
||||
.catch((err) => {
|
||||
logger.debug('createTeam error: ', err)
|
||||
return err
|
||||
})
|
||||
},
|
||||
async deleteTeam(parent, { slug }, ctx, info) {
|
||||
return ctx.db.mutation.deleteTeam({ where: { slug } }, info)
|
||||
.catch((res) => {
|
||||
logger.info('deleteTeam error: ', res)
|
||||
const errors = res.graphQLErrors.map((error) => {
|
||||
return error.message
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { logger, AuthentificationError, DatabaseError } from '../../../logger'
|
||||
|
||||
export const member = async (parent, arg, ctx, info) => {
|
||||
logger.info(ctx.request.userId, ' --> resolver.member')
|
||||
const authId = ctx.request.userId
|
||||
if (!authId) {
|
||||
throw new AuthentificationError()
|
||||
}
|
||||
return ctx.db.query.member({ where: { authId: arg.authId } }, info)
|
||||
.catch(err => {
|
||||
logger.debug('resolver.member error: ')
|
||||
logger.debug(err)
|
||||
throw new DatabaseError(`Member Data Error: ${err.message}`)
|
||||
})
|
||||
}
|
||||
|
||||
export const owner = async (parent, args, ctx, info) => {
|
||||
logger.info('resolver.query.owner ctx: ')
|
||||
const authId = ctx.request.userId
|
||||
if (!authId) {
|
||||
return throw new AuthentificationError()
|
||||
}
|
||||
return ctx.db.query.member({ where: { authId: authId } }, info)
|
||||
.catch(err => {
|
||||
logger.debug('resolver.owner error: ')
|
||||
logger.debug(err)
|
||||
throw new DatabaseError(`Member Data Error: ${err.message}`)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { logger } from '../../../logger'
|
||||
|
||||
import TEAMS_CONNECTIONS_FRAGMENT from '../../fragments/TeamsConnectionsFragment'
|
||||
import TEAMS_FRAGMENT from '../../fragments/TeamsFragment'
|
||||
|
||||
export const teams = async (parent, args, ctx, info) => {
|
||||
logger.info('teams: ', ctx.request.res)
|
||||
return ctx.db.query.teamsConnection({}, TEAMS_CONNECTIONS_FRAGMENT)
|
||||
}
|
||||
|
||||
export const teamById = async (parent, { id }, ctx, info) => {
|
||||
return ctx.db.query.team({ where: { id } }, info)
|
||||
}
|
||||
|
||||
export const teamByName = async (parent, { name }, ctx, info) => {
|
||||
return ctx.db.query.team({ where: { name: name } }, `{ name }`)
|
||||
}
|
||||
|
||||
export const teamWithRole = async (parent, { teamId, role }, ctx, info) => {
|
||||
return ctx.db.query.teamsConnection({where: {AND: [{id: teamId},{members_some:{role: role}}]}, first:1}, info)
|
||||
}
|
||||
|
||||
export const teamsByOwner = async (parent, { ownerId }, ctx, info) => {
|
||||
logger.info('teamsByOwner')
|
||||
logger.info(ctx.req.headers)
|
||||
logger.info(ctx.req.token)
|
||||
return ctx.db.query.teams({where: { owner: ownerId }, orderBy:'updatedAt_DESC'}, TEAMS_FRAGMENT)
|
||||
}
|
||||
|
||||
export const teamsByRole = async (parent, args, ctx, info) => {
|
||||
const authId = ctx.request.userId
|
||||
let teamAdmin
|
||||
try {
|
||||
teamAdmin= await ctx.db.query.teams({where: {members_some: {AND: [{member: {authId: authId}, role_not:'MEMBER'}]}}}, TEAMS_FRAGMENT)
|
||||
} catch (err) {
|
||||
logger.debug('teamsByRole error: ')
|
||||
logger.debug(err)
|
||||
const errors = res.graphQLErrors.map((error) => {
|
||||
return error.message
|
||||
})
|
||||
return errors
|
||||
}
|
||||
logger.info('teamsByRole teamAdmin: ', teamAdmin)
|
||||
return teamAdmin
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { logger } from '../../../logger'
|
||||
|
||||
export const fbByTeamMember = async (parent, args, ctx, info) => {
|
||||
logger.info('fbByTeamMember: ', args, ctx.request, ctx.request.res.req.user)
|
||||
const authId = ctx.request.userId
|
||||
let teamMemberFB = await ctx.db.query.teams({where: {members_some: {AND: [{member: {authId: authId}}]}}, orderBy: 'updatedAt_DESC'}, TEAM_FB_FRAGMENT)
|
||||
logger.info('fbByTeamMember response: ', await teamMemberFB[0])
|
||||
return teamMemberFB[0]
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { logger } from '../../../logger'
|
||||
|
||||
import { member, owner } from './Member'
|
||||
import { teams, teamById, teamByName, teamWithRole, teamsByOwner, teamsByRole } from './Team'
|
||||
import{ fbByTeamMember } from './TeamMember'
|
||||
|
||||
export const resolvers = {
|
||||
Query: {
|
||||
member: (parent, arg, ctx, info) => member(parent, arg, ctx, info),
|
||||
teams: (parent, arg, ctx, info) => teams(parent, arg, ctx, info),
|
||||
teamById: (parent, arg, ctx, info) => teamById(parent, arg, ctx, info),
|
||||
teamByName: (parent, arg, ctx, info) => teamByName(parent, arg, ctx, info),
|
||||
teamWithRole: (parent, arg, ctx, info) => teamWithRole(parent, arg, ctx, info),
|
||||
teamsByOwner: (parent, arg, ctx, info) => teamsByOwner(parent, arg, ctx, info),
|
||||
teamsByRole: (parent, arg, ctx, info) => teamsByRole(parent, arg, ctx, info),
|
||||
owner: (parent, arg, ctx, info) => owner(parent, arg, ctx, info),
|
||||
fbByTeamMember: (parent, arg, ctx, info) => fbByTeamMember(parent, arg, ctx, info)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import merge from 'lodash.merge'
|
||||
|
||||
import { resolvers as queryResolvers } from './Query'
|
||||
import { resolvers as mutationResolvers } from './Mutation'
|
||||
|
||||
const resolvers = merge(queryResolvers, mutationResolvers)
|
||||
@@ -1,4 +1,4 @@
|
||||
# import Query.TeamConnection, Team from "./generated/prisma.graphql"
|
||||
# import Query.TeamConnection, Team from "../generated/prisma.graphql"
|
||||
|
||||
directive @isAuthenticated on QUERY | FIELD | MUTATION
|
||||
directive @hasRole(roles: [String]) on QUERY | FIELD | MUTATION
|
||||
@@ -15,8 +15,7 @@ type Query {
|
||||
teamsByRole: [Team!]! @isAuthenticated
|
||||
fbByTeamMember: Team @isAuthenticated
|
||||
owner: Member @isAuthenticated
|
||||
currentMember: Member @isAuthenticated
|
||||
member(authId: String!): Member @isAuthenticated
|
||||
member: Member @isAuthenticated
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
@@ -35,18 +34,14 @@ fragment MemberInfo on Member {
|
||||
id
|
||||
authId
|
||||
alias
|
||||
isActive
|
||||
profile {
|
||||
...MemberProfileInfo
|
||||
visible
|
||||
status {
|
||||
...MemberStatusInfo
|
||||
}
|
||||
}
|
||||
|
||||
fragment MemberProfileInfo on MemberProfile {
|
||||
firstName
|
||||
lastName
|
||||
email
|
||||
avatar
|
||||
role {
|
||||
name
|
||||
}
|
||||
fragment MemberStatusInfo on MemberStatus {
|
||||
status
|
||||
reason
|
||||
createdAt
|
||||
}
|
||||
+4
-274
@@ -13,17 +13,10 @@ import { importSchema } from 'graphql-import'
|
||||
import parser from 'fast-xml-parser'
|
||||
import axios from 'axios'
|
||||
|
||||
import checkJwt from './auth/middleware/jwt'
|
||||
import { getMember, getUser } from './auth/middleware/getMember'
|
||||
import { validateIdToken } from './auth/validateIdToken'
|
||||
import { resolvers } from './graphql/resolvers'
|
||||
|
||||
import { schemaDirectives } from './directives'
|
||||
|
||||
import { sendTeamMemberInvite, sendTeamCreateConfirmation, verifyInviteToken } from './email/sendgrid'
|
||||
|
||||
import TEAMS_FRAGMENT from './graphql/TeamsFragment'
|
||||
import TEAMS_CONNECTIONS_FRAGMENT from './graphql/TeamsConnectionsFragment'
|
||||
import TEAM_FB_FRAGMENT from './graphql/TeamFBFragment'
|
||||
|
||||
import pubsub from './pubsub'
|
||||
import { logger } from './logger'
|
||||
|
||||
@@ -32,249 +25,6 @@ const GRAPHQL_SUBSCRIPTIONS = '/graphql'
|
||||
const PORT = 4001
|
||||
const NODE_ENV = 'development'
|
||||
|
||||
const createMember = async function (ctx, info, authId) {
|
||||
logger.info('createMember', authId)
|
||||
const member = await ctx.db.mutation.upsertMember({
|
||||
where: {
|
||||
authId: authId,
|
||||
},
|
||||
create: {
|
||||
authId: authId,
|
||||
alias: idToken.nickname
|
||||
},
|
||||
update: {
|
||||
authId: authId,
|
||||
alias: idToken.nickname
|
||||
}
|
||||
}, info)
|
||||
return member
|
||||
}
|
||||
|
||||
const ctxMember = ctx => ctx.user
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
async member(parent, arg, ctx, info) {
|
||||
logger.info('member: ', parent, arg)
|
||||
return ctx.db.query.member({ where: { authId: arg.authId } }, info)
|
||||
},
|
||||
async currentMember(parent, args, ctx, info) {
|
||||
logger.info('currentMember: ', ctx.request.res.req.user, ctx.token)
|
||||
const authId = ctx.request.res.req.user.sub
|
||||
|
||||
return ctx.db.query.member({ where: { authId } }, info)
|
||||
},
|
||||
teams(parent, args, ctx, info) {
|
||||
logger.info('teams: ', ctx.request.res)
|
||||
return ctx.db.query.teamsConnection({}, TEAMS_CONNECTIONS_FRAGMENT)
|
||||
},
|
||||
async teamById(parent, { id }, ctx, info) {
|
||||
return ctx.db.query.team({ where: { id } }, info)
|
||||
},
|
||||
async teamByName(parent, { name }, ctx, info) {
|
||||
return ctx.db.query.team({ where: { name: name } }, `{ name }`)
|
||||
},
|
||||
async teamWithRole(parent, { teamId, role }, ctx, info) {
|
||||
return ctx.db.query.teamsConnection({where: {AND: [{id: teamId},{members_some:{role: role}}]}, first:1}, info)
|
||||
},
|
||||
async teamsByOwner(parent, { ownerId }, ctx, info) {
|
||||
logger.info('teamsByOwner')
|
||||
logger.info(ctx.req.headers)
|
||||
logger.info(ctx.req.token)
|
||||
return ctx.db.query.teams({where: { owner: ownerId }, orderBy:'updatedAt_DESC'}, TEAMS_FRAGMENT)
|
||||
},
|
||||
async teamsByRole(parent, args, ctx, info) {
|
||||
const authId = ctx.request.userId
|
||||
let teamAdmin
|
||||
try {
|
||||
teamAdmin= await ctx.db.query.teams({where: {members_some: {AND: [{member: {authId: authId}, role_not:'MEMBER'}]}}}, TEAMS_FRAGMENT)
|
||||
} catch (err) {
|
||||
logger.debug('teamsByRole error: ')
|
||||
logger.debug(err)
|
||||
const errors = res.graphQLErrors.map((error) => {
|
||||
return error.message
|
||||
})
|
||||
return errors
|
||||
}
|
||||
logger.info('teamsByRole teamAdmin: ', teamAdmin)
|
||||
return teamAdmin
|
||||
},
|
||||
async fbByTeamMember(parent, args, ctx, info) {
|
||||
logger.info('fbByTeamMember: ', args, ctx.request, ctx.request.res.req.user)
|
||||
const authId = ctx.request.userId
|
||||
let teamMemberFB = await ctx.db.query.teams({where: {members_some: {AND: [{member: {authId: authId}}]}}, orderBy: 'updatedAt_DESC'}, TEAM_FB_FRAGMENT)
|
||||
logger.info('fbByTeamMember response: ', await teamMemberFB[0])
|
||||
return teamMemberFB[0]
|
||||
},
|
||||
async owner(parent, args, ctx, info) {
|
||||
logger.info('resolver.query.owner ctx: ', ctxMember(ctx))
|
||||
return ctx.db.query.member({ where: { id: ctxMember(ctx).authId } }, info)
|
||||
.catch(err => {
|
||||
logger.debug('createTeam error: ', err)
|
||||
const errors = res.graphQLErrors.map((error) => {
|
||||
return error.message
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
Mutation: {
|
||||
async authenticate(parent, { idToken }, ctx, info) {
|
||||
let memberToken = null
|
||||
try {
|
||||
memberToken = await validateIdToken(idToken)
|
||||
logger.info('authenticate.memberToken: ', await memberToken)
|
||||
} catch (err) {
|
||||
logger.debug('authenticat.validateIdToken err: ', err)
|
||||
throw new Error(err.message)
|
||||
}
|
||||
const authId = ctx.userId
|
||||
let member = await ctx.db.query.member({ where: { authId } }, info)
|
||||
|
||||
if (!member) {
|
||||
try {
|
||||
return createMember(ctx, info, authId)
|
||||
} catch (error) {
|
||||
throw new Error(error.message)
|
||||
}
|
||||
}
|
||||
return member
|
||||
},
|
||||
async sendMemberInviteSG(parent, { email, teamId }, ctx, info) {
|
||||
const team = await ctx.db.query.team({ where: { id: teamId } }, TEAMS_FRAGMENT)
|
||||
const addMember = await ctx.db.mutation.upsertTeamMembers({
|
||||
where:{email: email},
|
||||
create:{role:'MEMBER', email:email, team: {connect: {id: teamId}}, status:{create:{status: 'INVITED', reason: `Invited by ${team.members[0].member.alias}`}}},
|
||||
update:{role: 'MEMBER', email: email, team: {connect: {id: teamId}}, status:{create:{status: 'INVITED', reason: `Invite resent by ${team.members[0].member.alias}`}}}},
|
||||
`{ id }`)
|
||||
const sendInvite = await sendTeamMemberInvite(email, team)
|
||||
return sendInvite
|
||||
},
|
||||
async verifyTeamInvite(parent, { token }, ctx, info) {
|
||||
let verifiedToken = null
|
||||
let team = null
|
||||
try {
|
||||
verifiedToken = await verifyInviteToken(token)
|
||||
team = {
|
||||
email: verifiedToken.email,
|
||||
team: {
|
||||
slug: verifiedToken.team
|
||||
}
|
||||
}
|
||||
logger.info('verifyTeamInvite.token: ', await verifiedToken)
|
||||
} catch (err) {
|
||||
logger.debug('verifyTeamInvite. err: ', err)
|
||||
throw new Error(err.message)
|
||||
}
|
||||
return team
|
||||
},
|
||||
async createTeam(parent, { name, slug, botName, botSlug }, ctx, info) {
|
||||
logger.info('createTeam ctx.request.user:')
|
||||
logger.info(ctx.request.user)
|
||||
|
||||
const authId = ctx.userId
|
||||
|
||||
return getUser(authId)
|
||||
.then(async result => {
|
||||
logger.info('axios:')
|
||||
logger.info(result)
|
||||
|
||||
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'
|
||||
|
||||
const createTeamUrl = encodeURI(`${slug}/${name}/${alias}/${botSlug}/${botName}`)
|
||||
logger.info('createTeamUrl:')
|
||||
logger.info(JSON.stringify(await createTeamUrl))
|
||||
|
||||
const platformUrl = 'https://develop.advancedalgos.net/AABrowserAPI/teamSetup/'
|
||||
// const platformUrl = 'http://localhost:1337/AABrowserAPI/teamSetup/'
|
||||
|
||||
logger.info(`${platformUrl}${createTeamUrl}/${authId}`)
|
||||
const createPlatformTeam = await axios.get(`${platformUrl}${createTeamUrl}/${authId}`)
|
||||
.then((result) => {
|
||||
console.log('createPlatformTeam result:', result.data)
|
||||
if(result.data.message === 'Team Name already taken'){
|
||||
return result.data.message
|
||||
}
|
||||
if(result.data.result === 'Fail'){
|
||||
return result.data.message
|
||||
}
|
||||
return result
|
||||
})
|
||||
.catch(err =>{
|
||||
logger.debug('createPlatformTeam err:')
|
||||
logger.debug(err)
|
||||
throw new Error(err)
|
||||
})
|
||||
console.log('createPlatformTeam returned: ', await createPlatformTeam)
|
||||
if(await createPlatformTeam === 'Team Name already taken'){
|
||||
return createPlatformTeam
|
||||
}
|
||||
|
||||
const existingMember = await ctx.db.query.member({ where: { authId } }, `{id}`)
|
||||
.catch((err) => {
|
||||
logger.debug(err, 'existingMember error: ')
|
||||
return err
|
||||
})
|
||||
|
||||
logger.info('existingMember:')
|
||||
logger.info(await existingMember)
|
||||
|
||||
let createTeam
|
||||
if(existingMember.id !== null){
|
||||
logger.info('createTeam with existingMember:')
|
||||
createTeam = await ctx.db.mutation.createTeam({ data: {name: name, slug: slug, owner: authId, members: {create: {member: {connect: {authId: authId}}, role: 'OWNER', status: { create: { status: 'ACTIVE', reason: `Connected to Team ${name}`}}}}, profile: {create: {avatar: avatar, banner: banner}}, fb: {create: {name: botName, slug: botSlug, kind:'TRADER', avatar: avatar, status: {create: {status: 'ACTIVE', reason: "Cloned on team creation"}}}}, status: {create: {status: 'ACTIVE', reason:"Team created"}}} }, TEAMS_FRAGMENT)
|
||||
.catch((err) => {
|
||||
logger.debug(err, 'createTeamMutation error: ')
|
||||
return err
|
||||
})
|
||||
} else {
|
||||
logger.info('createTeam without existingMember:')
|
||||
createTeam = await ctx.db.mutation.createTeam({ data: {name: name, slug: slug, owner: authId, members: {create: {member: {create: {authId: authId, alias: alias, visible:'true', status: { create: { status: 'ACTIVE', reason: `Created team ${name}`}}}}, role: 'OWNER', status: { create: { status: 'ACTIVE', reason: `Created with Team ${name}`}}}}, profile: {create: {avatar: avatar, banner: banner}}, fb: {create: {name: botName, slug: botSlug, kind:'TRADER', avatar: avatar, status: {create: {status: 'ACTIVE', reason: "Cloned on team creation"}}}}, status: {create: {status: 'ACTIVE', reason:"Team created"}}} }, TEAMS_FRAGMENT)
|
||||
.catch((err) => {
|
||||
logger.debug(err, 'createTeamMutation error: ')
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// sendTeamCreateConfirmation(email, name, botName)
|
||||
|
||||
return createTeam
|
||||
})
|
||||
.catch((err) => {
|
||||
logger.debug('createTeam error: ')
|
||||
return err
|
||||
})
|
||||
},
|
||||
async updateTeamProfile(parent, { slug, owner, description, motto, avatar, banner }, ctx, info) {
|
||||
return ctx.db.mutation.updateTeam({data:{profile: {update: {description: description, motto: motto, avatar: avatar, banner: banner}}}, where:{slug: slug}}, TEAMS_FRAGMENT)
|
||||
.catch((err) => {
|
||||
logger.debug('createTeam error: ', err)
|
||||
return err
|
||||
})
|
||||
},
|
||||
async updateFB(parent, { fbId, avatar}, ctx, info) {
|
||||
return ctx.db.mutation.updateFinancialBeings({data:{avatar:avatar}, where:{id:fbId}}, info)
|
||||
.catch((err) => {
|
||||
logger.debug('createTeam error: ', err)
|
||||
return err
|
||||
})
|
||||
},
|
||||
async deleteTeam(parent, { slug }, ctx, info) {
|
||||
return ctx.db.mutation.deleteTeam({ where: { slug } }, info)
|
||||
.catch((res) => {
|
||||
logger.info('deleteTeam error: ', res)
|
||||
const errors = res.graphQLErrors.map((error) => {
|
||||
return error.message
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const db = new Prisma({
|
||||
fragmentReplacements: extractFragmentReplacements(resolvers),
|
||||
typeDefs: 'src/generated/prisma.graphql',
|
||||
@@ -285,24 +35,7 @@ const db = new Prisma({
|
||||
|
||||
const app = express()
|
||||
|
||||
const connectionMiddlewares = [
|
||||
checkJwt,
|
||||
function (err, req, res, next) {
|
||||
logger.info('checkJwt: ')
|
||||
logger.error(err)
|
||||
logger.info(req.headers)
|
||||
logger.info(req.user)
|
||||
if (err) {
|
||||
const error = err.message ? err.message : err
|
||||
return res.status(201).send(error)
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
},
|
||||
(req, res, done) => getMember(req, res, done, db)
|
||||
]
|
||||
|
||||
app.post(GRAPHQL_ENDPOINT, ...connectionMiddlewares)
|
||||
app.post(GRAPHQL_ENDPOINT)
|
||||
|
||||
const corsOptions = {
|
||||
"origin": "*",
|
||||
@@ -322,9 +55,8 @@ const options = {
|
||||
const server = createApolloServer(app, {
|
||||
graphqlEndpoint: GRAPHQL_ENDPOINT,
|
||||
subscriptionsEndpoint: GRAPHQL_SUBSCRIPTIONS,
|
||||
wsMiddlewares: connectionMiddlewares,
|
||||
apolloServerOptions: { formatError },
|
||||
typeDefs: importSchema('src/schema.graphql'),
|
||||
typeDefs: importSchema('src/graphql/schema.graphql'),
|
||||
resolvers,
|
||||
resolverValidationOptions: { requireResolversForResolveType: false },
|
||||
schemaDirectives,
|
||||
@@ -343,5 +75,3 @@ server.listen({ port: PORT }, () => {
|
||||
`🚀 GraphQL Server is running on http://localhost:${PORT}${GRAPHQL_ENDPOINT} in "${NODE_ENV}" mode\n`
|
||||
)
|
||||
})
|
||||
|
||||
module.exports= { createMember }
|
||||
@@ -1,4 +1,4 @@
|
||||
import { logger } from '../../logger'
|
||||
import { logger } from '../logger'
|
||||
|
||||
export const getMember = async (req, res, next, db) => {
|
||||
if (!req.headers.userId) return next()
|
||||
File renamed without changes.
Reference in new issue
Block a user