diff --git a/app/Api/v1/Controllers/SettingController.php b/app/Api/v1/Controllers/SettingController.php
index f6b435bd..a0c8b9dc 100644
--- a/app/Api/v1/Controllers/SettingController.php
+++ b/app/Api/v1/Controllers/SettingController.php
@@ -6,6 +6,7 @@ use App\Api\v1\Requests\SettingStoreRequest;
use App\Api\v1\Requests\SettingUpdateRequest;
use App\Facades\Settings;
use App\Http\Controllers\Controller;
+use Illuminate\Validation\ValidationException;
class SettingController extends Controller
{
@@ -95,8 +96,18 @@ class SettingController extends Controller
abort(404);
}
- $appSettings = config('2fauth.settings');
- if (array_key_exists($settingName, $appSettings)) {
+ $defaultAppSettings = config('2fauth.settings');
+
+ // When deleting a setting, it may be an original or an additional one:
+ // - Additional settings are created by administrators to extend 2FAuth, they are not registered in the laravel config object.
+ // They are not nullable so empty string is not allowed.They only exist in the Options table, so it is possible to delete them.
+ // - Original settings are part of 2FAuth, they are registered in the laravel config object with their default value.
+ // When set by an admin, their custom value is stored in the Options table too. Deleting a custom value in the Options table from here
+ // won't delete the setting at all, so we reject all requests that ask for.
+ // But there is an exception with the restrictRule and restrictList settings:
+ // Unlike other settings, these two have to support empty strings. Because the Options table does not allow empty strings,
+ // the only way to set them like so is to restore their original value, an empty string.
+ if (array_key_exists($settingName, $defaultAppSettings) && $defaultAppSettings[$settingName] !== '') {
return response()->json(
['message' => 'bad request',
'reason' => [__('errors.delete_user_setting_only')],
diff --git a/config/2fauth.php b/config/2fauth.php
index db25deb4..87e40472 100644
--- a/config/2fauth.php
+++ b/config/2fauth.php
@@ -89,6 +89,8 @@ return [
'disableRegistration' => false,
'enableSso' => true,
'restrictRegistration' => false,
+ 'restrictList' => '',
+ 'restrictRule' => '',
'keepSsoRegistrationEnabled' => false,
],
diff --git a/resources/js/composables/appSettingsUpdater.js b/resources/js/composables/appSettingsUpdater.js
new file mode 100644
index 00000000..66381197
--- /dev/null
+++ b/resources/js/composables/appSettingsUpdater.js
@@ -0,0 +1,32 @@
+import appSettingService from '@/services/appSettingService'
+import { useAppSettingsStore } from '@/stores/appSettings'
+import { useNotifyStore } from '@/stores/notify'
+
+/**
+ * Saves a setting on the backend
+ * @param {string} preference
+ * @param {any} value
+ */
+export async function useAppSettingsUpdater(setting, value, returnValidationError = false) {
+
+ // const appSettings = useAppSettingsStore()
+ let data = null
+ let error = null
+
+ await appSettingService.update(setting, value, { returnError: true })
+ .then(response => {
+ // appSettings[setting] = value
+ data = value
+ useNotifyStore().success({ type: 'is-success', text: trans('settings.forms.setting_saved') })
+ })
+ .catch(err => {
+ if( returnValidationError && err.response.status === 422 ) {
+ error = err
+ }
+ else {
+ useNotifyStore().error(err);
+ }
+ })
+
+ return { data, error }
+}
\ No newline at end of file
diff --git a/resources/js/services/appSettingService.js b/resources/js/services/appSettingService.js
index e7743a98..03dcea5c 100644
--- a/resources/js/services/appSettingService.js
+++ b/resources/js/services/appSettingService.js
@@ -7,7 +7,7 @@ export default {
*
* @returns
*/
- get(config = {}) {
+ getAll(config = {}) {
return apiClient.get('/settings', { ...config })
},
@@ -15,8 +15,8 @@ export default {
*
* @returns
*/
- update(name, value) {
- return apiClient.put('/settings/' + name, { value: value })
+ update(name, value, config = {}) {
+ return apiClient.put('/settings/' + name, { value: value }, { ...config })
},
/**
diff --git a/resources/js/stores/appSettings.js b/resources/js/stores/appSettings.js
index 351464f8..f553f6c9 100644
--- a/resources/js/stores/appSettings.js
+++ b/resources/js/stores/appSettings.js
@@ -1,4 +1,6 @@
+import appSettingService from '@/services/appSettingService'
import { defineStore } from 'pinia'
+import { useNotifyStore } from '@/stores/notify'
export const useAppSettingsStore = defineStore({
id: 'appSettings',
@@ -8,6 +10,20 @@ export const useAppSettingsStore = defineStore({
},
actions: {
-
+
+ /**
+ * Fetches the appSetting collection from the backend
+ */
+ async fetch() {
+ appSettingService.getAll({ returnError: true })
+ .then(response => {
+ response.data.forEach(setting => {
+ this[setting.key] = setting.value
+ })
+ })
+ .catch(error => {
+ useNotifyStore().alert({ text: trans('errors.data_cannot_be_refreshed_from_server') })
+ })
+ },
},
})
diff --git a/resources/js/views/admin/AppSetup.vue b/resources/js/views/admin/AppSetup.vue
index a8d49671..8635f02c 100644
--- a/resources/js/views/admin/AppSetup.vue
+++ b/resources/js/views/admin/AppSetup.vue
@@ -1,7 +1,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/lang/en/admin.php b/resources/lang/en/admin.php
index 762175ec..9cad331d 100644
--- a/resources/lang/en/admin.php
+++ b/resources/lang/en/admin.php
@@ -15,6 +15,7 @@ return [
'admin' => 'Admin',
'app_setup' => 'App setup',
+ 'auth' => 'Auth',
'registrations' => 'Registrations',
'users' => 'Users',
'users_legend' => 'Manage users registered on your instance or create new ones.',
@@ -83,6 +84,7 @@ return [
'show_one_year_log' => 'Show entries from the last year',
'sort_by_date_asc' => 'Show least recent first',
'sort_by_date_desc' => 'Show most recent first',
+ 'single_sign_on' => 'Single Sign-On (SSO)',
'forms' => [
'use_encryption' => [
'label' => 'Protect sensitive data',
@@ -105,7 +107,7 @@ return [
'help' => 'Prevent new user registration. Unless overridden (see below), this affects SSO as well, so new users won\'t be able to sign in via SSO',
],
'enable_sso' => [
- 'label' => 'Enable Single Sign-On (SSO)',
+ 'label' => 'Enable SSO',
'help' => 'Allow visitors to authenticate using an external ID via the Single Sign-On scheme',
],
'keep_sso_registration_enabled' => [