feat: add s3 storages
This commit is contained in:
parent
2a7e7e978b
commit
f6e888ecf9
@ -8,6 +8,7 @@
|
|||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\TeamInvitation;
|
use App\Models\TeamInvitation;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Models\S3Storage;
|
||||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||||
use Illuminate\Routing\Controller as BaseController;
|
use Illuminate\Routing\Controller as BaseController;
|
||||||
@ -39,7 +40,7 @@ public function dashboard()
|
|||||||
{
|
{
|
||||||
$projects = Project::ownedByCurrentTeam()->get();
|
$projects = Project::ownedByCurrentTeam()->get();
|
||||||
$servers = Server::ownedByCurrentTeam()->get();
|
$servers = Server::ownedByCurrentTeam()->get();
|
||||||
|
$s3s = S3Storage::ownedByCurrentTeam()->get();
|
||||||
$resources = 0;
|
$resources = 0;
|
||||||
foreach ($projects as $project) {
|
foreach ($projects as $project) {
|
||||||
$resources += $project->applications->count();
|
$resources += $project->applications->count();
|
||||||
@ -49,6 +50,7 @@ public function dashboard()
|
|||||||
'servers' => $servers->count(),
|
'servers' => $servers->count(),
|
||||||
'projects' => $projects->count(),
|
'projects' => $projects->count(),
|
||||||
'resources' => $resources,
|
'resources' => $resources,
|
||||||
|
's3s' => $s3s,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
public function settings()
|
public function settings()
|
||||||
@ -83,6 +85,18 @@ public function team()
|
|||||||
'invitations' => $invitations,
|
'invitations' => $invitations,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
public function storages() {
|
||||||
|
$s3 = S3Storage::ownedByCurrentTeam()->get();
|
||||||
|
return view('team.storages.all', [
|
||||||
|
's3' => $s3,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
public function storages_show() {
|
||||||
|
$storage = S3Storage::ownedByCurrentTeam()->whereUuid(request()->storage_uuid)->firstOrFail();
|
||||||
|
return view('team.storages.show', [
|
||||||
|
'storage' => $storage,
|
||||||
|
]);
|
||||||
|
}
|
||||||
public function members()
|
public function members()
|
||||||
{
|
{
|
||||||
$invitations = [];
|
$invitations = [];
|
||||||
@ -136,4 +150,4 @@ public function revokeInvitation()
|
|||||||
throw $th;
|
throw $th;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
37
app/Http/Livewire/S3Test.php
Normal file
37
app/Http/Livewire/S3Test.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Livewire;
|
||||||
|
|
||||||
|
use App\Models\S3Storage;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Livewire\WithFileUploads;
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
class S3Test extends Component
|
||||||
|
{
|
||||||
|
use WithFileUploads;
|
||||||
|
public $s3;
|
||||||
|
public $file;
|
||||||
|
public function mount() {
|
||||||
|
$this->s3 = S3Storage::first();
|
||||||
|
ray($this->s3);
|
||||||
|
}
|
||||||
|
public function save() {
|
||||||
|
try {
|
||||||
|
$this->validate([
|
||||||
|
'file' => 'required|max:150', // 1MB Max
|
||||||
|
]);
|
||||||
|
set_s3_target($this->s3);
|
||||||
|
$this->file->storeAs('files', $this->file->getClientOriginalName(),'custom-s3');
|
||||||
|
$this->emit('success', 'File uploaded successfully.');
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return general_error_handler($th, $this, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public function get_files()
|
||||||
|
{
|
||||||
|
set_s3_target($this->s3);
|
||||||
|
dd(Storage::disk('custom-s3')->files('files'));
|
||||||
|
}
|
||||||
|
}
|
79
app/Http/Livewire/Team/Storage/Create.php
Normal file
79
app/Http/Livewire/Team/Storage/Create.php
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Livewire\Team\Storage;
|
||||||
|
|
||||||
|
use Livewire\Component;
|
||||||
|
use App\Models\S3Storage;
|
||||||
|
|
||||||
|
class Create extends Component
|
||||||
|
{
|
||||||
|
public string $name;
|
||||||
|
public string $description;
|
||||||
|
public string $region = 'us-east-1';
|
||||||
|
public string $key;
|
||||||
|
public string $secret;
|
||||||
|
public string $bucket;
|
||||||
|
public string $endpoint;
|
||||||
|
public S3Storage $storage;
|
||||||
|
protected $rules = [
|
||||||
|
'name' => 'nullable|min:3|max:255',
|
||||||
|
'description' => 'nullable|min:3|max:255',
|
||||||
|
'region' => 'required|max:255',
|
||||||
|
'key' => 'required|max:255',
|
||||||
|
'secret' => 'required|max:255',
|
||||||
|
'bucket' => 'required|max:255',
|
||||||
|
'endpoint' => 'nullable|url|max:255',
|
||||||
|
];
|
||||||
|
protected $validationAttributes = [
|
||||||
|
'name' => 'Name',
|
||||||
|
'description' => 'Description',
|
||||||
|
'region' => 'Region',
|
||||||
|
'key' => 'Key',
|
||||||
|
'secret' => "Secret",
|
||||||
|
'bucket' => 'Bucket',
|
||||||
|
'endpoint' => 'Endpoint',
|
||||||
|
];
|
||||||
|
public function mount() {
|
||||||
|
if (isDev()) {
|
||||||
|
$this->name = 'Local MinIO';
|
||||||
|
$this->description = 'Local MinIO';
|
||||||
|
$this->key = 'minioadmin';
|
||||||
|
$this->secret = 'minioadmin';
|
||||||
|
$this->bucket = 'local';
|
||||||
|
$this->endpoint = 'http://coolify-minio:9000';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private function test_s3_connection() {
|
||||||
|
try {
|
||||||
|
$this->storage->testConnection();
|
||||||
|
return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
|
||||||
|
} catch(\Throwable $th) {
|
||||||
|
return general_error_handler($th, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function submit() {
|
||||||
|
try {
|
||||||
|
$this->validate();
|
||||||
|
$this->storage = new S3Storage();
|
||||||
|
$this->storage->name = $this->name;
|
||||||
|
$this->storage->description = $this->description;
|
||||||
|
$this->storage->region = $this->region;
|
||||||
|
$this->storage->key = $this->key;
|
||||||
|
$this->storage->secret = $this->secret;
|
||||||
|
$this->storage->bucket = $this->bucket;
|
||||||
|
if (empty($this->endpoint)) {
|
||||||
|
$this->storage->endpoint = "https://s3.{$this->region}.amazonaws.com";
|
||||||
|
} else {
|
||||||
|
$this->storage->endpoint = $this->endpoint;
|
||||||
|
}
|
||||||
|
$this->storage->team_id = auth()->user()->currentTeam()->id;
|
||||||
|
$this->storage->testConnection();
|
||||||
|
$this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
|
||||||
|
$this->storage->save();
|
||||||
|
return redirect()->route('team.storages.show', $this->storage->uuid);
|
||||||
|
} catch(\Throwable $th) {
|
||||||
|
return general_error_handler($th, $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
57
app/Http/Livewire/Team/Storage/Form.php
Normal file
57
app/Http/Livewire/Team/Storage/Form.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Livewire\Team\Storage;
|
||||||
|
|
||||||
|
use Livewire\Component;
|
||||||
|
use App\Models\S3Storage;
|
||||||
|
|
||||||
|
class Form extends Component
|
||||||
|
{
|
||||||
|
public S3Storage $storage;
|
||||||
|
protected $rules = [
|
||||||
|
'storage.name' => 'nullable|min:3|max:255',
|
||||||
|
'storage.description' => 'nullable|min:3|max:255',
|
||||||
|
'storage.region' => 'required|max:255',
|
||||||
|
'storage.key' => 'required|max:255',
|
||||||
|
'storage.secret' => 'required|max:255',
|
||||||
|
'storage.bucket' => 'required|max:255',
|
||||||
|
'storage.endpoint' => 'required|url|max:255',
|
||||||
|
];
|
||||||
|
protected $validationAttributes = [
|
||||||
|
'storage.name' => 'Name',
|
||||||
|
'storage.description' => 'Description',
|
||||||
|
'storage.region' => 'Region',
|
||||||
|
'storage.key' => 'Key',
|
||||||
|
'storage.secret' => "Secret",
|
||||||
|
'storage.bucket' => 'Bucket',
|
||||||
|
'storage.endpoint' => 'Endpoint',
|
||||||
|
];
|
||||||
|
public function test_s3_connection() {
|
||||||
|
try {
|
||||||
|
$this->storage->testConnection();
|
||||||
|
return $this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
|
||||||
|
} catch(\Throwable $th) {
|
||||||
|
return general_error_handler($th, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function delete() {
|
||||||
|
try {
|
||||||
|
$this->storage->delete();
|
||||||
|
return redirect()->route('team.storages.all');
|
||||||
|
} catch(\Throwable $th) {
|
||||||
|
return general_error_handler($th, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function submit()
|
||||||
|
{
|
||||||
|
$this->validate();
|
||||||
|
try {
|
||||||
|
$this->storage->testConnection();
|
||||||
|
$this->emit('success', 'Connection is working. Tested with "ListObjectsV2" action.');
|
||||||
|
$this->storage->save();
|
||||||
|
$this->emit('success', 'Storage settings saved.');
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return general_error_handler($th, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
app/Models/S3Storage.php
Normal file
25
app/Models/S3Storage.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
|
||||||
|
class S3Storage extends BaseModel
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
protected $guarded = [];
|
||||||
|
|
||||||
|
static public function ownedByCurrentTeam(array $select = ['*'])
|
||||||
|
{
|
||||||
|
$selectArray = collect($select)->concat(['id']);
|
||||||
|
return S3Storage::whereTeamId(session('currentTeam')->id)->select($selectArray->all())->orderBy('name');
|
||||||
|
}
|
||||||
|
public function awsUrl() {
|
||||||
|
return "{$this->endpoint}/{$this->bucket}";
|
||||||
|
}
|
||||||
|
public function testConnection() {
|
||||||
|
set_s3_target($this);
|
||||||
|
return \Storage::disk('custom-s3')->files();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
bootstrap/helpers/s3.php
Normal file
22
bootstrap/helpers/s3.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\S3Storage;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
function set_s3_target(S3Storage $s3) {
|
||||||
|
$is_digital_ocean = false;
|
||||||
|
if ($s3->endpoint) {
|
||||||
|
$is_digital_ocean = Str::contains($s3->endpoint,'digitaloceanspaces.com');
|
||||||
|
}
|
||||||
|
config()->set('filesystems.disks.custom-s3', [
|
||||||
|
'driver' => 's3',
|
||||||
|
'region' => $s3['region'],
|
||||||
|
'key' => $s3['key'],
|
||||||
|
'secret' => $s3['secret'],
|
||||||
|
'bucket' => $s3['bucket'],
|
||||||
|
'endpoint' => $s3['endpoint'],
|
||||||
|
'use_path_style_endpoint' => true,
|
||||||
|
'bucket_endpoint' => $is_digital_ocean,
|
||||||
|
'aws_url' => $s3->awsUrl(),
|
||||||
|
]);
|
||||||
|
}
|
@ -18,6 +18,7 @@
|
|||||||
"laravel/tinker": "^v2.8.1",
|
"laravel/tinker": "^v2.8.1",
|
||||||
"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",
|
||||||
"livewire/livewire": "^v2.12.3",
|
"livewire/livewire": "^v2.12.3",
|
||||||
"masmerise/livewire-toaster": "^1.2",
|
"masmerise/livewire-toaster": "^1.2",
|
||||||
"nubs/random-name-generator": "^2.2",
|
"nubs/random-name-generator": "^2.2",
|
||||||
|
332
composer.lock
generated
332
composer.lock
generated
@ -4,8 +4,157 @@
|
|||||||
"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": "fa99d49c392ba6560f15eb6f3c5e4baa",
|
"content-hash": "ca293cd95f3fcb41f9122aaf474adb69",
|
||||||
"packages": [
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "aws/aws-crt-php",
|
||||||
|
"version": "v1.2.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/awslabs/aws-crt-php.git",
|
||||||
|
"reference": "2f1dc7b7eda080498be96a4a6d683a41583030e9"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/2f1dc7b7eda080498be96a4a6d683a41583030e9",
|
||||||
|
"reference": "2f1dc7b7eda080498be96a4a6d683a41583030e9",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.5"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^4.8.35||^5.6.3||^9.5",
|
||||||
|
"yoast/phpunit-polyfills": "^1.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality."
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"classmap": [
|
||||||
|
"src/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"Apache-2.0"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "AWS SDK Common Runtime Team",
|
||||||
|
"email": "aws-sdk-common-runtime@amazon.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "AWS Common Runtime for PHP",
|
||||||
|
"homepage": "https://github.com/awslabs/aws-crt-php",
|
||||||
|
"keywords": [
|
||||||
|
"amazon",
|
||||||
|
"aws",
|
||||||
|
"crt",
|
||||||
|
"sdk"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/awslabs/aws-crt-php/issues",
|
||||||
|
"source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.2"
|
||||||
|
},
|
||||||
|
"time": "2023-07-20T16:49:55+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "aws/aws-sdk-php",
|
||||||
|
"version": "3.269.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||||
|
"reference": "6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78",
|
||||||
|
"reference": "6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"aws/aws-crt-php": "^1.0.4",
|
||||||
|
"ext-json": "*",
|
||||||
|
"ext-pcre": "*",
|
||||||
|
"ext-simplexml": "*",
|
||||||
|
"guzzlehttp/guzzle": "^6.5.8 || ^7.4.5",
|
||||||
|
"guzzlehttp/promises": "^1.4.0",
|
||||||
|
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
|
||||||
|
"mtdowling/jmespath.php": "^2.6",
|
||||||
|
"php": ">=5.5"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"andrewsville/php-token-reflection": "^1.4",
|
||||||
|
"aws/aws-php-sns-message-validator": "~1.0",
|
||||||
|
"behat/behat": "~3.0",
|
||||||
|
"composer/composer": "^1.10.22",
|
||||||
|
"dms/phpunit-arraysubset-asserts": "^0.4.0",
|
||||||
|
"doctrine/cache": "~1.4",
|
||||||
|
"ext-dom": "*",
|
||||||
|
"ext-openssl": "*",
|
||||||
|
"ext-pcntl": "*",
|
||||||
|
"ext-sockets": "*",
|
||||||
|
"nette/neon": "^2.3",
|
||||||
|
"paragonie/random_compat": ">= 2",
|
||||||
|
"phpunit/phpunit": "^4.8.35 || ^5.6.3 || ^9.5",
|
||||||
|
"psr/cache": "^1.0",
|
||||||
|
"psr/http-message": "^1.0",
|
||||||
|
"psr/simple-cache": "^1.0",
|
||||||
|
"sebastian/comparator": "^1.2.3 || ^4.0",
|
||||||
|
"yoast/phpunit-polyfills": "^1.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"aws/aws-php-sns-message-validator": "To validate incoming SNS notifications",
|
||||||
|
"doctrine/cache": "To use the DoctrineCacheAdapter",
|
||||||
|
"ext-curl": "To send requests using cURL",
|
||||||
|
"ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages",
|
||||||
|
"ext-sockets": "To use client-side monitoring"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/functions.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Aws\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"Apache-2.0"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Amazon Web Services",
|
||||||
|
"homepage": "http://aws.amazon.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project",
|
||||||
|
"homepage": "http://aws.amazon.com/sdkforphp",
|
||||||
|
"keywords": [
|
||||||
|
"amazon",
|
||||||
|
"aws",
|
||||||
|
"cloud",
|
||||||
|
"dynamodb",
|
||||||
|
"ec2",
|
||||||
|
"glacier",
|
||||||
|
"s3",
|
||||||
|
"sdk"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
|
||||||
|
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||||
|
"source": "https://github.com/aws/aws-sdk-php/tree/3.269.0"
|
||||||
|
},
|
||||||
|
"time": "2023-04-26T18:21:04+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "bacon/bacon-qr-code",
|
"name": "bacon/bacon-qr-code",
|
||||||
"version": "2.0.8",
|
"version": "2.0.8",
|
||||||
@ -1206,33 +1355,29 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/promises",
|
"name": "guzzlehttp/promises",
|
||||||
"version": "2.0.0",
|
"version": "1.5.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/guzzle/promises.git",
|
"url": "https://github.com/guzzle/promises.git",
|
||||||
"reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6"
|
"reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
|
"url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e",
|
||||||
"reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
|
"reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.2.5 || ^8.0"
|
"php": ">=5.5"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"bamarni/composer-bin-plugin": "^1.8.1",
|
"symfony/phpunit-bridge": "^4.4 || ^5.1"
|
||||||
"phpunit/phpunit": "^8.5.29 || ^9.5.23"
|
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
|
||||||
"bamarni-bin": {
|
|
||||||
"bin-links": true,
|
|
||||||
"forward-command": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/functions_include.php"
|
||||||
|
],
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"GuzzleHttp\\Promise\\": "src/"
|
"GuzzleHttp\\Promise\\": "src/"
|
||||||
}
|
}
|
||||||
@ -1269,7 +1414,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/guzzle/promises/issues",
|
"issues": "https://github.com/guzzle/promises/issues",
|
||||||
"source": "https://github.com/guzzle/promises/tree/2.0.0"
|
"source": "https://github.com/guzzle/promises/tree/1.5.3"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -1285,20 +1430,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-05-21T13:50:22+00:00"
|
"time": "2023-05-21T12:31:43+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/psr7",
|
"name": "guzzlehttp/psr7",
|
||||||
"version": "2.5.0",
|
"version": "2.6.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/guzzle/psr7.git",
|
"url": "https://github.com/guzzle/psr7.git",
|
||||||
"reference": "b635f279edd83fc275f822a1188157ffea568ff6"
|
"reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6",
|
"url": "https://api.github.com/repos/guzzle/psr7/zipball/8bd7c33a0734ae1c5d074360512beb716bef3f77",
|
||||||
"reference": "b635f279edd83fc275f822a1188157ffea568ff6",
|
"reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -1385,7 +1530,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/guzzle/psr7/issues",
|
"issues": "https://github.com/guzzle/psr7/issues",
|
||||||
"source": "https://github.com/guzzle/psr7/tree/2.5.0"
|
"source": "https://github.com/guzzle/psr7/tree/2.6.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -1401,7 +1546,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-04-17T16:11:26+00:00"
|
"time": "2023-08-03T15:06:02+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "guzzlehttp/uri-template",
|
"name": "guzzlehttp/uri-template",
|
||||||
@ -2553,6 +2698,72 @@
|
|||||||
],
|
],
|
||||||
"time": "2023-05-04T09:04:26+00:00"
|
"time": "2023-05-04T09:04:26+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "league/flysystem-aws-s3-v3",
|
||||||
|
"version": "3.15.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git",
|
||||||
|
"reference": "d8de61ee10b6a607e7996cff388c5a3a663e8c8a"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/d8de61ee10b6a607e7996cff388c5a3a663e8c8a",
|
||||||
|
"reference": "d8de61ee10b6a607e7996cff388c5a3a663e8c8a",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"aws/aws-sdk-php": "^3.220.0",
|
||||||
|
"league/flysystem": "^3.10.0",
|
||||||
|
"league/mime-type-detection": "^1.0.0",
|
||||||
|
"php": "^8.0.2"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"guzzlehttp/guzzle": "<7.0",
|
||||||
|
"guzzlehttp/ringphp": "<1.1.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"League\\Flysystem\\AwsS3V3\\": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Frank de Jonge",
|
||||||
|
"email": "info@frankdejonge.nl"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "AWS S3 filesystem adapter for Flysystem.",
|
||||||
|
"keywords": [
|
||||||
|
"Flysystem",
|
||||||
|
"aws",
|
||||||
|
"file",
|
||||||
|
"files",
|
||||||
|
"filesystem",
|
||||||
|
"s3",
|
||||||
|
"storage"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/thephpleague/flysystem-aws-s3-v3/issues",
|
||||||
|
"source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.15.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://ecologi.com/frankdejonge",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/frankdejonge",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-05-02T20:02:14+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "league/flysystem-local",
|
"name": "league/flysystem-local",
|
||||||
"version": "3.15.0",
|
"version": "3.15.0",
|
||||||
@ -2615,26 +2826,26 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/mime-type-detection",
|
"name": "league/mime-type-detection",
|
||||||
"version": "1.11.0",
|
"version": "1.13.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/thephpleague/mime-type-detection.git",
|
"url": "https://github.com/thephpleague/mime-type-detection.git",
|
||||||
"reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd"
|
"reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
|
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/a6dfb1194a2946fcdc1f38219445234f65b35c96",
|
||||||
"reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
|
"reference": "a6dfb1194a2946fcdc1f38219445234f65b35c96",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"ext-fileinfo": "*",
|
"ext-fileinfo": "*",
|
||||||
"php": "^7.2 || ^8.0"
|
"php": "^7.4 || ^8.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"friendsofphp/php-cs-fixer": "^3.2",
|
"friendsofphp/php-cs-fixer": "^3.2",
|
||||||
"phpstan/phpstan": "^0.12.68",
|
"phpstan/phpstan": "^0.12.68",
|
||||||
"phpunit/phpunit": "^8.5.8 || ^9.3"
|
"phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -2655,7 +2866,7 @@
|
|||||||
"description": "Mime-type detection for Flysystem",
|
"description": "Mime-type detection for Flysystem",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/thephpleague/mime-type-detection/issues",
|
"issues": "https://github.com/thephpleague/mime-type-detection/issues",
|
||||||
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.11.0"
|
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.13.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -2667,7 +2878,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-04-17T13:12:02+00:00"
|
"time": "2023-08-05T12:09:49+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "livewire/livewire",
|
"name": "livewire/livewire",
|
||||||
@ -2911,6 +3122,67 @@
|
|||||||
],
|
],
|
||||||
"time": "2023-06-21T08:46:11+00:00"
|
"time": "2023-06-21T08:46:11+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "mtdowling/jmespath.php",
|
||||||
|
"version": "2.6.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/jmespath/jmespath.php.git",
|
||||||
|
"reference": "9b87907a81b87bc76d19a7fb2d61e61486ee9edb"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/9b87907a81b87bc76d19a7fb2d61e61486ee9edb",
|
||||||
|
"reference": "9b87907a81b87bc76d19a7fb2d61e61486ee9edb",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^5.4 || ^7.0 || ^8.0",
|
||||||
|
"symfony/polyfill-mbstring": "^1.17"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"composer/xdebug-handler": "^1.4 || ^2.0",
|
||||||
|
"phpunit/phpunit": "^4.8.36 || ^7.5.15"
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"bin/jp.php"
|
||||||
|
],
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "2.6-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/JmesPath.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"JmesPath\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Michael Dowling",
|
||||||
|
"email": "mtdowling@gmail.com",
|
||||||
|
"homepage": "https://github.com/mtdowling"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Declaratively specify how to extract elements from a JSON document",
|
||||||
|
"keywords": [
|
||||||
|
"json",
|
||||||
|
"jsonpath"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/jmespath/jmespath.php/issues",
|
||||||
|
"source": "https://github.com/jmespath/jmespath.php/tree/2.6.1"
|
||||||
|
},
|
||||||
|
"time": "2021-06-14T00:11:39+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "nesbot/carbon",
|
"name": "nesbot/carbon",
|
||||||
"version": "2.68.1",
|
"version": "2.68.1",
|
||||||
|
158
config/livewire.php
Normal file
158
config/livewire.php
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Class Namespace
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value sets the root namespace for Livewire component classes in
|
||||||
|
| your application. This value affects component auto-discovery and
|
||||||
|
| any Livewire file helper commands, like `artisan make:livewire`.
|
||||||
|
|
|
||||||
|
| After changing this item, run: `php artisan livewire:discover`.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'class_namespace' => 'App\\Http\\Livewire',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| View Path
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value sets the path for Livewire component views. This affects
|
||||||
|
| file manipulation helper commands like `artisan make:livewire`.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'view_path' => resource_path('views/livewire'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Layout
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| The default layout view that will be used when rendering a component via
|
||||||
|
| Route::get('/some-endpoint', SomeComponent::class);. In this case the
|
||||||
|
| the view returned by SomeComponent will be wrapped in "layouts.app"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'layout' => 'layouts.app',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Livewire Assets URL
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value sets the path to Livewire JavaScript assets, for cases where
|
||||||
|
| your app's domain root is not the correct path. By default, Livewire
|
||||||
|
| will load its JavaScript assets from the app's "relative root".
|
||||||
|
|
|
||||||
|
| Examples: "/assets", "myurl.com/app".
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'asset_url' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Livewire App URL
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value should be used if livewire assets are served from CDN.
|
||||||
|
| Livewire will communicate with an app through this url.
|
||||||
|
|
|
||||||
|
| Examples: "https://my-app.com", "myurl.com/app".
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'app_url' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Livewire Endpoint Middleware Group
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value sets the middleware group that will be applied to the main
|
||||||
|
| Livewire "message" endpoint (the endpoint that gets hit everytime
|
||||||
|
| a Livewire component updates). It is set to "web" by default.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'middleware_group' => 'web',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Livewire Temporary File Uploads Endpoint Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Livewire handles file uploads by storing uploads in a temporary directory
|
||||||
|
| before the file is validated and stored permanently. All file uploads
|
||||||
|
| are directed to a global endpoint for temporary storage. The config
|
||||||
|
| items below are used for customizing the way the endpoint works.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'temporary_file_upload' => [
|
||||||
|
'disk' => null, // Example: 'local', 's3' Default: 'default'
|
||||||
|
'rules' => null, // Example: ['file', 'mimes:png,jpg'] Default: ['required', 'file', 'max:12288'] (12MB)
|
||||||
|
'directory' => null, // Example: 'tmp' Default 'livewire-tmp'
|
||||||
|
'middleware' => null, // Example: 'throttle:5,1' Default: 'throttle:60,1'
|
||||||
|
'preview_mimes' => [ // Supported file types for temporary pre-signed file URLs.
|
||||||
|
'png', 'gif', 'bmp', 'svg', 'wav', 'mp4',
|
||||||
|
'mov', 'avi', 'wmv', 'mp3', 'm4a',
|
||||||
|
'jpg', 'jpeg', 'mpga', 'webp', 'wma',
|
||||||
|
],
|
||||||
|
'max_upload_time' => 5, // Max duration (in minutes) before an upload gets invalidated.
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Manifest File Path
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value sets the path to the Livewire manifest file.
|
||||||
|
| The default should work for most cases (which is
|
||||||
|
| "<app_root>/bootstrap/cache/livewire-components.php"), but for specific
|
||||||
|
| cases like when hosting on Laravel Vapor, it could be set to a different value.
|
||||||
|
|
|
||||||
|
| Example: for Laravel Vapor, it would be "/tmp/storage/bootstrap/cache/livewire-components.php".
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'manifest_path' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Back Button Cache
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value determines whether the back button cache will be used on pages
|
||||||
|
| that contain Livewire. By disabling back button cache, it ensures that
|
||||||
|
| the back button shows the correct state of components, instead of
|
||||||
|
| potentially stale, cached data.
|
||||||
|
|
|
||||||
|
| Setting it to "false" (default) will disable back button cache.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'back_button_cache' => false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Render On Redirect
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value determines whether Livewire will render before it's redirected
|
||||||
|
| or not. Setting it to "false" (default) will mean the render method is
|
||||||
|
| skipped when redirecting. And "true" will mean the render method is
|
||||||
|
| run before redirecting. Browsers bfcache can store a potentially
|
||||||
|
| stale view if render is skipped on redirect.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'render_on_redirect' => false,
|
||||||
|
|
||||||
|
];
|
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('s3_storages', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('uuid')->unique();
|
||||||
|
$table->string('name')->nullable();
|
||||||
|
$table->longText('description')->nullable();
|
||||||
|
$table->string('region')->default('us-east-1');
|
||||||
|
$table->longText('key');
|
||||||
|
$table->longText('secret');
|
||||||
|
$table->longText('bucket');
|
||||||
|
$table->longText('endpoint')->nullable();
|
||||||
|
|
||||||
|
$table->foreignId('team_id');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('s3_storages');
|
||||||
|
}
|
||||||
|
};
|
@ -31,6 +31,7 @@ public function run(): void
|
|||||||
ServiceSeeder::class,
|
ServiceSeeder::class,
|
||||||
EnvironmentVariableSeeder::class,
|
EnvironmentVariableSeeder::class,
|
||||||
LocalPersistentVolumeSeeder::class,
|
LocalPersistentVolumeSeeder::class,
|
||||||
|
S3StorageSeeder::class,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
35
database/seeders/S3StorageSeeder.php
Normal file
35
database/seeders/S3StorageSeeder.php
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use App\Models\S3Storage;
|
||||||
|
|
||||||
|
class S3StorageSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*/
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
S3Storage::create([
|
||||||
|
'name' => 'Local MinIO',
|
||||||
|
'description' => 'Local MinIO S3 Storage',
|
||||||
|
'key' => 'minioadmin',
|
||||||
|
'secret' => 'minioadmin',
|
||||||
|
'bucket' => 'local',
|
||||||
|
'endpoint' => 'http://coolify-minio:9000',
|
||||||
|
'team_id' => 0,
|
||||||
|
]);
|
||||||
|
S3Storage::create([
|
||||||
|
'name' => 'DO Spaces',
|
||||||
|
'description' => 'DO S3 Storage',
|
||||||
|
'key' => 'DO003UBFTACPQGUXUANY',
|
||||||
|
'secret' => 'eXDSco/04+5RHti19X8O/QE1aWIhZHAyyuOEs4J1JWA',
|
||||||
|
'bucket' => 'files',
|
||||||
|
'endpoint' => 'https://test-coolify.ams3.digitaloceanspaces.com',
|
||||||
|
'team_id' => 0,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -69,7 +69,20 @@ services:
|
|||||||
- "${FORWARD_MAILPIT_DASHBOARD_PORT:-8025}:8025"
|
- "${FORWARD_MAILPIT_DASHBOARD_PORT:-8025}:8025"
|
||||||
networks:
|
networks:
|
||||||
- coolify
|
- coolify
|
||||||
|
minio:
|
||||||
|
image: minio/minio:latest
|
||||||
|
container_name: coolify-minio
|
||||||
|
command: server /data --console-address ":9001"
|
||||||
|
ports:
|
||||||
|
- "${FORWARD_MINIO_PORT:-9000}:9000"
|
||||||
|
- "${FORWARD_MINIO_PORT_CONSOLE:-9001}:9001"
|
||||||
|
environment:
|
||||||
|
MINIO_ACCESS_KEY: "${MINIO_ACCESS_KEY:-minioadmin}"
|
||||||
|
MINIO_SECRET_KEY: "${MINIO_SECRET_KEY:-minioadmin}"
|
||||||
|
volumes:
|
||||||
|
- ./_data/_volumes/minio/:/data
|
||||||
|
networks:
|
||||||
|
- coolify
|
||||||
# buggregator:
|
# buggregator:
|
||||||
# image: ghcr.io/buggregator/server:latest
|
# image: ghcr.io/buggregator/server:latest
|
||||||
# container_name: coolify-debug
|
# container_name: coolify-debug
|
||||||
|
@ -27,6 +27,10 @@
|
|||||||
<a class="{{ request()->routeIs('team.members') ? 'text-white' : '' }}" href="{{ route('team.members') }}">
|
<a class="{{ request()->routeIs('team.members') ? 'text-white' : '' }}" href="{{ route('team.members') }}">
|
||||||
<button>Members</button>
|
<button>Members</button>
|
||||||
</a>
|
</a>
|
||||||
|
<a class="{{ request()->routeIs('team.storages.all') ? 'text-white' : '' }}"
|
||||||
|
href="{{ route('team.storages.all') }}">
|
||||||
|
<button>S3 Storages</button>
|
||||||
|
</a>
|
||||||
<a class="{{ request()->routeIs('team.notifications') ? 'text-white' : '' }}"
|
<a class="{{ request()->routeIs('team.notifications') ? 'text-white' : '' }}"
|
||||||
href="{{ route('team.notifications') }}">
|
href="{{ route('team.notifications') }}">
|
||||||
<button>Notifications</button>
|
<button>Notifications</button>
|
||||||
|
@ -17,5 +17,12 @@
|
|||||||
<div class="stat-value">{{ $resources }}</div>
|
<div class="stat-value">{{ $resources }}</div>
|
||||||
<div class="stat-desc">Applications, databases, etc...</div>
|
<div class="stat-desc">Applications, databases, etc...</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="stat">
|
||||||
|
<div class="stat-title">S3 Storages</div>
|
||||||
|
<div class="stat-value">{{ $s3s->count() }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@if (isDev())
|
||||||
|
<livewire:s3-test />
|
||||||
|
@endif
|
||||||
</x-layout>
|
</x-layout>
|
||||||
|
15
resources/views/livewire/s3-test.blade.php
Normal file
15
resources/views/livewire/s3-test.blade.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<div>
|
||||||
|
<h2>S3 Test</h2>
|
||||||
|
<form wire:submit.prevent="save">
|
||||||
|
<input type="file" wire:model="file">
|
||||||
|
@error('file')
|
||||||
|
<span class="error">{{ $message }}</span>
|
||||||
|
@enderror
|
||||||
|
<div wire:loading wire:target="file">Uploading to server...</div>
|
||||||
|
@if ($file)
|
||||||
|
<x-forms.button type="submit">Upload file to s3:/files</x-forms.button>
|
||||||
|
@endif
|
||||||
|
</form>
|
||||||
|
<h4>Functions</h4>
|
||||||
|
<x-forms.button wire:click="get_files">Get s3:/files</x-forms.button>
|
||||||
|
</div>
|
23
resources/views/livewire/team/storage/create.blade.php
Normal file
23
resources/views/livewire/team/storage/create.blade.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<div>
|
||||||
|
<h1>Create a new S3 Storage</h1>
|
||||||
|
<div class="pt-2 pb-10 ">S3 Storage used to save backups / files</div>
|
||||||
|
<form class="flex flex-col gap-2" wire:submit.prevent='submit'>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<x-forms.input label="Name" id="name" />
|
||||||
|
<x-forms.input label="Description" id="description" />
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<x-forms.input type="url" label="Endpoint" id="endpoint" />
|
||||||
|
<x-forms.input required label="Bucket" id="bucket" />
|
||||||
|
<x-forms.input required label="Region" id="region" />
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<x-forms.input required type="password" label="Access Key" id="key" />
|
||||||
|
<x-forms.input required type="password" label="Secret Key" id="secret" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<x-forms.button type="submit">
|
||||||
|
Save New S3 Storage
|
||||||
|
</x-forms.button>
|
||||||
|
</form>
|
||||||
|
</div>
|
38
resources/views/livewire/team/storage/form.blade.php
Normal file
38
resources/views/livewire/team/storage/form.blade.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<div>
|
||||||
|
<x-modal yesOrNo modalId="deleteS3Storage" modalTitle="Delete S3 Storage">
|
||||||
|
<x-slot:modalBody>
|
||||||
|
<p>This storage will be deleted. It is not reversible. Your data won't be touched!<br>Please think again..
|
||||||
|
</p>
|
||||||
|
</x-slot:modalBody>
|
||||||
|
</x-modal>
|
||||||
|
<form class="flex flex-col gap-2 pb-6" wire:submit.prevent='submit'>
|
||||||
|
<div class="flex items-start gap-2">
|
||||||
|
<div class="pb-4">
|
||||||
|
<h2>Storage Details</h2>
|
||||||
|
<div>{{ $storage->name }}</div>
|
||||||
|
</div>
|
||||||
|
<x-forms.button type="submit">
|
||||||
|
Save
|
||||||
|
</x-forms.button>
|
||||||
|
<x-forms.button wire:click="test_s3_connection">
|
||||||
|
Test Connection
|
||||||
|
</x-forms.button>
|
||||||
|
<x-forms.button isError isModal modalId="deleteS3Storage">
|
||||||
|
Delete
|
||||||
|
</x-forms.button>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<x-forms.input label="Name" id="storage.name" />
|
||||||
|
<x-forms.input label="Description" id="storage.description" />
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<x-forms.input required label="Endpoint" id="storage.endpoint" />
|
||||||
|
<x-forms.input required label="Bucket" id="storage.bucket" />
|
||||||
|
<x-forms.input required label="Region" id="storage.region" />
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<x-forms.input required type="password" label="Access Key" id="storage.key" />
|
||||||
|
<x-forms.input required type="password" label="Secret Key" id="storage.secret" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
@ -1,6 +1,6 @@
|
|||||||
<x-layout>
|
<x-layout>
|
||||||
<x-team.navbar :team="session('currentTeam')" />
|
<x-team.navbar :team="session('currentTeam')" />
|
||||||
<h3>Members</h3>
|
<h2>Members</h2>
|
||||||
<div class="pt-4 overflow-hidden">
|
<div class="pt-4 overflow-hidden">
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<x-layout>
|
<x-layout>
|
||||||
<x-team.navbar :team="session('currentTeam')" />
|
<x-team.navbar :team="session('currentTeam')" />
|
||||||
|
<h2 class="pb-4">Notifications</h2>
|
||||||
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'email' }" class="flex h-full">
|
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'email' }" class="flex h-full">
|
||||||
<div class="flex flex-col gap-4 min-w-fit">
|
<div class="flex flex-col gap-4 min-w-fit">
|
||||||
<a :class="activeTab === 'email' && 'text-white'"
|
<a :class="activeTab === 'email' && 'text-white'"
|
||||||
|
32
resources/views/team/storages/all.blade.php
Normal file
32
resources/views/team/storages/all.blade.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<x-layout>
|
||||||
|
<x-team.navbar :team="session('currentTeam')" />
|
||||||
|
<div class="flex items-start gap-2">
|
||||||
|
<h2 class="pb-4">S3 Storages</h2>
|
||||||
|
<x-forms.button class="btn">
|
||||||
|
<a class="text-white hover:no-underline" href="/team/storages/new">+ Add</a>
|
||||||
|
</x-forms.button>
|
||||||
|
</div>
|
||||||
|
<div class="grid gap-2 lg:grid-cols-2">
|
||||||
|
@forelse ($s3 as $storage)
|
||||||
|
<div x-data x-on:click="goto('{{ $storage->uuid }}')" @class(['gap-2 border cursor-pointer box group border-transparent'])>
|
||||||
|
<div class="flex flex-col mx-6">
|
||||||
|
<div class=" group-hover:text-white">
|
||||||
|
{{ $storage->name }}
|
||||||
|
</div>
|
||||||
|
<div class="text-xs group-hover:text-white">
|
||||||
|
{{ $storage->description }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@empty
|
||||||
|
<div>
|
||||||
|
<div>No storage found.</div>
|
||||||
|
<x-use-magic-bar link="/team/storages/new" />
|
||||||
|
</div>
|
||||||
|
@endforelse
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
function goto(uuid) {
|
||||||
|
window.location.href = '/team/storages/' + uuid;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</x-layout>
|
3
resources/views/team/storages/create.blade.php
Normal file
3
resources/views/team/storages/create.blade.php
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<x-layout>
|
||||||
|
<livewire:team.storage.create />
|
||||||
|
</x-layout>
|
4
resources/views/team/storages/show.blade.php
Normal file
4
resources/views/team/storages/show.blade.php
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<x-layout>
|
||||||
|
<x-team.navbar :team="session('currentTeam')" />
|
||||||
|
<livewire:team.storage.form :storage="$storage" />
|
||||||
|
</x-layout>
|
@ -92,6 +92,9 @@
|
|||||||
Route::get('/team', [Controller::class, 'team'])->name('team.show');
|
Route::get('/team', [Controller::class, 'team'])->name('team.show');
|
||||||
Route::get('/team/new', fn () => view('team.create'))->name('team.create');
|
Route::get('/team/new', fn () => view('team.create'))->name('team.create');
|
||||||
Route::get('/team/notifications', fn () => view('team.notifications'))->name('team.notifications');
|
Route::get('/team/notifications', fn () => view('team.notifications'))->name('team.notifications');
|
||||||
|
Route::get('/team/storages', [Controller::class, 'storages'])->name('team.storages.all');
|
||||||
|
Route::get('/team/storages/new', fn () => view('team.storages.create'))->name('team.storages.new');
|
||||||
|
Route::get('/team/storages/{storage_uuid}', [Controller::class, 'storages_show'])->name('team.storages.show');
|
||||||
Route::get('/team/members', [Controller::class, 'members'])->name('team.members');
|
Route::get('/team/members', [Controller::class, 'members'])->name('team.members');
|
||||||
Route::get('/command-center', fn () => view('command-center', ['servers' => Server::isReachable()->get()]))->name('command-center');
|
Route::get('/command-center', fn () => view('command-center', ['servers' => Server::isReachable()->get()]))->name('command-center');
|
||||||
Route::get('/invitations/{uuid}', [Controller::class, 'acceptInvitation'])->name('team.invitation.accept');
|
Route::get('/invitations/{uuid}', [Controller::class, 'acceptInvitation'])->name('team.invitation.accept');
|
||||||
|
Loading…
Reference in New Issue
Block a user