Added ability to run containers in web browser

This commit is contained in:
Lukasdotcom
2022-01-22 15:04:24 -05:00
parent 9d8f052140
commit 2e3ec08397
8 changed files with 212 additions and 7 deletions

31
html/api/docker.php Executable file
View File

@@ -0,0 +1,31 @@
<?php
require_once "api.php";
if (! $PRIVILEGE["docker"] and ! $PRIVILEGE["dockerAdmin"]) { // Makes sure that the person has the right privilege
missingPrivilege($USERNAME);
exit();
}
if (array_key_exists("containers", $_GET)) { // Will list all avaliable containers
echo json_encode(dbRequest2("SELECT * FROM docker WHERE owner='$USERNAME' or action='stopped'"));
} else if (array_key_exists("start", $_POST) and array_key_exists("image", $_POST)) { // Used to start a container and will return the password
$id = $_POST["start"];
$image = $OGPOST["image"];
if (! dbRequest2("SELECT * FROM docker WHERE action='stopped' and ID='$id'")) { // Will check if the container can be started
echo "Container does not exist or is used";
http_response_code(404);
} elseif (! dbRequest2("SELECT * FROM dockerImages WHERE realName=?", "*", [$image])) { // Will cheeck if the image exists
echo "Image does not exist";
http_response_code(404);
} else { // Will start the image
$password = $USERNAME;
$password .= rand();
$password = sanitize(substr(sha1($password), 5, 8));
dbCommand("UPDATE docker SET action='starting', image='$image', password='$password' WHERE ID='$id'");
writeLog(23, "$USERNAME is starting container with $image image and id $id and an IP of $address");
echo $password;
}
} else if (array_key_exists("images", $_GET)) {
echo json_encode(dbRequest2("SELECT * FROM dockerImages")); // Will list all available images
} else {
http_response_code(400);
echo "Invalid command";
}

59
html/docker/index.js Executable file
View File

