mirror of
https://github.com/Bubka/2FAuth.git
synced 2025-02-02 11:39:19 +01:00
Move debug information to the admin section - Closes #303
This commit is contained in:
parent
ee4b21eab2
commit
21fa77f348
@ -34,27 +34,15 @@ public function infos(Request $request)
|
||||
$infos['common']['Operating system'] = PHP_OS;
|
||||
$infos['common']['interface'] = PHP_SAPI;
|
||||
// Auth & Security infos
|
||||
if (! is_null($request->user())) {
|
||||
$infos['common']['Auth guard'] = config('auth.defaults.guard');
|
||||
if ($infos['common']['Auth guard'] === 'reverse-proxy-guard') {
|
||||
$infos['common']['Auth proxy logout url'] = config('2fauth.config.proxyLogoutUrl');
|
||||
$infos['common']['Auth proxy header for user'] = config('auth.auth_proxy_headers.user');
|
||||
$infos['common']['Auth proxy header for email'] = config('auth.auth_proxy_headers.email');
|
||||
}
|
||||
$infos['common']['webauthn user verification'] = config('webauthn.user_verification');
|
||||
$infos['common']['Trusted proxies'] = config('2fauth.config.trustedProxies') ?: 'none';
|
||||
|
||||
// Admin settings
|
||||
if ($request->user()->isAdministrator()) {
|
||||
$infos['admin_settings']['useEncryption'] = Settings::get('useEncryption');
|
||||
$infos['admin_settings']['lastRadarScan'] = Carbon::parse(Settings::get('lastRadarScan'))->format('Y-m-d H:i:s');
|
||||
$infos['admin_settings']['checkForUpdate'] = Settings::get('checkForUpdate');
|
||||
}
|
||||
}
|
||||
// User info
|
||||
if ($request->user()) {
|
||||
$infos['user_preferences'] = $request->user()->preferences->toArray();
|
||||
$infos['common']['Auth guard'] = config('auth.defaults.guard');
|
||||
if ($infos['common']['Auth guard'] === 'reverse-proxy-guard') {
|
||||
$infos['common']['Auth proxy logout url'] = config('2fauth.config.proxyLogoutUrl');
|
||||
$infos['common']['Auth proxy header for user'] = config('auth.auth_proxy_headers.user');
|
||||
$infos['common']['Auth proxy header for email'] = config('auth.auth_proxy_headers.email');
|
||||
}
|
||||
$infos['common']['webauthn user verification'] = config('webauthn.user_verification');
|
||||
$infos['common']['Trusted proxies'] = config('2fauth.config.trustedProxies') ?: 'none';
|
||||
$infos['common']['lastRadarScan'] = Carbon::parse(Settings::get('lastRadarScan'))->format('Y-m-d H:i:s');
|
||||
|
||||
return response()->json($infos);
|
||||
}
|
||||
|
@ -1,35 +1,9 @@
|
||||
<script setup>
|
||||
import systemService from '@/services/systemService'
|
||||
import { UseColorMode } from '@vueuse/components'
|
||||
import CopyButton from '@/components/CopyButton.vue'
|
||||
|
||||
const $2fauth = inject('2fauth')
|
||||
const router = useRouter()
|
||||
|
||||
const returnTo = router.options.history.state.back
|
||||
const infos = ref()
|
||||
const listInfos = ref(null)
|
||||
const userPreferences = ref(false)
|
||||
const listUserPreferences = ref(null)
|
||||
const adminSettings = ref(false)
|
||||
const listAdminSettings = ref(null)
|
||||
|
||||
onMounted(() => {
|
||||
systemService.getSystemInfos({returnError: true}).then(response => {
|
||||
infos.value = response.data.common
|
||||
|
||||
if (response.data.admin_settings) {
|
||||
adminSettings.value = response.data.admin_settings
|
||||
}
|
||||
|
||||
if (response.data.user_preferences) {
|
||||
userPreferences.value = response.data.user_preferences
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
infos.value = null
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -87,36 +61,6 @@
|
||||
<li>{{ $t('commons.logos_by') }} <a href="https://2fa.directory/">2FA Directory</a> <a class="is-size-7" href="https://github.com/2factorauth/twofactorauth/blob/master/LICENSE.md">(MIT License)</a></li>
|
||||
</ul>
|
||||
</p>
|
||||
<h2 class="title is-5 has-text-grey-light">
|
||||
{{ $t('commons.environment') }}
|
||||
</h2>
|
||||
<div v-if="infos" class="about-debug box is-family-monospace is-size-7">
|
||||
<CopyButton id="btnCopyEnvVars" :token="listInfos?.innerText" />
|
||||
<ul ref="listInfos" id="listInfos">
|
||||
<li v-for="(value, key) in infos" :value="value" :key="key"><b>{{key}}</b>: {{value}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-else-if="infos === null" class="about-debug box is-family-monospace is-size-7 has-text-warning-dark">
|
||||
{{ $t('errors.error_during_data_fetching') }}
|
||||
</div>
|
||||
<h2 v-if="adminSettings" class="title is-5 has-text-grey-light">
|
||||
{{ $t('settings.admin_settings') }}
|
||||
</h2>
|
||||
<div v-if="adminSettings" class="about-debug box is-family-monospace is-size-7">
|
||||
<CopyButton id="btnCopyAdminSettings" :token="listAdminSettings?.innerText" />
|
||||
<ul ref="listAdminSettings" id="listAdminSettings">
|
||||
<li v-for="(value, setting) in adminSettings" :value="value" :key="setting"><b>{{setting}}</b>: {{value}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<h2 v-if="userPreferences" class="title is-5 has-text-grey-light">
|
||||
{{ $t('settings.user_preferences') }}
|
||||
</h2>
|
||||
<div v-if="userPreferences" class="about-debug box is-family-monospace is-size-7">
|
||||
<CopyButton id="btnCopyUserPreferences" :token="listUserPreferences?.innerText" />
|
||||
<ul ref="listUserPreferences" id="listUserPreferences">
|
||||
<li v-for="(value, preference) in userPreferences" :value="value" :key="preference"><b>{{preference}}</b>: {{value}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- footer -->
|
||||
<VueFooter :showButtons="true">
|
||||
<ButtonBackCloseCancel :returnTo="{ path: returnTo }" action="back" />
|
||||
|
@ -1,15 +1,20 @@
|
||||
<script setup>
|
||||
import AdminTabs from '@/layouts/AdminTabs.vue'
|
||||
import appSettingService from '@/services/appSettingService'
|
||||
import systemService from '@/services/systemService'
|
||||
import { useAppSettingsStore } from '@/stores/appSettings'
|
||||
import { useNotifyStore } from '@/stores/notify'
|
||||
import VersionChecker from '@/components/VersionChecker.vue'
|
||||
import CopyButton from '@/components/CopyButton.vue'
|
||||
|
||||
const $2fauth = inject('2fauth')
|
||||
const notify = useNotifyStore()
|
||||
const appSettings = useAppSettingsStore()
|
||||
const returnTo = useStorage($2fauth.prefix + 'returnTo', 'accounts')
|
||||
|
||||
const infos = ref()
|
||||
const listInfos = ref(null)
|
||||
|
||||
/**
|
||||
* Saves a setting on the backend
|
||||
* @param {string} preference
|
||||
@ -27,6 +32,15 @@
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
systemService.getSystemInfos({returnError: true}).then(response => {
|
||||
infos.value = response.data.common
|
||||
})
|
||||
.catch(() => {
|
||||
infos.value = null
|
||||
})
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -48,6 +62,18 @@
|
||||
<!-- disable SSO registration -->
|
||||
<FormCheckbox v-model="appSettings.enableSso" @update:model-value="val => saveSetting('enableSso', val)" fieldName="enableSso" label="admin.forms.enable_sso.label" help="admin.forms.enable_sso.help" />
|
||||
</form>
|
||||
<h4 class="title is-4 pt-5 has-text-grey-light">{{ $t('commons.environment') }}</h4>
|
||||
<div v-if="infos" class="about-debug box is-family-monospace is-size-7">
|
||||
<CopyButton id="btnCopyEnvVars" :token="listInfos?.innerText" />
|
||||
<ul ref="listInfos" id="listInfos">
|
||||
<li v-for="(value, preference) in infos" :value="value" :key="preference">
|
||||
<b>{{ preference }}</b>: <span class="has-text-grey">{{ value }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-else-if="infos === null" class="about-debug box is-family-monospace is-size-7 has-text-warning-dark">
|
||||
{{ $t('errors.error_during_data_fetching') }}
|
||||
</div>
|
||||
</FormWrapper>
|
||||
</div>
|
||||
<VueFooter :showButtons="true">
|
||||
|
@ -77,7 +77,14 @@
|
||||
return csrf_token();
|
||||
});
|
||||
|
||||
Route::get('infos', [SystemController::class, 'infos'])->name('system.infos');
|
||||
|
||||
/**
|
||||
* Routes protected by an authentication guard and restricted to administrators
|
||||
*/
|
||||
Route::group(['middleware' => ['behind-auth', 'admin']], function () {
|
||||
Route::get('infos', [SystemController::class, 'infos'])->name('system.infos');
|
||||
});
|
||||
|
||||
Route::get('latestRelease', [SystemController::class, 'latestRelease'])->name('system.latestRelease');
|
||||
|
||||
/**
|
||||
|
@ -15,12 +15,12 @@
|
||||
#[CoversClass(SystemController::class)]
|
||||
class SystemControllerTest extends FeatureTestCase
|
||||
{
|
||||
use WithoutMiddleware;
|
||||
//use WithoutMiddleware;
|
||||
|
||||
/**
|
||||
* @var \App\Models\User|\Illuminate\Contracts\Auth\Authenticatable
|
||||
*/
|
||||
protected $user;
|
||||
protected $user, $admin;
|
||||
|
||||
/**
|
||||
* @test
|
||||
@ -30,6 +30,26 @@ public function setUp() : void
|
||||
parent::setUp();
|
||||
|
||||
$this->user = User::factory()->create();
|
||||
$this->admin = User::factory()->administrator()->create();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function test_infos_returns_unauthorized()
|
||||
{
|
||||
$response = $this->json('GET', '/infos')
|
||||
->assertUnauthorized();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function test_infos_returns_forbidden()
|
||||
{
|
||||
$response = $this->actingAs($this->user, 'api-guard')
|
||||
->json('GET', '/infos')
|
||||
->assertForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -37,7 +57,8 @@ public function setUp() : void
|
||||
*/
|
||||
public function test_infos_returns_only_base_collection()
|
||||
{
|
||||
$response = $this->json('GET', '/infos')
|
||||
$response = $this->actingAs($this->admin, 'api-guard')
|
||||
->json('GET', '/infos')
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'common' => [
|
||||
@ -54,61 +75,10 @@ public function test_infos_returns_only_base_collection()
|
||||
'PHP version',
|
||||
'Operating system',
|
||||
'interface',
|
||||
],
|
||||
])
|
||||
->assertJsonMissing([
|
||||
'user_preferences',
|
||||
'admin_settings',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function test_infos_returns_user_preferences_when_signed_in()
|
||||
{
|
||||
$response = $this->actingAs($this->user, 'api-guard')
|
||||
->json('GET', '/infos')
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'user_preferences' => [
|
||||
'showOtpAsDot',
|
||||
'closeOtpOnCopy',
|
||||
'copyOtpOnDisplay',
|
||||
'useBasicQrcodeReader',
|
||||
'displayMode',
|
||||
'showAccountsIcons',
|
||||
'kickUserAfter',
|
||||
'activeGroup',
|
||||
'rememberActiveGroup',
|
||||
'defaultGroup',
|
||||
'defaultCaptureMode',
|
||||
'useDirectCapture',
|
||||
'useWebauthnOnly',
|
||||
'getOfficialIcons',
|
||||
'lang',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function test_infos_returns_admin_settings_when_signed_in_as_admin()
|
||||
{
|
||||
/**
|
||||
* @var \App\Models\User|\Illuminate\Contracts\Auth\Authenticatable
|
||||
*/
|
||||
$admin = User::factory()->administrator()->create();
|
||||
|
||||
$response = $this->actingAs($admin, 'api-guard')
|
||||
->json('GET', '/infos')
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'admin_settings' => [
|
||||
'useEncryption',
|
||||
'lastRadarScan',
|
||||
'checkForUpdate',
|
||||
'Auth guard',
|
||||
'webauthn user verification',
|
||||
'Trusted proxies',
|
||||
'lastRadarScan'
|
||||
],
|
||||
]);
|
||||
}
|
||||
@ -118,11 +88,12 @@ public function test_infos_returns_admin_settings_when_signed_in_as_admin()
|
||||
*/
|
||||
public function test_infos_returns_proxy_collection_when_signed_in_behind_proxy()
|
||||
{
|
||||
$response = $this->actingAs($this->user, 'reverse-proxy-guard')
|
||||
$response = $this->actingAs($this->admin, 'reverse-proxy-guard')
|
||||
->json('GET', '/infos')
|
||||
->assertOk()
|
||||
->assertJsonStructure([
|
||||
'common' => [
|
||||
'Auth proxy logout url',
|
||||
'Auth proxy header for user',
|
||||
'Auth proxy header for email',
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user