- Add staff shit (no qemu monitor or user-specific actions just yet)
- Switch events to capture
This commit is contained in:
parent
3c1fb45e3c
commit
4aeb9437df
4 changed files with 149 additions and 10 deletions
7
dist/index.html
vendored
7
dist/index.html
vendored
|
@ -45,6 +45,13 @@
|
||||||
<button class="btn btn-secondary" id="changeUsernameBtn">Change Username</button>
|
<button class="btn btn-secondary" id="changeUsernameBtn">Change Username</button>
|
||||||
<button class="btn btn-secondary" id="voteResetButton">Vote for Reset</button>
|
<button class="btn btn-secondary" id="voteResetButton">Vote for Reset</button>
|
||||||
<button class="btn btn-secondary" id="screenshotButton">Screenshot</button>
|
<button class="btn btn-secondary" id="screenshotButton">Screenshot</button>
|
||||||
|
<div id="staffbtns">
|
||||||
|
<button class="btn btn-secondary" id="restoreBtn">Restore</button>
|
||||||
|
<button class="btn btn-secondary" id="rebootBtn">Reboot</button>
|
||||||
|
<button class="btn btn-secondary" id="clearQueueBtn">Clear Turn Queue</button>
|
||||||
|
<button class="btn btn-secondary" id="bypassTurnBtn">Bypass Turn</button>
|
||||||
|
<button class="btn btn-secondary" id="endTurnBtn">End Turn</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
|
|
7
dist/style.css
vendored
7
dist/style.css
vendored
|
@ -66,3 +66,10 @@
|
||||||
-moz-box-shadow: 0 0 9px 0 rgba(242,255,63,.75);
|
-moz-box-shadow: 0 0 9px 0 rgba(242,255,63,.75);
|
||||||
-webkit-box-shadow: 0 0 9px 0 rgba(242,255,63,.75)
|
-webkit-box-shadow: 0 0 9px 0 rgba(242,255,63,.75)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#staffbtns {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#staffbtns > button {
|
||||||
|
display: none;
|
||||||
|
}
|
122
src/index.js
122
src/index.js
|
@ -2,11 +2,13 @@ import { guacutils } from "./protocol";
|
||||||
import { config } from "./common";
|
import { config } from "./common";
|
||||||
import { GetKeysym } from "./keyboard";
|
import { GetKeysym } from "./keyboard";
|
||||||
import { createNanoEvents } from "nanoevents";
|
import { createNanoEvents } from "nanoevents";
|
||||||
|
import { makeperms } from "./permissions";
|
||||||
// None = -1
|
// None = -1
|
||||||
// Has turn = 0
|
// Has turn = 0
|
||||||
// In queue = <queue position>
|
// In queue = <queue position>
|
||||||
var turn = -1;
|
var turn = -1;
|
||||||
var perms = 0;
|
var perms = makeperms(0);
|
||||||
|
var rank = 0;
|
||||||
var connected = false;
|
var connected = false;
|
||||||
const vms = [];
|
const vms = [];
|
||||||
const users = [];
|
const users = [];
|
||||||
|
@ -14,7 +16,13 @@ const buttons = {
|
||||||
takeTurn: window.document.getElementById("takeTurnBtn"),
|
takeTurn: window.document.getElementById("takeTurnBtn"),
|
||||||
changeUsername: window.document.getElementById("changeUsernameBtn"),
|
changeUsername: window.document.getElementById("changeUsernameBtn"),
|
||||||
voteReset: window.document.getElementById("voteResetButton"),
|
voteReset: window.document.getElementById("voteResetButton"),
|
||||||
screenshot: window.document.getElementById("screenshotButton")
|
screenshot: window.document.getElementById("screenshotButton"),
|
||||||
|
// Staff
|
||||||
|
restore: window.document.getElementById("restoreBtn"),
|
||||||
|
reboot: window.document.getElementById("rebootBtn"),
|
||||||
|
clearQueue: window.document.getElementById("clearQueueBtn"),
|
||||||
|
bypassTurn: window.document.getElementById("bypassTurnBtn"),
|
||||||
|
endTurn: window.document.getElementById("endTurnBtn"),
|
||||||
}
|
}
|
||||||
var hasTurn = false;
|
var hasTurn = false;
|
||||||
var vm;
|
var vm;
|
||||||
|
@ -38,12 +46,14 @@ const votenobtn = document.getElementById("voteNoBtn");
|
||||||
const voteyeslabel = document.getElementById("voteYesLabel");
|
const voteyeslabel = document.getElementById("voteYesLabel");
|
||||||
const votenolabel = document.getElementById("voteNoLabel");
|
const votenolabel = document.getElementById("voteNoLabel");
|
||||||
const votetime = document.getElementById("votetime");
|
const votetime = document.getElementById("votetime");
|
||||||
|
const staffbtns = document.getElementById("staffbtns");
|
||||||
// needed to scroll to bottom
|
// needed to scroll to bottom
|
||||||
const chatListDiv = document.querySelector(".chat-table");
|
const chatListDiv = document.querySelector(".chat-table");
|
||||||
|
|
||||||
class CollabVMClient {
|
class CollabVMClient {
|
||||||
eventemitter = createNanoEvents();
|
eventemitter = createNanoEvents();
|
||||||
socket;
|
socket;
|
||||||
|
node;
|
||||||
#url;
|
#url;
|
||||||
constructor(url) {
|
constructor(url) {
|
||||||
this.#url = url;
|
this.#url = url;
|
||||||
|
@ -65,6 +75,7 @@ class CollabVMClient {
|
||||||
}
|
}
|
||||||
connectToVM(node) {
|
connectToVM(node) {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
|
this.node = node;
|
||||||
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"]));
|
||||||
|
@ -78,6 +89,9 @@ class CollabVMClient {
|
||||||
rej();
|
rej();
|
||||||
});
|
});
|
||||||
this.socket.send(guacutils.encode(["connect", node]));
|
this.socket.send(guacutils.encode(["connect", node]));
|
||||||
|
var pass = window.localStorage.getItem("password_"+this.#url);
|
||||||
|
if (pass)
|
||||||
|
this.admin.login(pass);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async #onMessage(event) {
|
async #onMessage(event) {
|
||||||
|
@ -202,7 +216,7 @@ class CollabVMClient {
|
||||||
turn = 0;
|
turn = 0;
|
||||||
turnstatus.innerText = "You have the turn.";
|
turnstatus.innerText = "You have the turn.";
|
||||||
display.className = "focused";
|
display.className = "focused";
|
||||||
}
|
}
|
||||||
// Highlight all waiting users and set their status
|
// Highlight all waiting users and set their status
|
||||||
if (queuedUsers > 1) {
|
if (queuedUsers > 1) {
|
||||||
for (var i = 1; i < queuedUsers; i++) {
|
for (var i = 1; i < queuedUsers; i++) {
|
||||||
|
@ -255,6 +269,50 @@ class CollabVMClient {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "admin":
|
||||||
|
switch (msgArr[1]) {
|
||||||
|
case "0":
|
||||||
|
// Login
|
||||||
|
switch (msgArr[2]) {
|
||||||
|
case "0":
|
||||||
|
this.eventemitter.emit('login', {error: 'badpassword'});
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
case "1":
|
||||||
|
perms = makeperms(65535);
|
||||||
|
rank = 2;
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
rank = 3;
|
||||||
|
perms = makeperms(parseInt(msgArr[3]))
|
||||||
|
}
|
||||||
|
this.eventemitter.emit('login', {perms: perms, rank: rank});
|
||||||
|
usernameSpan.classList.remove("text-light");
|
||||||
|
switch (rank) {
|
||||||
|
case 2:
|
||||||
|
usernameSpan.classList.add("text-danger");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
usernameSpan.classList.add("text-success");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Disabled for now until we figure out the issue of uservm
|
||||||
|
//window.localStorage.setItem("password_"+this.#url, password);
|
||||||
|
staffbtns.style.display = "block";
|
||||||
|
if (perms.restore) buttons.restore.style.display = "inline-block";
|
||||||
|
if (perms.reboot) buttons.reboot.style.display = "inline-block";
|
||||||
|
if (perms.bypassturn) {
|
||||||
|
buttons.bypassTurn.style.display = "inline-block";
|
||||||
|
buttons.clearQueue.style.display = "inline-block";
|
||||||
|
buttons.endTurn.style.display = "inline-block";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
window.cvmEvents.emit(msgArr[0], msgArr.slice(1));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reloadUsers() {
|
reloadUsers() {
|
||||||
|
@ -316,6 +374,28 @@ class CollabVMClient {
|
||||||
voteReset(reset) {
|
voteReset(reset) {
|
||||||
this.socket.send(guacutils.encode(["vote", reset ? "1" : "0"]));
|
this.socket.send(guacutils.encode(["vote", reset ? "1" : "0"]));
|
||||||
}
|
}
|
||||||
|
admin = {
|
||||||
|
login: (password) => {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
var unbind = this.eventemitter.on('login', (args) => {
|
||||||
|
unbind();
|
||||||
|
if (args.error) rej(error);
|
||||||
|
res(args);
|
||||||
|
})
|
||||||
|
this.socket.send(guacutils.encode(["admin", "2", password]));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
adminInstruction: (...args) => { // Compatibility
|
||||||
|
args.unshift("admin");
|
||||||
|
console.log(args);
|
||||||
|
this.socket.send(guacutils.encode(args));
|
||||||
|
},
|
||||||
|
restore: () => this.socket.send(guacutils.encode(["admin", "8", this.node])),
|
||||||
|
reboot: () => this.socket.send(guacutils.encode(["admin", "10", this.node])),
|
||||||
|
clearQueue: () => this.socket.send(guacutils.encode(["admin", "17", this.node])),
|
||||||
|
bypassTurn: () => this.socket.send(guacutils.encode(["admin", "20"])),
|
||||||
|
endTurn: () => this.socket.send(guacutils.encode(["admin", "16", users[0].username])),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function multicollab(url) {
|
function multicollab(url) {
|
||||||
return new Promise(async (res, rej) => {
|
return new Promise(async (res, rej) => {
|
||||||
|
@ -371,15 +451,15 @@ async function openVM(url, node) {
|
||||||
await vm.connectToVM(node);
|
await vm.connectToVM(node);
|
||||||
vmlist.style.display = "none";
|
vmlist.style.display = "none";
|
||||||
vmview.style.display = "block";
|
vmview.style.display = "block";
|
||||||
display.addEventListener('mousemove', (e) => vm.mouseevent(e))
|
display.addEventListener('mousemove', (e) => vm.mouseevent(e), {capture: true})
|
||||||
display.addEventListener('mousedown', (e) => vm.mouseevent(e));
|
display.addEventListener('mousedown', (e) => vm.mouseevent(e), {capture: true});
|
||||||
display.addEventListener('mouseup', (e) => vm.mouseevent(e));
|
display.addEventListener('mouseup', (e) => vm.mouseevent(e), {capture: true});
|
||||||
display.addEventListener('contextmenu', (e) => e.preventDefault());
|
display.addEventListener('contextmenu', (e) => e.preventDefault());
|
||||||
display.addEventListener('click', () => {
|
display.addEventListener('click', () => {
|
||||||
if (turn === -1) vm.turn();
|
if (turn === -1) vm.turn();
|
||||||
});
|
}, {capture: true});
|
||||||
display.addEventListener('keydown', (e) => vm.keyevent(e, true));
|
display.addEventListener('keydown', (e) => vm.keyevent(e, true), {capture: true});
|
||||||
display.addEventListener('keyup', (e) => vm.keyevent(e, false));
|
display.addEventListener('keyup', (e) => vm.keyevent(e, false), {capture: true});
|
||||||
}
|
}
|
||||||
function screenshotVM() {
|
function screenshotVM() {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
|
@ -413,9 +493,31 @@ buttons.takeTurn.addEventListener('click', () => vm.turn());
|
||||||
buttons.voteReset.addEventListener('click', () => vm.voteReset(true));
|
buttons.voteReset.addEventListener('click', () => vm.voteReset(true));
|
||||||
voteyesbtn.addEventListener('click', () => vm.voteReset(true));
|
voteyesbtn.addEventListener('click', () => vm.voteReset(true));
|
||||||
votenobtn.addEventListener('click', () => vm.voteReset(false));
|
votenobtn.addEventListener('click', () => vm.voteReset(false));
|
||||||
|
// Staff buttons
|
||||||
|
buttons.restore.addEventListener('click', () => vm.admin.restore());
|
||||||
|
buttons.reboot.addEventListener('click', () => vm.admin.reboot());
|
||||||
|
buttons.clearQueue.addEventListener('click', () => vm.admin.clearQueue());
|
||||||
|
buttons.bypassTurn.addEventListener('click', () => vm.admin.bypassTurn());
|
||||||
|
buttons.endTurn.addEventListener('click', () => vm.admin.endTurn());
|
||||||
|
// Login
|
||||||
|
var usernameClick = false;
|
||||||
|
usernameSpan.addEventListener('click', () => {
|
||||||
|
if (!usernameClick) {
|
||||||
|
usernameClick = true;
|
||||||
|
setInterval(() => {usernameClick = false;}, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var pass = window.prompt("🔑");
|
||||||
|
if (!pass) return;
|
||||||
|
vm.admin.login(pass);
|
||||||
|
});
|
||||||
|
|
||||||
// Load all vms
|
// Load all vms
|
||||||
config.serverAddresses.forEach(multicollab);
|
config.serverAddresses.forEach(multicollab);
|
||||||
// Export some stuff
|
// Export some stuff
|
||||||
window.screenshotVM = screenshotVM;
|
window.screenshotVM = screenshotVM;
|
||||||
window.multicollab = multicollab;
|
window.multicollab = multicollab;
|
||||||
|
window.getPerms = () => perms;
|
||||||
|
window.getRank = () => rank;
|
||||||
|
window.GetAdmin = () => vm.admin;
|
||||||
|
window.cvmEvents = createNanoEvents();
|
23
src/permissions.js
Normal file
23
src/permissions.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
export function makeperms(mask) {
|
||||||
|
const perms = {
|
||||||
|
restore: false,
|
||||||
|
reboot: false,
|
||||||
|
ban: false,
|
||||||
|
forcevote: false,
|
||||||
|
mute: false,
|
||||||
|
kick: false,
|
||||||
|
bypassturn: false,
|
||||||
|
rename: false,
|
||||||
|
grabip: false
|
||||||
|
};
|
||||||
|
if ((mask & 1) !== 0) perms.restore = true;
|
||||||
|
if ((mask & 2) !== 0) perms.reboot = true;
|
||||||
|
if ((mask & 4) !== 0) perms.ban = true;
|
||||||
|
if ((mask & 8) !== 0) perms.forcevote = true;
|
||||||
|
if ((mask & 16) !== 0) perms.mute = true;
|
||||||
|
if ((mask & 32) !== 0) perms.kick = true;
|
||||||
|
if ((mask & 64) !== 0) perms.bypassturn = true;
|
||||||
|
if ((mask & 128) !== 0) perms.rename = true;
|
||||||
|
if ((mask & 256) !== 0) perms.grabip = true;
|
||||||
|
return perms;
|
||||||
|
}
|
Loading…
Reference in a new issue