Create
This commit is contained in:
+30
@@ -0,0 +1,30 @@
|
|||||||
|
### IntelliJ IDEA ###
|
||||||
|
out/
|
||||||
|
!**/src/main/**/out/
|
||||||
|
!**/src/test/**/out/
|
||||||
|
.kotlin
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
bin/
|
||||||
|
!**/src/main/**/bin/
|
||||||
|
!**/src/test/**/bin/
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||||
|
|
||||||
|
<groupId>erfinderlabyrinth</groupId>
|
||||||
|
<artifactId>custompanel</artifactId>
|
||||||
|
<version>0.0.1</version>
|
||||||
|
<build>
|
||||||
|
<sourceDirectory>src</sourceDirectory>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>16</source>
|
||||||
|
<target>16</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.5.3</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<filters>
|
||||||
|
<filter>
|
||||||
|
<artifact>*:*</artifact>
|
||||||
|
<excludes>
|
||||||
|
<exclude>META-INF/*.SF</exclude>
|
||||||
|
<exclude>META-INF/*.DSA</exclude>
|
||||||
|
<exclude>META-INF/*.RSA</exclude>
|
||||||
|
</excludes>
|
||||||
|
</filter>
|
||||||
|
</filters>
|
||||||
|
<transformers>
|
||||||
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<mainClass>erfinderlabyrinth.panel.Main</mainClass>
|
||||||
|
</transformer>
|
||||||
|
<transformer
|
||||||
|
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||||
|
<resource>META-INF/services/java.sql.Driver</resource>
|
||||||
|
</transformer>
|
||||||
|
</transformers>
|
||||||
|
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>mvnrepository</id>
|
||||||
|
<url>https://mvnrepository.com/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.docker-java</groupId>
|
||||||
|
<artifactId>docker-java</artifactId>
|
||||||
|
<version>3.7.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-text</artifactId>
|
||||||
|
<version>1.14.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.json</groupId>
|
||||||
|
<artifactId>json</artifactId>
|
||||||
|
<version>20250517</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.xerial</groupId>
|
||||||
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
|
<version>3.51.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"database_url": "Hier könnte ihre Database stehen"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<h1>Unser tolles Panel</h1>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
var form = null
|
||||||
|
|
||||||
|
async function submit(e) {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
const formData = new FormData(form)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch("https://example.org/post", {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
})
|
||||||
|
|
||||||
|
const data = await response.json()
|
||||||
|
|
||||||
|
window.sessionStorage.setItem("user", data.user)
|
||||||
|
window.sessionStorage.setItem("session", data.session)
|
||||||
|
|
||||||
|
window.location.assign("/");
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = () => {
|
||||||
|
form = document.getElementById("login-form")
|
||||||
|
form.addEventListener("submit", submit)
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/** @type {HTMLElement} */
|
||||||
|
var serverList
|
||||||
|
|
||||||
|
window.onload = () => {
|
||||||
|
serverList = document.getElementById("server-list")
|
||||||
|
loadServerList()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadServerList() {
|
||||||
|
serversResponse = await fetch("/api/servers", {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
token: window.sessionStorage.getItem("session")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function addServerElement(name) {
|
||||||
|
const container = new HTMLDivElement()
|
||||||
|
const nameHeader = new HTMLHeadingElement()
|
||||||
|
nameHeader.textContent = name
|
||||||
|
container.appendChild(nameHeader)
|
||||||
|
document.appendChild(container)
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
<link href="style.css" rel="stylesheet">
|
||||||
|
<script src="js/login.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="fixed-center">
|
||||||
|
<h1>Login</h1>
|
||||||
|
<form id="login-form">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td><label for="username">Username</label></td>
|
||||||
|
<td><input autocomplete="username" type="text" id="username"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><label for="password">Password</label></td>
|
||||||
|
<td><input autocomplete="current-password" type="password" id="password"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<button type="submit">Login</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
<link href="style.css" rel="stylesheet">
|
||||||
|
<script src="js/server-list-insert.js"></script>
|
||||||
|
</head>
|
||||||
|
!!!file header.html!!!
|
||||||
|
<body>
|
||||||
|
<div class="center" id="server-list">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-center {
|
||||||
|
margin: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package erfinderlabyrinth.panel;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.json.JSONTokener;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class Config {
|
||||||
|
public static String database_url;
|
||||||
|
|
||||||
|
public static void load() {
|
||||||
|
if(!Files.exists(Path.of("config.json"))) {
|
||||||
|
try(FileOutputStream out = new FileOutputStream("config.json")) {
|
||||||
|
try(InputStream in = Config.class.getClassLoader().getResourceAsStream("/default-config.json")) {
|
||||||
|
if(in != null) {
|
||||||
|
in.transferTo(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try(FileReader reader = new FileReader("config.json")) {
|
||||||
|
JSONObject object = new JSONObject(new JSONTokener(reader));
|
||||||
|
|
||||||
|
database_url = object.getString("database_url");
|
||||||
|
} catch (IOException | JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package erfinderlabyrinth.panel;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.panel.Panel;
|
||||||
|
import erfinderlabyrinth.panel.panel.PanelSettings;
|
||||||
|
import erfinderlabyrinth.panel.panel.server.Server;
|
||||||
|
import erfinderlabyrinth.panel.panel.server.type.ServerType;
|
||||||
|
import erfinderlabyrinth.panel.website.api.APIManager;
|
||||||
|
import erfinderlabyrinth.panel.website.api.interfaces.LoginInterface;
|
||||||
|
import erfinderlabyrinth.panel.website.page.FilePage;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
Config.load();
|
||||||
|
registerInterfaces();
|
||||||
|
|
||||||
|
Panel panel = new Panel(new PanelSettings());
|
||||||
|
Server server = new Server(panel, new ServerType());
|
||||||
|
server.exec("eclipse-temurin:25", new String[]{"java", "-jar", "test.jar"}).onFinished(() -> {
|
||||||
|
System.out.println("test.jar is finished");
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void registerInterfaces() {
|
||||||
|
APIManager.registerInterface("login", new LoginInterface());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package erfinderlabyrinth.panel.database;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.Config;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
public class DatabaseManager {
|
||||||
|
static Connection connection;
|
||||||
|
public static void start() throws SQLException {
|
||||||
|
connection = DriverManager.getConnection(Config.database_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Connection getConnection() {
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
try {
|
||||||
|
connection.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package erfinderlabyrinth.panel.database;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.website.api.interfaces.LoginInterface;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
public class UserDatabase {
|
||||||
|
public static void init() throws SQLException {
|
||||||
|
String sql = "CREATE TABLE IF NOT EXISTS users (name varchar(64), password varchar(64));";
|
||||||
|
Statement statement = DatabaseManager.getConnection().createStatement();
|
||||||
|
statement.execute(sql);
|
||||||
|
statement.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LoginInterface.User getUser(String username, String password){
|
||||||
|
try {
|
||||||
|
String sql = "SELECT * FROM users WHERE name = ? AND password = ?";
|
||||||
|
PreparedStatement statement = DatabaseManager.getConnection().prepareStatement(sql);
|
||||||
|
statement.setString(1, username);
|
||||||
|
statement.setString(2, getSHA256(password));
|
||||||
|
|
||||||
|
ResultSet result = statement.executeQuery();
|
||||||
|
|
||||||
|
LoginInterface.User user = null;
|
||||||
|
if (result.next()) {
|
||||||
|
System.err.println("User exist with name " + result.getString("name"));
|
||||||
|
user = new LoginInterface.User(result.getString("name"));
|
||||||
|
}
|
||||||
|
statement.close();
|
||||||
|
|
||||||
|
return user;
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("error while getting the user");
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSHA256(String original) {
|
||||||
|
MessageDigest digest = null;
|
||||||
|
try {
|
||||||
|
digest = MessageDigest.getInstance("SHA-256");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
byte[] hash = digest.digest(
|
||||||
|
original.getBytes(StandardCharsets.UTF_8));
|
||||||
|
final StringBuilder hexString = new StringBuilder();
|
||||||
|
for (byte b : hash) {
|
||||||
|
final String hex = Integer.toHexString(0xff & b);
|
||||||
|
if (hex.length() == 1)
|
||||||
|
hexString.append('0');
|
||||||
|
hexString.append(hex);
|
||||||
|
}
|
||||||
|
return hexString.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package erfinderlabyrinth.panel.docker;
|
||||||
|
|
||||||
|
import javax.print.Doc;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.StandardProtocolFamily;
|
||||||
|
import java.net.UnixDomainSocketAddress;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.nio.channels.SocketChannel;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class DockerConnection {
|
||||||
|
public static Path DEFAULT_LINUX_DOCKER_PATH = Path.of("/unix/panel-connect");
|
||||||
|
|
||||||
|
public static DockerConnection open() throws IOException {
|
||||||
|
return open(DEFAULT_LINUX_DOCKER_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DockerConnection open(Path unixPath) throws IOException {
|
||||||
|
UnixDomainSocketAddress socketAddress = UnixDomainSocketAddress.of(unixPath);
|
||||||
|
try (SocketChannel channel = SocketChannel
|
||||||
|
.open(StandardProtocolFamily.UNIX)) {
|
||||||
|
channel.connect(socketAddress);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package erfinderlabyrinth.panel.panel;
|
||||||
|
|
||||||
|
import com.github.dockerjava.api.DockerClient;
|
||||||
|
import com.github.dockerjava.api.model.Container;
|
||||||
|
import com.github.dockerjava.api.model.Volume;
|
||||||
|
import com.github.dockerjava.core.DockerClientBuilder;
|
||||||
|
import erfinderlabyrinth.panel.panel.server.Server;
|
||||||
|
import erfinderlabyrinth.panel.website.Webserver;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class Panel {
|
||||||
|
public static final Map<String, String> GROUP_LABEL = Map.of("group", "customPanel");
|
||||||
|
Webserver webserver;
|
||||||
|
DockerClient dockerClient;
|
||||||
|
List<Server> servers;
|
||||||
|
|
||||||
|
public Panel(PanelSettings settings) {
|
||||||
|
webserver = new Webserver(settings.getPort(), this);
|
||||||
|
|
||||||
|
initDocker();
|
||||||
|
|
||||||
|
try {
|
||||||
|
webserver.start();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initDocker() {
|
||||||
|
dockerClient = DockerClientBuilder.getInstance().build();
|
||||||
|
|
||||||
|
List<Container> containerList = dockerClient.listContainersCmd().withShowAll(true).withLabelFilter(GROUP_LABEL).exec();
|
||||||
|
for (Container container : containerList) {
|
||||||
|
dockerClient.stopContainerCmd(container.getId());
|
||||||
|
dockerClient.removeContainerCmd(container.getId()).withForce(true).exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
System.out.println("Stopping Panel");
|
||||||
|
webserver.stop();
|
||||||
|
|
||||||
|
try {
|
||||||
|
dockerClient.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DockerClient getDockerClient() {
|
||||||
|
return dockerClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Server> getServers() {
|
||||||
|
return servers;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package erfinderlabyrinth.panel.panel;
|
||||||
|
|
||||||
|
public class PanelSettings {
|
||||||
|
public int getPort() {
|
||||||
|
return 443;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package erfinderlabyrinth.panel.panel.server;
|
||||||
|
|
||||||
|
import com.github.dockerjava.api.DockerClient;
|
||||||
|
import com.github.dockerjava.api.async.ResultCallback;
|
||||||
|
import com.github.dockerjava.api.exception.NotFoundException;
|
||||||
|
import com.github.dockerjava.api.model.Bind;
|
||||||
|
import com.github.dockerjava.api.model.HostConfig;
|
||||||
|
import com.github.dockerjava.api.model.PullResponseItem;
|
||||||
|
import com.github.dockerjava.api.model.Volume;
|
||||||
|
import erfinderlabyrinth.panel.panel.Panel;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public class ExecutedProcess {
|
||||||
|
CompletableFuture<Void> onFinish;
|
||||||
|
DockerClient client;
|
||||||
|
String dockerImage;
|
||||||
|
String[] command;
|
||||||
|
String containerId;
|
||||||
|
ExecutedProcess(DockerClient client, String dockerImage, String[] command) {
|
||||||
|
this.client = client;
|
||||||
|
this.dockerImage = dockerImage;
|
||||||
|
this.command = command;
|
||||||
|
|
||||||
|
execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void execute() {
|
||||||
|
try {
|
||||||
|
client.inspectImageCmd(dockerImage).exec();
|
||||||
|
start();
|
||||||
|
} catch (NotFoundException e) {
|
||||||
|
client.pullImageCmd(dockerImage).exec(new ResultCallback<PullResponseItem>() {
|
||||||
|
@Override
|
||||||
|
public void onStart(Closeable closeable) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNext(PullResponseItem object) {
|
||||||
|
if (object.getProgressDetail() != null) {
|
||||||
|
System.out.println(object.getProgressDetail().getStart() + " - " + object.getProgressDetail().getCurrent() + " - " + object.getProgressDetail().getTotal());
|
||||||
|
}else {
|
||||||
|
System.out.println("ProgressDetail is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable throwable) {
|
||||||
|
throw new RuntimeException(throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete() {
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void start() {
|
||||||
|
String containerId = client.createContainerCmd(dockerImage)
|
||||||
|
.withHostConfig(HostConfig.newHostConfig()
|
||||||
|
.withBinds(new Bind("/unix", new Volume("/unix")), new Bind("/test/server1", new Volume("/server")))
|
||||||
|
)//.withAutoRemove(false))
|
||||||
|
.withLabels(Panel.GROUP_LABEL)
|
||||||
|
.withCmd(command)
|
||||||
|
.withWorkingDir("/server")
|
||||||
|
.exec().getId();
|
||||||
|
client.startContainerCmd(containerId).exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onFinished(Runnable runnable) {
|
||||||
|
if (onFinish == null) {
|
||||||
|
onFinish = CompletableFuture.runAsync(() -> {
|
||||||
|
try {
|
||||||
|
client.waitContainerCmd(containerId).start().awaitCompletion();
|
||||||
|
} catch (InterruptedException ignored) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onFinish.thenAccept(ignored -> runnable.run());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package erfinderlabyrinth.panel.panel.server;
|
||||||
|
|
||||||
|
import com.github.dockerjava.api.async.ResultCallback;
|
||||||
|
import com.github.dockerjava.api.exception.NotFoundException;
|
||||||
|
import com.github.dockerjava.api.model.*;
|
||||||
|
import erfinderlabyrinth.panel.panel.Panel;
|
||||||
|
import erfinderlabyrinth.panel.panel.server.type.ServerType;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class Server {
|
||||||
|
Panel panel;
|
||||||
|
String name;
|
||||||
|
ServerType type;
|
||||||
|
File directory;
|
||||||
|
|
||||||
|
public Server(Panel panel, ServerType type) {
|
||||||
|
this.panel = panel;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void install(boolean deleteAllFiles) {
|
||||||
|
if (deleteAllFiles) {
|
||||||
|
for (File file : directory.listFiles()) {
|
||||||
|
deleteFile(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type.install(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteFile(File file) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
for (File file2 : file.listFiles()) {
|
||||||
|
deleteFile(file2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExecutedProcess exec(String dockerImage, String[] command) {
|
||||||
|
return new ExecutedProcess(panel.getDockerClient(), dockerImage, command);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package erfinderlabyrinth.panel.panel.server.type;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.panel.server.Server;
|
||||||
|
|
||||||
|
public class ServerType {
|
||||||
|
public String getDockerImage() {
|
||||||
|
return "eclipse-temurin:25";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void install(Server server) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package erfinderlabyrinth.panel.panel.server.type.install;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.panel.server.Server;
|
||||||
|
|
||||||
|
public class ExecutionStep implements InstallStep {
|
||||||
|
String dockerImage;
|
||||||
|
String[] command;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Server server) {
|
||||||
|
server.exec(dockerImage, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package erfinderlabyrinth.panel.panel.server.type.install;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.panel.server.Server;
|
||||||
|
|
||||||
|
public interface InstallStep {
|
||||||
|
void execute(Server server);
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package erfinderlabyrinth.panel.website;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.panel.Panel;
|
||||||
|
import erfinderlabyrinth.panel.website.api.APIManager;
|
||||||
|
import erfinderlabyrinth.panel.website.page.FilePage;
|
||||||
|
import erfinderlabyrinth.panel.website.page.Page;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
public class Connection {
|
||||||
|
Socket s;
|
||||||
|
Panel panel;
|
||||||
|
public Connection(Socket s, Panel panel) {
|
||||||
|
this.s = s;
|
||||||
|
this.panel = panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() throws Exception {
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
|
||||||
|
String line;
|
||||||
|
ConnectionType type = null;
|
||||||
|
String path = "";
|
||||||
|
String host = "";
|
||||||
|
int post_length = 0;
|
||||||
|
System.out.println("start reading");
|
||||||
|
while (!(line = reader.readLine()).isEmpty()) {
|
||||||
|
System.out.println("Input Line: " + line);
|
||||||
|
if (line.startsWith("GET")) {
|
||||||
|
type = ConnectionType.GET;
|
||||||
|
path = line.split(" ")[1];
|
||||||
|
}else if (line.startsWith("POST")) {
|
||||||
|
type = ConnectionType.POST;
|
||||||
|
path = line.split(" ")[1];
|
||||||
|
}else if (line.startsWith("OPTIONS")) {
|
||||||
|
type = ConnectionType.OPTIONS;
|
||||||
|
path = line.split(" ")[1];
|
||||||
|
} else if (line.startsWith("Host: ")) {
|
||||||
|
host = line.substring(6);
|
||||||
|
} else if (line.startsWith("Content-Length: ")) {
|
||||||
|
post_length = Integer.parseInt(line.substring(16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("Finished reading");
|
||||||
|
if (type == null) {
|
||||||
|
s.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] data = null;
|
||||||
|
|
||||||
|
if (type == ConnectionType.POST) {
|
||||||
|
System.out.println("Read Data: " + post_length + " Bytes");
|
||||||
|
data = new byte[post_length];
|
||||||
|
for (int i = 0; i < post_length; i++) {
|
||||||
|
data[i] = (byte)reader.read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.startsWith("/")) {
|
||||||
|
path = path.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputStream output = s.getOutputStream();
|
||||||
|
|
||||||
|
if (!path.startsWith("api/")) {
|
||||||
|
Page page;
|
||||||
|
|
||||||
|
page = FilePage.load(path);
|
||||||
|
|
||||||
|
if (page == null) {
|
||||||
|
output.write(("HTTP/1.0 404 UNKNOWN_PAGE\n\n").getBytes());
|
||||||
|
}else {
|
||||||
|
output.write(("HTTP/1.0 200 OK\n\n").getBytes());
|
||||||
|
output.write(page.getPageData());
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
path = path.substring("api/".length());
|
||||||
|
APIManager.call(path, type, data, output, panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
output.flush();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
System.out.println("Written");
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ConnectionType {
|
||||||
|
GET, POST, OPTIONS
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package erfinderlabyrinth.panel.website;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
public class Response {
|
||||||
|
int code;
|
||||||
|
JSONObject json;
|
||||||
|
public Response(int code, JSONObject json) {
|
||||||
|
this.code = code;
|
||||||
|
this.json = json;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Response ok(JSONObject json) {
|
||||||
|
return new Response(200, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Response missing(JSONObject json) {
|
||||||
|
return new Response(404, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Response unauthorized(JSONObject json) {
|
||||||
|
return new Response(401, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Response wrongConnectionType(JSONObject json) {
|
||||||
|
return new Response(405, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Response wrongData(JSONObject json) {
|
||||||
|
return new Response(400, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Response noContent(JSONObject json) {
|
||||||
|
return new Response(204, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getResponseCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject getJson() {
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package erfinderlabyrinth.panel.website;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.panel.Panel;
|
||||||
|
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.CharBuffer;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
public class Webserver {
|
||||||
|
int port;
|
||||||
|
Thread thread;
|
||||||
|
boolean running = true;
|
||||||
|
SSLServerSocket serverSocket;
|
||||||
|
Panel panel;
|
||||||
|
public Webserver(int port, Panel panel) {
|
||||||
|
this.port = port;
|
||||||
|
this.panel = panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() throws IOException {
|
||||||
|
byte[] passBytes;
|
||||||
|
try(FileInputStream in = new FileInputStream("pw.txt")) {
|
||||||
|
passBytes = in.readAllBytes();
|
||||||
|
} catch (IOException | NullPointerException e) {
|
||||||
|
System.err.println("Missing Password. Couldn't find the server keystore pass");
|
||||||
|
e.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ByteBuffer byteBuf = ByteBuffer.wrap(passBytes);
|
||||||
|
CharBuffer charBuf = StandardCharsets.UTF_8.decode(byteBuf);
|
||||||
|
char[] pass = charBuf.array();
|
||||||
|
|
||||||
|
try {
|
||||||
|
KeyStore store = KeyStore.getInstance("jks");
|
||||||
|
store.load(new FileInputStream("cert.jks"), pass);
|
||||||
|
|
||||||
|
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
|
||||||
|
keyManagerFactory.init(store, pass);
|
||||||
|
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
|
||||||
|
SSLContext context = SSLContext.getInstance("SSL");
|
||||||
|
context.init(keyManagers, null, new SecureRandom());
|
||||||
|
SSLServerSocketFactory factory = context.getServerSocketFactory();
|
||||||
|
serverSocket = (SSLServerSocket) factory.createServerSocket(port);
|
||||||
|
serverSocket.setNeedClientAuth(false);
|
||||||
|
serverSocket.setWantClientAuth(false);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
System.out.println("Port " + port + "is invalid.");
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("An error occured while opening the ServerSocket:");
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (serverSocket != null) {
|
||||||
|
thread = new Thread(() -> {
|
||||||
|
while(running) {
|
||||||
|
System.out.println("Server is running");
|
||||||
|
try {
|
||||||
|
Socket s = serverSocket.accept();
|
||||||
|
System.out.println("accepted");
|
||||||
|
Connection connection = new Connection(s, panel);
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
connection.start();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
running = false;
|
||||||
|
try {
|
||||||
|
serverSocket.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
thread.join();
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package erfinderlabyrinth.panel.website.api;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.panel.Panel;
|
||||||
|
import erfinderlabyrinth.panel.website.Connection;
|
||||||
|
import erfinderlabyrinth.panel.website.Response;
|
||||||
|
|
||||||
|
public interface APIInterface {
|
||||||
|
Response onCall(String path, Connection.ConnectionType connectionType, byte[] data, Panel panel);
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package erfinderlabyrinth.panel.website.api;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.panel.Panel;
|
||||||
|
import erfinderlabyrinth.panel.website.Connection;
|
||||||
|
import erfinderlabyrinth.panel.website.Response;
|
||||||
|
import erfinderlabyrinth.panel.website.api.interfaces.LoginInterface;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class APIManager {
|
||||||
|
public static HashMap<String, LoginInterface.Session> sessions = new HashMap<>();
|
||||||
|
static HashMap<String, APIInterface> interfaces = new HashMap<>();
|
||||||
|
public static void call(String path, Connection.ConnectionType connectionType, byte[] data, OutputStream output, Panel panel) throws IOException {
|
||||||
|
String mainCall = path.split("/")[0];
|
||||||
|
Response response = null;
|
||||||
|
if (connectionType == Connection.ConnectionType.OPTIONS) {
|
||||||
|
response = Response.noContent(new JSONObject());
|
||||||
|
}else {
|
||||||
|
APIInterface apiInterface = interfaces.get(mainCall);
|
||||||
|
if (apiInterface != null) {
|
||||||
|
response = apiInterface.onCall(path, connectionType, data, panel);
|
||||||
|
}
|
||||||
|
if (response == null) {
|
||||||
|
response = Response.missing(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output.write(("HTTP/1.0 " + response.getResponseCode() + " " + getDescription(response.getResponseCode()) + "\n").getBytes());
|
||||||
|
output.write(("""
|
||||||
|
Access-Control-Allow-Origin: *
|
||||||
|
Access-Control-Allow-Methods: POST, GET, OPTIONS
|
||||||
|
Access-Control-Allow-Headers: *
|
||||||
|
|
||||||
|
""").getBytes());
|
||||||
|
JSONObject json = response.getJson();
|
||||||
|
if (json == null) {
|
||||||
|
json = new JSONObject();
|
||||||
|
}
|
||||||
|
json.put("success", response.getJson() != null);
|
||||||
|
output.write(json.toString().getBytes());
|
||||||
|
output.flush();
|
||||||
|
output.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerInterface(String path, APIInterface apiInterface) {
|
||||||
|
interfaces.put(path, apiInterface);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getDescription(int responseCode) {
|
||||||
|
return switch (responseCode) {
|
||||||
|
case 200 -> "OK";
|
||||||
|
case 204 -> "NO CONTENT";
|
||||||
|
case 404 -> "UNKNOWN_API_CALL";
|
||||||
|
case 401 -> "UNAUTHORIZED";
|
||||||
|
case 405 -> "WRONG_METHODE";
|
||||||
|
case 400 -> "WRONG_DATA";
|
||||||
|
default -> "MISSING_DESCRIPTION";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package erfinderlabyrinth.panel.website.api;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import erfinderlabyrinth.panel.panel.Panel;
|
||||||
|
import erfinderlabyrinth.panel.website.Connection;
|
||||||
|
import erfinderlabyrinth.panel.website.Response;
|
||||||
|
import erfinderlabyrinth.panel.website.api.interfaces.LoginInterface;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
public interface LoginRequireAPIInterface extends APIInterface{
|
||||||
|
@Override
|
||||||
|
default Response onCall(String path, Connection.ConnectionType connectionType, byte[] data, Panel panel) {
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(new String(data));
|
||||||
|
String token = json.getString("token");
|
||||||
|
|
||||||
|
LoginInterface.Session session = APIManager.sessions.get(token);
|
||||||
|
if (session != null) {
|
||||||
|
return onLoggedinCall(path, connectionType, data, session, panel);
|
||||||
|
}
|
||||||
|
return onNotLoggedinCall(path, connectionType, data, panel);
|
||||||
|
}catch (IllegalStateException|NullPointerException e) {
|
||||||
|
return Response.wrongData(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Response onLoggedinCall(String path, Connection.ConnectionType connectionType, byte[] data, LoginInterface.Session session, Panel panel);
|
||||||
|
|
||||||
|
default Response onNotLoggedinCall(String path, Connection.ConnectionType connectionType, byte[] data, Panel panel) {
|
||||||
|
return Response.unauthorized(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package erfinderlabyrinth.panel.website.api.interfaces;
|
||||||
|
import erfinderlabyrinth.panel.database.UserDatabase;
|
||||||
|
import erfinderlabyrinth.panel.panel.Panel;
|
||||||
|
import erfinderlabyrinth.panel.website.Connection;
|
||||||
|
import erfinderlabyrinth.panel.website.Response;
|
||||||
|
import erfinderlabyrinth.panel.website.api.APIInterface;
|
||||||
|
import erfinderlabyrinth.panel.website.api.APIManager;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
public class LoginInterface implements APIInterface {
|
||||||
|
@Override
|
||||||
|
public Response onCall(String path, Connection.ConnectionType connectionType, byte[] data, Panel panel) {
|
||||||
|
if (path.equals("login/") || path.equals("login")) {
|
||||||
|
if (connectionType == Connection.ConnectionType.POST) {
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(new String(data));
|
||||||
|
String name = json.getString("name");
|
||||||
|
String password = json.getString("password");
|
||||||
|
|
||||||
|
User user = UserDatabase.getUser(name, password);
|
||||||
|
|
||||||
|
//if (name.equals("root") && UserDatabase.getSHA256(password).equals("2a7044b477960dd525b7f5990a3746a097cd189769603e670b7a5040ec797ffd")) {
|
||||||
|
// user = new User("root");
|
||||||
|
//}
|
||||||
|
if (user == null) {
|
||||||
|
return Response.ok(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Session session = new Session(user);
|
||||||
|
APIManager.sessions.put(session.getToken(), session);
|
||||||
|
|
||||||
|
JSONObject response = new JSONObject();
|
||||||
|
response.put("token", session.getToken());
|
||||||
|
response.put("user", session.getUser().getName());
|
||||||
|
return Response.ok(response);
|
||||||
|
|
||||||
|
}catch (IllegalStateException|NullPointerException e) {
|
||||||
|
return Response.wrongData(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Response.wrongConnectionType(null);
|
||||||
|
}
|
||||||
|
return Response.missing(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Session{
|
||||||
|
User user;
|
||||||
|
long sessionCreated;
|
||||||
|
String token;
|
||||||
|
Session(User user) {
|
||||||
|
this.user = user;
|
||||||
|
this.sessionCreated = System.currentTimeMillis();
|
||||||
|
this.token = generateToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateToken() {
|
||||||
|
SecureRandom random = new SecureRandom();
|
||||||
|
long randomLong1 = random.nextLong();
|
||||||
|
long randomLong2 = random.nextLong();
|
||||||
|
return Long.toHexString(randomLong1) + Long.toHexString(randomLong2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class User{
|
||||||
|
String name;
|
||||||
|
|
||||||
|
public User(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "User{" +
|
||||||
|
"name='" + name + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package erfinderlabyrinth.panel.website.api.interfaces;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.panel.Panel;
|
||||||
|
import erfinderlabyrinth.panel.panel.server.Server;
|
||||||
|
import erfinderlabyrinth.panel.website.Connection;
|
||||||
|
import erfinderlabyrinth.panel.website.Response;
|
||||||
|
import erfinderlabyrinth.panel.website.api.LoginRequireAPIInterface;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
public class RequestServerListInterface implements LoginRequireAPIInterface {
|
||||||
|
@Override
|
||||||
|
public Response onLoggedinCall(String path, Connection.ConnectionType connectionType, byte[] data, LoginInterface.Session session, Panel panel) {
|
||||||
|
JSONObject object = new JSONObject();
|
||||||
|
JSONArray serverList = new JSONArray();
|
||||||
|
object.append("servers", serverList);
|
||||||
|
|
||||||
|
for (Server server : panel.getServers()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return Response.ok(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package erfinderlabyrinth.panel.website.api.interfaces;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.website.Connection;
|
||||||
|
import erfinderlabyrinth.panel.website.Response;
|
||||||
|
import erfinderlabyrinth.panel.website.api.APIInterface;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class SubInterface implements APIInterface {
|
||||||
|
static HashMap<String, APIInterface> subInterfaces = new HashMap<>();
|
||||||
|
@Override
|
||||||
|
public Response onCall(String path, Connection.ConnectionType connectionType, byte[] data) {
|
||||||
|
String secondPath = path.split("/")[1];
|
||||||
|
if (subInterfaces.containsKey(secondPath)) {
|
||||||
|
return subInterfaces.get(secondPath).onCall(path, connectionType, data);
|
||||||
|
}else {
|
||||||
|
return Response.missing(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerSubInterface(String path, APIInterface apiInterface) {
|
||||||
|
subInterfaces.put(path, apiInterface);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package erfinderlabyrinth.panel.website.api.interfaces;
|
||||||
|
|
||||||
|
public class SubInterfaces {
|
||||||
|
public static final SubInterface PLAYER = new SubInterface();
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package erfinderlabyrinth.panel.website.api.interfaces;
|
||||||
|
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.panel.Panel;
|
||||||
|
import erfinderlabyrinth.panel.website.Connection;
|
||||||
|
import erfinderlabyrinth.panel.website.Response;
|
||||||
|
import erfinderlabyrinth.panel.website.api.LoginRequireAPIInterface;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
public class TokenCheckInterface implements LoginRequireAPIInterface {
|
||||||
|
@Override
|
||||||
|
public Response onLoggedinCall(String path, Connection.ConnectionType connectionType, byte[] data, LoginInterface.Session session, Panel panel) {
|
||||||
|
JSONObject object = new JSONObject();
|
||||||
|
object.put("username", session.getUser().getName());
|
||||||
|
return Response.ok(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response onNotLoggedinCall(String path, Connection.ConnectionType connectionType, byte[] data, Panel panel) {
|
||||||
|
return Response.ok(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package erfinderlabyrinth.panel.website.command;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.website.page.PageParser;
|
||||||
|
import erfinderlabyrinth.panel.website.page.RequestContext;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class FileCommand implements PageParser.PageCommand {
|
||||||
|
public static final String FILE_PATH_START = "insert/";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String apply(String args, RequestContext context) {
|
||||||
|
Path path = Path.of(FILE_PATH_START, args);
|
||||||
|
path = path.normalize();
|
||||||
|
|
||||||
|
if(path.startsWith(FILE_PATH_START)) {
|
||||||
|
try (InputStream in = getClass().getClassLoader().getResourceAsStream(FILE_PATH_START + args.replace("..", ""))) {
|
||||||
|
if (in != null) {
|
||||||
|
return new String(in.readAllBytes(), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean needsEscaping() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package erfinderlabyrinth.panel.website.page;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class FilePage implements Page{
|
||||||
|
byte[] data;
|
||||||
|
public FilePage(byte[] data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FilePage load(String path) {
|
||||||
|
try (InputStream input = FilePage.class.getResourceAsStream("/website/" + path.replace("..", ""))) {
|
||||||
|
|
||||||
|
if (input != null) {
|
||||||
|
byte[] bytes = input.readAllBytes();
|
||||||
|
|
||||||
|
if(path.endsWith(".html")) {
|
||||||
|
String text = new String(bytes, StandardCharsets.UTF_8);
|
||||||
|
String parsed = PageParser.parsePage(text, new RequestContext());
|
||||||
|
|
||||||
|
bytes = parsed.getBytes(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
return new FilePage(bytes);
|
||||||
|
}
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getPageData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package erfinderlabyrinth.panel.website.page;
|
||||||
|
|
||||||
|
public interface Page {
|
||||||
|
byte[] getPageData();
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package erfinderlabyrinth.panel.website.page;
|
||||||
|
|
||||||
|
import erfinderlabyrinth.panel.website.command.FileCommand;
|
||||||
|
import org.apache.commons.text.StringEscapeUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class PageParser {
|
||||||
|
private static final Map<String, PageCommand> commands = new HashMap<>(
|
||||||
|
Map.of(
|
||||||
|
"file", new FileCommand()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
public static String parsePage(String original, RequestContext context) {
|
||||||
|
int exclamationCount = 0;
|
||||||
|
|
||||||
|
StringBuilder output = new StringBuilder();
|
||||||
|
StringBuilder command = null;
|
||||||
|
|
||||||
|
boolean wasInTag = false;
|
||||||
|
boolean inTag = false;
|
||||||
|
|
||||||
|
for(int i = 0; i < original.length(); i++) {
|
||||||
|
|
||||||
|
char c = original.charAt(i);
|
||||||
|
if(c == '!') {
|
||||||
|
exclamationCount++;
|
||||||
|
if(exclamationCount == 3) {
|
||||||
|
inTag = !inTag;
|
||||||
|
if(inTag) {
|
||||||
|
command = new StringBuilder();
|
||||||
|
} else {
|
||||||
|
output.append(interpretCommand(command.toString(), context));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(!inTag && !wasInTag && exclamationCount > 0) {
|
||||||
|
for(int x = 0; x < exclamationCount; x++) {
|
||||||
|
output.append('!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exclamationCount = 0;
|
||||||
|
|
||||||
|
if(inTag) {
|
||||||
|
command.append(c);
|
||||||
|
} else {
|
||||||
|
output.append(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
wasInTag = inTag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String interpretCommand(String command, RequestContext context) {
|
||||||
|
int firstSpace = command.indexOf(' ');
|
||||||
|
String name = command.substring(0, firstSpace);
|
||||||
|
String cmdArgs = command.substring(firstSpace + 1, command.length() - 1);
|
||||||
|
|
||||||
|
PageCommand pageCommand = commands.get(name);
|
||||||
|
|
||||||
|
if(pageCommand == null) {
|
||||||
|
throw new RuntimeException("Command not found " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
String out = pageCommand.apply(cmdArgs, context);
|
||||||
|
|
||||||
|
if(pageCommand.needsEscaping()) {
|
||||||
|
return StringEscapeUtils.escapeHtml4(out);
|
||||||
|
} else {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface PageCommand {
|
||||||
|
String apply(String args, RequestContext context);
|
||||||
|
|
||||||
|
default boolean needsEscaping() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println(parsePage("fjjalöfjjwm!!f!kwsöqwlsd2,!!!p95!!!fjdqkpk47 ßz8dkß2kqla4qoj9cf69p576aop! ah faöohfaöh !!!testcommand1!!!", new RequestContext()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package erfinderlabyrinth.panel.website.page;
|
||||||
|
|
||||||
|
public class RequestContext {
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user