@@ -10,6 +10,7 @@ use App\Models\StandaloneMongodb;
 | 
				
			|||||||
use App\Models\StandalonePostgresql;
 | 
					use App\Models\StandalonePostgresql;
 | 
				
			||||||
use App\Models\StandaloneRedis;
 | 
					use App\Models\StandaloneRedis;
 | 
				
			||||||
use Illuminate\Console\Command;
 | 
					use Illuminate\Console\Command;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Storage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Init extends Command
 | 
					class Init extends Command
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -21,8 +22,23 @@ class Init extends Command
 | 
				
			|||||||
        ray()->clearAll();
 | 
					        ray()->clearAll();
 | 
				
			||||||
        $this->cleanup_in_progress_application_deployments();
 | 
					        $this->cleanup_in_progress_application_deployments();
 | 
				
			||||||
        $this->cleanup_stucked_resources();
 | 
					        $this->cleanup_stucked_resources();
 | 
				
			||||||
 | 
					        $this->cleanup_ssh();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private function cleanup_ssh() {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $files = Storage::allFiles('ssh/keys');
 | 
				
			||||||
 | 
					            foreach ($files as $file) {
 | 
				
			||||||
 | 
					                Storage::delete($file);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $files = Storage::allFiles('ssh/mux');
 | 
				
			||||||
 | 
					            foreach ($files as $file) {
 | 
				
			||||||
 | 
					                Storage::delete($file);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
 | 
					            echo "Error: {$e->getMessage()}\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    private function cleanup_in_progress_application_deployments()
 | 
					    private function cleanup_in_progress_application_deployments()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Cleanup any failed deployments
 | 
					        // Cleanup any failed deployments
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace App\Http\Livewire\Project\Database;
 | 
					namespace App\Http\Livewire\Project\Database;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Storage;
 | 
				
			||||||
use Livewire\Component;
 | 
					use Livewire\Component;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BackupExecutions extends Component
 | 
					class BackupExecutions extends Component
 | 
				
			||||||
@@ -23,6 +24,29 @@ class BackupExecutions extends Component
 | 
				
			|||||||
        $this->emit('success', 'Backup deleted successfully.');
 | 
					        $this->emit('success', 'Backup deleted successfully.');
 | 
				
			||||||
        $this->emit('refreshBackupExecutions');
 | 
					        $this->emit('refreshBackupExecutions');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    public function download($exeuctionId)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            $execution = $this->backup->executions()->where('id', $exeuctionId)->first();
 | 
				
			||||||
 | 
					            if (is_null($execution)) {
 | 
				
			||||||
 | 
					                $this->emit('error', 'Backup execution not found.');
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $filename = data_get($execution, 'filename');
 | 
				
			||||||
 | 
					            $server = $execution->scheduledDatabaseBackup->database->destination->server;
 | 
				
			||||||
 | 
					            $privateKeyLocation = savePrivateKeyToFs($server);
 | 
				
			||||||
 | 
					            $disk = Storage::build([
 | 
				
			||||||
 | 
					                'driver' => 'sftp',
 | 
				
			||||||
 | 
					                'host' => $server->ip,
 | 
				
			||||||
 | 
					                'port' => $server->port,
 | 
				
			||||||
 | 
					                'username' => $server->user,
 | 
				
			||||||
 | 
					                'privateKey' => $privateKeyLocation,
 | 
				
			||||||
 | 
					            ]);
 | 
				
			||||||
 | 
					            return $disk->download($filename);
 | 
				
			||||||
 | 
					        } catch (\Throwable $e) {
 | 
				
			||||||
 | 
					            return handleError($e, $this);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    public function refreshBackupExecutions(): void
 | 
					    public function refreshBackupExecutions(): void
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->executions = $this->backup->executions;
 | 
					        $this->executions = $this->backup->executions;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								app/Http/Livewire/Project/Shared/Webhooks.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								app/Http/Livewire/Project/Shared/Webhooks.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Livewire\Project\Shared;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Livewire\Component;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Webhooks extends Component
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public $resource;
 | 
				
			||||||
 | 
					    public ?string $deploywebhook = null;
 | 
				
			||||||
 | 
					    public function mount()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->deploywebhook = generateDeployWebhook($this->resource);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public function render()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return view('livewire.project.shared.webhooks');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -48,7 +48,7 @@ class RouteServiceProvider extends ServiceProvider
 | 
				
			|||||||
            if ($request->path() === 'api/health') {
 | 
					            if ($request->path() === 'api/health') {
 | 
				
			||||||
                return Limit::perMinute(1000)->by($request->user()?->id ?: $request->ip());
 | 
					                return Limit::perMinute(1000)->by($request->user()?->id ?: $request->ip());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return Limit::perMinute(30)->by($request->user()?->id ?: $request->ip());
 | 
					            return Limit::perMinute(200)->by($request->user()?->id ?: $request->ip());
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        RateLimiter::for('5', function (Request $request) {
 | 
					        RateLimiter::for('5', function (Request $request) {
 | 
				
			||||||
            return Limit::perMinute(5)->by($request->user()?->id ?: $request->ip());
 | 
					            return Limit::perMinute(5)->by($request->user()?->id ?: $request->ip());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,9 @@ use App\Models\Application;
 | 
				
			|||||||
use App\Models\InstanceSettings;
 | 
					use App\Models\InstanceSettings;
 | 
				
			||||||
use App\Models\Server;
 | 
					use App\Models\Server;
 | 
				
			||||||
use App\Models\Service;
 | 
					use App\Models\Service;
 | 
				
			||||||
 | 
					use App\Models\StandaloneMariadb;
 | 
				
			||||||
use App\Models\StandaloneMongodb;
 | 
					use App\Models\StandaloneMongodb;
 | 
				
			||||||
 | 
					use App\Models\StandaloneMysql;
 | 
				
			||||||
use App\Models\StandalonePostgresql;
 | 
					use App\Models\StandalonePostgresql;
 | 
				
			||||||
use App\Models\StandaloneRedis;
 | 
					use App\Models\StandaloneRedis;
 | 
				
			||||||
use App\Models\Team;
 | 
					use App\Models\Team;
 | 
				
			||||||
@@ -484,5 +486,18 @@ function queryResourcesByUuid(string $uuid)
 | 
				
			|||||||
    if ($redis) return $redis;
 | 
					    if ($redis) return $redis;
 | 
				
			||||||
    $mongodb = StandaloneMongodb::whereUuid($uuid)->first();
 | 
					    $mongodb = StandaloneMongodb::whereUuid($uuid)->first();
 | 
				
			||||||
    if ($mongodb) return $mongodb;
 | 
					    if ($mongodb) return $mongodb;
 | 
				
			||||||
 | 
					    $mysql = StandaloneMysql::whereUuid($uuid)->first();
 | 
				
			||||||
 | 
					    if ($mysql) return $mysql;
 | 
				
			||||||
 | 
					    $mariadb = StandaloneMariadb::whereUuid($uuid)->first();
 | 
				
			||||||
 | 
					    if ($mariadb) return $mariadb;
 | 
				
			||||||
    return $resource;
 | 
					    return $resource;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function generateDeployWebhook($resource) {
 | 
				
			||||||
 | 
					    $baseUrl = base_url();
 | 
				
			||||||
 | 
					    $api = Url::fromString($baseUrl) . '/api/v1';
 | 
				
			||||||
 | 
					    $endpoint = '/deploy';
 | 
				
			||||||
 | 
					    $uuid = data_get($resource, 'uuid');
 | 
				
			||||||
 | 
					    $url = $api . $endpoint . "?uuid=$uuid&force=false";
 | 
				
			||||||
 | 
					    return $url;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,7 @@
 | 
				
			|||||||
        "laravel/ui": "^4.2",
 | 
					        "laravel/ui": "^4.2",
 | 
				
			||||||
        "lcobucci/jwt": "^5.0.0",
 | 
					        "lcobucci/jwt": "^5.0.0",
 | 
				
			||||||
        "league/flysystem-aws-s3-v3": "^3.0",
 | 
					        "league/flysystem-aws-s3-v3": "^3.0",
 | 
				
			||||||
 | 
					        "league/flysystem-sftp-v3": "^3.0",
 | 
				
			||||||
        "livewire/livewire": "^v2.12.3",
 | 
					        "livewire/livewire": "^v2.12.3",
 | 
				
			||||||
        "lorisleiva/laravel-actions": "^2.7",
 | 
					        "lorisleiva/laravel-actions": "^2.7",
 | 
				
			||||||
        "masmerise/livewire-toaster": "^1.2",
 | 
					        "masmerise/livewire-toaster": "^1.2",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										62
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										62
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
				
			|||||||
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
 | 
					        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
 | 
				
			||||||
        "This file is @generated automatically"
 | 
					        "This file is @generated automatically"
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "content-hash": "de2c45be3f03d43430549d963778dc4a",
 | 
					    "content-hash": "21ed976753483557403be75318585442",
 | 
				
			||||||
    "packages": [
 | 
					    "packages": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "aws/aws-crt-php",
 | 
					            "name": "aws/aws-crt-php",
 | 
				
			||||||
@@ -2938,6 +2938,66 @@
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "time": "2023-08-30T10:23:59+00:00"
 | 
					            "time": "2023-08-30T10:23:59+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "name": "league/flysystem-sftp-v3",
 | 
				
			||||||
 | 
					            "version": "3.16.0",
 | 
				
			||||||
 | 
					            "source": {
 | 
				
			||||||
 | 
					                "type": "git",
 | 
				
			||||||
 | 
					                "url": "https://github.com/thephpleague/flysystem-sftp-v3.git",
 | 
				
			||||||
 | 
					                "reference": "1ba682def8e87fd7fa00883629553c0200d2e974"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "dist": {
 | 
				
			||||||
 | 
					                "type": "zip",
 | 
				
			||||||
 | 
					                "url": "https://api.github.com/repos/thephpleague/flysystem-sftp-v3/zipball/1ba682def8e87fd7fa00883629553c0200d2e974",
 | 
				
			||||||
 | 
					                "reference": "1ba682def8e87fd7fa00883629553c0200d2e974",
 | 
				
			||||||
 | 
					                "shasum": ""
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "require": {
 | 
				
			||||||
 | 
					                "league/flysystem": "^3.0.14",
 | 
				
			||||||
 | 
					                "league/mime-type-detection": "^1.0.0",
 | 
				
			||||||
 | 
					                "php": "^8.0.2",
 | 
				
			||||||
 | 
					                "phpseclib/phpseclib": "^3.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "type": "library",
 | 
				
			||||||
 | 
					            "autoload": {
 | 
				
			||||||
 | 
					                "psr-4": {
 | 
				
			||||||
 | 
					                    "League\\Flysystem\\PhpseclibV3\\": ""
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "notification-url": "https://packagist.org/downloads/",
 | 
				
			||||||
 | 
					            "license": [
 | 
				
			||||||
 | 
					                "MIT"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "authors": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Frank de Jonge",
 | 
				
			||||||
 | 
					                    "email": "info@frankdejonge.nl"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "description": "SFTP filesystem adapter for Flysystem.",
 | 
				
			||||||
 | 
					            "keywords": [
 | 
				
			||||||
 | 
					                "Flysystem",
 | 
				
			||||||
 | 
					                "file",
 | 
				
			||||||
 | 
					                "files",
 | 
				
			||||||
 | 
					                "filesystem",
 | 
				
			||||||
 | 
					                "sftp"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "support": {
 | 
				
			||||||
 | 
					                "issues": "https://github.com/thephpleague/flysystem-sftp-v3/issues",
 | 
				
			||||||
 | 
					                "source": "https://github.com/thephpleague/flysystem-sftp-v3/tree/3.16.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "funding": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "url": "https://ecologi.com/frankdejonge",
 | 
				
			||||||
 | 
					                    "type": "custom"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "url": "https://github.com/frankdejonge",
 | 
				
			||||||
 | 
					                    "type": "github"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "time": "2023-08-30T10:25:05+00:00"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "league/mime-type-detection",
 | 
					            "name": "league/mime-type-detection",
 | 
				
			||||||
            "version": "1.13.0",
 | 
					            "version": "1.13.0",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@ return [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // The release version of your application
 | 
					    // The release version of your application
 | 
				
			||||||
    // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
 | 
					    // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
 | 
				
			||||||
    'release' => '4.0.0-beta.101',
 | 
					    'release' => '4.0.0-beta.102',
 | 
				
			||||||
    // When left empty or `null` the Laravel environment will be used
 | 
					    // When left empty or `null` the Laravel environment will be used
 | 
				
			||||||
    'environment' => config('app.env'),
 | 
					    'environment' => config('app.env'),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,3 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return '4.0.0-beta.101';
 | 
					return '4.0.0-beta.102';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,10 +17,10 @@
 | 
				
			|||||||
            <div>Location: {{ data_get($execution, 'filename', 'N/A') }}</div>
 | 
					            <div>Location: {{ data_get($execution, 'filename', 'N/A') }}</div>
 | 
				
			||||||
            <div class="flex gap-2">
 | 
					            <div class="flex gap-2">
 | 
				
			||||||
                <div class="flex-1"></div>
 | 
					                <div class="flex-1"></div>
 | 
				
			||||||
 | 
					                @if (data_get($execution, 'status') === 'success')
 | 
				
			||||||
                {{-- @if (data_get($execution, 'status') !== 'failed') --}}
 | 
					                    <x-forms.button class=" hover:bg-coolgray-400"
 | 
				
			||||||
                {{-- <x-forms.button class="bg-coollabs-100 hover:bg-coollabs" wire:click="download">Download</x-forms.button> --}}
 | 
					                        wire:click="download({{ data_get($execution, 'id') }})">Download</x-forms.button>
 | 
				
			||||||
                {{-- @endif --}}
 | 
					                @endif
 | 
				
			||||||
                <x-forms.button isError onclick="sure({{ data_get($execution, 'id') }})">Delete</x-forms.button>
 | 
					                <x-forms.button isError onclick="sure({{ data_get($execution, 'id') }})">Delete</x-forms.button>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </form>
 | 
					        </form>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,16 +4,25 @@
 | 
				
			|||||||
    <div class="flex h-full pt-6">
 | 
					    <div class="flex h-full pt-6">
 | 
				
			||||||
        <div class="flex flex-col items-start gap-4 min-w-fit">
 | 
					        <div class="flex flex-col items-start gap-4 min-w-fit">
 | 
				
			||||||
            <a target="_blank" href="{{ $service->documentation() }}">Documentation <x-external-link /></a>
 | 
					            <a target="_blank" href="{{ $service->documentation() }}">Documentation <x-external-link /></a>
 | 
				
			||||||
            <a :class="activeTab === 'service-stack' && 'text-white'" @click.prevent="activeTab = 'service-stack';
 | 
					            <a :class="activeTab === 'service-stack' && 'text-white'"
 | 
				
			||||||
                window.location.hash = 'service-stack'" href="#">Service Stack</a>
 | 
					                @click.prevent="activeTab = 'service-stack';
 | 
				
			||||||
            <a :class="activeTab === 'storages' && 'text-white'" @click.prevent="activeTab = 'storages';
 | 
					                window.location.hash = 'service-stack'"
 | 
				
			||||||
                window.location.hash = 'storages'" href="#">Storages</a>
 | 
					                href="#">Service Stack</a>
 | 
				
			||||||
 | 
					            <a :class="activeTab === 'storages' && 'text-white'"
 | 
				
			||||||
 | 
					                @click.prevent="activeTab = 'storages';
 | 
				
			||||||
 | 
					                window.location.hash = 'storages'"
 | 
				
			||||||
 | 
					                href="#">Storages</a>
 | 
				
			||||||
 | 
					            <a :class="activeTab === 'webhooks' && 'text-white'"
 | 
				
			||||||
 | 
					                @click.prevent="activeTab = 'webhooks'; window.location.hash = 'webhooks'" href="#">Webhooks
 | 
				
			||||||
 | 
					            </a>
 | 
				
			||||||
            <a :class="activeTab === 'environment-variables' && 'text-white'"
 | 
					            <a :class="activeTab === 'environment-variables' && 'text-white'"
 | 
				
			||||||
                @click.prevent="activeTab = 'environment-variables'; window.location.hash = 'environment-variables'"
 | 
					                @click.prevent="activeTab = 'environment-variables'; window.location.hash = 'environment-variables'"
 | 
				
			||||||
                href="#">Environment
 | 
					                href="#">Environment
 | 
				
			||||||
                Variables</a>
 | 
					                Variables</a>
 | 
				
			||||||
            <a :class="activeTab === 'danger' && 'text-white'" @click.prevent="activeTab = 'danger';
 | 
					            <a :class="activeTab === 'danger' && 'text-white'"
 | 
				
			||||||
                window.location.hash = 'danger'" href="#">Danger Zone
 | 
					                @click.prevent="activeTab = 'danger';
 | 
				
			||||||
 | 
					                window.location.hash = 'danger'"
 | 
				
			||||||
 | 
					                href="#">Danger Zone
 | 
				
			||||||
            </a>
 | 
					            </a>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="w-full pl-8">
 | 
					        <div class="w-full pl-8">
 | 
				
			||||||
@@ -100,7 +109,9 @@
 | 
				
			|||||||
                @foreach ($databases as $database)
 | 
					                @foreach ($databases as $database)
 | 
				
			||||||
                    <livewire:project.service.storage wire:key="database-{{ $database->id }}" :resource="$database" />
 | 
					                    <livewire:project.service.storage wire:key="database-{{ $database->id }}" :resource="$database" />
 | 
				
			||||||
                @endforeach
 | 
					                @endforeach
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div x-cloak x-show="activeTab === 'webhooks'">
 | 
				
			||||||
 | 
					                <livewire:project.shared.webhooks :resource="$service" />
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <div x-cloak x-show="activeTab === 'environment-variables'">
 | 
					            <div x-cloak x-show="activeTab === 'environment-variables'">
 | 
				
			||||||
                <div x-cloak x-show="activeTab === 'environment-variables'">
 | 
					                <div x-cloak x-show="activeTab === 'environment-variables'">
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								resources/views/livewire/project/shared/webhooks.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								resources/views/livewire/project/shared/webhooks.blade.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					<div>
 | 
				
			||||||
 | 
					    <div class="flex items-center gap-2">
 | 
				
			||||||
 | 
					        <h2>Webhooks</h2>
 | 
				
			||||||
 | 
					        <x-helper
 | 
				
			||||||
 | 
					            helper="For more details goto our <a class='text-white underline' href='https://coolify.io/docs/api-endpoints' target='_blank'>docs</a>." />
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					        <x-forms.input readonly label="Deploy Webhook (auth required)" id="deploywebhook"></x-forms.input>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
@@ -19,6 +19,9 @@
 | 
				
			|||||||
            <a :class="activeTab === 'storages' && 'text-white'"
 | 
					            <a :class="activeTab === 'storages' && 'text-white'"
 | 
				
			||||||
                @click.prevent="activeTab = 'storages'; window.location.hash = 'storages'" href="#">Storages
 | 
					                @click.prevent="activeTab = 'storages'; window.location.hash = 'storages'" href="#">Storages
 | 
				
			||||||
            </a>
 | 
					            </a>
 | 
				
			||||||
 | 
					            <a :class="activeTab === 'webhooks' && 'text-white'"
 | 
				
			||||||
 | 
					                @click.prevent="activeTab = 'webhooks'; window.location.hash = 'webhooks'" href="#">Webhooks
 | 
				
			||||||
 | 
					            </a>
 | 
				
			||||||
            @if ($application->git_based())
 | 
					            @if ($application->git_based())
 | 
				
			||||||
                <a :class="activeTab === 'previews' && 'text-white'"
 | 
					                <a :class="activeTab === 'previews' && 'text-white'"
 | 
				
			||||||
                    @click.prevent="activeTab = 'previews'; window.location.hash = 'previews'" href="#">Preview
 | 
					                    @click.prevent="activeTab = 'previews'; window.location.hash = 'previews'" href="#">Preview
 | 
				
			||||||
@@ -57,6 +60,9 @@
 | 
				
			|||||||
            <div x-cloak x-show="activeTab === 'storages'">
 | 
					            <div x-cloak x-show="activeTab === 'storages'">
 | 
				
			||||||
                <livewire:project.service.storage :resource="$application" />
 | 
					                <livewire:project.service.storage :resource="$application" />
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div x-cloak x-show="activeTab === 'webhooks'">
 | 
				
			||||||
 | 
					                <livewire:project.shared.webhooks :resource="$application" />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
            <div x-cloak x-show="activeTab === 'previews'">
 | 
					            <div x-cloak x-show="activeTab === 'previews'">
 | 
				
			||||||
                <livewire:project.application.previews :application="$application" />
 | 
					                <livewire:project.application.previews :application="$application" />
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,9 @@
 | 
				
			|||||||
                window.location.hash = 'storages'"
 | 
					                window.location.hash = 'storages'"
 | 
				
			||||||
                href="#">Storages
 | 
					                href="#">Storages
 | 
				
			||||||
            </a>
 | 
					            </a>
 | 
				
			||||||
 | 
					            <a :class="activeTab === 'webhooks' && 'text-white'"
 | 
				
			||||||
 | 
					                @click.prevent="activeTab = 'webhooks'; window.location.hash = 'webhooks'" href="#">Webhooks
 | 
				
			||||||
 | 
					            </a>
 | 
				
			||||||
            <a :class="activeTab === 'resource-limits' && 'text-white'"
 | 
					            <a :class="activeTab === 'resource-limits' && 'text-white'"
 | 
				
			||||||
                @click.prevent="activeTab = 'resource-limits';
 | 
					                @click.prevent="activeTab = 'resource-limits';
 | 
				
			||||||
                window.location.hash = 'resource-limits'"
 | 
					                window.location.hash = 'resource-limits'"
 | 
				
			||||||
@@ -65,6 +68,9 @@
 | 
				
			|||||||
            <div x-cloak x-show="activeTab === 'storages'">
 | 
					            <div x-cloak x-show="activeTab === 'storages'">
 | 
				
			||||||
                <livewire:project.service.storage :resource="$database" />
 | 
					                <livewire:project.service.storage :resource="$database" />
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div x-cloak x-show="activeTab === 'webhooks'">
 | 
				
			||||||
 | 
					                <livewire:project.shared.webhooks :resource="$database" />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
            <div x-cloak x-show="activeTab === 'resource-limits'">
 | 
					            <div x-cloak x-show="activeTab === 'resource-limits'">
 | 
				
			||||||
                <livewire:project.shared.resource-limits :resource="$database" />
 | 
					                <livewire:project.shared.resource-limits :resource="$database" />
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,8 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use App\Actions\Database\StartMariadb;
 | 
				
			||||||
use App\Actions\Database\StartMongodb;
 | 
					use App\Actions\Database\StartMongodb;
 | 
				
			||||||
 | 
					use App\Actions\Database\StartMysql;
 | 
				
			||||||
use App\Actions\Database\StartPostgresql;
 | 
					use App\Actions\Database\StartPostgresql;
 | 
				
			||||||
use App\Actions\Database\StartRedis;
 | 
					use App\Actions\Database\StartRedis;
 | 
				
			||||||
use App\Actions\Service\StartService;
 | 
					use App\Actions\Service\StartService;
 | 
				
			||||||
@@ -32,7 +34,6 @@ Route::group([
 | 
				
			|||||||
        $teamId = data_get($token, 'team_id');
 | 
					        $teamId = data_get($token, 'team_id');
 | 
				
			||||||
        $uuid = $request->query->get('uuid');
 | 
					        $uuid = $request->query->get('uuid');
 | 
				
			||||||
        $force = $request->query->get('force') ?? false;
 | 
					        $force = $request->query->get('force') ?? false;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (is_null($teamId)) {
 | 
					        if (is_null($teamId)) {
 | 
				
			||||||
            return response()->json(['error' => 'Invalid token.'], 400);
 | 
					            return response()->json(['error' => 'Invalid token.'], 400);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -50,29 +51,56 @@ Route::group([
 | 
				
			|||||||
                );
 | 
					                );
 | 
				
			||||||
                return response()->json(['message' => 'Deployment queued.'], 200);
 | 
					                return response()->json(['message' => 'Deployment queued.'], 200);
 | 
				
			||||||
            } else if ($type === 'App\Models\StandalonePostgresql') {
 | 
					            } else if ($type === 'App\Models\StandalonePostgresql') {
 | 
				
			||||||
 | 
					                if (str($resource->status)->startsWith('running')) {
 | 
				
			||||||
 | 
					                    return response()->json(['message' => 'Database already running.'], 200);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                StartPostgresql::run($resource);
 | 
					                StartPostgresql::run($resource);
 | 
				
			||||||
                $resource->update([
 | 
					                $resource->update([
 | 
				
			||||||
                    'started_at' => now(),
 | 
					                    'started_at' => now(),
 | 
				
			||||||
                ]);
 | 
					                ]);
 | 
				
			||||||
                return response()->json(['message' => 'Database started.'], 200);
 | 
					                return response()->json(['message' => 'Database started.'], 200);
 | 
				
			||||||
            } else if ($type === 'App\Models\StandaloneRedis') {
 | 
					            } else if ($type === 'App\Models\StandaloneRedis') {
 | 
				
			||||||
 | 
					                if (str($resource->status)->startsWith('running')) {
 | 
				
			||||||
 | 
					                    return response()->json(['message' => 'Database already running.'], 200);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                StartRedis::run($resource);
 | 
					                StartRedis::run($resource);
 | 
				
			||||||
                $resource->update([
 | 
					                $resource->update([
 | 
				
			||||||
                    'started_at' => now(),
 | 
					                    'started_at' => now(),
 | 
				
			||||||
                ]);
 | 
					                ]);
 | 
				
			||||||
                return response()->json(['message' => 'Database started.'], 200);
 | 
					                return response()->json(['message' => 'Database started.'], 200);
 | 
				
			||||||
            } else if ($type === 'App\Models\StandaloneMongodb') {
 | 
					            } else if ($type === 'App\Models\StandaloneMongodb') {
 | 
				
			||||||
 | 
					                if (str($resource->status)->startsWith('running')) {
 | 
				
			||||||
 | 
					                    return response()->json(['message' => 'Database already running.'], 200);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                StartMongodb::run($resource);
 | 
					                StartMongodb::run($resource);
 | 
				
			||||||
                $resource->update([
 | 
					                $resource->update([
 | 
				
			||||||
                    'started_at' => now(),
 | 
					                    'started_at' => now(),
 | 
				
			||||||
                ]);
 | 
					                ]);
 | 
				
			||||||
                return response()->json(['message' => 'Database started.'], 200);
 | 
					                return response()->json(['message' => 'Database started.'], 200);
 | 
				
			||||||
            }else if ($type === 'App\Models\Service') {
 | 
					            } else if ($type === 'App\Models\StandaloneMysql') {
 | 
				
			||||||
 | 
					                if (str($resource->status)->startsWith('running')) {
 | 
				
			||||||
 | 
					                    return response()->json(['message' => 'Database already running.'], 200);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                StartMysql::run($resource);
 | 
				
			||||||
 | 
					                $resource->update([
 | 
				
			||||||
 | 
					                    'started_at' => now(),
 | 
				
			||||||
 | 
					                ]);
 | 
				
			||||||
 | 
					                return response()->json(['message' => 'Database started.'], 200);
 | 
				
			||||||
 | 
					            } else if ($type === 'App\Models\StandaloneMariadb') {
 | 
				
			||||||
 | 
					                if (str($resource->status)->startsWith('running')) {
 | 
				
			||||||
 | 
					                    return response()->json(['message' => 'Database already running.'], 200);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                StartMariadb::run($resource);
 | 
				
			||||||
 | 
					                $resource->update([
 | 
				
			||||||
 | 
					                    'started_at' => now(),
 | 
				
			||||||
 | 
					                ]);
 | 
				
			||||||
 | 
					                return response()->json(['message' => 'Database started.'], 200);
 | 
				
			||||||
 | 
					            } else if ($type === 'App\Models\Service') {
 | 
				
			||||||
                StartService::run($resource);
 | 
					                StartService::run($resource);
 | 
				
			||||||
                return response()->json(['message' => 'Service started.'], 200);
 | 
					                return response()->json(['message' => 'Service started. It could take a while, be patient.'], 200);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return response()->json(['error' => 'No resource found.'], 404);
 | 
					        return response()->json(['error' => "No resource found with {$uuid}."], 404);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,3 +14,5 @@ services:
 | 
				
			|||||||
      - APPSMITH_SMART_LOOK_ID=
 | 
					      - APPSMITH_SMART_LOOK_ID=
 | 
				
			||||||
    volumes:
 | 
					    volumes:
 | 
				
			||||||
      - stacks-data:/appsmith-stacks
 | 
					      - stacks-data:/appsmith-stacks
 | 
				
			||||||
 | 
					    healthcheck:
 | 
				
			||||||
 | 
					      test: ["NONE"]
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										38
									
								
								templates/compose/n8n-with-postgresql.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								templates/compose/n8n-with-postgresql.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					# documentation: https://docs.n8n.io/hosting/
 | 
				
			||||||
 | 
					# slogan: n8n is an extendable workflow automation tool which enables you to connect anything to everything via its open, fair-code model.
 | 
				
			||||||
 | 
					# tags: n8n,workflow,automation,open,source,low,code
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					services:
 | 
				
			||||||
 | 
					  n8n:
 | 
				
			||||||
 | 
					    image: docker.n8n.io/n8nio/n8n
 | 
				
			||||||
 | 
					    environment:
 | 
				
			||||||
 | 
					      - SERVICE_FQDN_N8N
 | 
				
			||||||
 | 
					      - N8N_EDITOR_BASE_URL=${SERVICE_FQDN_N8N}
 | 
				
			||||||
 | 
					      - N8N_HOST=${SERVICE_FQDN_N8N}
 | 
				
			||||||
 | 
					      - GENERIC_TIMEZONE="Europe/Berlin"
 | 
				
			||||||
 | 
					      - TZ="Europe/Berlin"
 | 
				
			||||||
 | 
					      - DB_TYPE=postgresdb
 | 
				
			||||||
 | 
					      - DB_POSTGRESDB_DATABASE=${POSTGRES_DB:-umami}
 | 
				
			||||||
 | 
					      - DB_POSTGRESDB_HOST=postgresql
 | 
				
			||||||
 | 
					      - DB_POSTGRESDB_PORT=5432
 | 
				
			||||||
 | 
					      - DB_POSTGRESDB_USER=$SERVICE_USER_POSTGRES
 | 
				
			||||||
 | 
					      - DB_POSTGRESDB_SCHEMA=public
 | 
				
			||||||
 | 
					      - DB_POSTGRESDB_PASSWORD=$SERVICE_PASSWORD_POSTGRES
 | 
				
			||||||
 | 
					    volumes:
 | 
				
			||||||
 | 
					      - n8n-data:/home/node/.n8n
 | 
				
			||||||
 | 
					    depends_on:
 | 
				
			||||||
 | 
					      - postgresql
 | 
				
			||||||
 | 
					  postgresql:
 | 
				
			||||||
 | 
					    image: postgres:15-alpine
 | 
				
			||||||
 | 
					    volumes:
 | 
				
			||||||
 | 
					      - postgresql-data:/var/lib/postgresql/data
 | 
				
			||||||
 | 
					    environment:
 | 
				
			||||||
 | 
					      - POSTGRES_USER=$SERVICE_USER_POSTGRES
 | 
				
			||||||
 | 
					      - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
 | 
				
			||||||
 | 
					      - POSTGRES_DB=${POSTGRES_DB:-umami}
 | 
				
			||||||
 | 
					    healthcheck:
 | 
				
			||||||
 | 
					      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
 | 
				
			||||||
 | 
					      interval: 5s
 | 
				
			||||||
 | 
					      timeout: 5s
 | 
				
			||||||
 | 
					      retries: 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								templates/compose/n8n.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								templates/compose/n8n.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					# documentation: https://docs.n8n.io/hosting/
 | 
				
			||||||
 | 
					# slogan: n8n is an extendable workflow automation tool which enables you to connect anything to everything via its open, fair-code model.
 | 
				
			||||||
 | 
					# tags: n8n,workflow,automation,open,source,low,code
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					services:
 | 
				
			||||||
 | 
					  n8n:
 | 
				
			||||||
 | 
					    image: docker.n8n.io/n8nio/n8n
 | 
				
			||||||
 | 
					    environment:
 | 
				
			||||||
 | 
					      - SERVICE_FQDN_N8N
 | 
				
			||||||
 | 
					      - N8N_EDITOR_BASE_URL=${SERVICE_FQDN_N8N}
 | 
				
			||||||
 | 
					      - N8N_HOST=${SERVICE_FQDN_N8N}
 | 
				
			||||||
 | 
					      - GENERIC_TIMEZONE="Europe/Berlin"
 | 
				
			||||||
 | 
					      - TZ="Europe/Berlin"
 | 
				
			||||||
 | 
					    volumes:
 | 
				
			||||||
 | 
					      - n8n-data:/home/node/.n8n
 | 
				
			||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
    "appsmith": {
 | 
					    "appsmith": {
 | 
				
			||||||
        "documentation": "https:\/\/docs.appsmith.com",
 | 
					        "documentation": "https:\/\/docs.appsmith.com",
 | 
				
			||||||
        "slogan": "Appsmith is an open-source, self-hosted application development platform that enables you to build powerful web applications with ease.",
 | 
					        "slogan": "Appsmith is an open-source, self-hosted application development platform that enables you to build powerful web applications with ease.",
 | 
				
			||||||
        "compose": "c2VydmljZXM6CiAgYXBwc21pdGg6CiAgICBpbWFnZTogJ2luZGV4LmRvY2tlci5pby9hcHBzbWl0aC9hcHBzbWl0aC1jZTpsYXRlc3QnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE4KICAgICAgLSBBUFBTTUlUSF9NQUlMX0VOQUJMRUQ9ZmFsc2UKICAgICAgLSBBUFBTTUlUSF9ESVNBQkxFX1RFTEVNRVRSWT10cnVlCiAgICAgIC0gQVBQU01JVEhfRElTQUJMRV9JTlRFUkNPTT10cnVlCiAgICAgIC0gQVBQU01JVEhfU0VOVFJZX0RTTj0KICAgICAgLSBBUFBTTUlUSF9TTUFSVF9MT09LX0lEPQogICAgdm9sdW1lczoKICAgICAgLSAnc3RhY2tzLWRhdGE6L2FwcHNtaXRoLXN0YWNrcycK",
 | 
					        "compose": "c2VydmljZXM6CiAgYXBwc21pdGg6CiAgICBpbWFnZTogJ2luZGV4LmRvY2tlci5pby9hcHBzbWl0aC9hcHBzbWl0aC1jZTpsYXRlc3QnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE4KICAgICAgLSBBUFBTTUlUSF9NQUlMX0VOQUJMRUQ9ZmFsc2UKICAgICAgLSBBUFBTTUlUSF9ESVNBQkxFX1RFTEVNRVRSWT10cnVlCiAgICAgIC0gQVBQU01JVEhfRElTQUJMRV9JTlRFUkNPTT10cnVlCiAgICAgIC0gQVBQU01JVEhfU0VOVFJZX0RTTj0KICAgICAgLSBBUFBTTUlUSF9TTUFSVF9MT09LX0lEPQogICAgdm9sdW1lczoKICAgICAgLSAnc3RhY2tzLWRhdGE6L2FwcHNtaXRoLXN0YWNrcycKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gTk9ORQo=",
 | 
				
			||||||
        "tags": [
 | 
					        "tags": [
 | 
				
			||||||
            "lowcode",
 | 
					            "lowcode",
 | 
				
			||||||
            "nocode",
 | 
					            "nocode",
 | 
				
			||||||
@@ -110,6 +110,34 @@
 | 
				
			|||||||
            "api"
 | 
					            "api"
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "n8n-with-postgresql": {
 | 
				
			||||||
 | 
					        "documentation": "https:\/\/docs.n8n.io\/hosting\/",
 | 
				
			||||||
 | 
					        "slogan": "n8n is an extendable workflow automation tool which enables you to connect anything to everything via its open, fair-code model.",
 | 
				
			||||||
 | 
					        "compose": "c2VydmljZXM6CiAgbjhuOgogICAgaW1hZ2U6IGRvY2tlci5uOG4uaW8vbjhuaW8vbjhuCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fTjhOCiAgICAgIC0gJ044Tl9FRElUT1JfQkFTRV9VUkw9JHtTRVJWSUNFX0ZRRE5fTjhOfScKICAgICAgLSAnTjhOX0hPU1Q9JHtTRVJWSUNFX0ZRRE5fTjhOfScKICAgICAgLSAnR0VORVJJQ19USU1FWk9ORT0iRXVyb3BlL0JlcmxpbiInCiAgICAgIC0gJ1RaPSJFdXJvcGUvQmVybGluIicKICAgICAgLSBEQl9UWVBFPXBvc3RncmVzZGIKICAgICAgLSAnREJfUE9TVEdSRVNEQl9EQVRBQkFTRT0ke1BPU1RHUkVTX0RCOi11bWFtaX0nCiAgICAgIC0gREJfUE9TVEdSRVNEQl9IT1NUPXBvc3RncmVzcWwKICAgICAgLSBEQl9QT1NUR1JFU0RCX1BPUlQ9NTQzMgogICAgICAtIERCX1BPU1RHUkVTREJfVVNFUj0kU0VSVklDRV9VU0VSX1BPU1RHUkVTCiAgICAgIC0gREJfUE9TVEdSRVNEQl9TQ0hFTUE9cHVibGljCiAgICAgIC0gREJfUE9TVEdSRVNEQl9QQVNTV09SRD0kU0VSVklDRV9QQVNTV09SRF9QT1NUR1JFUwogICAgdm9sdW1lczoKICAgICAgLSAnbjhuLWRhdGE6L2hvbWUvbm9kZS8ubjhuJwogICAgZGVwZW5kc19vbjoKICAgICAgLSBwb3N0Z3Jlc3FsCiAgcG9zdGdyZXNxbDoKICAgIGltYWdlOiAncG9zdGdyZXM6MTUtYWxwaW5lJwogICAgdm9sdW1lczoKICAgICAgLSAncG9zdGdyZXNxbC1kYXRhOi92YXIvbGliL3Bvc3RncmVzcWwvZGF0YScKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX1VTRVI9JFNFUlZJQ0VfVVNFUl9QT1NUR1JFUwogICAgICAtIFBPU1RHUkVTX1BBU1NXT1JEPSRTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTCiAgICAgIC0gJ1BPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LXVtYW1pfScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAncGdfaXNyZWFkeSAtVSAkJHtQT1NUR1JFU19VU0VSfSAtZCAkJHtQT1NUR1JFU19EQn0nCiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiAxMAo=",
 | 
				
			||||||
 | 
					        "tags": [
 | 
				
			||||||
 | 
					            "n8n",
 | 
				
			||||||
 | 
					            "workflow",
 | 
				
			||||||
 | 
					            "automation",
 | 
				
			||||||
 | 
					            "open",
 | 
				
			||||||
 | 
					            "source",
 | 
				
			||||||
 | 
					            "low",
 | 
				
			||||||
 | 
					            "code"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "n8n": {
 | 
				
			||||||
 | 
					        "documentation": "https:\/\/docs.n8n.io\/hosting\/",
 | 
				
			||||||
 | 
					        "slogan": "n8n is an extendable workflow automation tool which enables you to connect anything to everything via its open, fair-code model.",
 | 
				
			||||||
 | 
					        "compose": "c2VydmljZXM6CiAgbjhuOgogICAgaW1hZ2U6IGRvY2tlci5uOG4uaW8vbjhuaW8vbjhuCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fTjhOCiAgICAgIC0gJ044Tl9FRElUT1JfQkFTRV9VUkw9JHtTRVJWSUNFX0ZRRE5fTjhOfScKICAgICAgLSAnTjhOX0hPU1Q9JHtTRVJWSUNFX0ZRRE5fTjhOfScKICAgICAgLSAnR0VORVJJQ19USU1FWk9ORT0iRXVyb3BlL0JlcmxpbiInCiAgICAgIC0gJ1RaPSJFdXJvcGUvQmVybGluIicKICAgIHZvbHVtZXM6CiAgICAgIC0gJ244bi1kYXRhOi9ob21lL25vZGUvLm44bicK",
 | 
				
			||||||
 | 
					        "tags": [
 | 
				
			||||||
 | 
					            "n8n",
 | 
				
			||||||
 | 
					            "workflow",
 | 
				
			||||||
 | 
					            "automation",
 | 
				
			||||||
 | 
					            "open",
 | 
				
			||||||
 | 
					            "source",
 | 
				
			||||||
 | 
					            "low",
 | 
				
			||||||
 | 
					            "code"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "pairdrop": {
 | 
					    "pairdrop": {
 | 
				
			||||||
        "documentation": "https:\/\/github.com\/schlagmichdoch\/PairDrop\/blob\/master\/docs\/faq.md",
 | 
					        "documentation": "https:\/\/github.com\/schlagmichdoch\/PairDrop\/blob\/master\/docs\/faq.md",
 | 
				
			||||||
        "slogan": "Pairdrop is a self-hosted file sharing and collaboration platform, offering secure file sharing and collaboration capabilities for efficient teamwork.",
 | 
					        "slogan": "Pairdrop is a self-hosted file sharing and collaboration platform, offering secure file sharing and collaboration capabilities for efficient teamwork.",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@
 | 
				
			|||||||
            "version": "3.12.36"
 | 
					            "version": "3.12.36"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "v4": {
 | 
					        "v4": {
 | 
				
			||||||
            "version": "4.0.0-beta.101"
 | 
					            "version": "4.0.0-beta.102"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user