-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* add graphql to graphql branch (#159) * graphql * update * update * update * update * update * update per review comments * update * update * update apollo and graphql package vesions * update * update * update * update * update * update * bump package.json versions * update * update * update * update * update * update * update * update * update * share port 3333 between apollo and reset api * fix lint * update * add timeout value for stream init * temporarily skip vulnerability 1217 since it is impact dev not prod until a fix is available * add message type of resource * bump versions and fix a timeout value * update * update * fix package.json * remove port 8000 * enable steaming topic sharding for apollo * update
- Loading branch information
1 parent
6985dfa
commit 0206ebd
Showing
95 changed files
with
9,186 additions
and
1,141 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ build-tools/ | |
.nyc_output/ | ||
coverage/ | ||
test/ | ||
compose/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
# Local files | ||
local | ||
/local | ||
|
||
# Logs | ||
logs | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
/** | ||
* Copyright 2020 IBM Corp. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
const http = require('http'); | ||
const express = require('express'); | ||
const router = express.Router(); | ||
const ebl = require('express-bunyan-logger'); | ||
const bunyan = require('bunyan'); | ||
const { ApolloServer } = require('apollo-server-express'); | ||
const addRequestId = require('express-request-id')(); | ||
|
||
const { getBunyanConfig } = require('./utils/bunyan'); | ||
const { AUTH_MODEL, GRAPHQL_PATH } = require('./models/const'); | ||
const typeDefs = require('./schema'); | ||
const resolvers = require('./resolvers'); | ||
const { models, connectDb, setupDistributedCollections, closeDistributedConnections } = require('./models'); | ||
const bunyanConfig = getBunyanConfig('apollo'); | ||
const logger = bunyan.createLogger(bunyanConfig); | ||
|
||
const initModule = require(`./init.${AUTH_MODEL}`); | ||
|
||
const createDefaultApp = () => { | ||
const app = express(); | ||
app.set('trust proxy', true); | ||
app.use(addRequestId); | ||
app.use(function errorHandler(err, req, res, next) { | ||
if (err) { | ||
if (req.log && req.log.error) req.log.error(err); | ||
else logger.error(err); | ||
if (!res.headersSent) { | ||
const statusCode = err.statusCode || 500; | ||
return res.status(statusCode).send(); | ||
} | ||
return next(err); | ||
} | ||
return next(); | ||
}); | ||
return app; | ||
}; | ||
|
||
const buildCommonApolloContext = async ({ models, req, res, connection, logger }) => { | ||
const context = await initModule.buildApolloContext({ | ||
models, | ||
req, | ||
res, | ||
connection, | ||
logger, | ||
}); | ||
// populate req_id to apollo context | ||
if (connection) { | ||
context.req_id = connection.context.upgradeReq ? connection.context.upgradeReq.id : undefined; | ||
} else if (req) { | ||
context.req_id = req.id; | ||
} | ||
return context; | ||
}; | ||
|
||
const createApolloServer = () => { | ||
const server = new ApolloServer({ | ||
introspection: true, | ||
playground: process.env.NODE_ENV !== 'production', | ||
typeDefs, | ||
resolvers, | ||
formatError: error => { | ||
// remove the internal sequelize error message | ||
// leave only the important validation error | ||
const message = error.message | ||
.replace('SequelizeValidationError: ', '') | ||
.replace('Validation error: ', ''); | ||
return { | ||
...error, | ||
message, | ||
}; | ||
}, | ||
context: async ({ req, res, connection }) => { | ||
return buildCommonApolloContext({ | ||
models, | ||
req, | ||
res, | ||
connection, | ||
logger, | ||
}); | ||
}, | ||
subscriptions: { | ||
path: GRAPHQL_PATH, | ||
onConnect: async (connectionParams, webSocket, context) => { | ||
logger.trace({ req_id: webSocket.upgradeReq.id, connectionParams, context }, 'subscriptions:onConnect'); | ||
const me = await models.User.getMeFromConnectionParams( | ||
connectionParams, | ||
); | ||
logger.debug({ me }, 'subscriptions:onConnect upgradeReq getMe'); | ||
if (me === undefined) { | ||
throw Error( | ||
'Can not find the session for this subscription request.', | ||
); | ||
} | ||
// add original upgrade request to the context | ||
return { me, upgradeReq: webSocket.upgradeReq, logger, }; | ||
}, | ||
onDisconnect: (webSocket, context) => { | ||
logger.debug( | ||
{ req_id: webSocket.upgradeReq.id, headers: context.request.headers }, | ||
'subscriptions:onDisconnect upgradeReq getMe', | ||
); | ||
}, | ||
}, | ||
}); | ||
return server; | ||
}; | ||
|
||
const stop = async (apollo) => { | ||
await apollo.db.connection.close(); | ||
await closeDistributedConnections(); | ||
await apollo.server.stop(); | ||
await apollo.httpServer.close(() => { | ||
console.log('🏄 Apollo Server closed.'); | ||
}); | ||
}; | ||
|
||
const apollo = async (options = {}) => { | ||
|
||
if (!process.env.AUTH_MODEL) { | ||
logger.error('apollo server is enabled, however AUTH_MODEL is not defined.'); | ||
process.exit(1); | ||
} | ||
|
||
try { | ||
const db = await connectDb(options.mongo_url); | ||
const mongoUrls = | ||
options.mongo_urls || | ||
process.env.MONGO_URLS || | ||
options.mongo_url || | ||
process.env.MONGO_URL || | ||
'mongodb://localhost:3001/meteor'; | ||
await setupDistributedCollections(mongoUrls); | ||
|
||
const app = options.app ? options.app : createDefaultApp(); | ||
router.use(ebl(getBunyanConfig('apollo'))); | ||
app.use(GRAPHQL_PATH, router); | ||
initModule.initApp(app, models, logger); | ||
|
||
const server = createApolloServer(); | ||
server.applyMiddleware({ app, path: GRAPHQL_PATH }); | ||
|
||
const httpServer = options.httpServer ? options.httpServer : http.createServer(app); | ||
server.installSubscriptionHandlers(httpServer); | ||
httpServer.on('listening', () => { | ||
const addrHost = httpServer.address().address; | ||
const addrPort = httpServer.address().port; | ||
logger.info( | ||
`🏄 Apollo server listening on http://[${addrHost}]:${addrPort}${GRAPHQL_PATH}`, | ||
); | ||
}); | ||
|
||
if (!options.httpServer) { | ||
let port = process.env.GRAPHQL_PORT || 8000; | ||
if (options.graphql_port !== undefined) { | ||
port = options.graphql_port; | ||
} | ||
httpServer.listen({ port }); | ||
} | ||
return { db, server, httpServer, stop}; | ||
} catch (err) { | ||
logger.error(err, 'Apollo api error'); | ||
process.exit(1); | ||
} | ||
}; | ||
|
||
module.exports = apollo; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/** | ||
* Copyright 2020 IBM Corp. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
const cors = require('cors'); | ||
const { SECRET } = require('./models/const'); | ||
|
||
const initApp = (app, models, logger) => { | ||
logger.info('Initialize apollo application for local auth'); | ||
app.use(cors()); | ||
}; | ||
|
||
const buildApolloContext = async ({ models, req, res, connection, logger }) => { | ||
if (connection) { | ||
logger.trace({ connection, req, res }, 'context websocket connection is'); | ||
return { | ||
models, | ||
me: connection.context.me, | ||
logger, | ||
}; | ||
} | ||
if (req) { | ||
const me = await models.User.getMeFromRequest(req); | ||
return { | ||
models, | ||
me, | ||
secret: SECRET, | ||
logger, | ||
}; | ||
} | ||
return { models, me: {}, logger }; | ||
}; | ||
|
||
module.exports = { initApp, buildApolloContext }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/** | ||
* Copyright 2020 IBM Corp. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
const bcrypt=require('bcrypt'); | ||
const passport=require('passport'); | ||
const GraphQLLocalStrategy=require('graphql-passport').GraphQLLocalStrategy; | ||
const buildContext=require('graphql-passport').buildContext; | ||
const { SECRET, GRAPHQL_PATH} = require('./models/const'); | ||
|
||
|
||
const initApp = (app, models, logger) => { | ||
logger.info('initialize apollo application for passport local auth'); | ||
passport.use( | ||
new GraphQLLocalStrategy(async function(email, password, done) { | ||
const matchingUser = await models.User.find({ | ||
'services.passportlocal.email': email, | ||
}); | ||
let error = matchingUser[0] ? null : new Error('No matching user'); | ||
if (matchingUser[0]) { | ||
const validPass = await bcrypt.compare( | ||
password, | ||
matchingUser[0].services.passportlocal.password, | ||
); | ||
error = validPass ? null : new Error('Password didn\'t match'); | ||
done(error, matchingUser[0]); | ||
} | ||
done(error); | ||
}), | ||
); | ||
app.use(GRAPHQL_PATH, passport.initialize()); | ||
}; | ||
|
||
const buildApolloContext = async ({models, req, res, connection, logger}) => { | ||
if (connection) { | ||
logger.debug({ connection }, 'context websocket connection is'); | ||
return buildContext({ | ||
req, | ||
res, | ||
models, | ||
me: connection.context.me, | ||
logger, | ||
}); | ||
} | ||
if (req) { | ||
const me = await models.User.getMeFromRequest(req); | ||
return buildContext({ | ||
req, | ||
res, | ||
models, | ||
me, | ||
secret: SECRET, | ||
logger, | ||
}); | ||
} | ||
return buildContext({ req, res, me: {}, logger, models }); | ||
}; | ||
|
||
module.exports = { initApp, buildApolloContext }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** | ||
* Copyright 2020 IBM Corp. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
const mongoose = require('mongoose'); | ||
const ClusterSchema = require('./cluster.schema'); | ||
|
||
const Cluster = mongoose.model('clusters', ClusterSchema); | ||
|
||
module.exports = Cluster; |
Oops, something went wrong.