diff --git a/docker-compose.yml b/docker-compose.yml index cca8c36..e3f71c8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,6 +6,14 @@ services: ports: - 31346:6379 + reddichat_phpredisadmin: + image: erikdubbelboer/phpredisadmin:latest + environment: + - REDIS_1_HOST=reddichat_redis + - REDIS_1_NAME=reddichat + labels: + - 'traefik.frontend.rule=Host:phpredisadmin.reddichat.localhost' + reddichat_mysql: image: mysql:8 ports: diff --git a/src/client/index.scss b/src/client/index.scss index 2a0afb1..64e7c4a 100644 --- a/src/client/index.scss +++ b/src/client/index.scss @@ -73,7 +73,6 @@ code { } label { - align-items: left; background-color: rgba(255, 255, 255, 0.025); color: #ffffff; display: flex; diff --git a/src/server/app.js b/src/server/app.js index 098d148..2b21ed2 100644 --- a/src/server/app.js +++ b/src/server/app.js @@ -1,24 +1,9 @@ import express from 'express'; -import httpSession from 'express-session'; -import passport from 'passport'; -import {allModels} from './models/registrar'; import userRoutes from './routes/user'; +import passport from './passport'; import session from './session'; -let insideSession; - -passport.serializeUser((user, fn) => fn(null, user.id)); -passport.deserializeUser(async (id, fn) => { - const {User} = allModels(); - try { - fn(undefined, await User.findByPk(id)); - } - catch (error) { - fn(error); - } -}); - export default function createApp() { const app = express(); app.use(express.urlencoded({extended: true})); diff --git a/src/server/db.js b/src/server/db.js index db040bb..8d56e1d 100644 --- a/src/server/db.js +++ b/src/server/db.js @@ -8,7 +8,7 @@ import {allModels} from './models/registrar'; let map; export async function createDatabaseConnection() { - const Models = allModels(); + const Models = Object.values(allModels()); const sequelize = new Sequelize(mysqlOrigin); Models.filter((Model) => Model.attributes).forEach((Model) => { Model.init(Model.attributes, { diff --git a/src/server/http.js b/src/server/http.js index 06fe033..d58fdd1 100644 --- a/src/server/http.js +++ b/src/server/http.js @@ -36,7 +36,6 @@ export function createHttpServer() { res.sendFile(join(__dirname, '..', 'client', 'index.html')); }); } - return httpServer; } diff --git a/src/server/models/registrar.js b/src/server/models/registrar.js index ab71a52..f628278 100644 --- a/src/server/models/registrar.js +++ b/src/server/models/registrar.js @@ -5,10 +5,6 @@ import {all} from './models.scwp'; const modelTo = new Map(); const nameTo = new Map(); -export function allModels() { - return Object.entries(all()).map(([, M]) => M.default); -} - let hasMapped = false; function ensureNameMap() { if (!hasMapped) { @@ -33,6 +29,11 @@ registerHooks({ }, }, module.id); +export function allModels() { + ensureNameMap(); + return Array.from(nameTo.entries()).reduce((r, [key, M]) => ({...r, [key]: M}), {}); +} + export function lookupModel(name) { ensureNameMap(); return nameTo.get(name); diff --git a/src/server/models/user.model.js b/src/server/models/user.model.js index 2ebc45f..5561b8c 100644 --- a/src/server/models/user.model.js +++ b/src/server/models/user.model.js @@ -1,3 +1,6 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import {randomBytes} from 'crypto'; + import bcrypt from 'bcrypt'; import {registerHooks} from 'scwp'; import {DataTypes as Types} from 'sequelize'; @@ -44,12 +47,24 @@ User.saltRounds = 10; export default User; registerHooks({ - replCommands: () => ({ + replCommands: (socket) => ({ createUser: (spec) => { const [email, maybePassword] = spec.split(' ', 2); - const password = maybePassword || crypto.randomBytes(8).toString('hex'); + const password = maybePassword || randomBytes(8).toString('hex'); const user = User.build({email}); user.addHashedPassword(password).then(() => user.save()); }, + resetPassword: async (email) => { + const password = randomBytes(8).toString('hex'); + const user = await User.findOne({where: {email}}); + if (user) { + user.addHashedPassword(password) + .then(() => user.save()) + // eslint-disable-next-line no-console + .then(() => socket.write(`New password:\n\n${password}\n`)); + } + // eslint-disable-next-line no-console + console.log('User not found.'); + }, }), }, module.id); diff --git a/src/server/passport.js b/src/server/passport.js new file mode 100644 index 0000000..b3adfd9 --- /dev/null +++ b/src/server/passport.js @@ -0,0 +1,16 @@ +import passport from 'passport'; + +import {allModels} from './models/registrar'; + +passport.serializeUser((user, fn) => fn(null, user.id)); +passport.deserializeUser(async (id, fn) => { + const {User} = allModels(); + try { + fn(undefined, await User.findByPk(id)); + } + catch (error) { + fn(error); + } +}); + +export default passport; diff --git a/src/server/repl.js b/src/server/repl.js index 7ca68a2..d248853 100644 --- a/src/server/repl.js +++ b/src/server/repl.js @@ -16,7 +16,7 @@ export function createReplServer() { replServer.context[key] = value; }); Object.entries( - invokeHookFlat('replCommands').reduce((r, commands) => ({...r, ...commands}), {}), + invokeHookFlat('replCommands', socket).reduce((r, commands) => ({...r, ...commands}), {}), ).forEach(([key, value]) => { replServer.defineCommand(key, value); }); diff --git a/src/server/session.js b/src/server/session.js index a989a9f..1da0618 100644 --- a/src/server/session.js +++ b/src/server/session.js @@ -1,7 +1,11 @@ import redis from 'redis'; import session from 'express-session'; -const redisClient = redis.createClient(); +import {redisOrigin} from '~/common/environment'; + +const [host = 'localhost', port = 31346] = redisOrigin.split(':'); +const redisClient = redis.createClient(port, host); + // eslint-disable-next-line import/newline-after-import const RedisStore = require('connect-redis')(session); diff --git a/src/server/sockets.js b/src/server/sockets.js index ac1d3b7..f290ca7 100644 --- a/src/server/sockets.js +++ b/src/server/sockets.js @@ -6,21 +6,26 @@ import socketSession from 'express-socket.io-session'; import {redisOrigin} from '~/common/environment'; +import passport from './passport'; import session from './session'; export function createSocketServer(httpServer) { - const [redisHost, redisPort] = redisOrigin.split(':'); + const [host = 'localhost', port = 31346] = redisOrigin.split(':'); const socketServer = new SocketServer(httpServer, { - adapter: redisAdapter({ - host: redisHost || 'localhost', - port: redisPort || 31346, - }), + adapter: redisAdapter({host, port}), + }); + socketServer.io.use(socketSession(session())); + socketServer.io.use((socket, next) => { + passport.initialize()(socket.handshake, undefined, next); + }); + socketServer.io.use((socket, next) => { + passport.session()(socket.handshake, undefined, next); }); socketServer.on('connect', (socket) => { + const {req} = socket; socket.on('packet', (packet, fn) => { }); }); - socketServer.io.use(socketSession(session())); return socketServer; }