Skip to content

Instantly share code, notes, and snippets.

@Falieson
Last active February 14, 2018 20:13
Show Gist options
  • Save Falieson/855abee65621191d78575b7f28b26191 to your computer and use it in GitHub Desktop.
Save Falieson/855abee65621191d78575b7f28b26191 to your computer and use it in GitHub Desktop.
GQL passport auth
// data/models/mongoose.ts
import * as mongoose from 'mongoose'
import {consoleError as handleError } from '../../utils/errors'
(mongoose as any).Promise = global.Promise // tslint:disable-line no-any
const ObjectIdType = mongoose.Schema.Types.ObjectId
const ObjectId = mongoose.Types.ObjectId
class MongooseModel {
Collection: mongoose.Model<mongoose.Document>
title = ''
schema = new mongoose.Schema({
_id: ObjectIdType
})
constructor({
title = 'CollectionName',
schema = {},
plugin,
pluginOptions = {},
}: {
title: string,
schema: any, // tslint:disable-line no-any
plugin?: any, // tslint:disable-line no-any
pluginOptions?: any, // tslint:disable-line no-any
} = {
schema: {}, // tslint:disable-line no-any
title: 'CollectionName',
}) { // tslint:disable-line no-any
this.title = title
this.addToSchema(schema)
if (plugin) {
this.addSchemaPlugin(plugin, pluginOptions)
}
this.init()
}
defaultReturn = (err: any, res: any) => { // tslint:disable-line no-any
if (err) {return handleError(err)}
return res
}
defaultRecord = () => ({
_id: new ObjectId()
})
init() {
return this.Collection = mongoose.model(this.title, this.schema)
}
addToSchema(schema: any) { // tslint:disable-line no-any
this.schema.add(schema)
}
addSchemaPlugin(plugin: any, options: any = {}) { // tslint:disable-line no-any
this.schema.plugin(plugin, options)
}
findOne(args: any = {}, cb: any = this.defaultReturn) { // tslint:disable-line no-any
return this.Collection.findOne(args, cb)
}
find(args: any = {}, cb: any = this.defaultReturn) { // tslint:disable-line no-any
return this.Collection.find(args, cb)
}
async create(obj: any = {}) { // tslint:disable-line no-any
const args = {
...this.defaultRecord(),
...obj
}
const record = new this.Collection(args)
try {
const savedRecord = await record.save()
return savedRecord
} catch (err) {
return handleError(err)
}
}
count(args: any = {}, cb: any = this.defaultReturn) { // tslint:disable-line no-any
return this.Collection.count(args, cb)
}
}
export default MongooseModelserver_index.ts
// data/models/Passport.ts
import * as mongoose from 'mongoose'
import * as passport from 'passport'
import * as passportLocalMongoose from 'passport-local-mongoose'
import Model from './mongoose'
(mongoose as any).Promise = global.Promise
const ObjectIdType = mongoose.Schema.Types.ObjectId
const Passport: any = new Model({
plugin: passportLocalMongoose,
pluginOptions: {
usernameUnique: true,
},
schema: {
userId: { type: ObjectIdType, ref: 'User' }
},
title : 'Passport',
})
Passport.register = function (obj: any, pass: any) {
return new Promise(resolve =>
this.Collection.register(obj, pass,
(err: any, res: any) => resolve(res)))
}
Passport.login = async function (ctx: any, user: string, pass: string) {
let res = {};
console.log('loginUser user> ', ctx.req.user) // should not be undefined after first
if (typeof ctx.req.user === 'undefined') {
ctx.req.body.username = user
ctx.req.body.password = pass
const auth = new Promise(function(resolve, reject) {
passport.authenticate('local', function(err, user, info) {
if (err) {
reject(err);
}
if (info && info.name && info.name.indexOf('Error') !== -1) {
reject(new Error(info.message));
}
if (!user) {
reject(new Error('No user returned'));
}
ctx.req.logIn(user, function(err: any) {
if (err) {
reject(err);
}
resolve(user);
});
})(ctx.req);
});
await auth
.then(user => {
res = user;
})
.catch(err => {
res = err;
});
} else {
res = new Error('Already logged in');
}
return res;
}
// data/schema.ts
import { makeExecutableSchema } from 'graphql-tools' // addMockFunctionsToSchema,
// import mocks from './mocks'
import resolvers from './resolvers'
const typeDefs = `
type Passport {
_id: String
username: String
userId: String
user: User
}
type Profile {
_id: String
firstName: String
lastName: String
userId: String
user: User
viewId: String
view: View
}
type User {
_id: String
username: String
passportId: String
passport: Passport
profileId: String
profile: Profile
}
type View {
_id: String
views: Int
profileId: String
profile: Profile
}
type Query {
me: User
user(_id: String, username: String): User
profile(userId: String): Profile
passport(userId: String): Passport
view: View
}
type Mutation {
addUser(username: String!, password: String!, firstName: String!, lastName: String!): User
loginUser(username: String!, password: String!): Passport
logoutUser(username: String!): Boolean
}
`
const schema = makeExecutableSchema({ typeDefs, resolvers })
// addMockFunctionsToSchema({ schema, mocks })
export default schema
/* tslint:disable no-console */
import * as events from 'events';
import { graphqlExpress } from 'apollo-server-express'
import * as bodyParser from 'body-parser'
import * as express from 'express'
import * as session from 'express-session'
import expressPlayground from 'graphql-playground-middleware-express'
import * as mongoose from 'mongoose'
import * as passport from 'passport'
import { openMongo } from '../data/connectors'
import { Passport } from '../data/'
import schema from '../data/schema'
import { webaddress } from '../utils/string'
import { GRAPHQL_EXPLORE, GRAPHQL_PORT, GRAPHQL_REST } from './config'
const app = express()
const mongoStore = require('connect-mongo')(session) // tslint:disable-line no-var-requires
const env = process.env.NODE_ENV
class Loader extends events.EventEmitter {
constructor() {
super();
}
init() {
const self = this;
(mongoose as any).Promise = global.Promise
openMongo()
app.use(bodyParser.json());
// PASSPORT CONFIG
passport.use(Passport.Collection.createStrategy())
passport.serializeUser(Passport.Collection.serializeUser())
passport.deserializeUser(Passport.Collection.deserializeUser())
app.use(passport.initialize());
app.use(passport.session());
app.use(
session({
secret: 'keyboard cat',
saveUninitialized: true,
resave: true,
store: new mongoStore({ mongooseConnection: mongoose.connection })
})
);
// GQL ENDPOINT CONFIG
const rootValue = {
me: function (args: any, req: any) {
return req.user;
}
}
app.use(
GRAPHQL_REST,
bodyParser.json(),
graphqlExpress((req, res) => {
// console.log('user: ', req.user);
return {
schema,
rootValue,
context: {req}
}
})
)
// GQL PLAYGROUND CONFIG
app.use(GRAPHQL_EXPLORE, expressPlayground({ endpoint: GRAPHQL_REST}))
// APP STARTUP
app.listen(GRAPHQL_PORT, () => {
self.emit('server.loaded');
// tslint:disable-next-line no-console
console.log(`\n\n\n\n\n\n\n\n\n
๐ŸŒ GraphQL Server ๐ŸŒ
๐ŸŽฎ ${webaddress({ // explorer
path: GRAPHQL_EXPLORE,
port: GRAPHQL_PORT,
})}
๐Ÿ“ก ${webaddress({ // endpoint
path: GRAPHQL_REST,
port: GRAPHQL_PORT,
})}
`)
})
if (env === 'development' || env === null) {
// NOTE: NODEMON ISSUE
process.on('SIGINT', () => {
console.log('Bye bye!') // tslint:disable-line no-console
process.exit() // eslint-disable-line no-process-exit
})
}
}
}
export default new Loader();
import Server from './server';
Server.init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment