login pimpout

This commit is contained in:
ntr 2019-08-12 14:11:53 +10:00
parent b15a494a4b
commit b4dccf9f1c
11 changed files with 98 additions and 48 deletions

View File

@ -10,6 +10,7 @@
* graphs n shit * graphs n shit
* acp init * acp init
* DO postgres * DO postgres
* make our own toasts / msg pane
* only clear effects on post_resolve * only clear effects on post_resolve
electrify doesn't work if you ko the construct electrify doesn't work if you ko the construct

View File

@ -6,6 +6,7 @@ nav {
h1 { h1 {
margin-bottom: 0.5em; margin-bottom: 0.5em;
letter-spacing: 0.05em;
} }
h2:first-child { h2:first-child {

View File

@ -43,6 +43,9 @@ html {
h1 { h1 {
font-size: 2em; font-size: 2em;
margin: 0; margin: 0;
margin-bottom: 0.5em;
letter-spacing: 0.05em;
} }
h2 { h2 {
@ -175,9 +178,14 @@ button[disabled] {
*/ */
.login { .login {
width: 25%; width: 50%;
display: flex; display: flex;
flex-flow: column; flex-flow: column;
margin-bottom: 2em;
h2 {
margin-bottom: 0.5em;
}
} }
#mnml input, #mnml select { #mnml input, #mnml select {

View File

@ -50,7 +50,7 @@
main { main {
overflow-x: hidden; overflow-x: hidden;
padding: 0; padding: 0 0.5em;
} }
.login { .login {

View File

@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>mnml.gg</title> <title>mnml - abstract strategy</title>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name=apple-mobile-web-app-capable content=yes> <meta name=apple-mobile-web-app-capable content=yes>

View File

@ -21,6 +21,7 @@
"docco": "^0.7.0", "docco": "^0.7.0",
"izitoast": "^1.4.0", "izitoast": "^1.4.0",
"keymaster": "^1.6.2", "keymaster": "^1.6.2",
"linkstate": "^1.1.1",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"node-sass": "^4.12.0", "node-sass": "^4.12.0",
"parcel": "^1.12.3", "parcel": "^1.12.3",

View File

@ -16,7 +16,7 @@ const addState = connect(
function logout() { function logout() {
postData('/logout').then(() => window.location.reload(true)); postData('/account/logout').then(() => window.location.reload(true));
} }
function sendConstructSpawn(name) { function sendConstructSpawn(name) {
@ -71,7 +71,7 @@ function AccountStatus(args) {
<button>Update</button> <button>Update</button>
</form> </form>
<form> <form>
<label for="password">Change Password:</label> <label for="current">Change Password:</label>
<input <input
class="login-input" class="login-input"
type="password" type="password"

View File

@ -10,12 +10,14 @@ const addState = connect(
function receiveState(state) { function receiveState(state) {
const { const {
ws, ws,
account,
game, game,
instance, instance,
nav, nav,
} = state; } = state;
return { return {
account,
game, game,
instance, instance,
nav, nav,
@ -26,11 +28,14 @@ const addState = connect(
function Controls(args) { function Controls(args) {
const { const {
game, game,
account,
instance, instance,
nav, nav,
sendGameReady, sendGameReady,
} = args; } = args;
if (!account) return false;
if (game) return <GameCtrl />; if (game) return <GameCtrl />;
if (instance) return <InstanceCtrl />; if (instance) return <InstanceCtrl />;
if (nav === 'play' || !nav) return <PlayCtrl /> if (nav === 'play' || !nav) return <PlayCtrl />

View File

@ -2,6 +2,7 @@
const preact = require('preact'); const preact = require('preact');
const { Component } = require('preact') const { Component } = require('preact')
const { connect } = require('preact-redux'); const { connect } = require('preact-redux');
const linkState = require('linkstate').default;
const { postData, errorToast } = require('../utils'); const { postData, errorToast } = require('../utils');
@ -11,7 +12,7 @@ const addState = connect(
ws ws
} = state; } = state;
function submitLogin(name, password) { function submitLogin(name, password) {
postData('/login', { name, password }) postData('/account/login', { name, password })
.then(res => res.json()) .then(res => res.json())
.then(data => { .then(data => {
if (!data.success) return errorToast(data.error_message); if (!data.success) return errorToast(data.error_message);
@ -22,7 +23,7 @@ const addState = connect(
} }
function submitRegister(name, password, code) { function submitRegister(name, password, code) {
postData('/register', { name, password, code }) postData('/account/register', { name, password, code })
.then(res => res.json()) .then(res => res.json())
.then(data => { .then(data => {
if (!data.success) return errorToast(data.error_message); if (!data.success) return errorToast(data.error_message);
@ -43,70 +44,64 @@ class Login extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { name: '', password: '', code: ''}; this.state = {
login: { name: '', password: '', code: ''},
register: { name: '', password: '', confirm: '', code: ''},
};
this.nameInput = this.nameInput.bind(this);
this.passwordInput = this.passwordInput.bind(this);
this.codeInput = this.codeInput.bind(this);
this.loginSubmit = this.loginSubmit.bind(this); this.loginSubmit = this.loginSubmit.bind(this);
this.registerSubmit = this.registerSubmit.bind(this); this.registerSubmit = this.registerSubmit.bind(this);
} }
nameInput(event) {
this.setState({ name: event.target.value });
}
passwordInput(event) {
this.setState({ password: event.target.value });
}
codeInput(event) {
this.setState({ code: event.target.value });
}
loginSubmit(event) { loginSubmit(event) {
event.preventDefault(); event.preventDefault();
console.log(this.state); console.log(this.state);
this.props.submitLogin(this.state.name, this.state.password); this.props.submitLogin(this.state.login.name, this.state.login.password);
this.setState({ name: '', password: '' }); this.setState({ login: { name: '', password: '' }});
} }
registerSubmit(event) { registerSubmit(event) {
event.preventDefault(); event.preventDefault();
this.props.submitRegister(this.state.name, this.state.password, this.state.code); this.props.submitRegister(this.state.register.name, this.state.register.password, this.state.register.code);
console.log(this.state); this.setState({ register: { name: '', password: '', confirm: '', code: ''}});
this.setState({ name: '', password: '', code: ''});
} }
render() { render() {
const registerConfirm = () =>
this.state.register.password === this.state.register.confirm;
const registerDisabled = () => {
const { password, name, code } = this.state.register;
return !(registerConfirm() && password && name && code);
}
return ( return (
<main> <main>
<h1 class="mobile-title" >mnml.gg</h1> <h1>mnml.gg</h1>
<div class="login"> <div class="login">
<div>mnml is an abstract turn based strategy game.</div>
<div>free to play</div>
<div>no email required</div>
</div>
<div class="login">
<h2>Login</h2>
<label for="username">Username</label>
<input <input
class="login-input" class="login-input"
type="email" type="email"
placeholder="username" placeholder="username"
tabIndex={1} tabIndex={1}
value={this.state.name} value={this.state.login.name}
onInput={this.nameInput} onInput={linkState(this, 'login.name')}
/> />
<label for="password">Password</label>
<input <input
class="login-input" class="login-input"
type="password" type="password"
placeholder="password" placeholder="password"
tabIndex={2} tabIndex={2}
value={this.state.password} value={this.state.login.password}
onInput={this.passwordInput} onInput={linkState(this, 'login.password')}
/>
<input
class="login-input"
type="text"
placeholder="code"
tabIndex={3}
value={this.state.code}
onInput={this.codeInput}
/> />
<button <button
class="login-btn" class="login-btn"
@ -114,16 +109,51 @@ class Login extends Component {
onClick={this.loginSubmit}> onClick={this.loginSubmit}>
Login Login
</button> </button>
</div>
<div class="login">
<h2>Register</h2>
<label for="username">Username</label>
<input
class="login-input"
type="email"
placeholder="username"
value={this.state.register.name}
onInput={linkState(this, 'register.name')}
/>
<label for="password">Password - min 12 chars</label>
<input
class="login-input"
type="password"
placeholder="password"
value={this.state.register.password}
onInput={linkState(this, 'register.password')}
/>
<label for="confirm">Confirm Password</label>
<input
class={`${registerConfirm() ? '' : 'red'} login-input`}
type="password"
placeholder="confirm"
value={this.state.register.confirm}
onInput={linkState(this, 'register.confirm')}
/>
<label for="code">Access Code</label>
<input
class="login-input"
type="text"
placeholder="code"
value={this.state.register.code}
onInput={linkState(this, 'register.code')}
/>
<button <button
class="login-btn" class="login-btn"
tabIndex={5} disabled={registerDisabled()}
onClick={this.registerSubmit}> onClick={this.registerSubmit}>
Register Register
</button> </button>
<button <button
class="login-btn" class="login-btn"
onClick={() => document.location.assign('https://discord.gg/YJJgurM')}> onClick={() => document.location.assign('https://discord.gg/YJJgurM')}>
Discord + Invites Discord + Codes
</button> </button>
</div> </div>
</main> </main>

View File

@ -69,6 +69,8 @@ function Nav(args) {
hideNav, hideNav,
} = args; } = args;
if (!account) return false;
function navTo(p) { function navTo(p) {
return setNav(p); return setNav(p);
} }
@ -90,6 +92,7 @@ function Nav(args) {
const canJoin = team.some(c => !c); const canJoin = team.some(c => !c);
return ( return (
<nav onClick={hideNav} > <nav onClick={hideNav} >
<h1 class="header-title">mnml.gg</h1> <h1 class="header-title">mnml.gg</h1>

View File

@ -17,7 +17,7 @@ use payments::{stripe};
pub const TOKEN_HEADER: &str = "x-auth-token"; pub const TOKEN_HEADER: &str = "x-auth-token";
pub const AUTH_CLEAR: &str = pub const AUTH_CLEAR: &str =
"x-auth-token=; HttpOnly; SameSite=Strict; Max-Age=-1;"; "x-auth-token=; HttpOnly; SameSite=Strict; Path=/; Max-Age=-1;";
#[derive(Clone, Copy, Fail, Debug, Serialize, Deserialize)] #[derive(Clone, Copy, Fail, Debug, Serialize, Deserialize)]
pub enum MnmlHttpError { pub enum MnmlHttpError {
@ -163,6 +163,7 @@ fn token_res(token: String) -> Response {
let v = Cookie::build(TOKEN_HEADER, token) let v = Cookie::build(TOKEN_HEADER, token)
.http_only(true) .http_only(true)
.same_site(SameSite::Strict) .same_site(SameSite::Strict)
.path("/")
.max_age(Duration::weeks(1)) // 1 week aligns with db set .max_age(Duration::weeks(1)) // 1 week aligns with db set
.finish(); .finish();
@ -265,9 +266,9 @@ pub fn start(pool: PgPool) {
let mut router = Router::new(); let mut router = Router::new();
// auth // auth
router.post("/api/login", login, "login"); router.post("/api/account/login", login, "login");
router.post("/api/logout", logout, "logout"); router.post("/api/account/logout", logout, "logout");
router.post("/api/register", register, "register"); router.post("/api/account/register", register, "register");
// payments // payments
router.post("/api/payments/stripe", stripe, "stripe"); router.post("/api/payments/stripe", stripe, "stripe");