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 @@
-
@@ -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'],
));