import LinebridgeServer from 'linebridge/server' import bcrypt from 'bcrypt' import mongoose from 'mongoose' import passport from 'passport' import { User } from './models' import socketIo from 'socket.io' import http from "http" const b64Decode = global.b64Decode = (data) => { return Buffer.from(data, 'base64').toString('utf-8') } const b64Encode = global.b64Encode = (data) => { return Buffer.from(data, 'utf-8').toString('base64') } const JwtStrategy = require('passport-jwt').Strategy const ExtractJwt = require('passport-jwt').ExtractJwt const LocalStrategy = require('passport-local').Strategy const { Buffer } = require("buffer") class Server { constructor() { this.env = _env this.listenPort = this.env.listenPort ?? 3000 this.middlewares = require("./middlewares") this.controllers = require("./controllers") this.endpoints = require("./endpoints") this.instance = new LinebridgeServer({ listen: "0.0.0.0", middlewares: this.middlewares, controllers: this.controllers, endpoints: this.endpoints, port: this.listenPort }) this.server = this.instance.httpServer this.ioHttp = http.createServer() this.io = new socketIo.Server(this.ioHttp, { maxHttpBufferSize: 100000000, connectTimeout: 5000, transports: ['websocket', 'polling'], pingInterval: 25 * 1000, pingTimeout: 5000, allowEIO3: true, cors: { origin: "http://localhost:8000", methods: ["GET", "POST"], } }).of("/main") this.options = { jwtStrategy: { sessionLocationSign: this.instance.id, jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: this.instance.oskid, algorithms: ['sha1', 'RS256', 'HS256'], expiresIn: "1h" } } this.initialize() } async initialize() { await this.connectToDB() await this.initPassport() // register middlewares this.instance.middlewares["useJwtStrategy"] = (req, res, next) => { req.jwtStrategy = this.options.jwtStrategy next() } this.io.on("connection", (socket) => { console.log(socket.id) }) this.ioHttp.listen(9001) await this.instance.init() } getDBConnectionString() { const { db_user, db_driver, db_name, db_pwd, db_hostname, db_port } = _env return `${db_driver}://${db_user}:${db_pwd}@${db_hostname}:${db_port}/${db_name}` } connectToDB = () => { return new Promise((resolve, reject) => { try { console.log("🌐 Trying to connect to DB...") mongoose.connect(this.getDBConnectionString(), { useNewUrlParser: true, useUnifiedTopology: true }) .then((res) => { return resolve(true) }) .catch((err) => { return reject(err) }) } catch (err) { return reject(err) } }).then(done => { console.log(`✅ Connected to DB`) }).catch((error) => { console.log(`❌ Failed to connect to DB, retrying...\n`) console.log(error) setTimeout(() => { this.connectToDB() }, 1000) }) } setWebsocketRooms = () => { this.ws.register("/test", { onOpen: (socket) => { console.log(socket) setInterval(() => { socket.send("Hello") }, 1000) } }) this.ws.listen() } initPassport() { passport.use(new LocalStrategy({ usernameField: "username", passwordField: "password", session: false }, (username, password, done) => { User.findOne({ username: b64Decode(username) }).select('+password') .then((data) => { if (data === null) { return done(null, false, this.options.jwtStrategy) } else if (!bcrypt.compareSync(b64Decode(password), data.password)) { return done(null, false, this.options.jwtStrategy) } // create a token return done(null, data, this.options.jwtStrategy, { username, password }) }) .catch(err => done(err, null, this.options.jwtStrategy)) })) passport.use(new JwtStrategy(this.options.jwtStrategy, (token, callback) => { User.findOne({ _id: token.user_id }) .then((data) => { if (data === null) { return callback(null, false) } else { return callback(null, data, token) } }) .catch((err) => { return callback(err, null) }) })) this.server.use(passport.initialize()) } } new Server()