Fix server management issues and improve overall stability
Major server management fixes: - Replace Flatpak-specific pkill with universal process tree termination using pstree + process.kill() - Fix signal format errors (SIGTERM/SIGKILL instead of TERM/KILL strings) - Add 5-second cooldown after server stop to prevent race conditions with external detection - Enable Stop Server button for external servers in UI - Implement proper timeout handling with process tree killing ContentDB improvements: - Fix download retry logic and "closed" error by preventing concurrent zip extraction - Implement smart root directory detection and stripping during package extraction - Add game-specific timeout handling (8s for VoxeLibre vs 3s for simple games) World creation fixes: - Make world creation asynchronous to prevent browser hangs - Add WebSocket notifications for world creation completion status Other improvements: - Remove excessive debug logging - Improve error handling and user feedback throughout the application - Clean up temporary files and unnecessary logging 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,8 @@ const express = require('express');
|
||||
const AuthManager = require('../utils/auth');
|
||||
const { redirectIfAuthenticated } = require('../middleware/auth');
|
||||
const securityLogger = require('../utils/security-logger');
|
||||
const paths = require('../utils/paths');
|
||||
const appConfig = require('../utils/app-config');
|
||||
|
||||
const router = express.Router();
|
||||
const authManager = new AuthManager();
|
||||
@@ -50,10 +52,15 @@ router.get('/register', redirectIfAuthenticated, async (req, res) => {
|
||||
});
|
||||
}
|
||||
|
||||
// Detect available Luanti data directories
|
||||
const detectedDirectories = paths.detectLuantiDataDirectories();
|
||||
|
||||
res.render('auth/register', {
|
||||
title: 'Setup Administrator Account',
|
||||
isFirstUser: isFirstUser,
|
||||
currentPage: 'register'
|
||||
currentPage: 'register',
|
||||
detectedDirectories: detectedDirectories,
|
||||
defaultDataDir: paths.getDefaultDataDirectory()
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error checking first user:', error);
|
||||
@@ -119,29 +126,74 @@ router.post('/register', redirectIfAuthenticated, async (req, res) => {
|
||||
});
|
||||
}
|
||||
|
||||
const { username, password, confirmPassword } = req.body;
|
||||
const { username, password, confirmPassword, dataDirectory, customDataDirectory } = req.body;
|
||||
|
||||
// Validate inputs
|
||||
if (!username || !password || !confirmPassword) {
|
||||
const detectedDirectories = paths.detectLuantiDataDirectories();
|
||||
return res.render('auth/register', {
|
||||
title: 'Setup Administrator Account',
|
||||
error: 'All fields are required',
|
||||
isFirstUser: true,
|
||||
currentPage: 'register',
|
||||
formData: { username }
|
||||
formData: { username },
|
||||
detectedDirectories: detectedDirectories,
|
||||
defaultDataDir: paths.getDefaultDataDirectory()
|
||||
});
|
||||
}
|
||||
|
||||
if (password !== confirmPassword) {
|
||||
const detectedDirectories = paths.detectLuantiDataDirectories();
|
||||
return res.render('auth/register', {
|
||||
title: 'Setup Administrator Account',
|
||||
error: 'Passwords do not match',
|
||||
isFirstUser: true,
|
||||
currentPage: 'register',
|
||||
formData: { username }
|
||||
formData: { username },
|
||||
detectedDirectories: detectedDirectories,
|
||||
defaultDataDir: paths.getDefaultDataDirectory()
|
||||
});
|
||||
}
|
||||
|
||||
// Handle data directory selection
|
||||
let selectedDataDir = dataDirectory;
|
||||
if (dataDirectory === 'custom' && customDataDirectory) {
|
||||
selectedDataDir = customDataDirectory;
|
||||
}
|
||||
|
||||
// Validate the selected data directory
|
||||
if (selectedDataDir && selectedDataDir !== 'custom') {
|
||||
try {
|
||||
// Ensure the directory exists or can be created
|
||||
const fs = require('fs');
|
||||
if (!fs.existsSync(selectedDataDir)) {
|
||||
await fs.promises.mkdir(selectedDataDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Save the data directory to app config
|
||||
await appConfig.load();
|
||||
appConfig.setDataDirectory(selectedDataDir);
|
||||
await appConfig.save();
|
||||
|
||||
// Update paths to use the new directory
|
||||
paths.setDataDirectory(selectedDataDir);
|
||||
|
||||
console.log('Data directory set to:', selectedDataDir);
|
||||
} catch (error) {
|
||||
console.error('Error setting data directory:', error);
|
||||
const detectedDirectories = paths.detectLuantiDataDirectories();
|
||||
return res.render('auth/register', {
|
||||
title: 'Setup Administrator Account',
|
||||
error: `Invalid data directory: ${error.message}`,
|
||||
isFirstUser: true,
|
||||
currentPage: 'register',
|
||||
formData: { username },
|
||||
detectedDirectories: detectedDirectories,
|
||||
defaultDataDir: paths.getDefaultDataDirectory()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const user = await authManager.createUser(username, password);
|
||||
|
||||
// Create session for new user
|
||||
@@ -157,6 +209,7 @@ router.post('/register', redirectIfAuthenticated, async (req, res) => {
|
||||
} catch (error) {
|
||||
console.error('Registration error:', error);
|
||||
|
||||
const detectedDirectories = paths.detectLuantiDataDirectories();
|
||||
res.render('auth/register', {
|
||||
title: 'Register',
|
||||
error: error.message,
|
||||
@@ -164,7 +217,9 @@ router.post('/register', redirectIfAuthenticated, async (req, res) => {
|
||||
currentPage: 'register',
|
||||
formData: {
|
||||
username: req.body.username
|
||||
}
|
||||
},
|
||||
detectedDirectories: detectedDirectories,
|
||||
defaultDataDir: paths.getDefaultDataDirectory()
|
||||
});
|
||||
}
|
||||
});
|
||||
|
Reference in New Issue
Block a user