W5 done
This commit is contained in:
parent
0e2c114a84
commit
2c5995be3f
13 changed files with 632 additions and 0 deletions
240
w5/webserver.js
Normal file
240
w5/webserver.js
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
"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);
|
||||
Loading…
Add table
Add a link
Reference in a new issue