mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-05-13 08:45:01 +00:00
ability to download log from admin
This commit is contained in:
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+2
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* vee-validate v3.4.14
|
||||
* (c) 2021 Abdelrahman Awad
|
||||
* @license MIT
|
||||
*/
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[4738],{3187:(t,e,a)=>{a.d(e,{Z:()=>r});const n={name:"CardNavigation",props:["pages"],computed:{routeName:function(){return this.$route.name}},data:function(){return{fixedNav:!1}},created:function(){var t=this;window.addEventListener("scroll",(function(){var e=document.getElementById("card-navigation");t.fixedNav=e.getBoundingClientRect().top<0}))}};const r=(0,a(1900).Z)(n,(function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"mb-7",staticStyle:{height:"62px"},attrs:{id:"card-navigation"}},[a("div",{class:{"fixed top-0 left-0 right-0 z-10 rounded-none bg-white bg-opacity-50 px-6 backdrop-blur-lg backdrop-filter dark:bg-dark-foreground":t.fixedNav}},[a("div",{staticClass:"overflow-x-auto whitespace-nowrap"},t._l(t.pages,(function(e,n){return a("router-link",{key:n,staticClass:"border-bottom-theme inline-block border-b-2 border-transparent px-4 py-5 text-sm font-bold",class:{"text-theme":t.routeName===e.route,"text-gray-600 dark:text-gray-100":t.routeName!==e.route},attrs:{to:{name:e.route},replace:""}},[t._v("\n "+t._s(e.title)+"\n ")])})),1)])])}),[],!1,null,null,null).exports},6534:(t,e,a)=>{a.r(e),a.d(e,{default:()=>r});const n={name:"AppSettings",components:{CardNavigation:a(3187).Z},data:function(){return{pages:[{title:this.$t("admin_settings.tabs.others"),route:"AppOthers"},{title:this.$t("Login & Registration"),route:"AppSignInUp"},{title:this.$t("admin_settings.tabs.appearance"),route:"AppAppearance"},{title:this.$t("Adsense"),route:"AppAdsense"},{title:this.$t("Homepage"),route:"AppIndex"},{title:this.$t("admin_settings.tabs.email"),route:"AppEmail"},{title:this.$t("Server"),route:"AppServer"}]}},mounted:function(){this.$router.push({name:"AppOthers"})}};const r=(0,a(1900).Z)(n,(function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("div",{staticClass:"card z-10 shadow-card",staticStyle:{"padding-bottom":"0","padding-top":"0"}},[a("CardNavigation",{staticClass:"-mx-1",attrs:{pages:t.pages}})],1),t._v(" "),a("router-view")],1)}),[],!1,null,null,null).exports}}]);
|
||||
"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[4738],{3187:(t,e,n)=>{n.d(e,{Z:()=>r});const a={name:"CardNavigation",props:["pages"],computed:{routeName:function(){return this.$route.name}},data:function(){return{fixedNav:!1}},created:function(){var t=this;window.addEventListener("scroll",(function(){var e=document.getElementById("card-navigation");t.fixedNav=e.getBoundingClientRect().top<0}))}};const r=(0,n(1900).Z)(a,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"mb-7",staticStyle:{height:"62px"},attrs:{id:"card-navigation"}},[n("div",{class:{"fixed top-0 left-0 right-0 z-10 rounded-none bg-white bg-opacity-50 px-6 backdrop-blur-lg backdrop-filter dark:bg-dark-foreground":t.fixedNav}},[n("div",{staticClass:"overflow-x-auto whitespace-nowrap"},t._l(t.pages,(function(e,a){return n("router-link",{key:a,staticClass:"border-bottom-theme inline-block border-b-2 border-transparent px-4 py-5 text-sm font-bold",class:{"text-theme":t.routeName===e.route,"text-gray-600 dark:text-gray-100":t.routeName!==e.route},attrs:{to:{name:e.route},replace:""}},[t._v("\n "+t._s(e.title)+"\n ")])})),1)])])}),[],!1,null,null,null).exports},5002:(t,e,n)=>{n.r(e),n.d(e,{default:()=>r});const a={name:"AppSettings",components:{CardNavigation:n(3187).Z},data:function(){return{pages:[{title:this.$t("admin_settings.tabs.others"),route:"AppOthers"},{title:this.$t("Login & Registration"),route:"AppSignInUp"},{title:this.$t("admin_settings.tabs.appearance"),route:"AppAppearance"},{title:this.$t("Adsense"),route:"AppAdsense"},{title:this.$t("Homepage"),route:"AppIndex"},{title:this.$t("Environment"),route:"AppEnvironment"},{title:this.$t("Server"),route:"AppServer"}]}},mounted:function(){"/admin/settings"===this.$route.path&&this.$router.push({name:"AppOthers"})}};const r=(0,n(1900).Z)(a,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",[n("div",{staticClass:"card z-10 shadow-card",staticStyle:{"padding-bottom":"0","padding-top":"0"}},[n("CardNavigation",{staticClass:"-mx-1",attrs:{pages:t.pages}})],1),t._v(" "),n("router-view")],1)}),[],!1,null,null,null).exports}}]);
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -42,7 +42,7 @@
|
||||
"/js/chunks/app-settings.js": "/js/chunks/app-settings.js",
|
||||
"/js/chunks/app-appearance.js": "/js/chunks/app-appearance.js",
|
||||
"/js/chunks/app-index.js": "/js/chunks/app-index.js",
|
||||
"/js/chunks/app-email.js": "/js/chunks/app-email.js",
|
||||
"/js/chunks/app-environment.js": "/js/chunks/app-environment.js",
|
||||
"/js/chunks/app-others.js": "/js/chunks/app-others.js",
|
||||
"/js/chunks/app-sign-in-out.js": "/js/chunks/app-sign-in-out.js",
|
||||
"/js/chunks/app-adsense.js": "/js/chunks/app-adsense.js",
|
||||
@@ -71,6 +71,5 @@
|
||||
"/js/chunks/shared-with-me.js": "/js/chunks/shared-with-me.js",
|
||||
"/js/chunks/invitation.js": "/js/chunks/invitation.js",
|
||||
"/css/tailwind.css": "/css/tailwind.css",
|
||||
"/css/app.css": "/css/app.css",
|
||||
"/js/chunks/app-environment.js": "/js/chunks/app-environment.js"
|
||||
"/css/app.css": "/css/app.css"
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<div class="mb-8 flex items-center">
|
||||
<edit-2-icon v-if="!icon" size="22" class="vue-feather text-theme dark-text-theme mr-3" />
|
||||
<frown-icon v-if="icon === 'frown'" size="22" class="vue-feather text-theme dark-text-theme mr-3" />
|
||||
<list-icon v-if="icon === 'list'" size="22" class="vue-feather text-theme dark-text-theme mr-3" />
|
||||
<info-icon v-if="icon === 'info'" size="22" class="vue-feather text-theme dark-text-theme mr-3" />
|
||||
<database-icon v-if="icon === 'database'" size="22" class="vue-feather text-theme dark-text-theme mr-3" />
|
||||
<file-text-icon v-if="icon === 'file-text'" size="22" class="vue-feather text-theme dark-text-theme mr-3" />
|
||||
@@ -24,6 +25,7 @@
|
||||
|
||||
<script>
|
||||
import {
|
||||
ListIcon,
|
||||
MailIcon,
|
||||
InfoIcon,
|
||||
DatabaseIcon,
|
||||
@@ -46,6 +48,7 @@ export default {
|
||||
name: 'FormLabel',
|
||||
props: ['icon'],
|
||||
components: {
|
||||
ListIcon,
|
||||
MailIcon,
|
||||
InfoIcon,
|
||||
DatabaseIcon,
|
||||
|
||||
@@ -28,6 +28,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Logs-->
|
||||
<div class="card shadow-card">
|
||||
<FormLabel icon="list">Latest Server Logs</FormLabel>
|
||||
|
||||
<InfoBox v-if="!logs.length" class="!mb-0">
|
||||
<p v-html="$t('There is not any server log.')"></p>
|
||||
</InfoBox>
|
||||
|
||||
<div
|
||||
v-if="logs.length"
|
||||
v-for="(log, i) in logs"
|
||||
:key="i"
|
||||
class="md:flex md:space-y-0 space-y-3 items-center justify-between border-b border-dashed border-light py-3 dark:border-opacity-5"
|
||||
>
|
||||
<div class="text-left">
|
||||
<b class="block text-sm font-bold">
|
||||
{{ log }}
|
||||
</b>
|
||||
</div>
|
||||
<div @click="downloadLog(log)" class="flex h-8 w-8 items-center justify-center rounded-md bg-light-background transition-colors hover:bg-green-100 dark:bg-2x-dark-foreground cursor-pointer">
|
||||
<DownloadCloudIcon size="15" class="opacity-75" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Database Backups check-->
|
||||
<div class="card shadow-card">
|
||||
<FormLabel icon="database"> Latest Database Backups </FormLabel>
|
||||
@@ -150,10 +175,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import InfoBox from '../../../../components/Others/Forms/InfoBox'
|
||||
import { CheckIcon, XIcon, DownloadCloudIcon } from 'vue-feather-icons'
|
||||
import FormLabel from '../../../../components/Others/Forms/FormLabel'
|
||||
import PageTab from '../../../../components/Others/Layout/PageTab'
|
||||
import { CheckIcon, XIcon } from 'vue-feather-icons'
|
||||
import InfoBox from '../../../../components/Others/Forms/InfoBox'
|
||||
import { mapGetters } from 'vuex'
|
||||
import axios from 'axios'
|
||||
|
||||
@@ -163,6 +188,7 @@ export default {
|
||||
FormLabel,
|
||||
InfoBox,
|
||||
PageTab,
|
||||
DownloadCloudIcon,
|
||||
CheckIcon,
|
||||
XIcon,
|
||||
},
|
||||
@@ -181,6 +207,20 @@ export default {
|
||||
phpVersion: undefined,
|
||||
apiRunning: undefined,
|
||||
backups: undefined,
|
||||
logs: undefined,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
downloadLog(log) {
|
||||
|
||||
let anchor = document.createElement('a')
|
||||
|
||||
anchor.href = `/admin/log/${log}`
|
||||
anchor.download = log
|
||||
|
||||
document.body.appendChild(anchor)
|
||||
|
||||
anchor.click()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -192,6 +232,7 @@ export default {
|
||||
this.modules = response.data.modules
|
||||
this.phpVersion = response.data.php_version
|
||||
this.backups = response.data.backups
|
||||
this.logs = response.data.logs
|
||||
})
|
||||
|
||||
// Ping API
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
use Domain\Homepage\Controllers\IndexController;
|
||||
use Domain\Invoices\Controllers\GetInvoiceController;
|
||||
use Domain\Settings\Controllers\DownloadLogController;
|
||||
use Domain\Sharing\Controllers\SharePublicIndexController;
|
||||
use App\Socialite\Controllers\SocialiteCallbackController;
|
||||
use Domain\Sharing\Controllers\WebCrawlerOpenGraphController;
|
||||
@@ -16,6 +17,10 @@ Route::get('/translations/{lang}', CurrentLocalizationController::class);
|
||||
Route::get('/invoices/{invoice}', GetInvoiceController::class)
|
||||
->middleware('auth:sanctum');
|
||||
|
||||
Route::get('/admin/log/{log}', DownloadLogController::class)
|
||||
->middleware(['auth:sanctum', 'admin']);
|
||||
|
||||
|
||||
// Get og site for web crawlers
|
||||
if (Crawler::isCrawler()) {
|
||||
Route::get('/share/{share}', WebCrawlerOpenGraphController::class);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http;
|
||||
|
||||
use Fruitcake\Cors\HandleCors;
|
||||
use Support\Middleware\AdminCheck;
|
||||
use Support\Middleware\TrimStrings;
|
||||
use Support\Middleware\TrustProxies;
|
||||
use Support\Middleware\EncryptCookies;
|
||||
@@ -75,6 +77,7 @@ class Kernel extends HttpKernel
|
||||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'admin' => AdminCheck::class,
|
||||
'setup-wizard' => ProtectSetupWizardRoutes::class,
|
||||
'upload-request' => ProtectUploadRequestRoutes::class,
|
||||
];
|
||||
|
||||
@@ -48,7 +48,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||
->group(base_path('routes/upload-request.php'));
|
||||
|
||||
Route::prefix('api/admin')
|
||||
->middleware(['api', 'auth:sanctum'])
|
||||
->middleware(['api', 'auth:sanctum', 'admin'])
|
||||
->group(base_path('routes/admin.php'));
|
||||
|
||||
Route::middleware(['setup-wizard'])
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Domain\Settings\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
|
||||
class DownloadLogController extends Controller
|
||||
{
|
||||
public function __invoke($log): Response|BinaryFileResponse|Application|ResponseFactory
|
||||
{
|
||||
if (is_demo()) {
|
||||
return response('Done.', 204);
|
||||
}
|
||||
|
||||
// Get log path
|
||||
$logPath = storage_path("logs/$log");
|
||||
|
||||
// Download log
|
||||
return response()->download(
|
||||
storage_path("logs/$log"), $log, [
|
||||
'Accept-Ranges' => 'bytes',
|
||||
'Content-Type' => 'text/plain',
|
||||
'Content-Length' => File::size($logPath),
|
||||
'Content-Range' => 'bytes 0-600/' . File::size($logPath),
|
||||
'Content-Disposition' => "attachment; filename=$log",
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,9 @@ class GetServerStatusController
|
||||
// Get server data
|
||||
$status = ($this->getServerSetupStatus)();
|
||||
|
||||
// Get latest logs
|
||||
$status['logs'] = getListOfLatestLogs();
|
||||
|
||||
// Add latest database backups
|
||||
$status['backups'] = collect(Storage::allFiles('app-backup'))
|
||||
->map(fn ($path) => str_replace('app-backup/', '', $path))
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Support\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
class AdminCheck
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
// Check if user have access to administration settings
|
||||
if ( $request->user()->role !== 'admin') {
|
||||
abort(403, 'You don\'t have access for this operation!');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,22 @@ use Domain\Localization\Models\Language;
|
||||
use Intervention\Image\ImageManagerStatic as Image;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
|
||||
if (! function_exists('getListOfLatestLogs')) {
|
||||
/**
|
||||
* Check if cron is running
|
||||
*/
|
||||
function getListOfLatestLogs(): array
|
||||
{
|
||||
return array_slice(
|
||||
array_reverse(
|
||||
array_filter(
|
||||
scandir(storage_path() . '/logs'), fn($fn) => !str_starts_with($fn, '.')
|
||||
)
|
||||
), 0, 5, true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('isRunningCron')) {
|
||||
/**
|
||||
* Check if cron is running
|
||||
|
||||
Reference in New Issue
Block a user