mirror of
https://github.com/Bubka/2FAuth.git
synced 2025-08-16 08:37:53 +02:00
Add a Clear cache feature - Closes #316
This commit is contained in:
@ -7,6 +7,7 @@ use App\Notifications\TestEmailSettingNotification;
|
|||||||
use App\Services\ReleaseRadarService;
|
use App\Services\ReleaseRadarService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
@ -62,7 +63,7 @@ class SystemController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a test email.
|
* Send a test email
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
@ -76,4 +77,38 @@ class SystemController extends Controller
|
|||||||
|
|
||||||
return response()->json(['message' => 'Ok']);
|
return response()->json(['message' => 'Ok']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all app caches and rebuild them
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function optimize(Request $request)
|
||||||
|
{
|
||||||
|
$configCode = Artisan::call('config:cache');
|
||||||
|
$routeCode = Artisan::call('route:cache');
|
||||||
|
$eventCode = Artisan::call('event:cache');
|
||||||
|
$viewCode = Artisan::call('view:cache');
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'config-exit-code' => $configCode,
|
||||||
|
'route-exit-code' => $routeCode,
|
||||||
|
'event-exit-code' => $eventCode,
|
||||||
|
'view-exit-code' => $viewCode,
|
||||||
|
], 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears application cache
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function clear(Request $request)
|
||||||
|
{
|
||||||
|
$exitCode = Artisan::call('optimize:clear');
|
||||||
|
|
||||||
|
return response()->json(['exit-code' => $exitCode], 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
24
resources/js/services/systemService.js
vendored
24
resources/js/services/systemService.js
vendored
@ -8,7 +8,7 @@ export default {
|
|||||||
* @returns Promise
|
* @returns Promise
|
||||||
*/
|
*/
|
||||||
getSystemInfos(config = {}) {
|
getSystemInfos(config = {}) {
|
||||||
return webClient.get('infos', { ...config })
|
return webClient.get('system/infos', { ...config })
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,7 +16,7 @@ export default {
|
|||||||
* @returns Promise
|
* @returns Promise
|
||||||
*/
|
*/
|
||||||
getLastRelease(config = {}) {
|
getLastRelease(config = {}) {
|
||||||
return webClient.get('latestRelease', { ...config })
|
return webClient.get('system/latestRelease', { ...config })
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,7 +24,23 @@ export default {
|
|||||||
* @returns Promise
|
* @returns Promise
|
||||||
*/
|
*/
|
||||||
sendTestEmail(config = {}) {
|
sendTestEmail(config = {}) {
|
||||||
return webClient.post('testEmail', { ...config })
|
return webClient.post('system/test-email', { ...config })
|
||||||
}
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns Promise
|
||||||
|
*/
|
||||||
|
clearCache(config = {}) {
|
||||||
|
return webClient.get('system/clear-cache', { ...config })
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns Promise
|
||||||
|
*/
|
||||||
|
optimize(config = {}) {
|
||||||
|
return webClient.get('system/optimize', { ...config })
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
@ -17,6 +17,7 @@
|
|||||||
const infos = ref()
|
const infos = ref()
|
||||||
const listInfos = ref(null)
|
const listInfos = ref(null)
|
||||||
const isSendingTestEmail = ref(false)
|
const isSendingTestEmail = ref(false)
|
||||||
|
const isClearingCache = ref(false)
|
||||||
const fieldErrors = ref({
|
const fieldErrors = ref({
|
||||||
restrictList: null,
|
restrictList: null,
|
||||||
restrictRule: null,
|
restrictRule: null,
|
||||||
@ -91,6 +92,20 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clears app cache
|
||||||
|
*/
|
||||||
|
function clearCache() {
|
||||||
|
isClearingCache.value = true;
|
||||||
|
|
||||||
|
systemService.clearCache().then(response => {
|
||||||
|
useNotifyStore().success({ type: 'is-success', text: trans('admin.cache_cleared') })
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
isClearingCache.value = false;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
onBeforeRouteLeave((to) => {
|
onBeforeRouteLeave((to) => {
|
||||||
if (! to.name.startsWith('admin.')) {
|
if (! to.name.startsWith('admin.')) {
|
||||||
notify.clear()
|
notify.clear()
|
||||||
@ -134,6 +149,7 @@
|
|||||||
<!-- Check for update -->
|
<!-- Check for update -->
|
||||||
<FormCheckbox v-model="_settings.checkForUpdate" @update:model-value="val => saveSetting('checkForUpdate', val)" fieldName="checkForUpdate" label="commons.check_for_update" help="commons.check_for_update_help" />
|
<FormCheckbox v-model="_settings.checkForUpdate" @update:model-value="val => saveSetting('checkForUpdate', val)" fieldName="checkForUpdate" label="commons.check_for_update" help="commons.check_for_update_help" />
|
||||||
<VersionChecker />
|
<VersionChecker />
|
||||||
|
<!-- email config test -->
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<!-- <h5 class="title is-5">{{ $t('settings.security') }}</h5> -->
|
<!-- <h5 class="title is-5">{{ $t('settings.security') }}</h5> -->
|
||||||
<label class="label" v-html="$t('admin.forms.test_email.label')" />
|
<label class="label" v-html="$t('admin.forms.test_email.label')" />
|
||||||
@ -149,7 +165,8 @@
|
|||||||
<span>{{ $t('commons.send') }}</span>
|
<span>{{ $t('commons.send') }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4 class="title is-4 pt-4 has-text-grey-light">{{ $t('settings.security') }}</h4>
|
<h4 class="title is-4 pt-4 has-text-grey-light">{{ $t('settings.security') }}</h4>
|
||||||
<!-- protect db -->
|
<!-- protect db -->
|
||||||
<FormCheckbox v-model="_settings.useEncryption" @update:model-value="val => saveSetting('useEncryption', val)" fieldName="useEncryption" label="admin.forms.use_encryption.label" help="admin.forms.use_encryption.help" />
|
<FormCheckbox v-model="_settings.useEncryption" @update:model-value="val => saveSetting('useEncryption', val)" fieldName="useEncryption" label="admin.forms.use_encryption.label" help="admin.forms.use_encryption.help" />
|
||||||
@ -165,7 +182,25 @@
|
|||||||
<!-- disable SSO registration -->
|
<!-- disable SSO registration -->
|
||||||
<FormCheckbox v-model="_settings.enableSso" @update:model-value="val => saveSetting('enableSso', val)" fieldName="enableSso" label="admin.forms.enable_sso.label" help="admin.forms.enable_sso.help" />
|
<FormCheckbox v-model="_settings.enableSso" @update:model-value="val => saveSetting('enableSso', val)" fieldName="enableSso" label="admin.forms.enable_sso.label" help="admin.forms.enable_sso.help" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<h4 class="title is-4 pt-5 has-text-grey-light">{{ $t('commons.environment') }}</h4>
|
<h4 class="title is-4 pt-5 has-text-grey-light">{{ $t('commons.environment') }}</h4>
|
||||||
|
<!-- cache management -->
|
||||||
|
<div class="field">
|
||||||
|
<!-- <h5 class="title is-5">{{ $t('settings.security') }}</h5> -->
|
||||||
|
<label class="label" v-html="$t('admin.forms.cache_management.label')" />
|
||||||
|
<p class="help" v-html="$t('admin.forms.cache_management.help')" />
|
||||||
|
</div>
|
||||||
|
<div class="field mb-5 is-grouped">
|
||||||
|
<p class="control">
|
||||||
|
<button type="button" :class="isClearingCache ? 'is-loading' : ''" class="button is-link is-rounded is-small" @click="clearCache">
|
||||||
|
{{ $t('commons.clear') }}
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<!-- env vars -->
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" v-html="$t('admin.variables')" />
|
||||||
|
</div>
|
||||||
<div v-if="infos" class="about-debug box is-family-monospace is-size-7">
|
<div v-if="infos" class="about-debug box is-family-monospace is-size-7">
|
||||||
<CopyButton id="btnCopyEnvVars" :token="listInfos?.innerText" />
|
<CopyButton id="btnCopyEnvVars" :token="listInfos?.innerText" />
|
||||||
<ul ref="listInfos" id="listInfos">
|
<ul ref="listInfos" id="listInfos">
|
||||||
|
@ -63,6 +63,9 @@ return [
|
|||||||
'user_role_updated' => 'User role updated',
|
'user_role_updated' => 'User role updated',
|
||||||
'pats_succesfully_revoked' => 'User\'s PATs successfully revoked',
|
'pats_succesfully_revoked' => 'User\'s PATs successfully revoked',
|
||||||
'security_devices_succesfully_revoked' => 'User\'s security devices successfully revoked',
|
'security_devices_succesfully_revoked' => 'User\'s security devices successfully revoked',
|
||||||
|
'variables' => 'Variables',
|
||||||
|
'cache_cleared' => 'Cache cleared',
|
||||||
|
'cache_optimized' => 'Cache optimized',
|
||||||
'check_now' => 'Check now',
|
'check_now' => 'Check now',
|
||||||
'view_on_github' => 'View on Github',
|
'view_on_github' => 'View on Github',
|
||||||
'x_is_available' => ':version is available',
|
'x_is_available' => ':version is available',
|
||||||
@ -99,6 +102,10 @@ return [
|
|||||||
'label' => 'Email configuration test',
|
'label' => 'Email configuration test',
|
||||||
'help' => 'Send a test email to control your instance\'s email configuration. It is important to have a working configuration, otherwise users will not be able to request a reset password.',
|
'help' => 'Send a test email to control your instance\'s email configuration. It is important to have a working configuration, otherwise users will not be able to request a reset password.',
|
||||||
'email_will_be_send_to_x' => 'The email will be send to <span class="is-family-code has-text-info">:email</span>',
|
'email_will_be_send_to_x' => 'The email will be send to <span class="is-family-code has-text-info">:email</span>',
|
||||||
|
],
|
||||||
|
'cache_management' => [
|
||||||
|
'label' => 'Cache management',
|
||||||
|
'help' => 'Sometimes cache needs to be cleared, for instance after a change to environment variables or an update. You can do it from here.',
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -81,4 +81,5 @@ return [
|
|||||||
'information' => 'Information',
|
'information' => 'Information',
|
||||||
'permissions' => 'Permissions',
|
'permissions' => 'Permissions',
|
||||||
'send' => 'Send',
|
'send' => 'Send',
|
||||||
|
'optimize' => 'Optimize',
|
||||||
];
|
];
|
||||||
|
@ -73,20 +73,21 @@ Route::group(['middleware' => ['behind-auth', 'rejectIfReverseProxy']], function
|
|||||||
Route::delete('webauthn/credentials/{credential}', [WebAuthnManageController::class, 'delete'])->name('webauthn.credentials.delete');
|
Route::delete('webauthn/credentials/{credential}', [WebAuthnManageController::class, 'delete'])->name('webauthn.credentials.delete');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('refresh-csrf', function () {
|
|
||||||
return csrf_token();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Routes protected by an authentication guard and restricted to administrators
|
* Routes protected by an authentication guard and restricted to administrators
|
||||||
*/
|
*/
|
||||||
Route::group(['middleware' => ['behind-auth', 'admin']], function () {
|
Route::group(['middleware' => ['behind-auth', 'admin']], function () {
|
||||||
Route::get('infos', [SystemController::class, 'infos'])->name('system.infos');
|
Route::get('system/infos', [SystemController::class, 'infos'])->name('system.infos');
|
||||||
Route::post('testEmail', [SystemController::class, 'testEmail'])->name('system.testEmail');
|
Route::post('system/test-email', [SystemController::class, 'testEmail'])->name('system.testEmail');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('latestRelease', [SystemController::class, 'latestRelease'])->name('system.latestRelease');
|
Route::get('system/optimize', [SystemController::class, 'optimize'])->name('system.optimize');
|
||||||
|
Route::get('system/clear-cache', [SystemController::class, 'clear'])->name('system.clear');
|
||||||
|
Route::get('system/latestRelease', [SystemController::class, 'latestRelease'])->name('system.latestRelease');
|
||||||
|
|
||||||
|
Route::get('refresh-csrf', function () {
|
||||||
|
return csrf_token();
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route for the main landing view
|
* Route for the main landing view
|
||||||
|
@ -37,7 +37,7 @@ class SystemControllerTest extends FeatureTestCase
|
|||||||
*/
|
*/
|
||||||
public function test_infos_returns_unauthorized()
|
public function test_infos_returns_unauthorized()
|
||||||
{
|
{
|
||||||
$response = $this->json('GET', '/infos')
|
$response = $this->json('GET', '/system/infos')
|
||||||
->assertUnauthorized();
|
->assertUnauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ class SystemControllerTest extends FeatureTestCase
|
|||||||
public function test_infos_returns_forbidden()
|
public function test_infos_returns_forbidden()
|
||||||
{
|
{
|
||||||
$response = $this->actingAs($this->user, 'api-guard')
|
$response = $this->actingAs($this->user, 'api-guard')
|
||||||
->json('GET', '/infos')
|
->json('GET', '/system/infos')
|
||||||
->assertForbidden();
|
->assertForbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ class SystemControllerTest extends FeatureTestCase
|
|||||||
public function test_infos_returns_only_base_collection()
|
public function test_infos_returns_only_base_collection()
|
||||||
{
|
{
|
||||||
$response = $this->actingAs($this->admin, 'api-guard')
|
$response = $this->actingAs($this->admin, 'api-guard')
|
||||||
->json('GET', '/infos')
|
->json('GET', '/system/infos')
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'common' => [
|
'common' => [
|
||||||
@ -88,7 +88,7 @@ class SystemControllerTest extends FeatureTestCase
|
|||||||
public function test_infos_returns_proxy_collection_when_signed_in_behind_proxy()
|
public function test_infos_returns_proxy_collection_when_signed_in_behind_proxy()
|
||||||
{
|
{
|
||||||
$response = $this->actingAs($this->admin, 'reverse-proxy-guard')
|
$response = $this->actingAs($this->admin, 'reverse-proxy-guard')
|
||||||
->json('GET', '/infos')
|
->json('GET', '/system/infos')
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJsonStructure([
|
->assertJsonStructure([
|
||||||
'common' => [
|
'common' => [
|
||||||
@ -109,7 +109,7 @@ class SystemControllerTest extends FeatureTestCase
|
|||||||
->once()
|
->once()
|
||||||
->andReturn('new_release');
|
->andReturn('new_release');
|
||||||
|
|
||||||
$response = $this->json('GET', '/latestRelease')
|
$response = $this->json('GET', '/system/latestRelease')
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertJson([
|
->assertJson([
|
||||||
'newRelease' => 'new_release',
|
'newRelease' => 'new_release',
|
||||||
@ -124,7 +124,7 @@ class SystemControllerTest extends FeatureTestCase
|
|||||||
Notification::fake();
|
Notification::fake();
|
||||||
|
|
||||||
$response = $this->actingAs($this->admin, 'web-guard')
|
$response = $this->actingAs($this->admin, 'web-guard')
|
||||||
->json('POST', '/testEmail', []);
|
->json('POST', '/system/test-email', []);
|
||||||
|
|
||||||
$response->assertStatus(200);
|
$response->assertStatus(200);
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ class SystemControllerTest extends FeatureTestCase
|
|||||||
*/
|
*/
|
||||||
public function test_testEmail_returns_unauthorized()
|
public function test_testEmail_returns_unauthorized()
|
||||||
{
|
{
|
||||||
$response = $this->json('GET', '/infos')
|
$response = $this->json('GET', '/system/infos')
|
||||||
->assertUnauthorized();
|
->assertUnauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +146,27 @@ class SystemControllerTest extends FeatureTestCase
|
|||||||
public function test_testEmail_returns_forbidden()
|
public function test_testEmail_returns_forbidden()
|
||||||
{
|
{
|
||||||
$response = $this->actingAs($this->user, 'api-guard')
|
$response = $this->actingAs($this->user, 'api-guard')
|
||||||
->json('GET', '/infos')
|
->json('GET', '/system/infos')
|
||||||
->assertForbidden();
|
->assertForbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function test_clearCache_returns_success()
|
||||||
|
{
|
||||||
|
$response = $this->json('GET', '/system/clear-cache');
|
||||||
|
|
||||||
|
$response->assertStatus(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function test_optimize_returns_success()
|
||||||
|
{
|
||||||
|
$response = $this->json('GET', '/system/optimize');
|
||||||
|
|
||||||
|
$response->assertStatus(200);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user