diff --git a/.eslintrc.yml b/.eslintrc.yml
index aee50cc9..ae8facba 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -29,5 +29,10 @@ rules: {
'camelcase': 'off',
'class-methods-use-this': 'off',
'prefer-destructuring': 'off',
+ 'vuejs-accessibility/click-events-have-key-events': 'off',
+ 'vuejs-accessibility/form-control-has-label': 'off',
+ 'vuejs-accessibility/label-has-for': 'off',
+ 'vuejs-accessibility/no-autofocus': 'off',
+ 'vuejs-accessibility/alt-text': 'off',
'semi': ['error', 'never']
}
diff --git a/.gitignore b/.gitignore
index f86db243..e75b0b1a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
/public/storage
/public/modpacks
/public/modpacks-data
+/public/launcher
/public/js
/public/css
/public/mix-manifest.json
diff --git a/README.md b/README.md
index 4c32767e..ed320917 100644
--- a/README.md
+++ b/README.md
@@ -52,6 +52,13 @@ foo@bar:~/MultigamingPanel$ npm run prod && php artisan migrate
###### Step 6 Configure your webserver to point to the public/ sub-directory
+###### Step 6 Open the required ports
+```console
+foo@bar:~/MultigamingPanel$ ufw allow 443
+foo@bar:~/MultigamingPanel$ ufw allow 6001
+foo@bar:~/MultigamingPanel$ ufw allow 6660
+```
+
## Emodyz Sponsors
You can sponsor us through various means.
diff --git a/app/Http/Controllers/ModPackController.php b/app/Http/Controllers/ModPackController.php
index 2c98390b..89c9dc49 100644
--- a/app/Http/Controllers/ModPackController.php
+++ b/app/Http/Controllers/ModPackController.php
@@ -125,7 +125,7 @@ public function edit(Request $request, Modpack $modpack): Response|ModPackResour
->get()
->map(fn(Server $server) => $server->only(['id', 'name', 'logo_url', 'game']));
- $modpack->servers;
+ $modpack->load('servers');
return inertia('ModPacks/Edit', compact('servers', 'modpack'));
}
@@ -209,6 +209,11 @@ public function cancelUpdate(Modpack $modpack): Response
}
$modpack->batch->cancel();
+
+ $modpack->update([
+ 'job_batch_id' => null,
+ ]);
+
return response()->noContent();
}
}
diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php
index 2c0dd562..14bb2dc8 100644
--- a/app/Http/Controllers/SettingsController.php
+++ b/app/Http/Controllers/SettingsController.php
@@ -4,7 +4,10 @@
use App\Actions\Emodyz\Settings\EditSettings;
use App\Http\Requests\Settings\EditVoiceSettingsRequest;
+use App\Services\Bridge\BridgeClientService;
use App\Settings\VoiceSettings;
+use Exception;
+use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Response;
@@ -17,18 +20,32 @@ public function __construct()
$this->middleware('can:settings-edit')->only(['edit']);
$this->middleware('can:settings-edit_voice')->only(['updateVoice']);
+
+ $this->middleware('can:settings-cp_update_check')->only(['checkForCpUpdate']);
+
+ $this->middleware('can:settings-cp_upgrade')->only(['checkForCpUpdate']);
}
/**
* Display a listing of the resource.
- *
- * @param VoiceSettings $voiceSettings
- * @return \Illuminate\Http\Response|Response|ResponseFactory
+ * @param VoiceSettings $voiceSettings
+ * @return Response|ResponseFactory
*/
public function edit(VoiceSettings $voiceSettings)
{
+ $version = 'unknown';
+ try {
+ $bridgeClient = new BridgeClientService();
+
+ $version = $bridgeClient->getControlPanelVersion();
+ } catch (Exception $e) {
+ flash('BRIDGE ERROR', $e->getMessage(), 'error');
+ }
+
+
return inertia('Settings/Edit', [
- 'voiceSettings' => $voiceSettings->toArray()
+ 'currentVersion' => $version,
+ 'voiceSettings' => $voiceSettings->toArray()
]);
}
@@ -39,12 +56,59 @@ public function edit(VoiceSettings $voiceSettings)
* @param EditSettings $editor
* @return RedirectResponse
*/
- public function updateVoice(EditVoiceSettingsRequest $request, EditSettings $editor): RedirectResponse
- {
+ public function updateVoice(EditVoiceSettingsRequest $request, EditSettings $editor): RedirectResponse
+ {
$editor->editVoiceSettings($request->all());
flash('Voice Settings', "Your voice settings has been successfully saved.")->success();
return redirect()->back();
- }
+ }
+
+ /**
+ * Check for control panel updates
+ *
+ * @return JsonResponse
+ */
+ public function checkForCpUpdate(): JsonResponse
+ {
+ $target = 'none';
+ try {
+ $bridgeClient = new BridgeClientService();
+
+ $target = $bridgeClient->checkForControlPanelUpdate();
+ } catch (Exception $e) {
+ flash('BRIDGE ERROR', $e->getMessage(), 'error');
+ }
+
+ if ($target !== 'none') {
+ flash('A new version of the Control Panel is available.', $target, 'info');
+ }
+
+ return response()->json([
+ 'target' => $target
+ ]);
+ }
+
+ /**
+ * Initiates the upgrade process for the control panel by calling the cli using the gRpc Bridge
+ *
+ * @return JsonResponse
+ */
+ public function upgradeCp(): JsonResponse
+ {
+ try {
+ $bridgeClient = new BridgeClientService();
+
+ $bridgeClient->upgradeControlPanel();
+ } catch (Exception $e) {
+ flash('BRIDGE ERROR', $e->getMessage(), 'error');
+ }
+
+ flash('Control Panel update started.', 'the application will be offline for a few minutes ', 'warning');
+
+ return response()->json([
+ 'upgrade' => 'started'
+ ]);
+ }
}
diff --git a/app/Jobs/ProcessModPackFile.php b/app/Jobs/ProcessModPackFile.php
index 6411e94d..3e1a8b33 100644
--- a/app/Jobs/ProcessModPackFile.php
+++ b/app/Jobs/ProcessModPackFile.php
@@ -4,6 +4,7 @@
use App\Events\ModPack\ModPackProcessProgress;
use App\Models\Modpack;
+use App\Services\Modpacks\ModpackUpdaterService;
use Illuminate\Bus\Batchable;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
@@ -27,8 +28,8 @@ class ProcessModPackFile implements ShouldQueue
/**
* Create a new job instance.
*
- * @param Modpack $modpack
- * @param string $filePath
+ * @param Modpack $modpack
+ * @param string $filePath
*/
public function __construct(Modpack $modpack, string $filePath)
{
@@ -36,6 +37,7 @@ public function __construct(Modpack $modpack, string $filePath)
$this->filePath = $filePath;
}
+
/**
* Execute the job.
*
@@ -44,10 +46,13 @@ public function __construct(Modpack $modpack, string $filePath)
*/
public function handle()
{
- if ($this->batch()->cancelled()) {
+ if ($this->batch()->cancelled() || $this->batch()->hasFailures()) {
+ info('Batch canceled or has failures, file skipped '. $this->filePath);
return;
}
+ info('Processing file '. $this->filePath);
+
$disk = $this->modpack->disk;
$filePath = Storage::disk($disk)->path($this->filePath);
@@ -55,25 +60,21 @@ public function handle()
$fileUrl = Storage::disk($disk)->url($this->filePath);
$fileHash = hash_file('sha256', $filePath);
$fileName = basename($filePath);
- $filePath = (string)Str::of($this->filePath)->replaceFirst(
+ $filePath = (string) Str::of($this->filePath)->replaceFirst(
$this->modpack->path,
$this->modpack->name
);
- $filePathPrevented = Str::of($filePath)
- ->replace('.', '-');
- $this->modpack->forceFill([
- "manifest_info->size" => $this->modpack->manifest_info['size'] + $fileSize,
- "manifest_info->files" => $this->modpack->manifest_info['files'] + 1,
- "manifest->{$filePathPrevented}" => [
- 'url' => $fileUrl,
- 'size' => $fileSize,
- 'name' => $fileName,
- 'path' => $filePath,
- 'sha256' => $fileHash
- ]
- ])->saveOrFail();
+ ModpackUpdaterService::fileProcessed(
+ modPack: $this->modpack,
+ fileName: $fileName,
+ fileSize: $fileSize,
+ fileUrl: $fileUrl,
+ filePath: $filePath,
+ fileHash: $fileHash
+ );
ModPackProcessProgress::broadcast($this->modpack, $this->batch()->progress());
}
}
+
diff --git a/app/Listeners/Modpack/StartModPackUpdate.php b/app/Listeners/Modpack/StartModPackUpdate.php
index 6a8c057e..f96035d9 100644
--- a/app/Listeners/Modpack/StartModPackUpdate.php
+++ b/app/Listeners/Modpack/StartModPackUpdate.php
@@ -8,10 +8,13 @@
use App\Events\ModPack\ModPackProcessStarted;
use App\Events\ModPack\ModPackUpdateRequested;
use App\Jobs\ProcessModPackFile;
+use App\Services\Modpacks\ModpackUpdaterService;
+use Exception;
use Illuminate\Bus\Batch;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Bus;
+use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Throwable;
@@ -29,9 +32,6 @@ class StartModPackUpdate implements ShouldQueue
public function handle(ModPackUpdateRequested $event)
{
$modpack = $event->modPack;
- $savedManifest = $modpack->manifest;
- $savedManifestInfo = $modpack->manifest_info;
- $modpack->cleanManifest();
$files = collect(Storage::disk($modpack->disk)->files($modpack->path, true));
if ($files->isEmpty()) {
@@ -39,27 +39,33 @@ public function handle(ModPackUpdateRequested $event)
return true;
}
+ ModpackUpdaterService::flush($modpack);
+
$jobs = $files->map(fn($file) => new ProcessModPackFile($modpack, $file));
$batch = Bus::batch($jobs->toArray())
- ->then(function (Batch $batch) use ($modpack, $savedManifest, $savedManifestInfo) {
+ ->then(function (Batch $batch) use ($modpack) {
if ($batch->canceled()) {
+ ModPackProcessCanceled::broadcast($modpack);
+ return;
+ }
+
+ [$manifest, $manifestInfo] = ModpackUpdaterService::getUpdate($modpack);
+
+ if (!empty($manifest) && !empty($manifestInfo)) {
$modpack->update([
- 'manifest' => $savedManifest,
- 'manifest_info' => $savedManifestInfo
+ 'manifest' => collect($manifest)->map(fn ($value) => json_decode($value)),
+ 'manifest_info' => $manifestInfo,
+ 'manifest_last_update' => now()->toDateTimeString()
]);
- ModPackProcessCanceled::broadcast($modpack);
+ ModPackProcessDone::broadcast($modpack);
+ Log::info('Job done');
return;
}
- $modpack->update([
- 'manifest_last_update' => now()->toDateTimeString()
- ]);
- ModPackProcessDone::broadcast($modpack);
- })->catch(function () use ($modpack, $savedManifest, $savedManifestInfo) {
- $modpack->update([
- 'manifest' => $savedManifest,
- 'manifest_info' => $savedManifestInfo
- ]);
+
+ throw new Exception('Job not finalized correctly...');
+ })->catch(function () use ($modpack) {
ModPackProcessFailed::broadcast($modpack);
+ Log::alert('Job failed');
})->finally(function () use ($modpack) {
$modpack->update([
'job_batch_id' => null,
diff --git a/app/Models/Modpack.php b/app/Models/Modpack.php
index 407a7d83..ab7409fb 100644
--- a/app/Models/Modpack.php
+++ b/app/Models/Modpack.php
@@ -89,18 +89,4 @@ public function getBatchAttribute(): ?Batch
}
return Bus::findBatch($this->job_batch_id);
}
-
- /**
- * void
- */
- public function cleanManifest()
- {
- $this->update([
- 'manifest' => [],
- 'manifest_info' => [
- "size" => 0,
- "files" => 0
- ]
- ]);
- }
}
diff --git a/app/Services/Bridge/BridgeClientService.php b/app/Services/Bridge/BridgeClientService.php
new file mode 100644
index 00000000..90ab4120
--- /dev/null
+++ b/app/Services/Bridge/BridgeClientService.php
@@ -0,0 +1,78 @@
+client = new BridgeClient('host.docker.internal:6660', [
+ 'credentials' => \Grpc\ChannelCredentials::createSsl(
+ Storage::disk('bridge')->get('ca.pem'),
+ Storage::disk('bridge')->get('cert.key'),
+ Storage::disk('bridge')->get('cert.crt')
+ ),
+ ]);
+ }
+
+ /**
+ * @throws Exception
+ * @return string
+ */
+ public function getControlPanelVersion(): string {
+ $request = new EmptyMessage();
+ list($response, $status) = $this->client->getCpVersion($request)->wait();
+ if ($status->code !== \Grpc\STATUS_OK) {
+ throw new Exception('Error while retrieving current version: ' . $status->code . ", " . $status->details . PHP_EOL);
+ }
+ return $response->getVersion();
+ }
+
+ /**
+ * @throws Exception
+ * @return string
+ */
+ public function checkForControlPanelUpdate(): string {
+ $request = new EmptyMessage();
+ list($response, $status) = $this->client->CheckForCpUpdate($request)->wait();
+ if ($status->code !== \Grpc\STATUS_OK) {
+ throw new Exception('Error while checking for Control Panel updates: ' . $status->code . ", " . $status->details . PHP_EOL);
+ }
+ return $response->getTarget();
+ }
+
+ /**
+ * @throws Exception
+ * @return void
+ */
+ public function upgradeControlPanel(): void {
+ $request = new UpgradeCpRequest();
+
+ $target = $this->checkForControlPanelUpdate();
+ if ($target === 'none') {
+ throw new Exception('Error while initiating Control Panel upgrade: No valid upgrade target found');
+ }
+
+ $request->setVersion($target);
+ list($response, $status) = $this->client->UpgradeCp($request)->wait();
+ if ($status->code !== \Grpc\STATUS_OK) {
+ throw new Exception('Error while initiating Control Panel upgrade: ' . $status->code . ", " . $status->details . PHP_EOL);
+ }
+ }
+}
diff --git a/app/Services/Modpacks/ModpackUpdaterService.php b/app/Services/Modpacks/ModpackUpdaterService.php
new file mode 100644
index 00000000..a73bd3d3
--- /dev/null
+++ b/app/Services/Modpacks/ModpackUpdaterService.php
@@ -0,0 +1,63 @@
+id";
+ }
+
+ private static function getManifestInfoKey(Modpack $modpack): string
+ {
+ return "modPack:manifestInfoUpdate:$modpack->id";
+ }
+
+
+ static public function flush(Modpack $modpack): void
+ {
+ Redis::del(self::getManifestKey($modpack));
+ Redis::del(self::getManifestInfoKey($modpack));
+ }
+
+ static public function getUpdate(Modpack $modpack): array
+ {
+ return [
+ Redis::hGetAll(self::getManifestKey($modpack)),
+ Redis::hGetAll(self::getManifestInfoKey($modpack)),
+ ];
+ }
+
+ public static function fileProcessed(
+ Modpack $modPack,
+ string $fileName,
+ int $fileSize,
+ string $fileUrl,
+ string $filePath,
+ string $fileHash,
+ )
+ {
+ $manifestKey = self::getManifestKey($modPack);
+ $manifestInfoKey = self::getManifestInfoKey($modPack);
+
+ $safeFilePath = Str::of($filePath)
+ ->replace('.', '-');
+
+
+ Redis::hIncrBy($manifestInfoKey, 'size', $fileSize);
+ Redis::hIncrBy($manifestInfoKey, 'files', 1);
+
+ Redis::hSet($manifestKey, $safeFilePath, json_encode([
+ 'url' => $fileUrl,
+ 'size' => $fileSize,
+ 'name' => $fileName,
+ 'path' => $filePath,
+ 'sha256' => $fileHash
+ ]));
+ }
+}
diff --git a/bridge/Bridge/BridgeClient.php b/bridge/Bridge/BridgeClient.php
index 1470a611..a4a3b024 100644
--- a/bridge/Bridge/BridgeClient.php
+++ b/bridge/Bridge/BridgeClient.php
@@ -32,4 +32,47 @@ public function SayHello(\Bridge\HelloRequest $argument,
$metadata, $options);
}
+ /**
+ * Get the current version of the control panel
+ * @param \Bridge\EmptyMessage $argument input argument
+ * @param array $metadata metadata
+ * @param array $options call options
+ * @return \Grpc\UnaryCall
+ */
+ public function GetCpVersion(\Bridge\EmptyMessage $argument,
+ $metadata = [], $options = []) {
+ return $this->_simpleRequest('/bridge.Bridge/GetCpVersion',
+ $argument,
+ ['\Bridge\GetCpVersionReply', 'decode'],
+ $metadata, $options);
+ }
+
+ /**
+ * @param \Bridge\EmptyMessage $argument input argument
+ * @param array $metadata metadata
+ * @param array $options call options
+ * @return \Grpc\UnaryCall
+ */
+ public function CheckForCpUpdate(\Bridge\EmptyMessage $argument,
+ $metadata = [], $options = []) {
+ return $this->_simpleRequest('/bridge.Bridge/CheckForCpUpdate',
+ $argument,
+ ['\Bridge\CheckForCpUpdateReply', 'decode'],
+ $metadata, $options);
+ }
+
+ /**
+ * @param \Bridge\UpgradeCpRequest $argument input argument
+ * @param array $metadata metadata
+ * @param array $options call options
+ * @return \Grpc\UnaryCall
+ */
+ public function UpgradeCp(\Bridge\UpgradeCpRequest $argument,
+ $metadata = [], $options = []) {
+ return $this->_simpleRequest('/bridge.Bridge/UpgradeCp',
+ $argument,
+ ['\Bridge\EmptyMessage', 'decode'],
+ $metadata, $options);
+ }
+
}
diff --git a/bridge/Bridge/BridgeStub.php b/bridge/Bridge/BridgeStub.php
index 9021acb8..be35546e 100644
--- a/bridge/Bridge/BridgeStub.php
+++ b/bridge/Bridge/BridgeStub.php
@@ -23,6 +23,49 @@ public function SayHello(
return null;
}
+ /**
+ * Get the current version of the control panel
+ * @param \Bridge\EmptyMessage $request client request
+ * @param \Grpc\ServerContext $context server request context
+ * @return \Bridge\GetCpVersionReply for response data, null if if error occured
+ * initial metadata (if any) and status (if not ok) should be set to $context
+ */
+ public function GetCpVersion(
+ \Bridge\EmptyMessage $request,
+ \Grpc\ServerContext $context
+ ): ?\Bridge\GetCpVersionReply {
+ $context->setStatus(\Grpc\Status::unimplemented());
+ return null;
+ }
+
+ /**
+ * @param \Bridge\EmptyMessage $request client request
+ * @param \Grpc\ServerContext $context server request context
+ * @return \Bridge\CheckForCpUpdateReply for response data, null if if error occured
+ * initial metadata (if any) and status (if not ok) should be set to $context
+ */
+ public function CheckForCpUpdate(
+ \Bridge\EmptyMessage $request,
+ \Grpc\ServerContext $context
+ ): ?\Bridge\CheckForCpUpdateReply {
+ $context->setStatus(\Grpc\Status::unimplemented());
+ return null;
+ }
+
+ /**
+ * @param \Bridge\UpgradeCpRequest $request client request
+ * @param \Grpc\ServerContext $context server request context
+ * @return \Bridge\EmptyMessage for response data, null if if error occured
+ * initial metadata (if any) and status (if not ok) should be set to $context
+ */
+ public function UpgradeCp(
+ \Bridge\UpgradeCpRequest $request,
+ \Grpc\ServerContext $context
+ ): ?\Bridge\EmptyMessage {
+ $context->setStatus(\Grpc\Status::unimplemented());
+ return null;
+ }
+
/**
* Get the method descriptors of the service for server registration
*
@@ -37,6 +80,24 @@ public final function getMethodDescriptors(): array
'\Bridge\HelloRequest',
\Grpc\MethodDescriptor::UNARY_CALL
),
+ '/bridge.Bridge/GetCpVersion' => new \Grpc\MethodDescriptor(
+ $this,
+ 'GetCpVersion',
+ '\Bridge\EmptyMessage',
+ \Grpc\MethodDescriptor::UNARY_CALL
+ ),
+ '/bridge.Bridge/CheckForCpUpdate' => new \Grpc\MethodDescriptor(
+ $this,
+ 'CheckForCpUpdate',
+ '\Bridge\EmptyMessage',
+ \Grpc\MethodDescriptor::UNARY_CALL
+ ),
+ '/bridge.Bridge/UpgradeCp' => new \Grpc\MethodDescriptor(
+ $this,
+ 'UpgradeCp',
+ '\Bridge\UpgradeCpRequest',
+ \Grpc\MethodDescriptor::UNARY_CALL
+ ),
];
}
diff --git a/bridge/Bridge/CheckForCpUpdateReply.php b/bridge/Bridge/CheckForCpUpdateReply.php
new file mode 100644
index 00000000..62a8da38
--- /dev/null
+++ b/bridge/Bridge/CheckForCpUpdateReply.php
@@ -0,0 +1,58 @@
+bridge.CheckForCpUpdateReply
+ */
+class CheckForCpUpdateReply extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Generated from protobuf field string target = 1;
+ */
+ protected $target = '';
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $target
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Bridge::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Generated from protobuf field string target = 1;
+ * @return string
+ */
+ public function getTarget()
+ {
+ return $this->target;
+ }
+
+ /**
+ * Generated from protobuf field string target = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setTarget($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->target = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/bridge/Bridge/EmptyMessage.php b/bridge/Bridge/EmptyMessage.php
new file mode 100644
index 00000000..4e6836c9
--- /dev/null
+++ b/bridge/Bridge/EmptyMessage.php
@@ -0,0 +1,31 @@
+bridge.EmptyMessage
+ */
+class EmptyMessage extends \Google\Protobuf\Internal\Message
+{
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Bridge::initOnce();
+ parent::__construct($data);
+ }
+
+}
+
diff --git a/bridge/Bridge/GetCpVersionReply.php b/bridge/Bridge/GetCpVersionReply.php
new file mode 100644
index 00000000..8715fd69
--- /dev/null
+++ b/bridge/Bridge/GetCpVersionReply.php
@@ -0,0 +1,58 @@
+bridge.GetCpVersionReply
+ */
+class GetCpVersionReply extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Generated from protobuf field string version = 1;
+ */
+ protected $version = '';
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $version
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Bridge::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Generated from protobuf field string version = 1;
+ * @return string
+ */
+ public function getVersion()
+ {
+ return $this->version;
+ }
+
+ /**
+ * Generated from protobuf field string version = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setVersion($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->version = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/bridge/Bridge/UpgradeCpRequest.php b/bridge/Bridge/UpgradeCpRequest.php
new file mode 100644
index 00000000..3e7de7c4
--- /dev/null
+++ b/bridge/Bridge/UpgradeCpRequest.php
@@ -0,0 +1,58 @@
+bridge.UpgradeCpRequest
+ */
+class UpgradeCpRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Generated from protobuf field string version = 1;
+ */
+ protected $version = '';
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $version
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Bridge::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Generated from protobuf field string version = 1;
+ * @return string
+ */
+ public function getVersion()
+ {
+ return $this->version;
+ }
+
+ /**
+ * Generated from protobuf field string version = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setVersion($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->version = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/bridge/GPBMetadata/Bridge.php b/bridge/GPBMetadata/Bridge.php
index 3f1723b9..ac482aab 100644
Binary files a/bridge/GPBMetadata/Bridge.php and b/bridge/GPBMetadata/Bridge.php differ
diff --git a/composer.json b/composer.json
index 57d436d4..bb78a0a7 100644
--- a/composer.json
+++ b/composer.json
@@ -21,7 +21,7 @@
"fideloper/proxy": "^4.4",
"fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^7.0.1",
- "inertiajs/inertia-laravel": "^0.4.4",
+ "inertiajs/inertia-laravel": "^0.5.4",
"laravel/framework": "^8.48",
"laravel/jetstream": "^1.5",
"laravel/sail": "^1.4",
@@ -30,7 +30,7 @@
"laravel/tinker": "^2.5",
"mattiasgeniar/php-percentages": "^1.3",
"spatie/laravel-settings": "^1.0",
- "tightenco/ziggy": "^0.9.4",
+ "tightenco/ziggy": "^v1.4.6",
"ukfast/laravel-health-check": "^1.10"
},
"require-dev": {
diff --git a/composer.lock b/composer.lock
index 993b4f9d..4c85bf5a 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "a552e7dc82aa01c47bc023c80a146522",
+ "content-hash": "5c22502393a3a79b3233fda61ab8850e",
"packages": [
{
"name": "asm89/stack-cors",
@@ -2024,26 +2024,27 @@
},
{
"name": "inertiajs/inertia-laravel",
- "version": "v0.4.5",
+ "version": "v0.5.4",
"source": {
"type": "git",
"url": "https://github.com/inertiajs/inertia-laravel.git",
- "reference": "406b15af162e78be5c7793b25aadd5a183eea84b"
+ "reference": "6a050ce04a710ac4809161558ac09fe49f13075e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/406b15af162e78be5c7793b25aadd5a183eea84b",
- "reference": "406b15af162e78be5c7793b25aadd5a183eea84b",
+ "url": "https://api.github.com/repos/inertiajs/inertia-laravel/zipball/6a050ce04a710ac4809161558ac09fe49f13075e",
+ "reference": "6a050ce04a710ac4809161558ac09fe49f13075e",
"shasum": ""
},
"require": {
"ext-json": "*",
- "laravel/framework": "^5.4|^6.0|^7.0|^8.0",
- "php": "^7.2|^8.0"
+ "laravel/framework": "^6.0|^7.0|^8.74|^9.0",
+ "php": "^7.2|~8.0.0|~8.1.0"
},
"require-dev": {
- "orchestra/testbench": "^4.0|^5.0|^6.0",
- "phpunit/phpunit": "^8.0|^9.0",
+ "mockery/mockery": "^1.3.3",
+ "orchestra/testbench": "^4.0|^5.0|^6.4|^7.0",
+ "phpunit/phpunit": "^8.0|^9.5.8",
"roave/security-advisories": "dev-master"
},
"type": "library",
@@ -2080,7 +2081,7 @@
],
"support": {
"issues": "https://github.com/inertiajs/inertia-laravel/issues",
- "source": "https://github.com/inertiajs/inertia-laravel/tree/v0.4.5"
+ "source": "https://github.com/inertiajs/inertia-laravel/tree/v0.5.4"
},
"funding": [
{
@@ -2088,7 +2089,7 @@
"type": "github"
}
],
- "time": "2021-10-27T09:37:59+00:00"
+ "time": "2022-01-18T10:59:08+00:00"
},
{
"name": "jaybizzle/crawler-detect",
@@ -8381,23 +8382,25 @@
},
{
"name": "tightenco/ziggy",
- "version": "0.9.4",
+ "version": "v1.4.6",
"source": {
"type": "git",
"url": "https://github.com/tighten/ziggy.git",
- "reference": "82ea6ec6cb6ab3545b0245310b2a424316fe48d8"
+ "reference": "a9e0e078ae6f0768836bc640a80f4cf99fa3d08f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/tighten/ziggy/zipball/82ea6ec6cb6ab3545b0245310b2a424316fe48d8",
- "reference": "82ea6ec6cb6ab3545b0245310b2a424316fe48d8",
+ "url": "https://api.github.com/repos/tighten/ziggy/zipball/a9e0e078ae6f0768836bc640a80f4cf99fa3d08f",
+ "reference": "a9e0e078ae6f0768836bc640a80f4cf99fa3d08f",
"shasum": ""
},
"require": {
+ "ext-json": "*",
"laravel/framework": ">=5.4@dev"
},
"require-dev": {
- "orchestra/testbench": "^5.0"
+ "orchestra/testbench": "^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0",
+ "phpunit/phpunit": "^6.0 || ^7.0 || ^8.0 || ^9.0"
},
"type": "library",
"extra": {
@@ -8424,10 +8427,14 @@
{
"name": "Jake Bathman",
"email": "jake@tighten.co"
+ },
+ {
+ "name": "Jacob Baker-Kretzmar",
+ "email": "jacob@tighten.co"
}
],
"description": "Generates a Blade directive exporting all of your named Laravel routes. Also provides a nice route() helper function in JavaScript.",
- "homepage": "https://github.com/tightenco/ziggy",
+ "homepage": "https://github.com/tighten/ziggy",
"keywords": [
"Ziggy",
"javascript",
@@ -8436,9 +8443,9 @@
],
"support": {
"issues": "https://github.com/tighten/ziggy/issues",
- "source": "https://github.com/tighten/ziggy/tree/0.9.4"
+ "source": "https://github.com/tighten/ziggy/tree/v1.4.6"
},
- "time": "2020-06-05T14:42:41+00:00"
+ "time": "2022-04-08T15:12:23+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
diff --git a/config/cerberus.php b/config/cerberus.php
index b4649619..bdc31d4d 100644
--- a/config/cerberus.php
+++ b/config/cerberus.php
@@ -141,5 +141,13 @@
'slug' => 'settings-edit_voice',
'description' => 'a user can edit voice provider settings'
],
+ [
+ 'slug' => 'settings-cp_update_check',
+ 'description' => 'a user can check if an update of the control panel is available'
+ ],
+ [
+ 'slug' => 'settings-cp_upgrade',
+ 'description' => 'a user can initiate the upgrade process for the control panel.'
+ ],
]
];
diff --git a/config/filesystems.php b/config/filesystems.php
index 68a17b3b..a6637c5f 100644
--- a/config/filesystems.php
+++ b/config/filesystems.php
@@ -77,6 +77,13 @@
'root' => storage_path('bridge'),
'visibility' => 'private',
],
+
+ 'launcher' => [
+ 'driver' => 'local',
+ 'root' => storage_path('launcher'),
+ 'url' => env('APP_URL').'/launcher',
+ 'visibility' => 'public',
+ ],
],
/*
@@ -93,6 +100,7 @@
'links' => [
public_path('storage') => storage_path('app/public'),
public_path('modpacks-data') => storage_path('app/modpacks'),
+ public_path('launcher') => storage_path('launcher'),
],
];
diff --git a/database/seeders/ServerSeeder.php b/database/seeders/ServerSeeder.php
index 285a109f..70edc12f 100644
--- a/database/seeders/ServerSeeder.php
+++ b/database/seeders/ServerSeeder.php
@@ -22,8 +22,8 @@ public function run()
$minecraft = Game::whereIdentifier('minecraft')->first();
$server = Server::factory()->create([
- 'name' => 'GrandTheftArma',
- 'ip' => 's1.grandtheftarma.com',
+ 'name' => 'LIVEYOURLIFE - Altis',
+ 'ip' => 'altis.lyl.gg',
'port' => 2302,
'game_id' => $arma3->id
]);
diff --git a/package.json b/package.json
index bf996247..33cf4747 100644
--- a/package.json
+++ b/package.json
@@ -13,60 +13,67 @@
"⚠️ The project will not build unless you specifically set the version of postcss-loader to >= 4.1.0"
],
"devDependencies": {
- "@inertiajs/inertia": "^0.10.1",
- "@inertiajs/inertia-vue": "^0.7.2",
- "@inertiajs/progress": "^0.2.6",
- "@tailwindcss/aspect-ratio": "^0.2.0",
- "@tailwindcss/forms": "^0.2.1",
- "@tailwindcss/typography": "^0.3.1",
+ "@inertiajs/inertia": "^0.11.0",
+ "@inertiajs/inertia-vue": "^0.8.0",
+ "@inertiajs/progress": "^0.2.7",
+ "@tailwindcss/aspect-ratio": "^0.4.0",
+ "@tailwindcss/forms": "^0.5.2",
+ "@tailwindcss/typography": "^0.5.3",
"@types/chart.js": "^2.9.30",
"@types/lodash": "^4.14.165",
"@types/marked": "^1.2.1",
"@types/qs": "^6.9.5",
- "@types/ziggy-js": "^0.9.0",
- "@typescript-eslint/eslint-plugin": "^4.14.0",
- "@typescript-eslint/parser": "^4.14.2-alpha.1",
- "@vue/cli-service": "^4.5.10",
- "@vue/eslint-config-airbnb": "^5.3.0",
- "@vue/eslint-config-typescript": "^7.0.0",
- "autoprefixer": "^10.1.0",
+ "@types/ziggy-js": "^1.3.2",
+ "@typescript-eslint/eslint-plugin": "^5.30.5",
+ "@typescript-eslint/parser": "^5.30.5",
+ "@vue/cli-service": "^5.0.8",
+ "@vue/eslint-config-airbnb": "^6.0.0",
+ "@vue/eslint-config-typescript": "^9.1.0",
+ "autoprefixer": "^10.4.7",
"axios": "^0.21.1",
"chart.js": "2.9.3",
"collect.js": "^4.28.6",
"cross-env": "^7.0",
"css-loader": "^5.0.1",
"eslint": "^7.18.0",
- "eslint-plugin-import": "^2.18.2",
- "eslint-plugin-vue": "^7.0.0",
- "eslint-webpack-plugin": "^2.4.1",
- "fork-ts-checker-notifier-webpack-plugin": "^4.0.0",
- "fork-ts-checker-webpack-plugin": "^6.1.0",
+ "eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-vue": "^8.7.1",
+ "eslint-plugin-vuejs-accessibility": "^1.1.0",
+ "eslint-webpack-plugin": "^3.0.0",
+ "fork-ts-checker-notifier-webpack-plugin": "^6.0.0",
+ "fork-ts-checker-webpack-plugin": "^7.2.11",
"fuse.js": "^6.4.6",
"laravel-echo": "^1.9.0",
- "laravel-mix": "^6.0.0",
+ "laravel-mix": "^6.0.49",
"lodash": "^4.17.19",
"marked": "^1.2.7",
"moment": "^2.29.1",
"moment-timezone": "^0.5.32",
"portal-vue": "^2.1.7",
- "postcss": "^8.2.1",
+ "postcss": "^8.4.14",
"postcss-loader": "^4.1.0",
"pusher-js": "^7.0.1",
"qs": "^6.9.4",
"resolve-url-loader": "^3.1.2",
"sass": "^1.32.6",
"sass-loader": "^10.1.1",
- "tailwindcss": "^2.2.7",
+ "tailwindcss": "^3.1.5",
"ts-loader": "^8.0.12",
"typescript": "^4.1.3",
"v-click-outside": "^3.1.2",
- "vue": "^2.6.14",
+ "vue": "^2.7.4",
"vue-class-component": "^7.2.6",
- "vue-loader": "^15.9.6",
+ "vue-loader": "^15.10.0",
"vue-lodash": "^2.1.2",
- "vue-property-decorator": "^9.0.2",
- "vue-template-compiler": "^2.6.14",
+ "vue-property-decorator": "^9.1.2",
+ "vue-template-compiler": "^2.7.4",
"webpack": "^5.11.0",
- "ziggy-js": "^1.3.5"
+ "ziggy-js": "^1.4.6"
+ },
+ "resolutions": {
+ "vue-loader": "^15.10.0"
+ },
+ "dependencies": {
+ "retry-axios": "^3.0.0"
}
}
diff --git a/resources/css/app.css b/resources/css/app.css
index 09da47cf..03e3bb2b 100644
--- a/resources/css/app.css
+++ b/resources/css/app.css
@@ -3,54 +3,50 @@
@tailwind utilities;
@layer components {
- @variants dark {
- .form-input {
- @apply border border-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-400 focus:border-transparent
- dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700 dark:placeholder-gray-600;
- }
+ .form-input {
+ @apply border border-zinc-300 focus:outline-none focus:ring-2 focus:ring-indigo-400 focus:border-transparent
+ dark:bg-zinc-900 dark:text-zinc-100 dark:border-zinc-700 dark:placeholder-zinc-600;
+ }
- .form-checkbox {
- @apply rounded-md p-3 border border-gray-300 bg-gray-50 dark:bg-gray-900 dark:checked:bg-indigo-400 dark:border-gray-700 checked:border-transparent
- focus:outline-none focus:ring-indigo-300 focus:ring-offset-0 hover:cursor-pointer;
- }
+ .form-checkbox {
+ @apply rounded-md p-3 border border-zinc-300 bg-zinc-50 dark:bg-zinc-900 dark:checked:bg-indigo-400 dark:border-zinc-700 checked:border-transparent
+ focus:outline-none focus:ring-indigo-300 focus:ring-offset-0 hover:cursor-pointer;
+ }
- .link-brand {
- @apply text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 focus:outline-none;
- }
+ .link-brand {
+ @apply text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 focus:outline-none;
+ }
- .link-success {
- @apply text-emerald-600 hover:text-emerald-900 dark:text-emerald-500 dark:hover:text-emerald-400 focus:outline-none;
- }
+ .link-success {
+ @apply text-emerald-600 hover:text-emerald-900 dark:text-emerald-500 dark:hover:text-emerald-400 focus:outline-none;
+ }
- .link-danger {
- @apply text-red-600 hover:text-red-900 dark:text-red-500 dark:hover:text-red-400 focus:outline-none;
- }
+ .link-danger {
+ @apply text-red-600 hover:text-red-900 dark:text-red-500 dark:hover:text-red-400 focus:outline-none;
+ }
- .breadcrumb {
- @apply font-semibold text-xl text-gray-800 dark:text-gray-100 leading-tight;
- }
+ .breadcrumb {
+ @apply font-semibold text-xl text-zinc-800 dark:text-zinc-100 leading-tight;
+ }
- .breadcrumb-separator {
- @apply text-gray-400 dark:text-gray-500;
- }
+ .breadcrumb-separator {
+ @apply text-zinc-400 dark:text-zinc-500;
}
}
@layer utilities {
- @variants responsive {
- .h-page {
- height: calc(100vh - 14.6rem);
- max-height: 30rem;
- }
+ .h-page {
+ height: calc(100vh - 14.6rem);
+ max-height: 30rem;
+ }
- .w-page {
- width: 80rem;
- max-width: 80rem;
- }
+ .w-page {
+ width: 80rem;
+ max-width: 80rem;
+ }
- .w-prose {
- width: calc(65ch + 1.5rem)
- }
+ .w-prose {
+ width: calc(65ch + 1.5rem)
}
}
@@ -58,17 +54,17 @@
body {
--scrollbarBG: theme('colors.white');
- --thumbBG: theme('colors.gray.300');
- --thumbBG_Hover: theme('colors.gray.400');
- --scrollbarBG_Hover: theme('colors.gray.50');
+ --thumbBG: theme('colors.zinc.300');
+ --thumbBG_Hover: theme('colors.zinc.400');
+ --scrollbarBG_Hover: theme('colors.zinc.50');
--scrollbarBG_Shadow: none;
}
body.dark {
- --scrollbarBG: theme('colors.gray.800');
- --thumbBG: theme('colors.gray.700');
- --thumbBG_Hover: theme('colors.gray.600');
- --scrollbarBG_Hover: theme('colors.gray.600');
+ --scrollbarBG: theme('colors.zinc.800');
+ --thumbBG: theme('colors.zinc.700');
+ --thumbBG_Hover: theme('colors.zinc.600');
+ --scrollbarBG_Hover: theme('colors.zinc.600');
--scrollbarBG_Shadow: inset 0 0 6px rgba(0, 0, 0, 0.5);
}
diff --git a/resources/js/Jetstream/ActionMessage.vue b/resources/js/Jetstream/ActionMessage.vue
index aa399622..1d8810e1 100644
--- a/resources/js/Jetstream/ActionMessage.vue
+++ b/resources/js/Jetstream/ActionMessage.vue
@@ -7,7 +7,7 @@
>