diff --git a/server/auth.js b/server/auth.js index b699630..dd904b5 100644 --- a/server/auth.js +++ b/server/auth.js @@ -14,16 +14,18 @@ export default class AuthHandler { } isLoggedInUser(req, res) { - const token = req.cookies.auth_token; // read cookie + const token = req.cookies.auth_token; if (!token) { - return false + return false; } try { - return true + const decoded = jwt.verify(token, process.env.JWT_SECRET); + req.user = decoded; + return true; } catch (err) { - return false + return false; } } diff --git a/server/db/db.js b/server/db/db.js index 0b82315..495b76b 100644 --- a/server/db/db.js +++ b/server/db/db.js @@ -1,7 +1,7 @@ import QuillDB from "../_/quilldb.js" export default class Database extends QuillDB { - + get = { user: (id) => { return this.nodes[id] diff --git a/server/index.js b/server/index.js index 6b15d46..ed81526 100644 --- a/server/index.js +++ b/server/index.js @@ -2,6 +2,7 @@ import express from 'express'; import cors from 'cors' import cookieParser from 'cookie-parser' import http from 'http' +import fs from 'fs' import chalk from 'chalk' import moment from 'moment' import path from 'path'; @@ -20,11 +21,13 @@ class Server { db; auth; UIPath = path.join(__dirname, '../ui') + DBPath = path.join(__dirname, '../db') registerRoutes(router) { // router.post('/api/location', handlers.updateLocation) router.post('/login', this.auth.login) router.get('/signout', this.auth.logout) + router.get('/db/images/*', this.getUserImage) router.get('/*', this.get) return router } @@ -49,24 +52,49 @@ class Server { } } + getUserImage = async (req, res) => { + function getFileByNumber(dir, number) { + const files = fs.readdirSync(dir); + const match = files.find(file => { + const base = path.parse(file).name; // filename without extension + return base === String(number); + }); + return match ? path.join(dir, match) : null; + } + let filePath = getFileByNumber(path.join(this.DBPath, "images"), path.basename(req.url)) + + res.sendFile(filePath) + } + get = async (req, res) => { if(!this.auth.isLoggedInUser(req, res)) { console.log("Not logged in") let url = req.url - if(url === "/") { - url = "/index.html" - } else if(!url.includes(".")) { // TODO: Make public app single-page - url = path.join("/pages", url) + ".html" - } - let filePath; - if(url.startsWith("/_")) { - filePath = path.join(this.UIPath, url); - } else { - filePath = path.join(this.UIPath, "public", url); - } + if(!url.includes(".")) { // Page request + if(url === "/") { + url = "/index.html" + } else { + url = path.join("/pages", url) + ".html" + } - res.sendFile(filePath); + let filePath = path.join(this.UIPath, "public", url); + res.sendFile(filePath, (err) => { + if (err) { + console.log("File not found, sending fallback:", filePath); + res.redirect("/"); + } + }); + } else { // File Request + let filePath; + if(url.startsWith("/_")) { + filePath = path.join(this.UIPath, url); + } else { + filePath = path.join(this.UIPath, "public", url); + } + + res.sendFile(filePath); + } } else { let url = req.url diff --git a/ui/_/code/quill.js b/ui/_/code/quill.js index 376deb9..ef9148a 100644 --- a/ui/_/code/quill.js +++ b/ui/_/code/quill.js @@ -1,6 +1,7 @@ /* Sam Russell Captured Sun + 11.9.25 - changed p(innerText) to p(innerHTML), adjusted onNavigate to work for multiple elements and with correct "this" scope 11.7.25 - changed registerShadow() to register(), changed onClick() to be like onHover() 11.6.25 - adding default value for "button()" "children" parameter 10.29.25 - adding "gap()" and "label()" functions @@ -562,12 +563,12 @@ HTMLImageElement.prototype.backgroundColor = function(value) { return this; // Always returns the element itself }; -window.p = function p(innerText) { +window.p = function p(innerHTML) { let el = document.createElement("p") if(typeof innerText === "function") { - el.render = innerText + el.render = innerHTML } else { - el.innerText = innerText + el.innerHTML = innerHTML } el.style.margin = "0"; quill.render(el) @@ -765,13 +766,15 @@ HTMLElement.prototype.onKeyDown = function(cb) { return this; }; -/* QUIRK 1: -In all the other callback functions, the user can choose the scope of "this". It can be either the parent shadow or the element itself. -This listener only allows for the latter functionality. This is because the navigate event fires on the window. -Without binding, "this" would refer only to the window. So here we are compromising on one of the two. +/* WHY THIS LISTENER IS THE WAY IT IS: +- If we dispatch the "navigate" event on the window (as one would expect for a "navigate" event), a listener placed on the element will not pick it up. +- However, if we add the event as a window event, it won't have the "this" scope that a callback normally would. +- Then, if we try to add that scope using bind(), it makes the function.toString() unreadable, which means we will get false positives for duplicate listeners. +- Therefore, we just have to attach the navigate event to the element, and manually trigger that when the window listener fires. */ HTMLElement.prototype.onNavigate = function(cb) { - window._storeListener(window, "navigate", cb.bind(this)); + this._storeListener("navigate", cb); + window.addEventListener("navigate", () => this.dispatchEvent(new CustomEvent("navigate"))) return this; }; diff --git a/ui/public/index.html b/ui/public/index.html index e8f8bb8..fab5fd2 100644 --- a/ui/public/index.html +++ b/ui/public/index.html @@ -3,7 +3,7 @@