First version of OpenAuth remake

This commit is contained in:
Fabian Stamm
2018-11-06 20:48:50 +01:00
commit ac69e73344
89 changed files with 14355 additions and 0 deletions

View File

@ -0,0 +1,115 @@
<html>
<head>
<title>{{i18n "Register"}}</title>
<meta charset="utf8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
</head>
<body>
<hgroup>
<h1>{{i18n "Register"}}</h1>
</hgroup>
<form action="JavaScript:void(0)">
<div class="error invisible" id="error" style="font-size: 18px; margin-bottom: 16px"></div>
<div class="floating group">
<input type="text" id="regcode">
<span class="highlight"></span>
<span class="bar"></span>
<label>{{i18n "Registration code"}}</label>
<div class="error invisible" id="err_regcode"></div>
</div>
<div class="floating group">
<input type="text" id="username">
<span class="highlight"></span>
<span class="bar"></span>
<label>{{i18n "Username"}}</label>
<div class="error invisible" id="err_username"></div>
</div>
<div class="floating group">
<input type="text" id="name">
<span class="highlight"></span>
<span class="bar"></span>
<label>{{i18n "Name"}}</label>
<div class="error invisible" id="err_name"></div>
</div>
<div class="error invisible" id="err_gender"></div>
<div class="mdc-form-field group">
<div class="mdc-radio">
<input class="mdc-radio__native-control" type="radio" id="radio-male" name="radios" checked>
<div class="mdc-radio__background">
<div class="mdc-radio__outer-circle"></div>
<div class="mdc-radio__inner-circle"></div>
</div>
</div>
<label for="radio-male" style="position: relative;">{{i18n "Male"}}</label>
<div class="mdc-radio">
<input class="mdc-radio__native-control" type="radio" id="radio-female" name="radios" checked>
<div class="mdc-radio__background">
<div class="mdc-radio__outer-circle"></div>
<div class="mdc-radio__inner-circle"></div>
</div>
</div>
<label for="radio-female" style="position: relative;">{{i18n "Female"}}</label>
<div class="mdc-radio">
<input class="mdc-radio__native-control" type="radio" id="radio-other" name="radios" checked>
<div class="mdc-radio__background">
<div class="mdc-radio__outer-circle"></div>
<div class="mdc-radio__inner-circle"></div>
</div>
</div>
<label for="radio-other" style="position: relative;">{{i18n "Other"}}</label>
</div>
<div class="floating group">
<input type="text" id="mail">
<span class="highlight"></span>
<span class="bar"></span>
<label>{{i18n "Mail"}}</label>
<div class="error invisible" id="err_mail"></div>
</div>
<div class="floating group">
<input type="password" id="password">
<span class="highlight"></span>
<span class="bar"></span>
<label>{{i18n "Password"}}</label>
<div class="error invisible" id="err_password"></div>
</div>
<div class="floating group">
<input type="password" id="passwordrep">
<span class="highlight"></span>
<span class="bar"></span>
<label>{{i18n "Repeat Password"}}</label>
<div class="error invisible" id="err_passwordrep"></div>
</div>
<button type="button" id="registerbutton" class="mdc-button mdc-button--raised">{{i18n "Register"}}
</button>
</form>
<footer>
<p>Powered by {{appname}}</p>
</footer>
<script type="json" id="error_codes">
{
"noregcode": "{{i18n "Registration code required"}}",
"nousername": "{{i18n "Username required"}}",
"noname": "{{i18n "Name required"}}",
"nomail": "{{i18n "Mail required"}}",
"nogender": "{{i18n "You need to select one of the options"}}",
"nopassword": "{{i18n "Password is required"}}",
"nomatch": "{{i18n "The passwords do not match"}}"
}
</script>
</body>
</html>

View File

@ -0,0 +1,149 @@
import "inputs";
import sha from "sha512";
import fireEvent from "event"
(() => {
const translations = JSON.parse(document.getElementById("error_codes").innerText)
const regcode = document.getElementById("regcode")
regcode.value = new URL(window.location.href).searchParams.get("regcode")
fireEvent(regcode, "change");
function showError(element, message) {
if (typeof element === "string")
element = document.getElementById(element)
if (!element) console.error("Element not found,", element)
element.innerText = message;
if (!message) {
if (!element.classList.contains("invisible"))
element.classList.add("invisible")
} else {
element.classList.remove("invisible");
}
}
function makeid(length) {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < length; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
const username = document.getElementById("username")
const name = document.getElementById("name")
const mail = document.getElementById("mail")
const password = document.getElementById("password")
const passwordrep = document.getElementById("passwordrep")
const radio_male = document.getElementById("radio-male")
const radio_female = document.getElementById("radio-female")
const radio_other = document.getElementById("radio-other")
const registerButton = document.getElementById("registerbutton")
registerButton.onclick = () => {
console.log("Register")
showError("error");
let error = false;
if (!regcode.value) {
showError("err_regcode", translations["noregcode"])
error = true;
} else {
showError("err_regcode")
}
if (!username.value) {
showError("err_username", translations["nousername"])
error = true;
} else {
showError("err_username")
}
if (!name.value) {
showError("err_name", translations["noname"])
error = true;
} else {
showError("err_name")
}
if (!mail.value) {
showError("err_mail", translations["nomail"])
error = true;
} else {
showError("err_mail")
}
if (!password.value) {
showError("err_password", translations["nopassword"])
error = true;
} else {
showError("err_password")
}
if (password.value !== passwordrep.value) {
showError("err_passwordrep", translations["nomatch"])
error = true;
} else {
showError("err_passwordrep")
}
if (error) return;
let gender;
if (radio_male.checked) {
gender = "male"
} else if (radio_female.checked) {
gender = "female"
} else {
gender = "other"
}
let salt = makeid(10)
//username, password, salt, mail, gender, name, birthday, regcode
let body = {
username: username.value,
gender: gender,
mail: mail.value,
name: name.value,
regcode: regcode.value,
salt: salt,
password: sha(salt + password.value)
}
fetch("/api/user/register", {
method: "POST",
body: JSON.stringify(body),
headers: {
'content-type': 'application/json'
},
}).then(async e => {
if (e.status !== 200) return Promise.reject(new Error(await e.text() || e.statusText));
return e.json()
}).then(data => {
if (data.error) {
if (!Array.isArray(data.error)) return Promise.reject(new Error(data.error));
let ce = [];
data.error.forEach(e => {
let ef = document.getElementById("err_" + e.field);
if (!ef) ce.push(e);
else {
showError(ef, e.message);
}
})
if (ce.length > 0) {
showError("error", ce.join("<br>"));
}
} else {
window.location.href = "/login";
}
}).catch(e => {
showError("error", e.message);
})
}
})()

View File

@ -0,0 +1,95 @@
@import "@material/button/mdc-button";
@import "@material/form-field/mdc-form-field";
@import "@material/radio/mdc-radio";
@import "inputs";
* {
box-sizing: border-box;
}
body {
font-family: Helvetica;
background: #eee;
-webkit-font-smoothing: antialiased;
}
hgroup {
text-align: center;
margin-top: 1em;
}
h1,
h3 {
font-weight: 300;
}
h1 {
color: #636363;
}
h3 {
color: $primary;
}
form {
max-width: 380px;
margin: 1em auto;
padding: 3em 2em 2em 2em;
background: #fafafa;
border: 1px solid #ebebeb;
box-shadow: rgba(0, 0, 0, 0.14902) 0px 1px 1px 0px, rgba(0, 0, 0, 0.09804) 0px 1px 2px 0px;
}
#registerbutton {
width: 100%;
background: $primary;
text-shadow: 1px 1px 0 rgba(39, 110, 204, .5);
}
footer {
text-align: center;
}
footer p {
color: #888;
font-size: 13px;
letter-spacing: .4px;
}
footer a {
color: $primary;
text-decoration: none;
transition: all .2s ease;
}
footer a:hover {
color: #666;
text-decoration: underline;
}
footer img {
width: 80px;
transition: all .2s ease;
}
footer img:hover {
opacity: .83;
}
footer img:focus,
footer a:focus {
outline: none;
}
.invisible {
display: none;
}
.errorColor {
background: $error !important;
}
.error {
color: $error;
margin-top: 5px;
font-size: 13px;
}