240 lines
6.9 KiB
JavaScript
240 lines
6.9 KiB
JavaScript
"use strict";
|
|
|
|
import { createServer, IncomingMessage, ServerResponse } from "http";
|
|
import { parse as urlParse } from "querystring";
|
|
import { readFileSync } from "fs";
|
|
import { createHash } from "crypto";
|
|
import { Router, route } from "./router.js";
|
|
import { getCookies, renderTemplate, redirect, consumePostForm, setCookies } from "./utils.js";
|
|
import { User, UserDB } from "./userdb.js";
|
|
|
|
const udb = new UserDB();
|
|
const hasher = (hashable) => createHash("sha256").update(hashable).digest("hex");
|
|
|
|
/**
|
|
*
|
|
* @param {IncomingMessage} req
|
|
* @param {ServerResponse} res
|
|
* @param {String} path
|
|
* @param {Object} params
|
|
*/
|
|
const mainPage = function (req, res, path, params) {
|
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
res.write(
|
|
`Hello on ${path}!\n You can go on: <br>` +
|
|
`1. Parameters display (in JSON): <a href="/sparamsAsJson?hello=i&am=JSON">*click*</a><br>` +
|
|
`2. Parameters display (in TEXT): <a href="/sparamsAsText?why=yes&i=am&a=plain+text">*click*</a><br>` +
|
|
`3. See some pretty cats: <a href="/showMeACat">*click*</a><br>` +
|
|
`4. Open dashboard: <a href="/dashboard">*click*</a>`
|
|
);
|
|
res.end();
|
|
}
|
|
|
|
const showParameters = function (type) {
|
|
const contentType = type === "JSON" ? "application/json" : "text/plain";
|
|
const serializer = type === "JSON" ? JSON.stringify : (obj => Array.from(Object.keys(obj)).map(e => `Key: ${e}; Value: ${obj[e]}`).join("\n"));
|
|
|
|
/**
|
|
*
|
|
* @param {IncomingMessage} req
|
|
* @param {ServerResponse} res
|
|
* @param {String} path
|
|
* @param {Object} params
|
|
*/
|
|
return function (req, res, path, params) {
|
|
res.writeHead(200, { "Content-Type": contentType });
|
|
res.write(serializer(params));
|
|
res.end();
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {IncomingMessage} req
|
|
* @param {ServerResponse} res
|
|
* @param {String} path
|
|
* @param {Object} params
|
|
*/
|
|
const showACat = function (req, res, path, params) {
|
|
res.writeHead(200, { "Content-Type": "image/png" });
|
|
res.write(readFileSync("./Cat_poster_1.png"));
|
|
res.end();
|
|
}
|
|
|
|
const router = new Router();
|
|
router.addRoute(route("GET", "/"), mainPage);
|
|
router.addRoute(route("GET", "/sparamsAsJson"), showParameters("JSON"));
|
|
router.addRoute(route("GET", "/sparamsAsText"), showParameters("TEXT"));
|
|
router.addRoute(route("GET", "/showMeACat"), showACat);
|
|
|
|
|
|
/**
|
|
*
|
|
* @param {IncomingMessage} req
|
|
* @param {ServerResponse} res
|
|
* @param {String} path
|
|
* @param {Object} params
|
|
*/
|
|
const userRegisterView = (req, res, path, params) => {
|
|
const cookies = getCookies(req);
|
|
if (cookies["user"]) return redirect(res, "/dashboard");
|
|
|
|
return renderTemplate(res, "./templates/register.html");
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {IncomingMessage} req
|
|
* @param {ServerResponse} res
|
|
* @param {String} path
|
|
* @param {Object} params
|
|
*/
|
|
const userRegister = async function (req, res, path, params) {
|
|
const cookies = getCookies(req);
|
|
if (cookies["user"]) return redirect(res, "/dashboard");
|
|
|
|
const response = {
|
|
ok: true,
|
|
message: ""
|
|
};
|
|
try {
|
|
const post = await consumePostForm(req);
|
|
console.log(post);
|
|
const login = post.login;
|
|
const password = post.password;
|
|
const passwordRepeated = post.passwordRepeated;
|
|
const status = udb.getUsersCount() === 0 ? "admin" : "user";
|
|
if (udb.hasUser(login)) {
|
|
throw new Error("User already exists!");
|
|
} else if (password != passwordRepeated) {
|
|
throw new Error("Passwords must match!");
|
|
} else {
|
|
udb.putUser(new User(login, hasher(password), status));
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
response.ok = false;
|
|
response.message = e.message;
|
|
}
|
|
|
|
res.statusCode = 200;
|
|
res.setHeader("Content-Type", "application/json");
|
|
res.write(JSON.stringify(response));
|
|
res.end();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {IncomingMessage} req
|
|
* @param {ServerResponse} res
|
|
* @param {String} path
|
|
* @param {Object} params
|
|
*/
|
|
const userLoginView = (req, res, path, params) => {
|
|
const cookies = getCookies(req);
|
|
if (cookies["user"]) return redirect(res, "/dashboard");
|
|
|
|
return renderTemplate(res, "./templates/login.html");
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {IncomingMessage} req
|
|
* @param {ServerResponse} res
|
|
* @param {String} path
|
|
* @param {Object} params
|
|
*/
|
|
const userLogin = async function (req, res, path, params) {
|
|
const cookies = getCookies(req);
|
|
if (cookies["user"]) return redirect(res, "/dashboard");
|
|
|
|
let response = {
|
|
ok: true,
|
|
message: ""
|
|
};
|
|
try {
|
|
const post = await consumePostForm(req);
|
|
const login = post.login;
|
|
const password = hasher(post.password);
|
|
if (!udb.hasUser(login)) {
|
|
throw new Error("User not exists!");
|
|
}
|
|
const user = udb.getUser(login);
|
|
if (password !== user.password) {
|
|
throw new Error("Password doesn't match!");
|
|
}
|
|
response["user"] = {
|
|
login,
|
|
status: user.status
|
|
};
|
|
} catch (e) {
|
|
console.error(e);
|
|
response.ok = false;
|
|
response.message = e.message;
|
|
}
|
|
|
|
res.statusCode = 200;
|
|
res.setHeader("Content-Type", "application/json");
|
|
if (response.ok) {
|
|
setCookies(res, {
|
|
user: JSON.stringify(response["user"])
|
|
});
|
|
}
|
|
res.write(JSON.stringify(response));
|
|
res.end();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {IncomingMessage} req
|
|
* @param {ServerResponse} res
|
|
* @param {String} path
|
|
* @param {Object} params
|
|
*/
|
|
const userDashboardView = function (req, res, path, params) {
|
|
const cookies = getCookies(req);
|
|
if (!cookies["user"]) return redirect(res, "/login");
|
|
|
|
const user = JSON.parse(cookies["user"]);
|
|
return renderTemplate(res, "./templates/dashboard.html", [
|
|
["user.name", user.login],
|
|
["user.status", user.status],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Sadly, not working(
|
|
* @param {IncomingMessage} req
|
|
* @param {ServerResponse} res
|
|
* @param {String} path
|
|
* @param {Object} params
|
|
*/
|
|
const userDashboardLogout = function (req, res, path, params) {
|
|
let cookies = getCookies(req);
|
|
if (cookies["user"]) {
|
|
cookies["user"] = "";
|
|
setCookies(res, cookies);
|
|
}
|
|
|
|
return redirect(res, "/login");
|
|
}
|
|
|
|
router.addRoute(route("GET", "/register"), userRegisterView);
|
|
router.addRoute(route("POST", "/register"), userRegister);
|
|
router.addRoute(route("GET", "/login"), userLoginView);
|
|
router.addRoute(route("POST", "/login"), userLogin);
|
|
router.addRoute(route("GET", "/dashboard"), userDashboardView);
|
|
router.addRoute(route("GET", "/dashboard/logout"), userDashboardLogout);
|
|
|
|
/**
|
|
*
|
|
* @param {IncomingMessage} req
|
|
* @param {ServerResponse} res
|
|
*/
|
|
const requestDispatcher = function (req, res) {
|
|
const [path, params] = req.url.includes("?") ? req.url.split("?", 2) : [req.url, ""];
|
|
const parsedParams = urlParse(params);
|
|
router.dispatch(route(req.method, path))(req, res, path, parsedParams);
|
|
}
|
|
|
|
createServer(requestDispatcher).listen(9889);
|