diff --git a/.env.testing b/.env.testing index 8c705736..b9f884b9 100644 --- a/.env.testing +++ b/.env.testing @@ -1,6 +1,6 @@ APP_NAME=Laravel APP_ENV=local -APP_KEY=base64:qpZihuLxIkDkK3rsQND5Ksv10zVWQ3yih2KiuY6IfXk= +APP_KEY=base64:H+C6Ovly2gudhK4Zyn0EOED/ZOKNXthKIr6fv6bXJUM= APP_DEBUG=true APP_URL=http://localhost APP_DEMO=false diff --git a/changelog.md b/changelog.md index 1cba9341..67df6d37 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,7 @@ +## Version 2.0.17 +#### Release date: 12. April 2022 +- Added option to use FTP as VueFileManager file storage server + ## Version 2.0.16 #### Release date: 8. April 2022 - Test mailgun, ses and postmark connection before storing your credentials into the app diff --git a/config/vuefilemanager.php b/config/vuefilemanager.php index 3077dc87..2ddb595f 100644 --- a/config/vuefilemanager.php +++ b/config/vuefilemanager.php @@ -1,7 +1,7 @@ '2.0.16', + 'version' => '2.0.17', 'is_demo' => env('APP_DEMO', false), diff --git a/resources/js/components/Setup/StorageSetup.vue b/resources/js/components/Setup/StorageSetup.vue index b513f67a..1f3d1983 100644 --- a/resources/js/components/Setup/StorageSetup.vue +++ b/resources/js/components/Setup/StorageSetup.vue @@ -21,12 +21,12 @@ -
+
@@ -72,7 +71,7 @@ >
+ +
+ + + + + + + + + + + + + + + +
@@ -143,10 +178,10 @@ deep: true }, 'storage.driver': function () { - this.storage.region = undefined + this.storage.s3.region = undefined }, - 'storage.region': function (val) { - this.storage.endpoint = { + 'storage.s3.region': function (val) { + this.storage.s3.endpoint = { storj: 'https://gateway.' + val + '.storjshare.io', spaces: 'https://' + val + '.digitaloceanspaces.com', wasabi: 'https://s3.' + val + '.wasabisys.com', @@ -180,11 +215,18 @@ return { storage: { driver: undefined, - key: undefined, - secret: undefined, - endpoint: undefined, - region: undefined, - bucket: undefined, + s3: { + key: undefined, + secret: undefined, + endpoint: undefined, + region: undefined, + bucket: undefined, + }, + ftp: { + host: undefined, + user: undefined, + password: undefined, + } }, ossRegions: [ { @@ -336,6 +378,15 @@ value: 'fra1', }, ], + s3PredefinedList: [ + 's3', + 'storj', + 'spaces', + 'wasabi', + 'backblaze', + 'oss', + 'other', + ], storageServiceList: [ { label: 'Local Driver', @@ -369,6 +420,10 @@ label: 'Other S3 Compatible Service', value: 'other', }, + { + label: 'FTP', + value: 'ftp', + }, ], } } diff --git a/resources/js/views/Admin/AppSettings/AppSettingsTabs/Environment.vue b/resources/js/views/Admin/AppSettings/AppSettingsTabs/Environment.vue index c6fd1fd4..b3612cbb 100644 --- a/resources/js/views/Admin/AppSettings/AppSettingsTabs/Environment.vue +++ b/resources/js/views/Admin/AppSettings/AppSettingsTabs/Environment.vue @@ -309,9 +309,9 @@ export default { }) }) .catch((error) => { - if (error.response.status === 401 && error.response.data.type === 's3-connection-error') { + if ([401, 500].includes(error.response.status)) { events.$emit('alert:open', { - title: 'S3 Connection Error - Wrong Credentials or Not Permitted', + title: error.response.data.title || this.$t('popup_error.title'), message: error.response.data.message, }) } else { diff --git a/resources/js/views/SetupWizard/EnvironmentSetup.vue b/resources/js/views/SetupWizard/EnvironmentSetup.vue index 367f8786..e9546c51 100644 --- a/resources/js/views/SetupWizard/EnvironmentSetup.vue +++ b/resources/js/views/SetupWizard/EnvironmentSetup.vue @@ -316,19 +316,11 @@ export default { this.$router.push({ name: 'AppSetup' }) }) .catch((error) => { - if (error.response.status === 401 && error.response.data.type === 's3-connection-error') { - events.$emit('alert:open', { - title: 'S3 Connection Error - Wrong Credentials or Not Permitted', - message: error.response.data.message, - }) - } else if ( - error.response.status === 401 && - error.response.data.type === 'mailer-connection-error' - ) { - events.$emit('alert:open', { - title: 'Mailer Connection Error - Wrong Credentials', - message: error.response.data.message, - }) + if ([401, 500].includes(error.response.status)) { + events.$emit('alert:open', { + title: error.response.data.title || 'Whooops, something went wrong!', + message: error.response.data.message, + }) } else { this.isError = true } diff --git a/src/Domain/Files/Actions/UploadFileAction.php b/src/Domain/Files/Actions/UploadFileAction.php index 2dc8d64a..6fd8f7e5 100644 --- a/src/Domain/Files/Actions/UploadFileAction.php +++ b/src/Domain/Files/Actions/UploadFileAction.php @@ -86,6 +86,7 @@ class UploadFileAction match (config('filesystems.default')) { 's3' => ($this->moveFileToExternalStorage)($fileName, $user->id), 'ftp', 'azure' => ($this->moveFileToFTPStorage)($fileName, $user->id), + default => null }; // Create new file diff --git a/src/Domain/Settings/Actions/TestFTPConnectionAction.php b/src/Domain/Settings/Actions/TestFTPConnectionAction.php new file mode 100644 index 00000000..c6a5ef1a --- /dev/null +++ b/src/Domain/Settings/Actions/TestFTPConnectionAction.php @@ -0,0 +1,43 @@ + [ + 'driver' => 'ftp', + 'host' => $credentials['host'], + 'username' => $credentials['user'], + 'password' => $credentials['password'], + ], + ]); + + // Try to get files + Storage::disk('ftp')->allFiles(); + + // Try to create folder + Storage::disk('ftp')->makeDirectory('ftp-test'); + + // Delete test folder + Storage::disk('ftp')->deleteDirectory('ftp-test'); + } catch (ErrorException | UnableToWriteFile | UnableToAuthenticate $error) { + abort( + response()->json([ + 'type' => 'ftp-connection-error', + 'title' => 'FTP Connection Error', + 'message' => $error->getMessage(), + ], 401) + ); + } + } +} \ No newline at end of file diff --git a/src/Domain/Settings/Actions/TestS3ConnectionAction.php b/src/Domain/Settings/Actions/TestS3ConnectionAction.php index 16108804..230f13dd 100644 --- a/src/Domain/Settings/Actions/TestS3ConnectionAction.php +++ b/src/Domain/Settings/Actions/TestS3ConnectionAction.php @@ -35,7 +35,7 @@ class TestS3ConnectionAction abort( response()->json([ 'type' => 's3-connection-error', - 'title' => 'S3 Connection Error', + 'title' => 'S3 Connection Error - Wrong Credentials or Not Permitted', 'message' => $error->getMessage(), ], 401) ); diff --git a/src/Domain/Settings/Actions/TestSMTPConnectionAction.php b/src/Domain/Settings/Actions/TestSMTPConnectionAction.php index c2441098..bd8b6186 100644 --- a/src/Domain/Settings/Actions/TestSMTPConnectionAction.php +++ b/src/Domain/Settings/Actions/TestSMTPConnectionAction.php @@ -39,7 +39,7 @@ class TestSMTPConnectionAction abort( response()->json([ 'type' => 'mailer-connection-error', - 'title' => 'Mail Connection Error', + 'title' => 'Mailer Connection Error - Wrong Credentials', 'message' => $error->getMessage(), ], 401) ); diff --git a/src/Domain/Settings/Controllers/StoreStorageCredentialsController.php b/src/Domain/Settings/Controllers/StoreStorageCredentialsController.php index 0468ce26..c996c3ba 100644 --- a/src/Domain/Settings/Controllers/StoreStorageCredentialsController.php +++ b/src/Domain/Settings/Controllers/StoreStorageCredentialsController.php @@ -2,9 +2,8 @@ namespace Domain\Settings\Controllers; use Artisan; +use Domain\Settings\Actions\TestFTPConnectionAction; use Illuminate\Http\Response; -use Aws\S3\Exception\S3Exception; -use League\Flysystem\UnableToWriteFile; use Domain\Settings\DTO\S3CredentialsData; use Domain\Settings\Actions\TestS3ConnectionAction; use Domain\Settings\Requests\StoreStorageCredentialsRequest; @@ -12,9 +11,9 @@ use Domain\Settings\Requests\StoreStorageCredentialsRequest; class StoreStorageCredentialsController { public function __construct( + private TestFTPConnectionAction $testFTPConnection, private TestS3ConnectionAction $testS3Connection, - ) { - } + ) {} /** * Set new email credentials to .env file @@ -24,20 +23,27 @@ class StoreStorageCredentialsController // Abort in demo mode abort_if(is_demo(), 204, 'Done.'); + // Get storage driver from request + $driver = match ($request->input('storage.driver')) { + 's3', 'storj', 'spaces', 'wasabi', 'backblaze', 'oss', 'other' => 's3', + 'local' => 'local', + 'ftp' => 'ftp', + }; + if (! app()->runningUnitTests()) { - // Test s3 credentials - if ($request->input('storage.driver') !== 'local') { - try { - // connect to the s3 - ($this->testS3Connection)(S3CredentialsData::fromRequest($request)); - } catch (S3Exception | UnableToWriteFile $error) { - return response([ - 'type' => 's3-connection-error', - 'title' => 'S3 Connection Error', - 'message' => $error->getMessage(), - ], 401); - } - } + + // Test driver connection + match ($driver) { + 's3' => ($this->testS3Connection)( + S3CredentialsData::fromRequest($request) + ), + 'ftp' => ($this->testFTPConnection)([ + 'host' => $request->input('storage.ftp.host'), + 'user' => $request->input('storage.ftp.user'), + 'password' => $request->input('storage.ftp.password'), + ]), + default => null + }; $drivers = [ 'local' => [ @@ -45,17 +51,20 @@ class StoreStorageCredentialsController ], 's3' => [ 'FILESYSTEM_DISK' => 's3', - 'S3_ACCESS_KEY_ID' => $request->input('storage.key') ?? null, - 'S3_SECRET_ACCESS_KEY' => $request->input('storage.secret') ?? null, - 'S3_DEFAULT_REGION' => $request->input('storage.region') ?? null, - 'S3_BUCKET' => $request->input('storage.bucket') ?? null, - 'S3_URL' => $request->input('storage.endpoint') ?? null, + 'S3_ACCESS_KEY_ID' => $request->input('storage.s3.key') ?? null, + 'S3_SECRET_ACCESS_KEY' => $request->input('storage.s3.secret') ?? null, + 'S3_DEFAULT_REGION' => $request->input('storage.s3.region') ?? null, + 'S3_BUCKET' => $request->input('storage.s3.bucket') ?? null, + 'S3_URL' => $request->input('storage.s3.endpoint') ?? null, + ], + 'ftp' => [ + 'FILESYSTEM_DISK' => 'ftp', + 'FTP_HOST' => $request->input('storage.ftp.host') ?? null, + 'FTP_USERNAME' => $request->input('storage.ftp.user') ?? null, + 'FTP_PASSWORD' => $request->input('storage.ftp.password') ?? null, ], ]; - // Get storage driver from request - $driver = 'local' === $request->input('storage.driver') ? 'local' : 's3'; - // Storage credentials for storage setEnvironmentValue($drivers[$driver]); diff --git a/src/Domain/Settings/DTO/S3CredentialsData.php b/src/Domain/Settings/DTO/S3CredentialsData.php index 320b1fb4..708a8c72 100644 --- a/src/Domain/Settings/DTO/S3CredentialsData.php +++ b/src/Domain/Settings/DTO/S3CredentialsData.php @@ -14,11 +14,11 @@ class S3CredentialsData extends DataTransferObject public static function fromRequest($request): self { return new self([ - 'key' => $request->input('storage.key'), - 'secret' => $request->input('storage.secret'), - 'region' => $request->input('storage.region'), - 'bucket' => $request->input('storage.bucket'), - 'endpoint' => $request->input('storage.endpoint'), + 'key' => $request->input('storage.s3.key'), + 'secret' => $request->input('storage.s3.secret'), + 'region' => $request->input('storage.s3.region'), + 'bucket' => $request->input('storage.s3.bucket'), + 'endpoint' => $request->input('storage.s3.endpoint'), ]); } } diff --git a/src/Domain/SetupWizard/Controllers/StoreEnvironmentSettingsController.php b/src/Domain/SetupWizard/Controllers/StoreEnvironmentSettingsController.php index 2fe4caef..78251f6c 100644 --- a/src/Domain/SetupWizard/Controllers/StoreEnvironmentSettingsController.php +++ b/src/Domain/SetupWizard/Controllers/StoreEnvironmentSettingsController.php @@ -2,6 +2,7 @@ namespace Domain\SetupWizard\Controllers; use Artisan; +use Domain\Settings\Actions\TestFTPConnectionAction; use Illuminate\Http\JsonResponse; use App\Http\Controllers\Controller; use Domain\Settings\DTO\S3CredentialsData; @@ -17,11 +18,11 @@ class StoreEnvironmentSettingsController extends Controller public function __construct( private TestS3ConnectionAction $testS3Connection, private TestSESConnectionAction $testSESConnection, + private TestFTPConnectionAction $testFTPConnection, private TestSMTPConnectionAction $testSMTPConnection, private TestMailgunConnectionAction $testMailgunConnection, private TestPostmarkConnectionAction $testPostmarkConnection, - ) { - } + ) {} /** * Store environment setup @@ -30,10 +31,25 @@ class StoreEnvironmentSettingsController extends Controller StoreEnvironmentSetupRequest $request, ): JsonResponse { if (! app()->runningUnitTests()) { - // Test s3 credentials - if ($request->input('storage.driver') !== 'local') { - ($this->testS3Connection)(S3CredentialsData::fromRequest($request)); - } + // Get storage driver from request + $StorageDriver = match ($request->input('storage.driver')) { + 's3', 'storj', 'spaces', 'wasabi', 'backblaze', 'oss', 'other' => 's3', + 'local' => 'local', + 'ftp' => 'ftp', + }; + + // Test driver connection + match ($StorageDriver) { + 's3' => ($this->testS3Connection)( + S3CredentialsData::fromRequest($request) + ), + 'ftp' => ($this->testFTPConnection)([ + 'host' => $request->input('storage.ftp.host'), + 'user' => $request->input('storage.ftp.user'), + 'password' => $request->input('storage.ftp.password'), + ]), + default => null + }; // Test email connection match ($request->input('mailDriver')) { @@ -93,11 +109,17 @@ class StoreEnvironmentSettingsController extends Controller ], 's3' => [ 'FILESYSTEM_DISK' => 's3', - 'S3_ACCESS_KEY_ID' => $request->input('storage.key') ?? null, - 'S3_SECRET_ACCESS_KEY' => $request->input('storage.secret') ?? null, - 'S3_DEFAULT_REGION' => $request->input('storage.region') ?? null, - 'S3_BUCKET' => $request->input('storage.bucket') ?? null, - 'S3_URL' => $request->input('storage.endpoint') ?? null, + 'S3_ACCESS_KEY_ID' => $request->input('storage.s3.key') ?? null, + 'S3_SECRET_ACCESS_KEY' => $request->input('storage.s3.secret') ?? null, + 'S3_DEFAULT_REGION' => $request->input('storage.s3.region') ?? null, + 'S3_BUCKET' => $request->input('storage.s3.bucket') ?? null, + 'S3_URL' => $request->input('storage.s3.endpoint') ?? null, + ], + 'ftp' => [ + 'FILESYSTEM_DISK' => 'ftp', + 'FTP_HOST' => $request->input('storage.ftp.host') ?? null, + 'FTP_USERNAME' => $request->input('storage.ftp.user') ?? null, + 'FTP_PASSWORD' => $request->input('storage.ftp.password') ?? null, ], ], 'mail' => [ @@ -155,15 +177,12 @@ class StoreEnvironmentSettingsController extends Controller ], ]; - // Get storage driver from request - $driver = 'local' === $request->input('storage.driver') ? 'local' : 's3'; - // Set other environment variables setEnvironmentValue(array_merge( $setup['broadcasting'][$request->input('broadcast.driver')], $setup['environment'][$request->input('environment')], $setup['mail'][$request->input('mailDriver')], - $setup['drivers'][$driver], + $setup['drivers'][$StorageDriver], $setup['others'], ));