diff --git a/TODO.md b/TODO.md index 73ecee5..da1fad8 100644 --- a/TODO.md +++ b/TODO.md @@ -13,4 +13,6 @@ - [ ] A Forum - [ ] Make it easier to view journal entries - [x] Users can fuck with invite codes by using an invite code and then making an account with it and then having more invite codes SO MAKE IT The case that only users with the trusted status may Do that -- [ ] Private journals are stored in plaintext and can be found if a database breach happens, maybe (optionally?) encrypt them (with PGP keys?) +- [ ] Private journals are stored in plaintext and can be found if a database breach happens, maybe (optionally?) encrypt them (with PGP keys?) (or database encryption) +- [ ] What If mipilin Existed On Geminispace +- [ ] Failed requests that dont go through just redirect to other pages with a 200 or 302 when u SHOULD be using an external api that actually properly communicates these errors and just tells it to the frontend diff --git a/db/schema.ts b/db/schema.ts index 6d2be40..63ae53a 100644 --- a/db/schema.ts +++ b/db/schema.ts @@ -9,7 +9,7 @@ import { export const users = pgTable("users", { id: integer().primaryKey().generatedAlwaysAsIdentity(), - email: varchar().unique().notNull(), //! make this required on signup + email: varchar().unique().notNull(), name: varchar({ length: 26 }).unique().notNull(), pass: varchar({ length: 255 }).notNull(), registered: timestamp().notNull(), diff --git a/routes/login.ts b/routes/login.ts index a287d08..964637c 100644 --- a/routes/login.ts +++ b/routes/login.ts @@ -1,12 +1,10 @@ import { Express } from "express"; import bcrypt from "bcrypt"; -import { render } from "./util.js"; +import { render, validateEmail } from "./util.js"; import { NodePgDatabase } from "drizzle-orm/node-postgres"; import { follows, inviteCodes, profiles, users } from "../db/schema.js"; import { eq } from "drizzle-orm"; -//! TEMP Also not sanitized like at all -//! Also make sure user isnt logged in before doing this export default function(app: Express, db: NodePgDatabase) { app.get("/register", (req, res) => { if (req.session["loggedIn"]) { @@ -41,6 +39,11 @@ export default function(app: Express, db: NodePgDatabase) { res.redirect("/register"); return; } + if (!validateEmail(req.body.email)) { + req.flash("error", "That email is invalid or malformed."); + res.redirect("/register"); + return; + } //! dumb req.body.name = req.body.name.trim(); @@ -101,7 +104,7 @@ export default function(app: Express, db: NodePgDatabase) { //@ts-expect-error .values({ name: req.body.name, - email: req.body.email, //! Not actually validating this like at all??? + email: req.body.email, pass: hash, status: code.confers, registered: new Date(Date.now()) diff --git a/routes/users.ts b/routes/users.ts index 977543a..d2e9163 100644 --- a/routes/users.ts +++ b/routes/users.ts @@ -8,7 +8,7 @@ import { users } from "../db/schema.js"; import { and, desc, eq, ne } from "drizzle-orm"; -import { getMoods, render, render404, UserStatus } from "./util.js"; +import { getMoods, render, render404, UserStatus, validateUrl } from "./util.js"; import { PgColumn } from "drizzle-orm/pg-core"; import dayjs from "dayjs"; @@ -139,6 +139,11 @@ export default async function (app: Express, db: NodePgDatabase) { res.redirect("/login"); return; } + if (!validateUrl(req.body.website)) { + req.flash("error", "The website URL provided is invalid or malformed."); + res.redirect(req.get("Referrer") || "/"); + return; + } const { uname } = ( await db .select({ uname: users.name }) @@ -153,7 +158,7 @@ export default async function (app: Express, db: NodePgDatabase) { return; } - await db //! no sanitization here either BROOOOOOO + await db .update(profiles) .set({ // @ts-expect-error diff --git a/routes/util.ts b/routes/util.ts index cfe09a7..c8a8261 100644 --- a/routes/util.ts +++ b/routes/util.ts @@ -140,3 +140,12 @@ export function confirm( ) { render(db, "confirm", "Confirm action", res, req, { body: req.body, url: req.url }); } + +const emailRegex = /^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*$/i; +const urlRegex = /https?:\/\/(?:www\.)?(?:[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b)*(?:\/[\/\d\w\.-]*)*(?:[\?])*(?:.+)*/i; +export function validateEmail(email: string) { + return emailRegex.test(email); +} +export function validateUrl(url: string) { + return urlRegex.test(url); +}