diff --git a/changelog.md b/changelog.md index 58b0abb2..ae423eea 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,7 @@ #### Release date: 1. April 2022 - Improved email setup in administration settings and setup wizard - Ability to set custom s3 compatible service in administration settings and setup wizard +- Test s3 connection before set up in administration settings and setup wizard ## Version 2.0.0 - 2.0.10 #### Release date: 31. March 2022 diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 177235ec..f8815be0 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -42,7 +42,7 @@ "/chunks/app-settings.js": "/chunks/app-settings.js?id=55da23af2b076069", "/chunks/app-appearance.js": "/chunks/app-appearance.js?id=a694a01f3641712c", "/chunks/app-index.js": "/chunks/app-index.js?id=efdbfa062749ca00", - "/chunks/app-environment.js": "/chunks/app-environment.js?id=1f5458233a20b263", + "/chunks/app-environment.js": "/chunks/app-environment.js?id=9be9c6b1a20b00cb", "/chunks/app-others.js": "/chunks/app-others.js?id=16dc948aa2205189", "/chunks/app-sign-in-out.js": "/chunks/app-sign-in-out.js?id=1cfffc99465b9a7a", "/chunks/app-adsense.js": "/chunks/app-adsense.js?id=a5dc9e715f8561bd", @@ -72,5 +72,5 @@ "/chunks/invitation.js": "/chunks/invitation.js?id=9ed8456c9d6d5ce1", "/css/tailwind.css": "/css/tailwind.css", "/css/app.css": "/css/app.css", - "/chunks/environment.js": "/chunks/environment.js?id=cef6ee74e56cb0d0" + "/chunks/environment.js": "/chunks/environment.js?id=520e1f9745f40ada" } diff --git a/resources/js/components/FilesView/Alert.vue b/resources/js/components/FilesView/Alert.vue index abbb8603..8b9c36dd 100644 --- a/resources/js/components/FilesView/Alert.vue +++ b/resources/js/components/FilesView/Alert.vue @@ -62,7 +62,7 @@ export default { this.title = args.title || undefined this.message = args.message || undefined - this.button = this.$t('alerts.error_confirm') + this.button = this.$te('alerts.error_confirm') ? this.$t('alerts.error_confirm') : 'That’s horrible!' this.emoji = '😢😢😢' this.buttonStyle = 'danger' diff --git a/resources/js/views/Admin/AppSettings/AppSettingsTabs/Environment.vue b/resources/js/views/Admin/AppSettings/AppSettingsTabs/Environment.vue index b11f85d0..20cbe2de 100644 --- a/resources/js/views/Admin/AppSettings/AppSettingsTabs/Environment.vue +++ b/resources/js/views/Admin/AppSettings/AppSettingsTabs/Environment.vue @@ -932,20 +932,6 @@ export default { storage: this.storage }) .then(() => { - events.$emit('toaster', { - type: 'success', - message: this.$t('storage_driver_updated'), - }) - }) - .catch(() => { - events.$emit('toaster', { - type: 'danger', - message: this.$t('popup_error.title'), - }) - }) - .finally(() => { - this.isSendingStorageForm = false - this.storage = { driver: undefined, key: undefined, @@ -954,6 +940,28 @@ export default { region: undefined, bucket: undefined, } + + events.$emit('toaster', { + type: 'success', + message: this.$t('storage_driver_updated'), + }) + }) + .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 { + events.$emit('toaster', { + type: 'danger', + message: this.$t('popup_error.title'), + }) + } + }) + .finally(() => { + this.isSendingStorageForm = false }) }, async emailSetupSubmit() { diff --git a/resources/js/views/SetupWizard/EnvironmentSetup.vue b/resources/js/views/SetupWizard/EnvironmentSetup.vue index c855a6bc..d447d5f6 100644 --- a/resources/js/views/SetupWizard/EnvironmentSetup.vue +++ b/resources/js/views/SetupWizard/EnvironmentSetup.vue @@ -544,6 +544,7 @@ import Headline from '../Auth/Headline' import { required } from 'vee-validate/dist/rules' import axios from 'axios' import { mapGetters } from 'vuex' +import {events} from "../../bus"; export default { name: 'EnvironmentSetup', @@ -982,7 +983,14 @@ export default { this.$router.push({ name: 'AppSetup' }) }) .catch((error) => { - this.isError = true + 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 { + this.isError = true + } }) .finally(() => { this.isLoading = false diff --git a/src/Domain/Settings/Actions/TestS3ConnectionAction.php b/src/Domain/Settings/Actions/TestS3ConnectionAction.php new file mode 100644 index 00000000..c6953edc --- /dev/null +++ b/src/Domain/Settings/Actions/TestS3ConnectionAction.php @@ -0,0 +1,32 @@ + [ + 'driver' => 's3', + 'key' => $credentials->key, + 'secret' => $credentials->secret, + 'region' => $credentials->region, + 'bucket' => $credentials->bucket, + 'endpoint' => $credentials->endpoint, + ], + ]); + + // Try to get files + Storage::disk('s3')->allFiles(); + + // Try to create folder + Storage::disk('s3')->makeDirectory('s3-test'); + + // Delete test folder + Storage::disk('s3')->deleteDirectory('s3-test'); + } +} diff --git a/src/Domain/Settings/Controllers/StoreStorageCredentialsController.php b/src/Domain/Settings/Controllers/StoreStorageCredentialsController.php index 09800749..044aa6ad 100644 --- a/src/Domain/Settings/Controllers/StoreStorageCredentialsController.php +++ b/src/Domain/Settings/Controllers/StoreStorageCredentialsController.php @@ -3,10 +3,19 @@ namespace Domain\Settings\Controllers; use Artisan; 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; class StoreStorageCredentialsController { + public function __construct( + private TestS3ConnectionAction $testS3Connection, + ) { + } + /** * Set new email credentials to .env file */ @@ -15,6 +24,20 @@ class StoreStorageCredentialsController // Abort in demo mode abort_if(is_demo(), 204, 'Done.'); + // 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); + } + } + if (! app()->runningUnitTests()) { $drivers = [ 'local' => [ @@ -34,10 +57,9 @@ class StoreStorageCredentialsController $driver = 'local' === $request->input('storage.driver') ? 'local' : 's3'; // Storage credentials for storage - setEnvironmentValue( - $drivers[$driver] - ); + setEnvironmentValue($drivers[$driver]); + // Cache the config Artisan::call('config:cache'); } diff --git a/src/Domain/Settings/DTO/S3CredentialsData.php b/src/Domain/Settings/DTO/S3CredentialsData.php new file mode 100644 index 00000000..320b1fb4 --- /dev/null +++ b/src/Domain/Settings/DTO/S3CredentialsData.php @@ -0,0 +1,24 @@ + $request->input('storage.key'), + 'secret' => $request->input('storage.secret'), + 'region' => $request->input('storage.region'), + 'bucket' => $request->input('storage.bucket'), + 'endpoint' => $request->input('storage.endpoint'), + ]); + } +} diff --git a/src/Domain/SetupWizard/Controllers/StoreEnvironmentSettingsController.php b/src/Domain/SetupWizard/Controllers/StoreEnvironmentSettingsController.php index be0a791a..47a2d5d0 100644 --- a/src/Domain/SetupWizard/Controllers/StoreEnvironmentSettingsController.php +++ b/src/Domain/SetupWizard/Controllers/StoreEnvironmentSettingsController.php @@ -3,11 +3,20 @@ namespace Domain\SetupWizard\Controllers; use Artisan; use Illuminate\Http\Response; +use Aws\S3\Exception\S3Exception; use App\Http\Controllers\Controller; +use League\Flysystem\UnableToWriteFile; +use Domain\Settings\DTO\S3CredentialsData; +use Domain\Settings\Actions\TestS3ConnectionAction; use Domain\SetupWizard\Requests\StoreEnvironmentSetupRequest; class StoreEnvironmentSettingsController extends Controller { + public function __construct( + private TestS3ConnectionAction $testS3Connection, + ) { + } + /** * Store environment setup */ @@ -15,6 +24,20 @@ class StoreEnvironmentSettingsController extends Controller StoreEnvironmentSetupRequest $request, ): Response { 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); + } + } + $setup = [ 'broadcasting' => [ 'pusher' => [