add captcha support

This commit is contained in:
elijahr2411 2023-02-10 08:52:44 -05:00
parent a40199dda0
commit 45774ff2ae
5 changed files with 65 additions and 12 deletions

10
dist/index.html vendored
View file

@ -36,6 +36,15 @@
</div> </div>
</div> </div>
</div> </div>
<div class="modal fade" id="hcaptchaModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content bg-dark text-light">
<div class="modal-body">
<div id="captcha-box"></div>
</div>
</div>
</div>
</div>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" href="#">CollabVM</a> <a class="navbar-brand" href="#">CollabVM</a>
@ -128,6 +137,7 @@
</div> </div>
</div> </div>
</div> </div>
<script src="https://js.hcaptcha.com/1/api.js" async defer></script>
<script src="main.js" type="application/javascript"></script> <script src="main.js" type="application/javascript"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
</body> </body>

View file

@ -10,6 +10,7 @@
"author": "Elijah R", "author": "Elijah R",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@hcaptcha/types": "^1.0.3",
"nanoevents": "^7.0.1", "nanoevents": "^7.0.1",
"serve": "^14.2.0", "serve": "^14.2.0",
"webpack": "^5.75.0", "webpack": "^5.75.0",

13
src/captcha.js Normal file
View file

@ -0,0 +1,13 @@
export default function doCaptcha(sitekey) {
return new Promise((res, rej) => {
const modal = new bootstrap.Modal(document.getElementById('hcaptchaModal'));
modal.show();
hcaptcha.render("captcha-box", {
sitekey: sitekey,
callback: (c) => {
modal.hide();
res(c);
},
});
})
}

View file

@ -1,14 +1,6 @@
export const config = { export const config = {
serverAddresses: [ serverAddresses: [
"wss://computernewb.com/collab-vm/vm0", "ws://127.0.0.1:6004",
"wss://computernewb.com/collab-vm/vm1",
"wss://computernewb.com/collab-vm/vm2",
"wss://computernewb.com/collab-vm/vm3",
"wss://computernewb.com/collab-vm/vm4",
"wss://computernewb.com/collab-vm/vm5",
"wss://computernewb.com/collab-vm/vm6",
"wss://computernewb.com/collab-vm/vm7",
"wss://computernewb.com/collab-vm/vm8",
], ],
chatSound: "https://computernewb.com/collab-vm/notify.ogg", chatSound: "https://computernewb.com/collab-vm/notify.ogg",
// What XSS implementation the server uses // What XSS implementation the server uses

View file

@ -3,6 +3,7 @@ import { config } from "./common";
import { GetKeysym } from "./keyboard"; import { GetKeysym } from "./keyboard";
import { createNanoEvents } from "nanoevents"; import { createNanoEvents } from "nanoevents";
import { makeperms } from "./permissions"; import { makeperms } from "./permissions";
import doCaptcha from "./captcha";
// None = -1 // None = -1
// Has turn = 0 // Has turn = 0
// In queue = <queue position> // In queue = <queue position>
@ -67,10 +68,13 @@ class CollabVMClient {
socket; socket;
node; node;
#url; #url;
#captcha = false;
captchaToken;
constructor(url) { constructor(url) {
this.#url = url; this.#url = url;
} }
connect() { connect(hcaptchatoken) {
this.captchaToken = hcaptchatoken;
return new Promise((res, rej) => { return new Promise((res, rej) => {
try { try {
this.socket = new WebSocket(this.#url, "guacamole"); this.socket = new WebSocket(this.#url, "guacamole");
@ -101,9 +105,24 @@ class CollabVMClient {
return this.#url; return this.#url;
} }
connectToVM(node) { connectToVM(node) {
return new Promise((res, rej) => { return new Promise(async (res, rej) => {
this.socket.addEventListener('close', () => this.#onClose()); this.socket.addEventListener('close', () => this.#onClose());
this.node = node; this.node = node;
if (this.captchaToken !== null) {
await new Promise((reso, reje) => {
var unbind = this.eventemitter.on('captcha', (result) => {
unbind();
if (result === true) {
reso();
return;
}
else {
reje();
}
});
this.socket.send(guacutils.encode(["captcha", this.captchaToken]));
});
}
var savedUsername = window.localStorage.getItem("username"); var savedUsername = window.localStorage.getItem("username");
if (savedUsername === null) if (savedUsername === null)
this.socket.send(guacutils.encode(["rename"])); this.socket.send(guacutils.encode(["rename"]));
@ -139,6 +158,18 @@ class CollabVMClient {
break; break;
} }
break; break;
case "captcha":
switch (msgArr[1]) {
case "0":
this.#captcha = msgArr[2];
console.log(this.#captcha);
break;
case "1":
this.eventemitter.emit('captcha', true);
break;
case "2":
this.eventemitter.emit('captcha', false);
}
case "chat": case "chat":
if (!connected) return; if (!connected) return;
for (var i = 1; i < msgArr.length; i += 2) { for (var i = 1; i < msgArr.length; i += 2) {
@ -155,6 +186,7 @@ class CollabVMClient {
id: msgArr[i], id: msgArr[i],
name: msgArr[i+1], name: msgArr[i+1],
thumb: msgArr[i+2], thumb: msgArr[i+2],
captcha: this.#captcha,
}); });
} }
@ -685,9 +717,14 @@ function addUserDropdownItem(ul, text, func) {
async function openVM(url, node) { async function openVM(url, node) {
if (connected) return; if (connected) return;
connected = true; connected = true;
var vm = vms.find(v => v.url === url);
var token = null;
if (vm.captcha !== false) {
token = await doCaptcha(vm.captcha);
}
window.location.href = "#" + node; window.location.href = "#" + node;
vm = new CollabVMClient(url); vm = new CollabVMClient(url);
await vm.connect(); await vm.connect(token);
await vm.connectToVM(node); await vm.connectToVM(node);
vmlist.style.display = "none"; vmlist.style.display = "none";
vmview.style.display = "block"; vmview.style.display = "block";