const express = require("express"); const session = require("express-session"); const { Issuer } = require("openid-client"); const wol = require("wake_on_lan"); const { createTemplateRenderer } = require("./utils/templates.jsm"); require("dotenv").config(); const PORT = process.env.PORT || 3000; const COMPUTER_NAME = process.env.COMPUTER_NAME || "MyComputer"; const app = express(); app.use(express.json()); app.use( session({ secret: process.env.COOKIE_SECRET, saveUninitialized: false, cookie: { maxAge: 10 * 60 * 1000 }, }) ); const renderHtml = createTemplateRenderer({ useCache: process.env.NODE_ENV === "production", }); let client; (async () => { const issuer = await Issuer.discover(process.env.OIDC_WELL_KNOWN_URL); client = new issuer.Client({ client_id: process.env.CLIENT_ID, client_secret: process.env.CLIENT_SECRET, response_types: ["code"], }); app.get("/", (req, res) => { if (req.session.user) { res.send( renderHtml("index.html", { COMPUTER_NAME, USERNAME: req.session.user.sub, }) ); } else { res.send(renderHtml("login.html", { COMPUTER_NAME })); } }); const stateMap = {}; app.post("/authorize", (req, res) => { const { redirectUri } = req.body; if (!redirectUri) { return res.send( renderHtml("login-fail.html", { COMPUTER_NAME, ERROR: "redirectUri missing or invalid", }) ); } const state = Math.random().toString(36).substring(2); stateMap[state] = { redirectUri }; const url = client.authorizationUrl({ scope: "openid profile", redirect_uri: redirectUri, state, }); // 回傳 JSON 給前端,讓前端負責導向 res.json({ redirect: url }); }); app.get("/callback", async (req, res) => { try { const state = req.query.state; const { redirectUri } = stateMap[state]; const params = client.callbackParams(req); const tokenSet = await client.callback(redirectUri, params, { state }); const userinfo = await client.userinfo(tokenSet.access_token); req.session.user = userinfo; res.redirect("/"); } catch (error) { res.send(renderHtml("login-fail.html", { COMPUTER_NAME, ERROR: error })); } }); app.get("/wakeup", (req, res) => { if (!req.session.user) return res.redirect("/"); wol.wake(process.env.MAC_ADDRESS, (error) => { if (error) { res.send( renderHtml("wakeup-fail.html", { COMPUTER_NAME, ERROR: error }) ); } else { res.send(renderHtml("wakeup-success.html", { COMPUTER_NAME })); } }); }); app.post("/logout", (req, res) => { req.session.destroy(() => { res.redirect("/"); }); }); app.listen(PORT, () => { console.log(`wakeup3770 listening at http://localhost:${PORT}`); }); })();