328 lines
11 KiB
PHP
328 lines
11 KiB
PHP
<?php
|
|
|
|
/**
|
|
* ============================================================
|
|
*
|
|
* @project biiproject
|
|
*
|
|
* @author Andika Debi Putra
|
|
*
|
|
* @email andikadebiputra@gmail.com
|
|
*
|
|
* @website https://biiproject.com
|
|
*
|
|
* @copyright Copyright (c) 2026 Andika Debi Putra
|
|
* @license Proprietary - All Rights Reserved
|
|
*
|
|
* @version 1.0.0
|
|
*
|
|
* @created 2026-05-01
|
|
* ============================================================
|
|
*
|
|
* Unauthorized copying, modification, distribution, or use
|
|
* of this file is strictly prohibited without prior written
|
|
* permission from the author.
|
|
* ============================================================
|
|
*/
|
|
|
|
namespace App\Providers;
|
|
|
|
use App\Events\ActivityLogCreated;
|
|
use App\Listeners\AnalyzeSystemError;
|
|
use App\Models\Permission;
|
|
use App\Models\Role;
|
|
use App\Models\User;
|
|
use App\Observers\PermissionObserver;
|
|
use App\Observers\RoleObserver;
|
|
use App\Observers\UserObserver;
|
|
use App\Services\Monitoring\SystemMonitoringService;
|
|
use App\Services\SystemConfig\SystemConfigService;
|
|
use Google\Client;
|
|
use Google\Service\Drive;
|
|
use Illuminate\Auth\Events\Login;
|
|
use Illuminate\Cache\RateLimiting\Limit;
|
|
use Illuminate\Filesystem\FilesystemAdapter;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Log\Events\MessageLogged;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Event;
|
|
use Illuminate\Support\Facades\Gate;
|
|
use Illuminate\Support\Facades\RateLimiter;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Facades\URL;
|
|
use Illuminate\Support\Facades\Blade;
|
|
use Illuminate\Support\ServiceProvider;
|
|
use League\Flysystem\Filesystem;
|
|
use Masbug\Flysystem\GoogleDriveAdapter;
|
|
use Spatie\Activitylog\Models\Activity;
|
|
|
|
class AppServiceProvider extends ServiceProvider
|
|
{
|
|
/**
|
|
* Register any application services.
|
|
*/
|
|
public function register(): void
|
|
{
|
|
//
|
|
}
|
|
|
|
/**
|
|
* Bootstrap any application services.
|
|
*/
|
|
public function boot(): void
|
|
{
|
|
// 🔒 Configure Rate Limiters
|
|
$this->configureRateLimiting();
|
|
|
|
// Super Admin Gate (Developer has full power)
|
|
Gate::before(function ($user, $capability) {
|
|
// Monitoring dynamic gates
|
|
$monitoringKeys = [
|
|
'view pulse' => 'engine_pulse_enabled',
|
|
'view telescope' => 'engine_telescope_enabled',
|
|
'view api docs' => 'engine_swagger_enabled',
|
|
'viewHorizon' => 'engine_horizon_enabled',
|
|
];
|
|
|
|
if (isset($monitoringKeys[$capability])) {
|
|
if (!get_setting($monitoringKeys[$capability], true)) {
|
|
return false; // Force deny if disabled at engine level
|
|
}
|
|
}
|
|
|
|
return $user->hasRole('Developer') ? true : null;
|
|
});
|
|
|
|
// Force HTTPS in production
|
|
if ($this->app->environment('production')) {
|
|
URL::forceScheme('https');
|
|
}
|
|
|
|
// Global Password Reset Expiry Override
|
|
if ($this->app->bound(SystemConfigService::class)) {
|
|
$expiry = get_setting('password_reset_link_expiry', 60);
|
|
config(['auth.passwords.users.expire' => $expiry]);
|
|
}
|
|
|
|
// User Observer
|
|
User::observe(UserObserver::class);
|
|
|
|
// Role Observer
|
|
Role::observe(RoleObserver::class);
|
|
|
|
// Permission Observer
|
|
Permission::observe(PermissionObserver::class);
|
|
|
|
// Windows Backup Compatibility Layer
|
|
$this->ensureWindowsBackupCompatibility();
|
|
|
|
// Google Drive Filesystem Adapter
|
|
$this->registerGoogleDriveAdapter();
|
|
|
|
// S3 Dynamic Config
|
|
$this->injectS3DynamicConfig();
|
|
|
|
// Backup Dynamic Config
|
|
$this->injectBackupDynamicConfig();
|
|
|
|
// Monitoring Dynamic Config
|
|
$this->injectMonitoringDynamicConfig();
|
|
|
|
// Dashboard View Composer
|
|
$this->registerDashboardComposer();
|
|
|
|
// Tab-permission Blade directives
|
|
$this->registerTabPermissionDirectives();
|
|
|
|
// 📡 Real-time Activity Log Broadcasting
|
|
Activity::created(function ($activity) {
|
|
try {
|
|
broadcast(new ActivityLogCreated($activity))->toOthers();
|
|
} catch (\Throwable $e) {
|
|
// Silently fail if Reverb is not running
|
|
}
|
|
});
|
|
|
|
// 🔍 Register AI error analysis listener (not auto-discovered for MessageLogged)
|
|
Event::listen(
|
|
MessageLogged::class,
|
|
AnalyzeSystemError::class
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Configure the rate limiters for the application.
|
|
*/
|
|
protected function configureRateLimiting(): void
|
|
{
|
|
// Rate limiting for API
|
|
RateLimiter::for('api', function (Request $request) {
|
|
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
|
|
});
|
|
|
|
// Rate limiting for Login attempts
|
|
RateLimiter::for('login', function (Request $request) {
|
|
return Limit::perMinute(5)->by($request->ip())->response(function (Request $request, array $headers) {
|
|
return response()->json([
|
|
'message' => 'Too many login attempts. Please try again in 1 minute.',
|
|
'status' => 'error',
|
|
], 429, $headers);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Inject Monitoring configuration from database.
|
|
*/
|
|
protected function injectMonitoringDynamicConfig(): void
|
|
{
|
|
if (!$this->app->bound(SystemConfigService::class)) {
|
|
return;
|
|
}
|
|
|
|
config(['pulse.enabled' => get_setting('engine_pulse_enabled', true)]);
|
|
config(['telescope.enabled' => get_setting('engine_telescope_enabled', true)]);
|
|
|
|
if (!get_setting('engine_swagger_enabled', true)) {
|
|
config(['l5-swagger.documentations.default.routes.api' => null]);
|
|
config(['l5-swagger.defaults.routes.docs' => null]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register a view composer for the dashboard.
|
|
*/
|
|
protected function registerDashboardComposer(): void
|
|
{
|
|
view()->composer('pages.dashboard', function ($view) {
|
|
$stats = Cache::remember('dashboard_stats', now()->addMinutes(5), function () {
|
|
return [
|
|
'total_users' => User::count(),
|
|
'active_sessions' => app(SystemMonitoringService::class)->getActiveUsers(),
|
|
'today_actions' => Activity::whereDate('created_at', now()->today())->count(),
|
|
'failed_jobs' => DB::table('failed_jobs')->count(),
|
|
'recent_activities' => Activity::with('causer')->latest()->take(5)->get(),
|
|
];
|
|
});
|
|
|
|
$view->with('dashboardStats', $stats);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Register Google Drive filesystem adapter.
|
|
*/
|
|
protected function registerGoogleDriveAdapter(): void
|
|
{
|
|
Storage::extend('google', function ($app, $config) {
|
|
$clientId = get_setting('gdrive_client_id', $config['clientId'] ?? '');
|
|
$clientSecret = get_setting('gdrive_client_secret', $config['clientSecret'] ?? '');
|
|
$refreshToken = get_setting('gdrive_refresh_token', $config['refreshToken'] ?? '');
|
|
$folder = get_setting('gdrive_folder', $config['folder'] ?? 'LaravelBackups');
|
|
|
|
$client = new Client;
|
|
$client->setClientId($clientId);
|
|
$client->setClientSecret($clientSecret);
|
|
|
|
if ($refreshToken) {
|
|
$token = $client->refreshToken($refreshToken);
|
|
if (!isset($token['error'])) {
|
|
$client->setAccessToken($token);
|
|
}
|
|
}
|
|
|
|
$service = new Drive($client);
|
|
$adapter = new GoogleDriveAdapter($service, $folder, []);
|
|
$driver = new Filesystem($adapter);
|
|
|
|
return new FilesystemAdapter($driver, $adapter, $config);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Inject S3 credentials from database if set.
|
|
*/
|
|
protected function injectS3DynamicConfig(): void
|
|
{
|
|
if (get_setting('backup_db_driver') === 's3') {
|
|
config([
|
|
'filesystems.disks.s3.key' => get_setting('s3_key', config('filesystems.disks.s3.key')),
|
|
'filesystems.disks.s3.secret' => get_setting('s3_secret', config('filesystems.disks.s3.secret')),
|
|
'filesystems.disks.s3.region' => get_setting('s3_region', config('filesystems.disks.s3.region')),
|
|
'filesystems.disks.s3.bucket' => get_setting('s3_bucket', config('filesystems.disks.s3.bucket')),
|
|
'filesystems.disks.s3.endpoint' => get_setting('s3_endpoint', config('filesystems.disks.s3.endpoint')),
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ensures Windows backup compatibility.
|
|
*/
|
|
protected function ensureWindowsBackupCompatibility(): void
|
|
{
|
|
if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
|
|
return;
|
|
}
|
|
|
|
$dbDriver = config('database.default');
|
|
if (config("database.connections.{$dbDriver}.dump.dump_binary_path")) {
|
|
return;
|
|
}
|
|
|
|
$isPg = $dbDriver === 'pgsql';
|
|
$binary = $isPg ? 'pg_dump.exe' : 'mysqldump.exe';
|
|
$paths = $isPg ? ['C:\laragon\bin\postgresql\*\bin', 'C:\Program Files\PostgreSQL\*\bin'] : ['C:\laragon\bin\mysql\*\bin', 'C:\xampp\mysql\bin'];
|
|
|
|
foreach ($paths as $path) {
|
|
$matchedPaths = glob($path, GLOB_ONLYDIR);
|
|
if (!$matchedPaths) {
|
|
continue;
|
|
}
|
|
$foundPath = $matchedPaths[count($matchedPaths) - 1];
|
|
if (file_exists($foundPath . DIRECTORY_SEPARATOR . $binary)) {
|
|
config(["database.connections.{$dbDriver}.dump.dump_binary_path" => $foundPath]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Register Blade if/unless directives for tab-level permission checks.
|
|
*
|
|
* Usage in Blade:
|
|
* @cantab('global settings', 'login-security') ... @endcantab
|
|
* @managetab('mobile settings', 'branding') ... @endmanagetab
|
|
*/
|
|
protected function registerTabPermissionDirectives(): void
|
|
{
|
|
Blade::if('cantab', fn (string $menu, string $tab) => can_view_tab($menu, $tab));
|
|
Blade::if('managetab', fn (string $menu, string $tab) => can_manage_tab($menu, $tab));
|
|
Blade::if('canviewanytab', fn (string $menu) => can_view_any_tab($menu));
|
|
Blade::if('canmanageanytab', fn (string $menu) => can_manage_any_tab($menu));
|
|
}
|
|
|
|
/**
|
|
* Inject Backup configuration from database.
|
|
*/
|
|
protected function injectBackupDynamicConfig(): void
|
|
{
|
|
if (!$this->app->bound(SystemConfigService::class)) {
|
|
return;
|
|
}
|
|
|
|
$driver = get_setting('backup_db_driver', 'local');
|
|
config(['backup.backup.destination.disks' => [$driver]]);
|
|
config(['backup.monitor_backups.0.disks' => [$driver]]);
|
|
|
|
if ($driver === 'gdrive') {
|
|
config([
|
|
'filesystems.disks.gdrive.clientId' => get_setting('gdrive_client_id'),
|
|
'filesystems.disks.gdrive.clientSecret' => get_setting('gdrive_client_secret'),
|
|
'filesystems.disks.gdrive.refreshToken' => get_setting('gdrive_refresh_token'),
|
|
'filesystems.disks.gdrive.folder' => get_setting('gdrive_folder', 'LaravelBackups'),
|
|
]);
|
|
}
|
|
}
|
|
}
|