@@ -0,0 +1,59 @@
function start(id) { // Used to start a container
const ajax = new XMLHttpRequest();
ajax.onload = function() {
if (ajax.status != 200) {
JQerror(this.responseText);
}
update();
}
ajax.open("POST", `/api/docker.php`);
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
ajax.send(`start=${id}&image=${$(`#${id}image`).val()}&key='${getCookie('user')}'`);
}
function update() { // Used to update the table
const ajax = new XMLHttpRequest();
ajax.onload = function() {
if (ajax.status == 200) {
let text = "<tr><th>ID</th><th>Status</th><th>Image</th><th>Password</th><th>Link</th></tr>";
Object.values(JSON.parse(this.responseText)).forEach(element => {
let password = "";
let image = "";
if (element["action"] == "started") {
password = element["password"];
}
if (element["action"] == "started") { // Used to find the Human Readable name of the image
image = "unknown";
Object.values(images).forEach(element2 => {
if (element2["realName"] == element["image"]) {
image = element2["shortName"];
}
});
} else if (element["action"] == "stopped") {
image = "<select>"
Object.values(images).forEach(element2 => {
image += `<option id='${element["ID"]}image' value='${element2["realName"]}'>${element2["shortName"]}</option>`;
});
image += "</select>";
}
text += `<tr><td>${element["ID"]}</td><td>${element["action"]}</td><td>${image}</td><td>${password}</td><td>${element["link"]}</td>`;
if (element["action"] == "stopped") { // Used to add button to start container
text += `<td><button onclick='start("${element["ID"]}")'>Start</button></td>`;
}
text += "</tr>"
});
$("#docker").html(text);
} else {
JQerror(this.responseText);
}
}
ajax.open("GET", `/api/docker.php?containers=get&key='${getCookie('user')}'`);
ajax.send();
}
$(document).ready(function() {
update();
setInterval(update, 5000);
});

48
html/docker/index.php Executable file
View File

@@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<title>
Schaefer Family - Containers
</title>
<?php
$DESCRIPTION = "A way to start a few VM and access them in a web browser";
require_once '../include/all.php';
?>
</head>
<body>
<?php
include '../include/menu.php';
echo "<div class='main'>";
if (! $USERNAME) {
echo "<h2>You are not logged in redirecting...</h2>";
header("Refresh:3; url=/login.php", true);
http_response_code(401);
} else if (! $PRIVILEGE["docker"]) {
http_response_code(403);
header("Refresh:3; url=/index.php", true);
echo "<h2>Forbidden redirecting...</h2>";
} else {
$images = dbRequest2("SELECT * FROM dockerImages");
echo "<script>var images=JSON.parse('";
echo json_encode($images);
echo "')</script>";
?>
<script type='text/javascript' src='index.js'></script>
<h1>Run Containers</h1>
<table>
<tbody id='docker'>
<tr>
<th>ID</th><th>Status</th><th>Image</th><th>Password</th><th>Link</th>
</tr>
</tbody>
</table>
<?php
}
?>
</div>
</body>
</html>

View File

@@ -134,6 +134,7 @@ function dbRequest2($command, $result="*", $prepare=[])
} else if ($length == 1) {
$stmt = mysqli_prepare($connection, $command);
$parameter1 = $prepare[0];
echo $parameter1;
mysqli_stmt_bind_param($stmt, "s", $parameter1);
mysqli_stmt_execute($stmt);
$response = mysqli_stmt_get_result($stmt);
@@ -266,7 +267,7 @@ foreach ($_COOKIE as $pointer => $value) {
// Removes all expired cookies from the database
$Time = time();
dbCommand("DELETE FROM cookies WHERE expire < $Time and expire != 0");
$PRIVILEGELIST = ["root", "internet", "editUser", "deleteUser", "deleteElectricity", "deleteLog", "viewLog", "changeCredintials", "deleteElectricity", "deleteError", "restartServer", "updateServer", "serverStatus", "viewBackup", "restore"]; // A List of all possible privileges
$PRIVILEGELIST = ["root", "internet", "editUser", "deleteUser", "deleteElectricity", "deleteLog", "viewLog", "changeCredintials", "deleteElectricity", "deleteError", "restartServer", "updateServer", "serverStatus", "viewBackup", "restore", "docker", "dockerAdmin"]; // A List of all possible privileges
function noUser() { # Used to set everything up as if no yser is logged in
global $USERNAME, $PRIVILEGE, $PRIVILEGELIST;
$USERNAME = "";

View File

@@ -1,5 +1,5 @@
<?php
$MENUITEMS = [["Main Page", "/index.php"], ["Internet", "/internet/index.php"], ["Dice Game", "/diceGame/index.php"], ["Space 3", "/space3/index.php"], ["Electricity Log", "/electricity.php"], ["Floppy", "/floppy.php"], ["Soccer", "/soccer.php"], ["Golf", "/golf/index.php"], ["privilege", "viewLog", "/log/index.php", "Server Log"], ["privilege", "viewBackup", "/backup/index.php", "Backups"], ["Cookie Clicker Addon", "/cookieClicker/index.php"], ["user", "/usermenu/index.php", "User Menu"], ["user", "/usermenu/key.php", "Session Manager"], ["notUser", "/login.php", "Login/Signup"], ["user", "/login.php", "Logout"]];
$MENUITEMS = [["Main Page", "/index.php"], ["Internet", "/internet/index.php"], ["Dice Game", "/diceGame/index.php"], ["Space 3", "/space3/index.php"], ["Electricity Log", "/electricity.php"], ["Floppy", "/floppy.php"], ["Soccer", "/soccer.php"], ["Golf", "/golf/index.php"], ["Docker Containers", "/docker/index.php"], ["privilege", "viewLog", "/log/index.php", "Server Log"], ["privilege", "viewBackup", "/backup/index.php", "Backups"], ["Cookie Clicker Addon", "/cookieClicker/index.php"], ["user", "/usermenu/index.php", "User Menu"], ["user", "/usermenu/key.php", "Session Manager"], ["notUser", "/login.php", "Login/Signup"], ["user", "/login.php", "Logout"]];
echo "<div class='vertical-menu'>";
function menuItem($link, $name)
{

View File

@@ -113,5 +113,35 @@
"type": "22",
"name": "Session created",
"color": "#00ccff"
},
{
"type": "23",
"name": "Started Container",
"color": "#660099"
},
{
"type": "24",
"name": "Stopped Container",
"color": "#660099"
},
{
"type": "25",
"name": "Created Image",
"color": "#660099"
},
{
"type": "26",
"name": "Deleted Image",
"color": "#660099"
},
{
"type": "27",
"name": "Created Container",
"color": "#660099"
},
{
"type": "28",
"name": "Deleted Container",
"color": "#660099"
}
]

View File

@@ -179,7 +179,9 @@ def repair(): # Repairs all tables
"space3likes" : [["id", 1], ["account", 0]],
"golfGamePlayers" : [["gameID", 1], ["multiplier", 1], ["user", 0], ["points", 1], ["orderID", 1], ["lastMode", 0], ["upToDate", 6]],
"golfGameCards" : [["gameID", 1], ["user", 0], ["card", 1], ["cardPlacement", 1], ["faceUp", 6]],
"golfGame" : [["ID", 5], ["deck", 4], ["discard", 4], ["cardNumber", 1], ["flipNumber", 1], ["multiplierForFlip", 1], ["pointsToEnd", 1], ["name", 0], ["password", 0], ["players", 1], ["playersToStart", 1], ["currentPlayer", 1], ["turnStartTime", 1], ["locked", 6]]
"golfGame" : [["ID", 5], ["deck", 4], ["discard", 4], ["cardNumber", 1], ["flipNumber", 1], ["multiplierForFlip", 1], ["pointsToEnd", 1], ["name", 0], ["password", 0], ["players", 1], ["playersToStart", 1], ["currentPlayer", 1], ["turnStartTime", 1], ["locked", 6]],
"docker" : [["link", 0], ["action", 0], ["image", 0], ["password", 0], ["owner", 0], ["port", 1], ["ID", 0]],
"dockerImages" : [["realName", 0], ["shortName", 0], ["description", 0]]
}
changedTables = []
for x in databaseDict:
@@ -245,9 +247,14 @@ def repair(): # Repairs all tables
command("ALTER TABLE cookies ADD lastIP varchar(255) NULL")
version = "v1.1"
updatedVersions.append("v1.1")
if versionNumber == "v1.1":
createTable("docker", [["link", 0], ["action", 0], ["image", 0], ["password", 0], ["owner", 0], ["port", 1], ["ID", 0]])
createTable("dockerImage", [["realName", 0], ["shortName", 0], ["description", 0]])
version = "v2.0"
updatedVersions.append("v2.0")
# Fixes the version if it is invalid to the latest version
if version != "v1.1":
version = "v1.1"
if version != "v2.0":
version = "v2.0"
except:
1
command("DELETE FROM information WHERE pointer='version'")

View File

@@ -15,7 +15,12 @@ import os
import datetime
import sys
import glob
try:
import docker
dockerClient = docker.from_env()
skipDocker = False
except:
skipDocker = True
def error(e):
return "".join(traceback.format_exception(etype=type(e), value=e, tb=e.__traceback__))
@@ -230,9 +235,11 @@ try:
database.command("DELETE FROM golfGameCards WHERE NOT EXISTS (SELECT * FROM golfGame WHERE golfGameCards.gameID = golfGame.ID)") # Removes players from games that do not exist
writeLog("Server maintenance ran succesfully.", 12)
# Will add to log if the GPIO library exists
# Will add to log if a library could not be connected to
if skipGPIO:
writeLog("Could not import GPIO library", 9)
if skipDocker:
writeLog("Could not connect to docker", 9)
while True: # will wait until connected to internet
try:
urllib.request.urlopen("https://google.com")
@@ -341,6 +348,28 @@ try:
# Will check every 2 seconds if the button is pressed and when it is show it on the led and then wait another second to verify that it is an actual press
while True:
time.sleep(2)
# Will check if a docker container should be started or stopped.
if not skipDocker:
dockerList = database.trueSearch("SELECT * FROM docker")
for x in dockerList:
print(x)
# Will check if the container has already been stopped
id = x[6]
if x[1] == "started":
try:
dockerClient.containers.get(id)
except Exception:
database.command(f"UPDATE docker SET action='stopped' WHERE ID='{id}'")
writeLog(f"Container with id of {id} was stopped", 24)
elif x[1] == "starting": # Will start all containers that are neccessary
password = x[3]
newID = dockerClient.containers.run(x[2], detach=True, ports={'80/tcp':x[5]}, remove=True, environment=[f"VNC_PASSWD={password}"]).attrs["Id"]
database.command(f"UPDATE docker SET action='started', id='{newID}' WHERE ID='{id}'")
writeLog(f"Container with id of {id} which changed to {newID} was started", 23)
elif x[1] == "stopping": # Stops all containers that need to be stopped.
dockerClient.containers.get(id).stop()
database.command(f"UPDATE docker SET action='stopped' WHERE ID='{id}'")
writeLog(f"Container with id of {id} was stopped", 24)
if os.path.isfile(location + "restart.json"): # Used to restart the server
writeLog("Server is being restarted", 12)
os.remove(location + "restart.json")