fuck it call it v0
This commit is contained in:
parent
e51ccfa79c
commit
2c24f0878f
@ -2,3 +2,4 @@ DEFAULT_USER_PASSWORD=
|
|||||||
ROOT_DOMAIN=
|
ROOT_DOMAIN=
|
||||||
DATA_ROOT=
|
DATA_ROOT=
|
||||||
PORT=
|
PORT=
|
||||||
|
PROTO=
|
31
src/auth.ts
31
src/auth.ts
@ -59,3 +59,34 @@ export function sessionValidate(session: string): string|null {
|
|||||||
const row = sessionUserResponse.parse(rawrow);
|
const row = sessionUserResponse.parse(rawrow);
|
||||||
return row.user;
|
return row.user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const canCreateNewUsersResponse = z.object({
|
||||||
|
allowNewUserCreation: z.number()
|
||||||
|
});
|
||||||
|
export function canCreateNewUsers(username: string): boolean {
|
||||||
|
const rawrow = db.prepare("SELECT allowNewUserCreation FROM users WHERE username = ?").get(username);
|
||||||
|
if (!rawrow) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const row = canCreateNewUsersResponse.parse(rawrow);
|
||||||
|
|
||||||
|
return row.allowNewUserCreation === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createNewUser(username: string, password: string, allowNewUserCreation: boolean) {
|
||||||
|
db.prepare(`INSERT INTO users(username, passwordHash, allowNewUserCreation) VALUES(?, ?, ?)
|
||||||
|
ON CONFLICT DO NOTHING`).run(username, await argon2.hash(password, {
|
||||||
|
timeCost: 5
|
||||||
|
}), allowNewUserCreation ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updatePassword(username: string, password: string) {
|
||||||
|
db.prepare(`UPDATE users SET passwordHash = ? WHERE username = ?`).run(await argon2.hash(password, {
|
||||||
|
timeCost: 5
|
||||||
|
}), username);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteSession(sid: string) {
|
||||||
|
db.prepare(`DELETE FROM sessions WHERE id = ?`).run(sid);
|
||||||
|
}
|
@ -20,3 +20,8 @@ if (!process.env["PORT"] || !parseInt(process.env["PORT"]) || parseInt(process.e
|
|||||||
throw new Error("PORT must be set and be an integer between 1 and 65535");
|
throw new Error("PORT must be set and be an integer between 1 and 65535");
|
||||||
}
|
}
|
||||||
export const Port: number = parseInt(process.env["PORT"]);
|
export const Port: number = parseInt(process.env["PORT"]);
|
||||||
|
|
||||||
|
if (!process.env["PROTO"]) {
|
||||||
|
throw new Error("PROTO must be set");
|
||||||
|
}
|
||||||
|
export const Protocol: string = process.env["PROTO"];
|
@ -45,12 +45,12 @@ export function getGame(name: string): z.infer<typeof manifest> {
|
|||||||
return manifestCache.get(name)!;
|
return manifestCache.get(name)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLocalStorageDatabaseForUser(name: string, user: string): Database.Database {
|
export function getStorageDatabaseForUser(storageName: string, name: string, user: string): Database.Database {
|
||||||
if (!manifestCache.has(name)) throw new Error("no game (ps5 reference)");
|
if (!manifestCache.has(name)) throw new Error("no game (ps5 reference)");
|
||||||
|
|
||||||
mkdirSync(join(DataRoot, "storage", user, name), { recursive: true });
|
mkdirSync(join(DataRoot, "storage", user, name), { recursive: true });
|
||||||
|
|
||||||
const db = new Database(join(DataRoot, "storage", user, name, "localStorage.db"));
|
const db = new Database(join(DataRoot, "storage", user, name, storageName + ".db"));
|
||||||
db.pragma("journal_mode = WAL");
|
db.pragma("journal_mode = WAL");
|
||||||
|
|
||||||
db.exec("CREATE TABLE IF NOT EXISTS kv(key TEXT PRIMARY KEY, value TEXT)");
|
db.exec("CREATE TABLE IF NOT EXISTS kv(key TEXT PRIMARY KEY, value TEXT)");
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import express from "express";
|
import express from "express";
|
||||||
import { sessionValidate } from "./auth.js";
|
import { sessionValidate } from "./auth.js";
|
||||||
import "./game.js";
|
import "./game.js";
|
||||||
import { getGame, getLocalStorageDatabaseForUser } from "./game.js";
|
import { getGame, getStorageDatabaseForUser } from "./game.js";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { DataRoot, RootDomain } from "./env.js";
|
import { DataRoot, RootDomain } from "./env.js";
|
||||||
import mime from "mime";
|
import mime from "mime";
|
||||||
@ -53,8 +53,13 @@ postauthRouter.get("/cgi-bin/rpc/dollhouse_authenticate", (req, res) => {
|
|||||||
|
|
||||||
postauthRouter.use("/cgi-bin/static", express.static(path.join(base, "injections")));
|
postauthRouter.use("/cgi-bin/static", express.static(path.join(base, "injections")));
|
||||||
|
|
||||||
postauthRouter.get("/cgi-bin/rpc/ls/read_all", (req, res) => {
|
postauthRouter.get("/cgi-bin/rpc/storage/:name/read_all", (req, res) => {
|
||||||
const db = getLocalStorageDatabaseForUser(req.game, req.active_user);
|
if (!(["localStorage", "sessionStorage"]).includes(req.params.name)) {
|
||||||
|
res.status(400).send("Bad Request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = getStorageDatabaseForUser(req.params.name, req.game, req.active_user);
|
||||||
|
|
||||||
const results = db.prepare("SELECT * FROM kv").all();
|
const results = db.prepare("SELECT * FROM kv").all();
|
||||||
db.close();
|
db.close();
|
||||||
@ -66,11 +71,19 @@ const upsertRequest = z.object({
|
|||||||
value: z.string()
|
value: z.string()
|
||||||
});
|
});
|
||||||
|
|
||||||
postauthRouter.post("/cgi-bin/rpc/ls/upsert", express.json({
|
postauthRouter.post("/cgi-bin/rpc/storage/:name/upsert", express.json({
|
||||||
limit: 1024 * 1024 * 1024 * 16
|
limit: 1024 * 1024 * 1024 * 16,
|
||||||
|
type: () => true
|
||||||
}), (req, res) => {
|
}), (req, res) => {
|
||||||
|
if (!(["localStorage", "sessionStorage"]).includes(req.params.name)) {
|
||||||
|
res.status(400).send("Bad Request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = getStorageDatabaseForUser(req.params.name, req.game, req.active_user);
|
||||||
const body = upsertRequest.parse(req.body);
|
const body = upsertRequest.parse(req.body);
|
||||||
const db = getLocalStorageDatabaseForUser(req.game, req.active_user);
|
|
||||||
|
console.log("It is quite upserting", req.params.name, body.key);
|
||||||
|
|
||||||
db.prepare("INSERT INTO kv(key, value) VALUES(?, ?) ON CONFLICT (key) DO UPDATE SET value = ? WHERE key = ?").run(
|
db.prepare("INSERT INTO kv(key, value) VALUES(?, ?) ON CONFLICT (key) DO UPDATE SET value = ? WHERE key = ?").run(
|
||||||
body.key,
|
body.key,
|
||||||
@ -87,9 +100,16 @@ const removeRequest = z.object({
|
|||||||
key: z.string()
|
key: z.string()
|
||||||
});
|
});
|
||||||
|
|
||||||
postauthRouter.post("/cgi-bin/rpc/ls/remove", express.json(), (req, res) => {
|
postauthRouter.post("/cgi-bin/rpc/storage/:name/remove", express.json({
|
||||||
|
type: () => true
|
||||||
|
}), (req, res) => {
|
||||||
|
if (!(["localStorage", "sessionStorage"]).includes(req.params.name)) {
|
||||||
|
res.status(400).send("Bad Request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = getStorageDatabaseForUser(req.params.name, req.game, req.active_user);
|
||||||
const body = removeRequest.parse(req.body);
|
const body = removeRequest.parse(req.body);
|
||||||
const db = getLocalStorageDatabaseForUser(req.game, req.active_user);
|
|
||||||
|
|
||||||
db.prepare("DELETE FROM kv WHERE key = ?").run(
|
db.prepare("DELETE FROM kv WHERE key = ?").run(
|
||||||
body.key
|
body.key
|
||||||
@ -99,8 +119,13 @@ postauthRouter.post("/cgi-bin/rpc/ls/remove", express.json(), (req, res) => {
|
|||||||
res.json({ ok: true });
|
res.json({ ok: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
postauthRouter.post("/cgi-bin/rpc/ls/clear", (req, res) => {
|
postauthRouter.post("/cgi-bin/rpc/storage/:name/clear", (req, res) => {
|
||||||
const db = getLocalStorageDatabaseForUser(req.game, req.active_user);
|
if (!(["localStorage", "sessionStorage"]).includes(req.params.name)) {
|
||||||
|
res.status(400).send("Bad Request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = getStorageDatabaseForUser(req.params.name, req.game, req.active_user);
|
||||||
|
|
||||||
db.prepare("DELETE FROM kv").run();
|
db.prepare("DELETE FROM kv").run();
|
||||||
db.close();
|
db.close();
|
||||||
|
@ -2,160 +2,185 @@
|
|||||||
// Local Storage TODOs:
|
// Local Storage TODOs:
|
||||||
// - Consistent order operation with the server
|
// - Consistent order operation with the server
|
||||||
// - Compressing requests
|
// - Compressing requests
|
||||||
|
// - websocket and firing storage events
|
||||||
|
|
||||||
const backingStore = new Map();
|
function createStorage(name) {
|
||||||
let keys = [];
|
const backingStore = new Map();
|
||||||
|
let keys = [];
|
||||||
|
|
||||||
function getKey(key) {
|
function post(endpoint, body) {
|
||||||
console.log("[LocalStorageTracker] [G]", key);
|
fetch("/cgi-bin/rpc/storage/" + name + "/" + endpoint, {
|
||||||
|
method: "POST",
|
||||||
if (backingStore.has(key.toString())) {
|
body: JSON.stringify(body),
|
||||||
return backingStore.get(key.toString());
|
headers: {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
}).then(res => res.json()).then(r => {
|
||||||
|
if (r.ok) {
|
||||||
|
console.log("Sync ok");
|
||||||
|
} else {
|
||||||
|
console.error("Sync fucked");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
function getKey(key) {
|
||||||
}
|
if (backingStore.has(key.toString())) {
|
||||||
|
return backingStore.get(key.toString());
|
||||||
function setKey(key, value) {
|
|
||||||
console.log("[LocalStorageTracker] [S]", key, value);
|
|
||||||
|
|
||||||
fetch("/cgi-bin/rpc/ls/upsert", {
|
|
||||||
body: JSON.stringify({
|
|
||||||
key: key.toString(),
|
|
||||||
value: value.toString()
|
|
||||||
}),
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
},
|
|
||||||
method: "POST"
|
|
||||||
}).then(res => res.json()).then(r => {
|
|
||||||
if (r.ok) {
|
|
||||||
console.log("Sync ok");
|
|
||||||
} else {
|
|
||||||
console.error("Sync fucked");
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
if (keys.indexOf(key.toString()) === -1) {
|
return null;
|
||||||
keys.push(key.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
backingStore.set(key.toString(), value.toString());
|
function hasKey(key) {
|
||||||
}
|
return backingStore.has(key.toString());
|
||||||
|
}
|
||||||
|
|
||||||
function removeKey(key) {
|
function setKey(key, value) {
|
||||||
console.log("[LocalStorageTracker] [R]", key);
|
// navigator.sendBeacon("/cgi-bin/rpc/storage/" + name + "/upsert", JSON.stringify({
|
||||||
|
// key: key.toString(),
|
||||||
|
// value: value.toString()
|
||||||
|
// }))
|
||||||
|
if (name === "sessionStorage") {
|
||||||
|
try {
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("POST", "/cgi-bin/rpc/storage/" + name + "/upsert", false);
|
||||||
|
xhr.send(JSON.stringify({
|
||||||
|
key: key.toString(),
|
||||||
|
value: value.toString()
|
||||||
|
}));
|
||||||
|
} catch(e) {
|
||||||
|
// fucking try anything idk
|
||||||
|
post("upsert", {
|
||||||
|
key: key.toString(),
|
||||||
|
value: value.toString()
|
||||||
|
})
|
||||||
|
navigator.sendBeacon("/cgi-bin/rpc/storage/" + name + "/upsert", JSON.stringify({
|
||||||
|
key: key.toString(),
|
||||||
|
value: value.toString()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
post("upsert", {
|
||||||
|
key: key.toString(),
|
||||||
|
value: value.toString()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fetch("/cgi-bin/rpc/ls/remove", {
|
if (keys.indexOf(key.toString()) === -1) {
|
||||||
body: JSON.stringify({
|
keys.push(key.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
backingStore.set(key.toString(), value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeKey(key) {
|
||||||
|
post("remove", {
|
||||||
key: key.toString()
|
key: key.toString()
|
||||||
|
})
|
||||||
|
|
||||||
|
if (keys.indexOf(key.toString()) !== -1) {
|
||||||
|
keys = keys.filter(k => k !== key.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
backingStore.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear() {
|
||||||
|
post("clear", {});
|
||||||
|
|
||||||
|
keys = [];
|
||||||
|
|
||||||
|
backingStore.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getKeyByIndex(index) {
|
||||||
|
let realIndex = Number(index);
|
||||||
|
if (Number.isNaN(realIndex)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (realIndex < 0 || realIndex >= keys.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys[realIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
const api = {
|
||||||
|
"clear": clear,
|
||||||
|
"getItem": getKey,
|
||||||
|
"setItem": setKey,
|
||||||
|
"removeItem": removeKey,
|
||||||
|
"key": getKeyByIndex,
|
||||||
|
"__rdh_debug": function() {
|
||||||
|
console.log(keys, backingStore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(window, name, {
|
||||||
|
value: new Proxy({}, {
|
||||||
|
set(_, key, value, __) {
|
||||||
|
setKey(key, value);
|
||||||
|
},
|
||||||
|
get(_, k, __) {
|
||||||
|
if (api[k]) {
|
||||||
|
return api[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k === "length") {
|
||||||
|
return keys.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getKey(k);
|
||||||
|
},
|
||||||
|
ownKeys(_) {
|
||||||
|
return [...keys];
|
||||||
|
},
|
||||||
|
has(_, k) {
|
||||||
|
return hasKey(k);
|
||||||
|
},
|
||||||
|
getOwnPropertyDescriptor(_, k) {
|
||||||
|
const exists = hasKey(k);
|
||||||
|
if (!exists) return undefined;
|
||||||
|
return {
|
||||||
|
value: getKey(k),
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isExtensible() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
headers: {
|
writable: false,
|
||||||
"Content-Type": "application/json"
|
configurable: false
|
||||||
},
|
});
|
||||||
method: "POST"
|
|
||||||
}).then(res => res.json()).then(r => {
|
|
||||||
if (r.ok) {
|
|
||||||
console.log("Sync ok");
|
|
||||||
} else {
|
|
||||||
console.error("Sync fucked");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (keys.indexOf(key.toString()) !== -1) {
|
const xhr = new XMLHttpRequest();
|
||||||
keys = keys.filter(k => k !== key.toString());
|
xhr.open("GET", "/cgi-bin/rpc/storage/" + name + "/read_all", false);
|
||||||
|
xhr.send(null);
|
||||||
|
|
||||||
|
if (xhr.status !== 200) {
|
||||||
|
alert("it appears to be fucked");
|
||||||
|
window.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
backingStore.delete(key);
|
const responseBody = JSON.parse(xhr.responseText);
|
||||||
}
|
for (let { key, value } of responseBody) {
|
||||||
|
keys.push(key);
|
||||||
function clear() {
|
backingStore.set(key, value);
|
||||||
console.log("[LocalStorageTracker] [C]");
|
|
||||||
|
|
||||||
fetch("/cgi-bin/rpc/ls/clear", {
|
|
||||||
body: JSON.stringify({}),
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
},
|
|
||||||
method: "POST"
|
|
||||||
}).then(res => res.json()).then(r => {
|
|
||||||
if (r.ok) {
|
|
||||||
console.log("Sync ok");
|
|
||||||
} else {
|
|
||||||
console.error("Sync fucked");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
keys = [];
|
|
||||||
|
|
||||||
backingStore.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getKeyByIndex(index) {
|
|
||||||
console.log("[LocalStorageTracker] [K]", index);
|
|
||||||
|
|
||||||
let realIndex = Number(index);
|
|
||||||
if (Number.isNaN(realIndex)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (realIndex < 0 || realIndex >= keys.length) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return keys[realIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
const api = {
|
|
||||||
"clear": clear,
|
|
||||||
"getItem": getKey,
|
|
||||||
"setItem": setKey,
|
|
||||||
"removeItem": removeKey,
|
|
||||||
"key": getKeyByIndex,
|
|
||||||
"__rdh_debug": function() {
|
|
||||||
console.log(keys, backingStore);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.defineProperty(window, "localStorage", {
|
|
||||||
value: new Proxy({}, {
|
|
||||||
set(_, key, value, __) {
|
|
||||||
setKey(key, value);
|
|
||||||
},
|
|
||||||
get(_, k, __) {
|
|
||||||
if (api[k]) {
|
|
||||||
return api[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (k === "length") {
|
let deadline = Date.now() + 1000;
|
||||||
return keys.length;
|
while (Date.now() < deadline){};
|
||||||
}
|
|
||||||
|
|
||||||
return getKey(k);
|
createStorage("localStorage");
|
||||||
},
|
createStorage("sessionStorage");
|
||||||
ownKeys(_) {
|
|
||||||
return [...keys];
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
writable: false,
|
|
||||||
configurable: false
|
|
||||||
});
|
|
||||||
|
|
||||||
// Populate it with our initial values
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open("GET", "/cgi-bin/rpc/ls/read_all", false);
|
|
||||||
xhr.send(null);
|
|
||||||
|
|
||||||
if (xhr.status !== 200) {
|
|
||||||
alert("it appears to be fucked");
|
|
||||||
window.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
const responseBody = JSON.parse(xhr.responseText);
|
|
||||||
for (let { key, value } of responseBody) {
|
|
||||||
keys.push(key);
|
|
||||||
backingStore.set(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DIE. DIE. DIE. (IndexedDB is hell to implement. I will do it later, for now zap it away so games fall back to localstorage.)
|
// DIE. DIE. DIE. (IndexedDB is hell to implement. I will do it later, for now zap it away so games fall back to localstorage.)
|
||||||
Object.defineProperty(window, "indexedDB", {
|
Object.defineProperty(window, "indexedDB", {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import express, { urlencoded } from "express";
|
import express, { urlencoded } from "express";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import z from "zod";
|
import z from "zod";
|
||||||
import { authenticate, sessionValidate } from "./auth.js";
|
import { authenticate, canCreateNewUsers, createNewUser, deleteSession, sessionValidate, updatePassword } from "./auth.js";
|
||||||
import { getAllGames } from "./game.js";
|
import { getAllGames } from "./game.js";
|
||||||
import { RootDomain } from "./env.js";
|
import { Protocol, RootDomain } from "./env.js";
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const preauthRouter = express.Router();
|
const preauthRouter = express.Router();
|
||||||
@ -43,13 +43,75 @@ preauthRouter.post("/", async (req, res) => {
|
|||||||
postauthRouter.get("/", (req, res) => {
|
postauthRouter.get("/", (req, res) => {
|
||||||
let html = `<h1>Available games</h1><ul>`;
|
let html = `<h1>Available games</h1><ul>`;
|
||||||
for (let game of getAllGames()) {
|
for (let game of getAllGames()) {
|
||||||
html = html + `<li><a href="${req.protocol}://${game.slug}.${RootDomain}/cgi-bin/rpc/dollhouse_authenticate?sid=${req.cookies["rdh_sid"]}">${game.name}</a></li>`
|
html = html + `<li><a href="${Protocol}://${game.slug}.${RootDomain}/cgi-bin/rpc/dollhouse_authenticate?sid=${req.cookies["rdh_sid"]}">${game.name}</a></li>`
|
||||||
}
|
}
|
||||||
html = html + "</ul>"
|
html = html + "</ul>"
|
||||||
|
|
||||||
|
if (canCreateNewUsers(req.active_user)) {
|
||||||
|
html = html + `<br><h1>Create a new user</h1><form action='/create_user' method='POST'>
|
||||||
|
<label>Username: <input type="username" name="username"></label><br/>
|
||||||
|
<label>Password: <input type="password" name="password"></label><br/>
|
||||||
|
<label>Allow new user creation: <input type="checkbox" name="allow"></label><br/>
|
||||||
|
<input type="submit">
|
||||||
|
</form>`
|
||||||
|
}
|
||||||
|
|
||||||
|
html = html + `<br><h1>Change password</h1><form action='/change_password' method='POST'>
|
||||||
|
<label>New Password: <input type="password" name="password"></label><br/>
|
||||||
|
<input type="submit">
|
||||||
|
</form>
|
||||||
|
<form action='/delete_session' method='POST'>
|
||||||
|
<input type="hidden" name="deletion" value="delete">
|
||||||
|
<input type="submit" value="Delete Session">
|
||||||
|
</form>`
|
||||||
res.set("Content-Type", "text/html;charset=UTF-8");
|
res.set("Content-Type", "text/html;charset=UTF-8");
|
||||||
res.send(html);
|
res.send(html);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const createPayload = z.object({
|
||||||
|
username: z.string(),
|
||||||
|
password: z.string(),
|
||||||
|
allow: z.optional(z.literal("on"))
|
||||||
|
});
|
||||||
|
postauthRouter.post('/create_user', urlencoded(), (req, res) => {
|
||||||
|
if (!canCreateNewUsers(req.active_user)) {
|
||||||
|
res.status(401).send("Unauthorized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = createPayload.parse(req.body);
|
||||||
|
const allow = body.allow === "on";
|
||||||
|
|
||||||
|
createNewUser(body.username, body.password, allow);
|
||||||
|
|
||||||
|
res.set('Location', '/');
|
||||||
|
res.status(303).send("Welcome");
|
||||||
|
});
|
||||||
|
|
||||||
|
const changePasswordPayload = z.object({
|
||||||
|
password: z.string()
|
||||||
|
});
|
||||||
|
postauthRouter.post('/change_password', urlencoded(), (req, res) => {
|
||||||
|
const body = changePasswordPayload.parse(req.body);
|
||||||
|
|
||||||
|
updatePassword(req.active_user, body.password);
|
||||||
|
|
||||||
|
res.set('Location', '/');
|
||||||
|
res.status(303).send("Welcome");
|
||||||
|
})
|
||||||
|
|
||||||
|
const deleteSessionPayload = z.object({
|
||||||
|
deletion: z.literal('delete')
|
||||||
|
});
|
||||||
|
postauthRouter.post('/delete_session', urlencoded(), (req, res) => {
|
||||||
|
deleteSessionPayload.parse(req.body);
|
||||||
|
|
||||||
|
deleteSession(req.cookies["rdh_sid"]);
|
||||||
|
|
||||||
|
res.set('Location', '/');
|
||||||
|
res.status(303).send("Welcome");
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
router.use((req, res, next) => {
|
router.use((req, res, next) => {
|
||||||
const session = req.cookies["rdh_sid"];
|
const session = req.cookies["rdh_sid"];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user