~vpzom/bracketmonster

4a3c73d8feef70df6530e131e903cc46d51c2b18 — Colin Reeder 5 months ago 5f3b194
Support login without javascript
M rosebush/package-lock.json => rosebush/package-lock.json +13 -3
@@ 3051,6 3051,16 @@
        "p-finally": "^1.0.0",
        "signal-exit": "^3.0.0",
        "strip-eof": "^1.0.0"
      },
      "dependencies": {
        "get-stream": {
          "version": "4.1.0",
          "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
          "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
          "requires": {
            "pump": "^3.0.0"
          }
        }
      }
    },
    "expand-brackets": {


@@ 3510,9 3520,9 @@
      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
    },
    "get-stream": {
      "version": "4.1.0",
      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
      "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
      "version": "5.1.0",
      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
      "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
      "requires": {
        "pump": "^3.0.0"
      }

M rosebush/package.json => rosebush/package.json +1 -0
@@ 17,6 17,7 @@
    "babel-loader": "^8.1.0",
    "css-loader": "^3.5.3",
    "decko": "^1.2.0",
    "get-stream": "^5.1.0",
    "http-proxy": "^1.18.0",
    "isomorphic-cookie": "^1.2.4",
    "jsesc": "^3.0.1",

M rosebush/src/client/pages/login.tsx => rosebush/src/client/pages/login.tsx +1 -1
@@ 23,7 23,7 @@ export default class LoginPage extends Component<Props, State> {

			<h1><Text id="login" /></h1>

			<form onSubmit={this.submit.bind(this)}>
			<form action="/formSubmit/login" method="POST" onSubmit={this.submit.bind(this)}>
				<p>
					<label>
						<Text id="username" />: <input type="text" name="username" />

M rosebush/src/server/index.tsx => rosebush/src/server/index.tsx +53 -2
@@ 1,5 1,6 @@
import * as acceptLanguageNegotiator from "accept-language-negotiator";
import * as fs from "fs";
import getStream from "get-stream";
import * as http from "http";
import * as httpProxy from "http-proxy";
import isomorphicCookie from "isomorphic-cookie";


@@ 11,8 12,10 @@ import { Dictionary, IntlProvider } from "preact-jsx-i18n";
import { render } from "preact-render-to-string";
import { Route, RouteProps, Router } from "preact-router";
import * as serveStatic from "serve-static";
import * as querystring from "querystring";

import App, { UserInfo } from "../client/App";
import { COOKIE_AGE } from "../client/constants";
import Data, { LoadState } from "../client/Data";
import Helmet, { rewindClear } from "../client/Helmet";
import { PreloadedDataContext } from "../client/preload";


@@ 78,8 81,8 @@ function apiFetchRaw(srcReq: http.IncomingMessage, url: string, init?: RequestIn
	return fetch(API_HOST + "/" + url, {...init, headers});
}

function apiFetch(srcReq: http.IncomingMessage, url: string): ReturnType<typeof fetch> {
	return apiFetchRaw(srcReq, url)
function apiFetch(srcReq: http.IncomingMessage, url: string, init?: RequestInit): ReturnType<typeof fetch> {
	return apiFetchRaw(srcReq, url, init)
		.then(res => {
			if(res.status < 200 || res.status >= 300) {
				return res.text()


@@ 143,6 146,54 @@ http.createServer(async (req_, res) => {
			res.end();
		});
	}
	else if(req.url.startsWith("/formSubmit/")) {
		if(req.method !== "POST") {
			res.writeHead(405);
			res.write("formSubmit can only be used with POST");
			res.end();
			return;
		}
		const rest = req.url.substring(12);

		if(rest === "login") {
			try {
				const fields = querystring.decode(await getStream(req));
				const resp = await apiFetchRaw(req, "unstable/loginSessions", {method: "POST", body: JSON.stringify({
					username: fields.username,
					password: fields.password,
				})});

				if(resp.status < 200 || resp.status >= 300) {
					const text = await resp.text();
					res.writeHead(resp.status);
					res.write(text);
					res.end();
					return;
				}

				const result = await resp.json();

				const token = result.token;

				res.writeHead(
					303,
					{"Set-Cookie": "rosebushToken=" + token + "; Path=/; Max-Age=" + COOKIE_AGE, Location: fields.continue || "/myBrackets"}
				);
				res.write("Successfully logged in.");
				res.end();
			} catch(e) {
				console.error(e);
				res.writeHead(500);
				res.write("Internal Server Error");
				res.end();
			}
		}
		else {
			res.writeHead(404);
			res.write("Not Found");
			res.end();
		}
	}
	else {
		const acceptLanguage = req.headers["accept-language"];
		const language = acceptLanguage ?