Merge pull request #10 from AdvancedAlgos/develop
Update to Apollo Server 2
This commit is contained in:
9 files changed
+2071
-285
No files matched your search
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": ["@babel/preset-env"]
|
||||
}
|
||||
Generated
+1598
-146
File diff suppressed because it is too large.
Load diff
+12
-2
@@ -2,26 +2,36 @@
|
||||
"name": "aa-team-api",
|
||||
"scripts": {
|
||||
"start": "NODE_ENV=production nodemon -e js,graphql -x node -r dotenv/config src/index.js",
|
||||
"debug": "nodemon -e js,graphql -x node --inspect -r dotenv/config src/index.js",
|
||||
"debug": "nodemon src/index.js --watch ./src --exec \"node --require @babel/register --require dotenv/config\"",
|
||||
"playground": "graphql playground --dotenv dotenv/config",
|
||||
"dev": "npm-run-all --parallel debug playground"
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/storage-blob": "^10.0.0-preview",
|
||||
"@babel/cli": "^7.1.2",
|
||||
"@babel/core": "^7.1.2",
|
||||
"@babel/node": "^7.0.0",
|
||||
"@babel/polyfill": "^7.0.0",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/register": "^7.0.0",
|
||||
"apollo-server-express": "^2.1.0",
|
||||
"axios": "^0.18.0",
|
||||
"cors": "^2.8.4",
|
||||
"debug": "^4.1.0",
|
||||
"dotenv": "^6.1.0",
|
||||
"express": "^4.16.4",
|
||||
"express-jwt": "^5.3.1",
|
||||
"fast-xml-parser": "^3.12.5",
|
||||
"graphql-import": "^0.6.0",
|
||||
"graphql-middleware": "^1.7.7",
|
||||
"graphql-subscriptions": "^1.0.0",
|
||||
"graphql-tag": "^2.10.0",
|
||||
"graphql-tools": "^4.0.1",
|
||||
"graphql-yoga": "^1.16.4",
|
||||
"jsonwebtoken": "^8.3.0",
|
||||
"jwks-rsa": "^1.3.0",
|
||||
"lodash.get": "^4.4.2",
|
||||
"nodemon": "^1.18.3",
|
||||
"nodemon": "^1.18.4",
|
||||
"prisma-binding": "2.1.4",
|
||||
"winston": "^3.1.0"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
import http from 'http'
|
||||
import { ApolloServer, makeExecutableSchema } from 'apollo-server-express'
|
||||
import { applyMiddleware as applyGraphQLMiddleware } from 'graphql-middleware'
|
||||
import { logger } from './logger'
|
||||
|
||||
/**
|
||||
*
|
||||
* @description Creates an Apollo Server. Setup based on `vue-cli-plugin-apollo`.
|
||||
* @param {Object} app Express application
|
||||
* @param {Object} options Apollo options
|
||||
* @returns {Object} HTTP Server
|
||||
*/
|
||||
export default function createApolloServer(
|
||||
app,
|
||||
{
|
||||
// Main options
|
||||
graphqlEndpoint = '',
|
||||
typeDefs = {},
|
||||
resolvers = {},
|
||||
schemaDirectives = {},
|
||||
directiveResolvers = {},
|
||||
graphqlMiddlewares = [],
|
||||
dataSources = () => ({}),
|
||||
context = () => ({}),
|
||||
// Subscriptions
|
||||
subscriptionsEndpoint = '',
|
||||
wsMiddlewares = [],
|
||||
// Mocks
|
||||
mocks,
|
||||
// Apollo Engine
|
||||
engineKey = '',
|
||||
// HTTP options
|
||||
cors = true,
|
||||
timeout = 120000,
|
||||
// Extra options for Apollo Server
|
||||
apolloServerOptions = {},
|
||||
}
|
||||
) {
|
||||
const schema = makeExecutableSchema({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
schemaDirectives,
|
||||
directiveResolvers,
|
||||
resolverValidationOptions: {
|
||||
requireResolversForResolveType: false,
|
||||
},
|
||||
})
|
||||
|
||||
// Apollo server options
|
||||
const options = {
|
||||
...apolloServerOptions,
|
||||
schema: applyGraphQLMiddleware(schema, ...graphqlMiddlewares),
|
||||
tracing: true,
|
||||
cacheControl: true,
|
||||
engine: engineKey ? { apiKey: engineKey } : false,
|
||||
dataSources,
|
||||
// Resolvers context in POST requests
|
||||
context: async ({ req, connection }) => {
|
||||
let contextData
|
||||
try {
|
||||
if (connection) {
|
||||
contextData = { ...connection.context }
|
||||
} else {
|
||||
contextData = await context({ req, request: req })
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
throw err
|
||||
}
|
||||
|
||||
return contextData
|
||||
},
|
||||
// Resolvers context in WebSocket requests
|
||||
subscriptions: {
|
||||
path: subscriptionsEndpoint,
|
||||
onConnect: async (connection, websocket) => {
|
||||
const { authorization } = connection
|
||||
|
||||
let contextData = {}
|
||||
try {
|
||||
// Simulate `req` object for auth
|
||||
const req = { headers: { authorization } }
|
||||
|
||||
// Call all middlewares in order and modify `req`
|
||||
await new Promise((resolve, reject) =>
|
||||
wsMiddlewares.reduceRight(
|
||||
(acc, m) => err => (err ? reject(err) : m(req, null, acc)),
|
||||
err => (err ? reject(err) : resolve())
|
||||
)()
|
||||
)
|
||||
|
||||
contextData = await context({
|
||||
connection,
|
||||
websocket,
|
||||
request: req,
|
||||
req,
|
||||
})
|
||||
} catch (err) {
|
||||
if (err.status !== 401) {
|
||||
logger.error(err)
|
||||
}
|
||||
|
||||
throw err
|
||||
}
|
||||
|
||||
return contextData
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Apollo Server
|
||||
const server = new ApolloServer(options)
|
||||
|
||||
// Express middleware
|
||||
server.applyMiddleware({
|
||||
app,
|
||||
cors,
|
||||
path: graphqlEndpoint,
|
||||
// gui: {
|
||||
// endpoint: graphqlEndpoint,
|
||||
// subscriptionEndpoint: graphqlSubscriptionsPath,
|
||||
// },
|
||||
})
|
||||
|
||||
// Create HTTP server and add subscriptions
|
||||
const httpServer = http.createServer(app)
|
||||
httpServer.setTimeout(timeout)
|
||||
server.installSubscriptionHandlers(httpServer)
|
||||
|
||||
return httpServer
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
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'
|
||||
|
||||
const memberLocationOnContext = 'request.user'
|
||||
const bearerAccessToken = 'request.headers.authorization'
|
||||
|
||||
const ctxMember = ctx => _get(ctx, memberLocationOnContext)
|
||||
const ctxToken = ctx => _get(ctx, bearerAccessToken)
|
||||
|
||||
const createMember = async (ctx, idToken, info) => {
|
||||
logger.info('createMember', idToken)
|
||||
const member = await ctx.db.mutation.upsertMember({
|
||||
where: {
|
||||
authId: idToken.sub,
|
||||
},
|
||||
create: {
|
||||
authId: idToken.sub,
|
||||
alias: idToken.nickname
|
||||
},
|
||||
update: {
|
||||
authId: idToken.sub,
|
||||
alias: idToken.nickname
|
||||
}
|
||||
}, info)
|
||||
return member
|
||||
}
|
||||
|
||||
const isLoggedIn = async ctx => {
|
||||
logger.info('isLoggedIn 0 : ', 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
|
||||
// console.log('isLoggedIn2 : ', token)
|
||||
try {
|
||||
memberToken = await validateIdToken(token)
|
||||
const authId = memberToken.sub
|
||||
// console.log('isLoggedIn3 : ', await authId, ctx.db.query.member)
|
||||
exists = await ctx.db.query.member({ where: { authId: authId } })
|
||||
// console.log('isLoggedIn4 : ', await exists, createMember )
|
||||
if (!member && exists === null) {
|
||||
member = await createMember(ctx, memberToken).then(res => {
|
||||
// console.log('isLoggedIn5 : ', res)
|
||||
return res
|
||||
})
|
||||
|
||||
return member
|
||||
}
|
||||
return member
|
||||
} catch (err) {
|
||||
memberToken = false
|
||||
}
|
||||
}
|
||||
}
|
||||
// console.log('isLoggedIn5 : ', await member)
|
||||
if (!member) {
|
||||
throw new AuthenticationError('Access token is missing or expired')
|
||||
}
|
||||
return member
|
||||
}
|
||||
|
||||
const isRequestingMemberAlsoOwner = ({ ctx, memberId, type, typeId }) =>
|
||||
ctx.db.exists[type]({ slug: typeId, owner: memberId })
|
||||
const isRequestingMember = ({ ctx, memberId }) => ctx.db.exists.Member({ authId: memberId })
|
||||
|
||||
|
||||
const getUser = ({ req = {}, request = {} }) => req.user || request.user || null
|
||||
const hasRole = (roles, ctx) => {
|
||||
const { role = '' } = getUser(ctx) || {}
|
||||
return role && roles.includes(role)
|
||||
}
|
||||
|
||||
const assertAuth = ctx => {
|
||||
if (!getUser(ctx)) {
|
||||
throw new AuthenticationError('Access token is missing or expired')
|
||||
}
|
||||
}
|
||||
|
||||
// Directive resolvers (apollo v1 syntax)
|
||||
export const directiveResolvers = {
|
||||
isAuthenticated: async (next, source, args, ctx) => {
|
||||
let result = await isLoggedIn(ctx)
|
||||
logger.info('directive isAuthenticated: ', result)
|
||||
return next(result)
|
||||
},
|
||||
hasRole: (next, source, { roles }, ctx) => {
|
||||
const { role } = isLoggedIn(ctx)
|
||||
logger.info('directive hasRole: ', role)
|
||||
if (roles.includes(role)) {
|
||||
return next()
|
||||
}
|
||||
throw new ForbiddenError('Insufficient permissions')
|
||||
},
|
||||
isOwner: async (next, source, { type }, ctx) => {
|
||||
logger.info('directive isOwner: ', source, type, ctx)
|
||||
const { slug: typeId } =
|
||||
source && source.id
|
||||
? source
|
||||
: ctx.request.body.variables ? ctx.request.body.variables : { id: null }
|
||||
const user = await isLoggedIn(ctx)
|
||||
// console.log('directive isOwner 0: ', typeId, user.sub)
|
||||
const memberId = user.sub
|
||||
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 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`)
|
||||
if (roles.includes(role)) {
|
||||
return next()
|
||||
}
|
||||
|
||||
const { authId: typeId } = ctx.request.body.variables
|
||||
const isOwner = await isRequestingMemberAlsoOwner({
|
||||
ctx,
|
||||
memberId,
|
||||
type,
|
||||
typeId
|
||||
})
|
||||
logger.info('directive isOwnerOrHasRole 2: ', typeId, memberId, role, isOwner)
|
||||
if (isOwner) {
|
||||
return next()
|
||||
}
|
||||
|
||||
const hasRole = await isRequestingMember({
|
||||
ctx,
|
||||
memberId,
|
||||
type,
|
||||
typeId
|
||||
})
|
||||
if(hasRole){
|
||||
return next()
|
||||
}
|
||||
throw new ForbiddenError('Insufficient permissions')
|
||||
}
|
||||
}
|
||||
|
||||
export const defaultFieldResolver = (source, args, contextValue, info) => {
|
||||
// ensure source is a value for which property access is acceptable.
|
||||
if (typeof source === 'object' || typeof source === 'function') {
|
||||
const property = source[info.fieldName]
|
||||
if (typeof property === 'function') {
|
||||
return source[info.fieldName](args, contextValue, info)
|
||||
}
|
||||
return property
|
||||
}
|
||||
}
|
||||
|
||||
// Schema directives (apollo v2 syntax)
|
||||
export const schemaDirectives = Object.keys(directiveResolvers).reduce(
|
||||
(acc, directiveName) => ({
|
||||
...acc,
|
||||
[directiveName]: class extends SchemaDirectiveVisitor {
|
||||
visitFieldDefinition(field) {
|
||||
const resolver = directiveResolvers[directiveName]
|
||||
const originalResolver = field.resolve || defaultFieldResolver
|
||||
const directiveArgs = this.args
|
||||
field.resolve = (...args) => {
|
||||
const [source, , context, info] = args
|
||||
return resolver(
|
||||
async () => originalResolver.apply(field, args),
|
||||
source,
|
||||
directiveArgs,
|
||||
context,
|
||||
info
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
{}
|
||||
)
|
||||
@@ -0,0 +1,28 @@
|
||||
import { ApolloError } from 'apollo-server-express'
|
||||
import { logger } from '../logger'
|
||||
|
||||
export {
|
||||
ApolloError,
|
||||
AuthenticationError,
|
||||
ForbiddenError,
|
||||
SyntaxError,
|
||||
UserInputError,
|
||||
ValidationError,
|
||||
} from 'apollo-server-express'
|
||||
|
||||
export function formatError(error) {
|
||||
// This can be used to send errors to third
|
||||
// party services like Sentry or Stackdriver
|
||||
logger.error(error)
|
||||
|
||||
return error
|
||||
}
|
||||
|
||||
// Define custom Apollo errors here
|
||||
export class ExternalServiceError extends ApolloError {
|
||||
constructor(message) {
|
||||
super(message, 'EXTERNAL_SERVICE_UNAVAILABLE')
|
||||
|
||||
Object.defineProperty(this, 'name', { value: this.constructor.name })
|
||||
}
|
||||
}
|
||||
+75
-102
@@ -1,33 +1,36 @@
|
||||
import '@babel/polyfill'
|
||||
require('dotenv').config();
|
||||
const { GraphQLServer } = require('graphql-yoga')
|
||||
const {
|
||||
import express from 'express'
|
||||
import createApolloServer from './ApolloServer'
|
||||
import { formatError } from './errors'
|
||||
import {
|
||||
Prisma,
|
||||
extractFragmentReplacements,
|
||||
forwardTo
|
||||
} = require('prisma-binding')
|
||||
const { makeExecutableSchema } = require('graphql-tools')
|
||||
const { importSchema } = require('graphql-import')
|
||||
const parser = require('fast-xml-parser')
|
||||
var axios = require('axios')
|
||||
} from 'prisma-binding'
|
||||
import { makeExecutableSchema } from 'graphql-tools'
|
||||
import { importSchema } from 'graphql-import'
|
||||
import parser from 'fast-xml-parser'
|
||||
import axios from 'axios'
|
||||
|
||||
const checkJwt = require('./auth/middleware/jwt')
|
||||
const { getMember } = require('./auth/middleware/getMember')
|
||||
const { validateIdToken } = require('./auth/validateIdToken')
|
||||
const { directiveResolvers } = require('./auth/authDirectives')
|
||||
import checkJwt from './auth/middleware/jwt'
|
||||
import { getMember } from './auth/middleware/getMember'
|
||||
import { validateIdToken } from './auth/validateIdToken'
|
||||
import { schemaDirectives } from './directives'
|
||||
|
||||
const Azure = require("@azure/storage-blob")
|
||||
const { createSASQueryURL } = require('./storage/azure')
|
||||
const azureAccount = process.env.AZURE_STORAGE_ACCOUNT
|
||||
const azureKey = process.env.AZURE_STORAGE_ACCESS_KEY
|
||||
const azureStorageUrl = process.env.AZURE_STORAGE_URL
|
||||
import { sendTeamMemberInvite, sendTeamCreateConfirmation, verifyInviteToken } from './email/sendgrid'
|
||||
|
||||
const { sendTeamMemberInvite, sendTeamCreateConfirmation, verifyInviteToken } = require('./email/sendgrid')
|
||||
import TEAMS_FRAGMENT from './graphql/TeamsFragment'
|
||||
import TEAMS_CONNECTIONS_FRAGMENT from './graphql/TeamsConnectionsFragment'
|
||||
import TEAM_FB_FRAGMENT from './graphql/TeamFBFragment'
|
||||
|
||||
const TEAMS_FRAGMENT = require('./graphql/TeamsFragment')
|
||||
const TEAMS_CONNECTIONS_FRAGMENT = require('./graphql/TeamsConnectionsFragment')
|
||||
const TEAM_FB_FRAGMENT = require('./graphql/TeamFBFragment')
|
||||
import pubsub from './pubsub'
|
||||
import { logger } from './logger'
|
||||
|
||||
const logger = require('./logger')
|
||||
const GRAPHQL_ENDPOINT = '/graphql'
|
||||
const GRAPHQL_SUBSCRIPTIONS = '/graphql'
|
||||
const PORT = 4001
|
||||
const NODE_ENV = 'development'
|
||||
|
||||
const createMember = async function (ctx, info, idToken) {
|
||||
logger.info('createMember', idToken)
|
||||
@@ -52,25 +55,17 @@ const ctxMember = ctx => ctx.request.user
|
||||
const resolvers = {
|
||||
Query: {
|
||||
async member(parent, arg, ctx, info) {
|
||||
console.log('member: ', parent, arg)
|
||||
logger.info('member: ', parent, arg)
|
||||
return ctx.db.query.member({ where: { authId: arg.authId } }, info)
|
||||
},
|
||||
async currentMember(parent, args, ctx, info) {
|
||||
console.log('currentMember: ', ctx.request.res.req.user, ctx.token)
|
||||
logger.info('currentMember: ', ctx.request.res.req.user, ctx.token)
|
||||
const authId = ctx.request.res.req.user.sub
|
||||
|
||||
fetch('URL_GOES_HERE', {
|
||||
method: 'post',
|
||||
headers: new Headers({
|
||||
'Authorization': 'Basic '+btoa('username:password'),
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}),
|
||||
body: 'A=1&B=2'
|
||||
})
|
||||
|
||||
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) {
|
||||
@@ -88,21 +83,21 @@ const resolvers = {
|
||||
async teamsByRole(parent, args, ctx, info) {
|
||||
const authId = ctx.request.user.sub
|
||||
let teamAdmin = await ctx.db.query.teams({where: {members_some: {OR: [{role: 'ADMIN'}, {role: 'OWNER'}], AND: [{member: {authId: authId}}]}}, orderBy: 'updatedAt_DESC'}, TEAMS_FRAGMENT)
|
||||
console.log('teamsByRole teamAdmin: ', teamAdmin)
|
||||
logger.info('teamsByRole teamAdmin: ', teamAdmin)
|
||||
return teamAdmin
|
||||
},
|
||||
async fbByTeamMember(parent, args, ctx, info) {
|
||||
console.log('fbByTeamMember: ', args, ctx.request, ctx.request.res.req.user)
|
||||
logger.info('fbByTeamMember: ', args, ctx.request, ctx.request.res.req.user)
|
||||
const authId = ctx.request.user.sub
|
||||
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) {
|
||||
console.log('resolver.query.owner ctx: ', ctxMember(ctx))
|
||||
logger.info('resolver.query.owner ctx: ', ctxMember(ctx))
|
||||
return ctx.db.query.member({ where: { id: ctxMember(ctx).authId } }, info)
|
||||
.catch((res) => {
|
||||
console.log('createTeam error: ', res)
|
||||
.catch(err => {
|
||||
logger.debug('createTeam error: ', err)
|
||||
const errors = res.graphQLErrors.map((error) => {
|
||||
return error.message
|
||||
})
|
||||
@@ -114,9 +109,9 @@ const resolvers = {
|
||||
let memberToken = null
|
||||
try {
|
||||
memberToken = await validateIdToken(idToken)
|
||||
console.log('authenticate.memberToken: ', await memberToken)
|
||||
logger.info('authenticate.memberToken: ', await memberToken)
|
||||
} catch (err) {
|
||||
console.log('authenticat.validateIdToken err: ', err)
|
||||
logger.debug('authenticat.validateIdToken err: ', err)
|
||||
throw new Error(err.message)
|
||||
}
|
||||
const authId = memberToken.sub
|
||||
@@ -152,9 +147,9 @@ const resolvers = {
|
||||
slug: verifiedToken.team
|
||||
}
|
||||
}
|
||||
console.log('verifyTeamInvite.token: ', await verifiedToken)
|
||||
logger.info('verifyTeamInvite.token: ', await verifiedToken)
|
||||
} catch (err) {
|
||||
console.log('verifyTeamInvite. err: ', err)
|
||||
logger.debug('verifyTeamInvite. err: ', err)
|
||||
throw new Error(err.message)
|
||||
}
|
||||
return team
|
||||
@@ -165,17 +160,17 @@ const resolvers = {
|
||||
const encodedAuthId = encodeURI(authId)
|
||||
const encodedURL = `https://users-api.advancedalgos.net/graphql?query=%7B%0A%20%20userByAuthId(authId%3A%20"${encodedAuthId}")%7B%0A%20%20%20%20id%0A%09%09email%0A%20%20%20%20alias%0A%20%20%7D%0A%7D`
|
||||
const decodedURL = decodeURI(encodedURL)
|
||||
console.log('createTeam URLs: ', encodedURL, decodedURL)
|
||||
logger.info('createTeam URLs: ', encodedURL, decodedURL)
|
||||
const getUserModuleUser = await axios.get(encodedURL)
|
||||
.then((result) => {
|
||||
console.log('getUserModuleUser axios:', result)
|
||||
logger.info('getUserModuleUser axios:', result)
|
||||
return result
|
||||
})
|
||||
.catch(err =>{
|
||||
console.log('getUserModuleUser err:', err)
|
||||
logger.debug('getUserModuleUser err:', err)
|
||||
})
|
||||
|
||||
console.log('getUserModuleUser:', await getUserModuleUser)
|
||||
logger.info('getUserModuleUser:', await getUserModuleUser)
|
||||
const alias = await getUserModuleUser.data.data.userByAuthId.alias
|
||||
const email = getUserModuleUser.data.data.userByAuthId.email
|
||||
const avatar = 'https://algobotcommstorage.blob.core.windows.net/aateammodule/aa-avatar-default.png'
|
||||
@@ -186,23 +181,23 @@ const resolvers = {
|
||||
// const platformUrl = 'http://localhost:3100/AABrowserAPI/teamSetup/'
|
||||
const createPlatformTeam = await axios.get(`${platformUrl}${createTeamUrl}`)
|
||||
.then((result) => {
|
||||
console.log('createPlatformTeam:', result)
|
||||
logger.info('createPlatformTeam:', result)
|
||||
if(result.data.message === 'Team Name already taken'){
|
||||
throw new Error(result.data.message)
|
||||
}
|
||||
return result
|
||||
})
|
||||
.catch(err =>{
|
||||
console.log('createPlatformTeam err:', err)
|
||||
logger.errror('createPlatformTeam err:', err)
|
||||
throw new Error(err)
|
||||
})
|
||||
console.log('createPlatformTeam: ', await createPlatformTeam)
|
||||
logger.info('createPlatformTeam: ', await createPlatformTeam)
|
||||
if(createPlatformTeam === 'Error: Team Name already taken'){
|
||||
return createPlatformTeam
|
||||
}
|
||||
const createTeam = await ctx.db.mutation.createTeam({ data: {name: name, slug: slug, owner: authId, members: {create: {member: {connect: {authId: authId}}, role: 'OWNER'}}, 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) => {
|
||||
console.log('createTeam error: ', err)
|
||||
logger.debug('createTeam error: ', err)
|
||||
return err
|
||||
})
|
||||
|
||||
@@ -213,21 +208,21 @@ const resolvers = {
|
||||
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) => {
|
||||
console.log('createTeam error: ', 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) => {
|
||||
console.log('createTeam error: ', err)
|
||||
logger.debug('createTeam error: ', err)
|
||||
return err
|
||||
})
|
||||
},
|
||||
async deleteTeam(parent, { slug }, ctx, info) {
|
||||
return ctx.db.mutation.deleteTeam({ where: { slug } }, info)
|
||||
.catch((res) => {
|
||||
console.log('deleteTeam error: ', res)
|
||||
logger.info('deleteTeam error: ', res)
|
||||
const errors = res.graphQLErrors.map((error) => {
|
||||
return error.message
|
||||
})
|
||||
@@ -244,25 +239,9 @@ const db = new Prisma({
|
||||
debug: true
|
||||
})
|
||||
|
||||
const schema = makeExecutableSchema({
|
||||
typeDefs: importSchema('src/schema.graphql'),
|
||||
resolvers,
|
||||
resolverValidationOptions: { requireResolversForResolveType: false },
|
||||
directiveResolvers
|
||||
})
|
||||
const app = express()
|
||||
|
||||
const server = new GraphQLServer({
|
||||
schema,
|
||||
context: req => ({
|
||||
token: req.headers,
|
||||
user: req.user,
|
||||
db,
|
||||
...req
|
||||
}),
|
||||
})
|
||||
|
||||
server.express.use(
|
||||
server.options.endpoint,
|
||||
const connectionMiddlewares = [
|
||||
checkJwt,
|
||||
function (err, req, res, next) {
|
||||
logger.info('checkJwt: ', err, req.headers, req.user)
|
||||
@@ -271,39 +250,11 @@ server.express.use(
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
server.express.post(server.options.endpoint, (req, res, done) => getUser(req, res, done, db))
|
||||
|
||||
/*
|
||||
let whitelist = [
|
||||
'http://localhost:3000',
|
||||
'http://localhost:3001',
|
||||
'http://localhost:3002',
|
||||
'http://localhost:4000',
|
||||
'http://localhost:4002',
|
||||
'http://localhost:1337',
|
||||
'http://localhost:4100',
|
||||
'https://teams.advancedalgos.net',
|
||||
'https://users.advancedalgos.net',
|
||||
'https://users-api.advancedalgos.net',
|
||||
'https://keyvault.advancedalgos.net',
|
||||
'https://keyvault-api.advancedalgos.net',
|
||||
'https://aawebdevelop.azurewebsites.net',
|
||||
'https://develop.advancedalgos.net'
|
||||
},
|
||||
// (req, res, done) => getMember(req, res, done, db)
|
||||
]
|
||||
|
||||
const corsOptionsDelegate = (req, callback) => {
|
||||
var corsOptions
|
||||
if (whitelist.indexOf(req.header('Origin')) !== -1) {
|
||||
corsOptions = { origin: true, credentials: true } // reflect (enable) the requested origin in the CORS response
|
||||
} else {
|
||||
corsOptions = { origin: false, credentials: true } // disable CORS for this request
|
||||
}
|
||||
callback(null, corsOptions) // callback expects two parameters: error and options
|
||||
}
|
||||
*/
|
||||
app.post(GRAPHQL_ENDPOINT, ...connectionMiddlewares)
|
||||
|
||||
const corsOptions = {
|
||||
"origin": "*",
|
||||
@@ -320,6 +271,28 @@ const options = {
|
||||
playground: '/graphiql'
|
||||
}
|
||||
|
||||
server.start(options, () => console.log(`Server is running on http://localhost:4001${server.options.endpoint}`))
|
||||
const server = createApolloServer(app, {
|
||||
graphqlEndpoint: GRAPHQL_ENDPOINT,
|
||||
subscriptionsEndpoint: GRAPHQL_SUBSCRIPTIONS,
|
||||
wsMiddlewares: connectionMiddlewares,
|
||||
apolloServerOptions: { formatError },
|
||||
typeDefs: importSchema('src/schema.graphql'),
|
||||
resolvers,
|
||||
resolverValidationOptions: { requireResolversForResolveType: false },
|
||||
schemaDirectives,
|
||||
context: req => ({
|
||||
...req ,
|
||||
token: req.headers,
|
||||
user: req.user,
|
||||
db,
|
||||
pubsub
|
||||
})
|
||||
})
|
||||
|
||||
server.listen({ port: PORT }, () => {
|
||||
logger.info(
|
||||
`🚀 GraphQL Server is running on http://localhost:${PORT}${GRAPHQL_ENDPOINT} in "${NODE_ENV}" mode\n`
|
||||
)
|
||||
})
|
||||
|
||||
module.exports= { createMember }
|
||||
+26
-35
@@ -1,39 +1,30 @@
|
||||
const { createLogger, format, transports } = require('winston')
|
||||
const { combine, timestamp, simple } = format
|
||||
import { createLogger, format, transports } from 'winston'
|
||||
|
||||
const options = {
|
||||
file: {
|
||||
level: 'info',
|
||||
filename: '../logs/app.log',
|
||||
handleExceptions: true,
|
||||
json: true,
|
||||
maxsize: 5242880, // 5MB
|
||||
maxFiles: 5,
|
||||
colorize: false,
|
||||
timestamp: true
|
||||
},
|
||||
console: {
|
||||
level: 'debug',
|
||||
handleExceptions: true,
|
||||
json: false,
|
||||
colorize: true,
|
||||
timestamp: true
|
||||
class LoggerService {
|
||||
constructor() {
|
||||
const winstonTransports = [
|
||||
new transports.Console({
|
||||
format: format.combine(
|
||||
format.colorize(),
|
||||
format.timestamp({ format: 'YYYY/MM/DD HH:mm' }),
|
||||
format.printf(
|
||||
info => `${info.timestamp} - ${info.level}: ${info.message}`
|
||||
)
|
||||
),
|
||||
}),
|
||||
]
|
||||
|
||||
const logger = createLogger({
|
||||
level: 'info',
|
||||
transports: winstonTransports,
|
||||
exceptionHandlers: winstonTransports,
|
||||
})
|
||||
|
||||
return new Proxy(this, {
|
||||
get: (target, propKey) => logger[propKey],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const logger = createLogger({
|
||||
level: 'info',
|
||||
format: combine(
|
||||
timestamp({
|
||||
format: 'YYYY-MM-DD HH:mm:ss'
|
||||
}),
|
||||
simple()
|
||||
),
|
||||
transports: [
|
||||
new transports.File(options.file),
|
||||
new transports.Console(options.console)
|
||||
],
|
||||
exitOnError: false // do not exit on handled exceptions
|
||||
})
|
||||
|
||||
module.exports= logger
|
||||
export const logger = new LoggerService() // Default logger
|
||||
export { LoggerService }
|
||||
@@ -0,0 +1,3 @@
|
||||
import { PubSub } from 'graphql-subscriptions'
|
||||
|
||||
export default new PubSub()
|
||||
Reference in new issue
Block a user