added file upload and checksum checks
This commit is contained in:
parent
d0b73e91fa
commit
6dc0f8b743
5 changed files with 188 additions and 59 deletions
|
@ -1,6 +1,17 @@
|
|||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
app: {
|
||||
head: {
|
||||
title: 'Minecraft Server Manager',
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content: 'Minecraft Server Manager by WeeXnes'
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
compatibilityDate: '2024-11-01',
|
||||
devtools: { enabled: true },
|
||||
modules: ['@nuxtjs/tailwindcss', '@nuxt/icon']
|
||||
modules: ['@nuxtjs/tailwindcss', '@nuxt/icon'],
|
||||
})
|
122
pages/index.vue
122
pages/index.vue
|
@ -9,7 +9,7 @@
|
|||
|
||||
<div class="mt-2 text-sm">
|
||||
<p><strong>Version:</strong> {{ server.version }}</p>
|
||||
<p><strong>Memory:</strong> {{ server.maxMemory }}GB</p>
|
||||
<p><strong>Memory:</strong> {{ server.maxMemory }} GB</p>
|
||||
</div>
|
||||
|
||||
<div class="form-control mt-4 flex flex-row gap-2">
|
||||
|
@ -48,11 +48,17 @@
|
|||
</div>
|
||||
<input v-model="addDialog.newServer.version" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">Jar Download URL</span>
|
||||
<span class="label-text">Jar File Upload</span>
|
||||
</div>
|
||||
<input v-model="addDialog.newServer.jar_url" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
<input
|
||||
type="file"
|
||||
accept=".jar"
|
||||
class="file-input file-input-bordered w-full max-w-xs"
|
||||
@change="onFileChange"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label class="form-control w-full max-w-xs">
|
||||
|
@ -144,7 +150,42 @@
|
|||
</div>
|
||||
<input v-model="editServerDialog.properties['pvp']" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
|
||||
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">Render Distance</span>
|
||||
</div>
|
||||
<input v-model="editServerDialog.properties['view-distance']" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">Simulation Distance</span>
|
||||
</div>
|
||||
<input v-model="editServerDialog.properties['simulation-distance']" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
|
||||
|
||||
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">Server Banner</span>
|
||||
</div>
|
||||
<input v-model="editServerDialog.properties['motd']" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="label">
|
||||
<span class="label-text">PVP</span>
|
||||
</div>
|
||||
<input v-model="editServerDialog.properties['pvp']" type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs" />
|
||||
</label>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -174,14 +215,15 @@
|
|||
|
||||
import type {MinecraftServer} from "~/types/MinecraftServer";
|
||||
import axios from 'axios';
|
||||
import { stringify , parse } from 'ini'
|
||||
import {parse, stringify} from 'ini'
|
||||
|
||||
const settings = reactive({
|
||||
servers: [] as MinecraftServer[],
|
||||
})
|
||||
|
||||
const addDialog = reactive({
|
||||
newServer: {} as MinecraftServer
|
||||
newServer: {} as MinecraftServer,
|
||||
uploadData: '' as string
|
||||
})
|
||||
|
||||
const serverLogDialog = reactive({
|
||||
|
@ -241,6 +283,9 @@ const getLogs = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const showEditServerDialog = async (server: MinecraftServer) => {
|
||||
editServerDialog.selectedServer = server
|
||||
await getProperties()
|
||||
|
@ -302,8 +347,13 @@ const deleteServer = async (server: MinecraftServer) => {
|
|||
|
||||
const addServer = async (server: MinecraftServer) => {
|
||||
try {
|
||||
const checksum = await calculateChecksum(addDialog.uploadData)
|
||||
const response = await axios.post('/api/addServer', {
|
||||
newServer: addDialog.newServer
|
||||
newServer: addDialog.newServer,
|
||||
fileUpload:{
|
||||
data: addDialog.uploadData,
|
||||
checksum: checksum
|
||||
}
|
||||
});
|
||||
console.log(response.data);
|
||||
await getServers()
|
||||
|
@ -313,6 +363,66 @@ const addServer = async (server: MinecraftServer) => {
|
|||
}
|
||||
|
||||
|
||||
const onFileChange = async (event: any) => {
|
||||
const file = event.target.files[0];
|
||||
addDialog.newServer.jarName = file.name;
|
||||
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
const readFile = new Promise<ArrayBuffer>((resolve, reject) => {
|
||||
reader.onload = (e) => {
|
||||
resolve(e.target?.result as ArrayBuffer);
|
||||
};
|
||||
reader.onerror = (error) => {
|
||||
reject(error);
|
||||
};
|
||||
});
|
||||
reader.readAsArrayBuffer(file);
|
||||
|
||||
try {
|
||||
const result = await readFile;
|
||||
addDialog.uploadData = arrayBufferToBase64(result);
|
||||
} catch (error) {
|
||||
console.error("Error reading file:", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const arrayBufferToBase64 = (buffer: ArrayBuffer): string => {
|
||||
const uint8Array = new Uint8Array(buffer);
|
||||
let binaryString = '';
|
||||
|
||||
uint8Array.forEach((byte) => {
|
||||
binaryString += String.fromCharCode(byte);
|
||||
});
|
||||
|
||||
return btoa(binaryString);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const calculateChecksum = async (data: any) => {
|
||||
try {
|
||||
const buffer = data instanceof ArrayBuffer ? data : new TextEncoder().encode(data);
|
||||
|
||||
const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
|
||||
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||
const hexString = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('');
|
||||
|
||||
console.log('Checksum (SHA-256):', hexString);
|
||||
return hexString;
|
||||
} catch (error) {
|
||||
console.error('Error calculating checksum:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
const startServer = async (server: MinecraftServer) => {
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import {getServerByName} from "~/types/MinecraftServer";
|
||||
import {getJarPath, getServerByName} from "~/types/MinecraftServer";
|
||||
import {environment} from "~/core/globals";
|
||||
import {saveJsonFile} from "~/util/jsonLoader";
|
||||
import * as crypto from 'crypto';
|
||||
import * as fs from "node:fs";
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
|
||||
const body = await readBody(event);
|
||||
const { newServer } = body;
|
||||
const { newServer, fileUpload } = body;
|
||||
|
||||
const server = getServerByName(newServer.name);
|
||||
|
||||
|
@ -13,12 +15,50 @@ export default defineEventHandler(async (event) => {
|
|||
return { message: "Server with name " + newServer.name + " does already exist" };
|
||||
}
|
||||
|
||||
let uploadData = fileUpload.data;
|
||||
|
||||
let checksumFromClient = fileUpload.checksum;
|
||||
let checksumFromServer = calculateChecksum(uploadData);
|
||||
|
||||
|
||||
try {
|
||||
|
||||
if(checksumFromServer != checksumFromClient) {
|
||||
return { status: 'error', error: "Checksum failed" };
|
||||
}
|
||||
|
||||
environment.settings.servers.push({...newServer})
|
||||
saveJsonFile()
|
||||
|
||||
|
||||
const decodedData = decodeBase64Node(uploadData)
|
||||
fs.writeFileSync(getJarPath(newServer), decodedData);
|
||||
|
||||
return { status: 'success' };
|
||||
} catch (error) {
|
||||
return { status: 'error', error: error };
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const calculateChecksum = (data: any) => {
|
||||
try {
|
||||
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data, 'utf-8');
|
||||
const hash = crypto.createHash('sha256');
|
||||
hash.update(buffer);
|
||||
const checksum = hash.digest('hex');
|
||||
console.log('Checksum (SHA-256):', checksum);
|
||||
return checksum;
|
||||
} catch (error) {
|
||||
console.error('Error calculating checksum:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
function decodeBase64Node(base64String: string): Buffer {
|
||||
return Buffer.from(base64String, 'base64');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import {environment} from "~/core/globals";
|
|||
export interface MinecraftServer {
|
||||
name: string;
|
||||
version: string;
|
||||
jar_url: string;
|
||||
jarName: string;
|
||||
maxMemory: number;
|
||||
process: any;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ export function getServerDirectory (server: MinecraftServer): string {
|
|||
}
|
||||
|
||||
export function getJarPath (server: MinecraftServer): string {
|
||||
return environment.paths.servers + "/" + server.name + "/server.jar"
|
||||
return environment.paths.servers + "/" + server.name + "/" + server.jarName
|
||||
}
|
||||
|
||||
export function getPropertiesPath (server: MinecraftServer): string {
|
||||
|
@ -25,6 +25,6 @@ export function getLogsPath (server: MinecraftServer): string {
|
|||
return environment.paths.servers + "/" + server.name + "/logs/latest.log"
|
||||
}
|
||||
|
||||
export function getServerByName(server_name: string): MinecraftServer | undefined{
|
||||
export function getServerByName(server_name: string): MinecraftServer | undefined {
|
||||
return environment.settings.servers.find(server => server.name == server_name);
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
import {environment} from "~/core/globals";
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import type {SettingsJsonFile} from "~/types/SettingsJsonFile";
|
||||
import * as https from "node:https";
|
||||
import type {MinecraftServer} from "~/types/MinecraftServer";
|
||||
import {getServerDirectory} from "~/types/MinecraftServer";
|
||||
|
||||
export function loadJsonFile(){
|
||||
try {
|
||||
|
@ -65,54 +65,22 @@ export function createPathIfNotExists(dirPath: string) {
|
|||
|
||||
export function checkAllServerDirectories(){
|
||||
environment.settings.servers.forEach(server => {
|
||||
createPathIfNotExists(environment.paths.servers + "/" + server.name)
|
||||
createPathIfNotExists(getServerDirectory(server))
|
||||
checkEulaFile(server)
|
||||
})
|
||||
}
|
||||
|
||||
environment.settings.servers.forEach(server => {
|
||||
const destinationPathJar = environment.paths.servers + "/" + server.name + "/server.jar"
|
||||
|
||||
export function checkEulaFile(server: MinecraftServer){
|
||||
const destinationPathEula = environment.paths.servers + "/" + server.name + "/eula.txt"
|
||||
try {
|
||||
fs.accessSync(destinationPathJar);
|
||||
console.log('Settings already exists!');
|
||||
} catch (error) {
|
||||
downloadFile(server.jar_url, destinationPathJar);
|
||||
}
|
||||
|
||||
try {
|
||||
fs.accessSync(destinationPathEula);
|
||||
console.log('eula exists');
|
||||
} catch (error) {
|
||||
console.log("setting eula to true")
|
||||
console.log(`Setting eula for ${server.name} to ${environment.settings.eula}`)
|
||||
fs.writeFileSync(destinationPathEula, 'eula=' + environment.settings.eula);
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function downloadFile(url: string, dest: string) {
|
||||
if(url == "")
|
||||
return;
|
||||
|
||||
|
||||
console.log(dest + ' doesnt exist, downloading now from ' + url);
|
||||
const file = fs.createWriteStream(dest);
|
||||
|
||||
https.get(url, (response) => {
|
||||
if (response.statusCode === 200) {
|
||||
response.pipe(file);
|
||||
} else {
|
||||
console.error(`Failed to download file. Status Code: ${response.statusCode}`);
|
||||
}
|
||||
|
||||
file.on('finish', () => {
|
||||
file.close();
|
||||
console.log('Download complete!');
|
||||
});
|
||||
}).on('error', (err) => {
|
||||
// Handle any errors during the download
|
||||
console.error('Error during download:', err.message);
|
||||
fs.unlink(dest, () => {});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue