Initial Ladill Hosting app with Gitea deploy pipeline.
Deploy Ladill Hosting / deploy (push) Failing after 17s
Deploy Ladill Hosting / deploy (push) Failing after 17s
Shared web hosting extracted from the platform monolith, with CI deploy to /var/www/ladill-hosting matching Bird/Domains/Email. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Hosting;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\HostingAccount;
|
||||
use App\Services\Hosting\BrowserTerminalSessionManager;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class HostingTerminalSessionController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private BrowserTerminalSessionManager $sessionManager,
|
||||
) {}
|
||||
|
||||
public function start(Request $request, HostingAccount $account): JsonResponse
|
||||
{
|
||||
$this->authorize('useTerminal', $account);
|
||||
$account->loadMissing('node');
|
||||
|
||||
$validated = $request->validate([
|
||||
'path' => 'nullable|string|max:255',
|
||||
'cols' => 'nullable|integer|min:40|max:240',
|
||||
'rows' => 'nullable|integer|min:10|max:80',
|
||||
]);
|
||||
|
||||
$session = $this->sessionManager->createSession(
|
||||
$account,
|
||||
(int) $request->user()->id,
|
||||
(string) ($validated['path'] ?? '/public_html'),
|
||||
(int) ($validated['cols'] ?? 120),
|
||||
(int) ($validated['rows'] ?? 30),
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'session_id' => $session['session_id'],
|
||||
'status' => $session['status'],
|
||||
]);
|
||||
}
|
||||
|
||||
public function read(Request $request, HostingAccount $account, string $session): JsonResponse
|
||||
{
|
||||
$this->authorize('useTerminal', $account);
|
||||
|
||||
try {
|
||||
$payload = $this->sessionManager->readOutput(
|
||||
$account,
|
||||
(int) $request->user()->id,
|
||||
$session,
|
||||
(int) $request->integer('offset', 0),
|
||||
);
|
||||
} catch (\RuntimeException $e) {
|
||||
return response()->json(['message' => $e->getMessage()], 404);
|
||||
}
|
||||
|
||||
return response()->json($payload);
|
||||
}
|
||||
|
||||
public function input(Request $request, HostingAccount $account, string $session): JsonResponse
|
||||
{
|
||||
$this->authorize('useTerminal', $account);
|
||||
|
||||
$input = $this->extractTerminalInput($request);
|
||||
|
||||
if ($input === null) {
|
||||
return response()->json(['message' => 'Invalid terminal input payload.'], 422);
|
||||
}
|
||||
|
||||
if (strlen($input) > 8192) {
|
||||
return response()->json(['message' => 'Terminal input payload is too large.'], 422);
|
||||
}
|
||||
|
||||
if ($input === '') {
|
||||
return response()->json(['ok' => true]);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->sessionManager->appendInput(
|
||||
$account,
|
||||
(int) $request->user()->id,
|
||||
$session,
|
||||
$input,
|
||||
);
|
||||
} catch (\RuntimeException $e) {
|
||||
return response()->json(['message' => $e->getMessage()], 404);
|
||||
}
|
||||
|
||||
return response()->json(['ok' => true]);
|
||||
}
|
||||
|
||||
public function resize(Request $request, HostingAccount $account, string $session): JsonResponse
|
||||
{
|
||||
$this->authorize('useTerminal', $account);
|
||||
|
||||
$validated = $request->validate([
|
||||
'cols' => 'required|integer|min:40|max:240',
|
||||
'rows' => 'required|integer|min:10|max:80',
|
||||
]);
|
||||
|
||||
try {
|
||||
$this->sessionManager->resizeSession(
|
||||
$account,
|
||||
(int) $request->user()->id,
|
||||
$session,
|
||||
(int) $validated['cols'],
|
||||
(int) $validated['rows'],
|
||||
);
|
||||
} catch (\RuntimeException $e) {
|
||||
return response()->json(['message' => $e->getMessage()], 404);
|
||||
}
|
||||
|
||||
return response()->json(['ok' => true]);
|
||||
}
|
||||
|
||||
public function close(Request $request, HostingAccount $account, string $session): JsonResponse
|
||||
{
|
||||
$this->authorize('useTerminal', $account);
|
||||
|
||||
try {
|
||||
$this->sessionManager->closeSession(
|
||||
$account,
|
||||
(int) $request->user()->id,
|
||||
$session,
|
||||
);
|
||||
} catch (\RuntimeException $e) {
|
||||
return response()->json(['message' => $e->getMessage()], 404);
|
||||
}
|
||||
|
||||
return response()->json(['ok' => true]);
|
||||
}
|
||||
|
||||
private function extractTerminalInput(Request $request): ?string
|
||||
{
|
||||
$input = $request->input('input');
|
||||
|
||||
if (is_string($input)) {
|
||||
return $input;
|
||||
}
|
||||
|
||||
$raw = $request->getContent();
|
||||
|
||||
if (! is_string($raw)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($raw === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
$decoded = json_decode($raw, true);
|
||||
|
||||
if (is_array($decoded) && array_key_exists('input', $decoded) && is_string($decoded['input'])) {
|
||||
return $decoded['input'];
|
||||
}
|
||||
|
||||
return $raw;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user