Last active
November 8, 2022 08:25
-
-
Save loopmode/d9c0329b05f991a8d9e714cf18c27476 to your computer and use it in GitHub Desktop.
node+express+orientjs+passport+redis
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
// orientdb/adapter.js | |
import connect from './connect'; | |
import autobind from 'autobind-decorator'; | |
import applySchema from './applySchema'; | |
import createBaseData from './createBaseData'; | |
const EventEmitter = require('events'); | |
class OrientAdapter extends EventEmitter { | |
get db() { | |
return this._db; | |
} | |
get server() { | |
return this._server; | |
} | |
on(eventName, listener) { | |
if (eventName === 'connect' && this._db && this._server) { | |
listener({ db: this._db, server: this._server }); | |
return this; | |
} | |
return super.on(eventName, listener); | |
} | |
@autobind | |
async connect(config, callback) { | |
if (this._db && this._server) { | |
return { | |
db, | |
server | |
}; | |
} | |
const { db, server } = await connect(config); | |
db.query.log = query => { | |
console.log(query); | |
return db.query(query); | |
}; | |
await applySchema(db, config.db.schema); | |
await createBaseData(db); | |
this._db = db; | |
this._server = server; | |
this.emit('connect', { db, server }); | |
if (callback) { | |
callback(db, server); | |
} | |
return { db, server }; | |
} | |
@autobind | |
async disconnect() { | |
if (this._db) this._db.close(); | |
if (this._server) this._server.close(); | |
this._db = null; | |
this._server = null; | |
} | |
} | |
export default new OrientAdapter(); |
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
import express from 'express'; | |
import passport from 'passport'; | |
import sessionMiddleware from './middlewares/session-middleware'; | |
import redisErrorsMiddleware from './middlewares/redis-errors-middleware'; | |
export function create() { | |
const app = express(); | |
// session middleware before other middlewares | |
app.use(sessionMiddleware); | |
// ... custom middlewares ... | |
// passport after session middleware | |
app.use(passport.initialize()); | |
app.use(passport.session()); | |
// ... route definitions ... | |
// redis error middleware at very end | |
app.use(redisErrorsMiddleware); | |
return app; | |
} |
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
// orientdb/connect.js | |
import OrientDB from 'orientjs'; | |
/** | |
* Connects to an orientdb server and ensures the app database exists. | |
* Returns a `{server, db}` object. | |
* | |
* If the database specified in `config.db.use.name` or any class or property in `config.db.schema` does not exist, it is created. | |
* | |
* @param {object} config - Config object | |
* @param {object} config.server - The DB server config object | |
* @param {object} config.server.use - Settings for which DB server to use | |
* @param {string} config.server.use.host - | |
* @param {number} config.server.use.port - | |
* @param {number} config.server.use.httpPort - | |
* @param {string} config.server.use.username - | |
* @param {string} config.server.use.password - | |
* @param {string} config.server.use.pool - | |
* @param {object} config.db - The db config object | |
* @param {object} config.db.schema - Custom schema definition for `schema.applySchema()` | |
* @param {object} config.db.use - Settings for which database to use (`server.use()` options) | |
* @param {string} config.db.use.name - The name of the database to use | |
* @param {string} config.db.use.host - The hostname of the DB server to use | |
* @param {number} config.db.use.port - The port of the DB server to use | |
* @param {string} config.db.use.username - The username for connecting to the DB server | |
* @param {string} config.db.use.password - The password for connecting to the DB server | |
* @param {object} config.db.create - Settings for creating the database (`server.create()` options) | |
* @param {string} config.db.create.type - | |
* @param {string} config.db.create.storage - | |
* @param {array<array<string>>} config.db.schema.classes - An array of ['ClassName', 'ParentClassName'] arrays for classes to create in the database. | |
* | |
* @return {object} - An `{db, server}` object | |
* @property {object} db - The OrientDB database object | |
* @property {object} server - The OrientDB server object that holds te connection | |
*/ | |
export default async function connect(config) { | |
const server = await connectServer(config.server); | |
const db = await connectDB(server, config.db); | |
return { db, server }; | |
} | |
export function connectServer(settings) { | |
const server = OrientDB(settings.use); | |
if (server) { | |
return server; | |
} | |
throw new Error('Unable to connect to database server'); | |
} | |
export async function connectDB(server, { use, create }) { | |
const dbs = await server.list(); | |
const { name } = use; | |
if (!dbs.find(db => db.name === name)) { | |
await server.create({ name, ...create }); | |
} | |
const db = server.use(use); | |
if (db) { | |
return db; | |
} | |
throw new Error('Unable to connect to database'); | |
} |
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
// entry point | |
import config from './config'; | |
import { create as createApp } from './app'; | |
import initPassport from './initPassport'; | |
import OrientAdapter from './orientdb/adapter'; | |
export default async function init() { | |
try { | |
await OrientAdapter.connect(config.orientdb); | |
process.on('exit', OrientAdapter.disconnect); | |
const app = createApp(); | |
app.listen(config.app.server.port, error => { | |
if (error) throw error; | |
initPassport(); | |
}); | |
} catch (error) { | |
console.warn('Unable to connect to orientDB'); | |
console.error(error); | |
process.exit(1); | |
} | |
} | |
init(); |
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
import bcrypt from 'bcrypt'; | |
import passport from 'passport'; | |
import { Strategy as LocalStrategy } from 'passport-local'; | |
import User from './model/User'; | |
export function init() { | |
passport.serializeUser(function(user, done) { | |
done(null, user.username); | |
}); | |
passport.deserializeUser(async function(req, username, done) { | |
try { | |
const user = await User.getByUsername(username); | |
if (user) { | |
done(null, user); | |
} else { | |
done(null); | |
} | |
} catch (error) { | |
done(null, false); | |
} | |
}); | |
passport.use( | |
new LocalStrategy({ passReqToCallback: true }, async (req, username, password, done) => { | |
try { | |
const user = await User.getByUsername(username); | |
if (!user) { | |
return done(null, false); | |
} | |
if (await bcrypt.compare(password, user.password)) { | |
done(null, user); | |
} else { | |
done(null, false); | |
} | |
} catch (error) { | |
return done(error); | |
} | |
}) | |
); | |
passport.authenticationMiddleware = function authenticationMiddleware() { | |
return function(req, res, next) { | |
if (req.isAuthenticated()) { | |
return next(); | |
} | |
res.sendStatus(401); | |
}; | |
}; | |
} |
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
/** | |
* Handles specific redis errors. | |
* | |
* Workaround for when orientdb data gets dumped while | |
* a user is logged in and his session persists in redis | |
* todo: do not rely on error messages | |
* in such case we simply kill the users session so he must log in again | |
*/ | |
export default function redisErrorMiddleware(err, req, res, next) { | |
if (err && err.message.match('Failed to deserialize')) { | |
req.logout(); | |
req.session.destroy(); | |
} | |
next(); | |
} |
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
import config from '../config'; | |
import redis from 'redis'; | |
import session from 'express-session'; | |
import ConnectRedis from 'connect-redis'; | |
const redisClient = redis.createClient({ | |
host: config.redis.host, | |
port: config.redis.port | |
}); | |
const RedisStore = ConnectRedis(session); | |
export default session({ | |
store: new RedisStore({ | |
client: redisClient, | |
host: config.redis.host, | |
port: config.redis.port | |
}), | |
secret: config.app.session.secret, | |
cookie: { httpOnly: true, maxAge: config.app.session.maxAge }, | |
saveUninitialized: false, | |
resave: false, | |
rolling: true | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment