basic version working
This commit is contained in:
commit
39f6e99abe
11 changed files with 782 additions and 0 deletions
208
static/index.html
Normal file
208
static/index.html
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<style>
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 2em;
|
||||
display: grid;
|
||||
grid-template-columns: max-content auto;
|
||||
gap: 2em;
|
||||
}
|
||||
|
||||
.labelgrid {
|
||||
display: grid;
|
||||
grid-template-columns: min-content auto;
|
||||
column-gap: 1em;
|
||||
}
|
||||
|
||||
.buttongrid {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-basis: 0;
|
||||
width: 100%;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.buttongrid>* {
|
||||
width: 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#votebuttons {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<div class="labelgrid">
|
||||
<label for="id"> ID</label>
|
||||
<input id="id" />
|
||||
|
||||
<label for="passcode"> passcode</label>
|
||||
<input id="passcode" />
|
||||
|
||||
<label for="pin"> pin</label>
|
||||
<input id="pin" />
|
||||
|
||||
<label for="auth"> authenticated</label>
|
||||
<input id="auth" type=checkbox onclick="return false" />
|
||||
</div>
|
||||
|
||||
<div class="buttongrid" id="authbuttons">
|
||||
<button onclick="startRegistration()">registrate</button>
|
||||
<button onclick="startAuthentication()">authenticate</button>
|
||||
</div>
|
||||
|
||||
<div class="buttongrid" id="votebuttons">
|
||||
<button onclick="vote(1)">1</button>
|
||||
<button onclick="vote(2)">2</button>
|
||||
<button onclick="vote(3)">3</button>
|
||||
<button onclick="vote(4)">4</button>
|
||||
<button onclick="vote(5)">5</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<h1 id="text"></h1>
|
||||
<div id="logger"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function preventDefault(e) {alert(); e.preventDefault()}
|
||||
function toHex(data) {
|
||||
return Array.from(data).map((b) => ("00" + b.toString(16)).slice(-2)).join(
|
||||
"",
|
||||
);
|
||||
}
|
||||
async function generateHMAC(key, message) {
|
||||
const encoder = new TextEncoder();
|
||||
const keyData = encoder.encode(key);
|
||||
const messageData = encoder.encode(message);
|
||||
|
||||
const cryptoKey = await crypto.subtle.importKey(
|
||||
"raw",
|
||||
keyData,
|
||||
{name: "HMAC", hash: {name: "SHA-256"}},
|
||||
false,
|
||||
["sign"],
|
||||
);
|
||||
|
||||
const signature = await crypto.subtle.sign(
|
||||
"HMAC",
|
||||
cryptoKey,
|
||||
messageData,
|
||||
);
|
||||
|
||||
return toHex(new Uint8Array(signature));
|
||||
}
|
||||
function log(text) {
|
||||
logger.innerHTML += text + "<br>";
|
||||
}
|
||||
function disableAuthBtns() {
|
||||
document.querySelectorAll("#authbuttons").forEach(v => v.disabled = false);
|
||||
}
|
||||
|
||||
const id = document.querySelector("#id");
|
||||
const pass = document.querySelector("#passcode");
|
||||
const pin = document.querySelector("#pin");
|
||||
const logger = document.querySelector("#logger")
|
||||
const text = document.querySelector("#text")
|
||||
const votebuttons = document.querySelector("#votebuttons")
|
||||
const auth = document.querySelector("#auth")
|
||||
|
||||
function websock() {
|
||||
let socket = new WebSocket("ws://localhost:8000/ws");
|
||||
|
||||
socket.sendln = (...e) => {
|
||||
log("device: " + e.join("\n"));
|
||||
socket.send(...e)
|
||||
}
|
||||
|
||||
socket.addEventListener("message", async (event) => {
|
||||
log("server: " + event.data);
|
||||
|
||||
let data = JSON.parse(event.data);
|
||||
switch (data.c) {
|
||||
case "ping": {
|
||||
socket.sendln(JSON.stringify({c: "pong"}));
|
||||
break
|
||||
}
|
||||
case "reg_pin": {
|
||||
pin.value = data.d.pin;
|
||||
break
|
||||
}
|
||||
case "reg_ok": {
|
||||
id.value = data.d.id;
|
||||
pass.value = data.d.password;
|
||||
socket.close();
|
||||
|
||||
pin.value = "";
|
||||
|
||||
log("### closing and reopening socket");
|
||||
websock()
|
||||
break
|
||||
}
|
||||
case "auth_nonce": {
|
||||
const signature = await generateHMAC(pass.value, data.d.nonce)
|
||||
console.log(pass.value, data.value, signature)
|
||||
socket.sendln(JSON.stringify({c: "auth_validate", d: {signature}}));
|
||||
break
|
||||
}
|
||||
case "auth_ok": {
|
||||
auth.checked = true;
|
||||
disableAuthBtns()
|
||||
break;
|
||||
}
|
||||
case "session_start": {
|
||||
text.style.display = "block";
|
||||
votebuttons.style.display = "flex";
|
||||
text.innerText = data.d.text;
|
||||
break;
|
||||
}
|
||||
case "session_stop": {
|
||||
text.style.display = "none";
|
||||
votebuttons.style.display = "none";
|
||||
text.innerText = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
socket.addEventListener("close", () => {
|
||||
auth.checked = false;
|
||||
disableAuthBtns()
|
||||
window.startRegistration = undefined;
|
||||
window.startAuthentication = undefined;
|
||||
text.innerText = ""
|
||||
})
|
||||
|
||||
socket.addEventListener("open", () => {
|
||||
window.startRegistration = () => {
|
||||
socket.sendln(JSON.stringify({c: "reg_start"}))
|
||||
}
|
||||
window.startAuthentication = () => {
|
||||
socket.sendln(JSON.stringify({c: "auth_start", d: {id: id.value}}))
|
||||
}
|
||||
window.vote = (num) => {
|
||||
socket.sendln(JSON.stringify({c: "session_vote", d: {vote: num}}))
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
websock()
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue