|
| 1 | +import express from "express"; |
| 2 | +import { createServer } from "http"; |
| 3 | +import { Server } from "socket.io"; |
| 4 | +import session from "express-session"; |
| 5 | +import bodyParser from "body-parser"; |
| 6 | +import passport from "passport"; |
| 7 | +import { Strategy as LocalStrategy } from "passport-local"; |
| 8 | +import { dirname, join } from "node:path"; |
| 9 | +import { fileURLToPath } from "node:url"; |
| 10 | + |
| 11 | +const port = process.env.PORT || 3000; |
| 12 | + |
| 13 | +const app = express(); |
| 14 | +const httpServer = createServer(app); |
| 15 | + |
| 16 | +const sessionMiddleware = session({ |
| 17 | + secret: "changeit", |
| 18 | + resave: true, |
| 19 | + saveUninitialized: true, |
| 20 | +}); |
| 21 | + |
| 22 | +app.use(sessionMiddleware); |
| 23 | +app.use(bodyParser.urlencoded({ extended: false })); |
| 24 | +app.use(passport.initialize()); |
| 25 | +app.use(passport.session()); |
| 26 | + |
| 27 | +const __dirname = dirname(fileURLToPath(import.meta.url)); |
| 28 | + |
| 29 | +app.get("/", (req, res) => { |
| 30 | + if (!req.user) { |
| 31 | + return res.redirect("/login"); |
| 32 | + } |
| 33 | + res.sendFile(join(__dirname, "index.html")); |
| 34 | +}); |
| 35 | + |
| 36 | +app.get("/login", (req, res) => { |
| 37 | + if (req.user) { |
| 38 | + return res.redirect("/"); |
| 39 | + } |
| 40 | + res.sendFile(join(__dirname, "login.html")); |
| 41 | +}); |
| 42 | + |
| 43 | +app.post( |
| 44 | + "/login", |
| 45 | + passport.authenticate("local", { |
| 46 | + successRedirect: "/", |
| 47 | + failureRedirect: "/", |
| 48 | + }), |
| 49 | +); |
| 50 | + |
| 51 | +app.post("/logout", (req, res) => { |
| 52 | + const sessionId = req.session.id; |
| 53 | + req.session.destroy(() => { |
| 54 | + // disconnect all Socket.IO connections linked to this session ID |
| 55 | + io.to(`session:${sessionId}`).disconnectSockets(); |
| 56 | + res.status(204).end(); |
| 57 | + }); |
| 58 | +}); |
| 59 | + |
| 60 | +passport.use( |
| 61 | + new LocalStrategy((username, password, done) => { |
| 62 | + if (username === "john" && password === "changeit") { |
| 63 | + console.log("authentication OK"); |
| 64 | + return done(null, { id: 1, username }); |
| 65 | + } else { |
| 66 | + console.log("wrong credentials"); |
| 67 | + return done(null, false); |
| 68 | + } |
| 69 | + }), |
| 70 | +); |
| 71 | + |
| 72 | +passport.serializeUser((user, cb) => { |
| 73 | + console.log(`serializeUser ${user.id}`); |
| 74 | + cb(null, user); |
| 75 | +}); |
| 76 | + |
| 77 | +passport.deserializeUser((user, cb) => { |
| 78 | + console.log(`deserializeUser ${user.id}`); |
| 79 | + cb(null, user); |
| 80 | +}); |
| 81 | + |
| 82 | +const io = new Server(httpServer); |
| 83 | + |
| 84 | +io.engine.use(sessionMiddleware); |
| 85 | +io.engine.use(passport.initialize()); |
| 86 | +io.engine.use(passport.session()); |
| 87 | + |
| 88 | +io.engine.use( |
| 89 | + (req, res, next) => { |
| 90 | + if (req.user) { |
| 91 | + next(); |
| 92 | + } else { |
| 93 | + res.writeHead(401); |
| 94 | + res.end(); |
| 95 | + } |
| 96 | + }, |
| 97 | +); |
| 98 | + |
| 99 | +io.on("connection", (socket) => { |
| 100 | + const req = socket.request; |
| 101 | + |
| 102 | + socket.join(`session:${req.session.id}`); |
| 103 | + socket.join(`user:${req.user.id}`); |
| 104 | + |
| 105 | + socket.on("whoami", (cb) => { |
| 106 | + cb(req.user.username); |
| 107 | + }); |
| 108 | +}); |
| 109 | + |
| 110 | +httpServer.listen(port, () => { |
| 111 | + console.log(`application is running at: http://localhost:${port}`); |
| 112 | +}); |
0 commit comments