mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-04-15 09:14:08 +00:00
configureMediaDisk() was calling FileDisk::setConfig() which mutates the global filesystems.default config on every request. This caused cascading requests on the File Disk admin page. Now registers the media disk config directly without changing the global default filesystem.
210 lines
7.3 KiB
PHP
210 lines
7.3 KiB
PHP
<?php
|
|
|
|
namespace App\Providers;
|
|
|
|
use App\Models\FileDisk;
|
|
use App\Models\Setting;
|
|
use App\Policies\CompanyPolicy;
|
|
use App\Policies\CustomerPolicy;
|
|
use App\Policies\DashboardPolicy;
|
|
use App\Policies\EstimatePolicy;
|
|
use App\Policies\ExpensePolicy;
|
|
use App\Policies\InvoicePolicy;
|
|
use App\Policies\ItemPolicy;
|
|
use App\Policies\ModulesPolicy;
|
|
use App\Policies\NotePolicy;
|
|
use App\Policies\OwnerPolicy;
|
|
use App\Policies\PaymentPolicy;
|
|
use App\Policies\RecurringInvoicePolicy;
|
|
use App\Policies\ReportPolicy;
|
|
use App\Policies\RolePolicy;
|
|
use App\Policies\SettingsPolicy;
|
|
use App\Policies\UserPolicy;
|
|
use App\Services\Setup\InstallUtils;
|
|
use App\Support\BouncerDefaultScope;
|
|
use Gate;
|
|
use Illuminate\Support\Facades\Broadcast;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use Illuminate\Support\Facades\Notification;
|
|
use Illuminate\Support\ServiceProvider;
|
|
use Silber\Bouncer\Database\Models as BouncerModels;
|
|
use Silber\Bouncer\Database\Role;
|
|
use View;
|
|
|
|
class AppServiceProvider extends ServiceProvider
|
|
{
|
|
/**
|
|
* The path to your application's "home" route.
|
|
*
|
|
* Typically, users are redirected here after authentication.
|
|
*
|
|
* @var string
|
|
*/
|
|
public const HOME = '/admin/dashboard';
|
|
|
|
/**
|
|
* The path to the "customer home" route for your application.
|
|
*
|
|
* This is used by Laravel authentication to redirect customers after login.
|
|
*
|
|
* @var string
|
|
*/
|
|
public const CUSTOMER_HOME = '/customer/dashboard';
|
|
|
|
/**
|
|
* Bootstrap any application services.
|
|
*/
|
|
public function boot(): void
|
|
{
|
|
|
|
if (InstallUtils::isDbCreated()) {
|
|
$this->addMenus();
|
|
$this->configureMediaDisk();
|
|
}
|
|
|
|
Gate::policy(Role::class, RolePolicy::class);
|
|
|
|
View::addNamespace('pdf_templates', storage_path('app/templates/pdf'));
|
|
|
|
$this->bootAuth();
|
|
$this->bootBroadcast();
|
|
|
|
// In demo mode, prevent all outgoing emails and notifications
|
|
if (config('app.env') === 'demo') {
|
|
Mail::fake();
|
|
Notification::fake();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register any application services.
|
|
*/
|
|
public function register(): void
|
|
{
|
|
BouncerModels::scope(new BouncerDefaultScope);
|
|
}
|
|
|
|
public function addMenus()
|
|
{
|
|
// main menu
|
|
\Menu::make('main_menu', function ($menu) {
|
|
foreach (config('invoiceshelf.main_menu') as $data) {
|
|
$this->generateMenu($menu, $data);
|
|
}
|
|
});
|
|
|
|
// admin menu (super admin mode)
|
|
\Menu::make('admin_menu', function ($menu) {
|
|
foreach (config('invoiceshelf.admin_menu') as $data) {
|
|
$this->generateMenu($menu, $data);
|
|
}
|
|
});
|
|
|
|
// setting menu
|
|
\Menu::make('setting_menu', function ($menu) {
|
|
foreach (config('invoiceshelf.setting_menu') as $data) {
|
|
$this->generateMenu($menu, $data);
|
|
}
|
|
});
|
|
|
|
\Menu::make('customer_portal_menu', function ($menu) {
|
|
foreach (config('invoiceshelf.customer_menu') as $data) {
|
|
$this->generateMenu($menu, $data);
|
|
}
|
|
});
|
|
}
|
|
|
|
public function generateMenu($menu, $data)
|
|
{
|
|
$menu->add($data['title'], $data['link'])
|
|
->data('icon', $data['icon'])
|
|
->data('name', $data['name'])
|
|
->data('owner_only', $data['owner_only'])
|
|
->data('super_admin_only', $data['super_admin_only'] ?? false)
|
|
->data('ability', $data['ability'])
|
|
->data('model', $data['model'])
|
|
->data('group', $data['group'])
|
|
->data('group_label', $data['group_label'] ?? '');
|
|
}
|
|
|
|
public function bootAuth()
|
|
{
|
|
|
|
Gate::define('create company', [CompanyPolicy::class, 'create']);
|
|
Gate::define('transfer company ownership', [CompanyPolicy::class, 'transferOwnership']);
|
|
Gate::define('delete company', [CompanyPolicy::class, 'delete']);
|
|
|
|
Gate::define('manage modules', [ModulesPolicy::class, 'manageModules']);
|
|
|
|
Gate::define('manage settings', [SettingsPolicy::class, 'manageSettings']);
|
|
Gate::define('manage company', [SettingsPolicy::class, 'manageCompany']);
|
|
Gate::define('manage backups', [SettingsPolicy::class, 'manageBackups']);
|
|
Gate::define('manage file disk', [SettingsPolicy::class, 'manageFileDisk']);
|
|
Gate::define('manage email config', [SettingsPolicy::class, 'manageEmailConfig']);
|
|
Gate::define('manage pdf config', [SettingsPolicy::class, 'managePDFConfig']);
|
|
Gate::define('manage notes', [NotePolicy::class, 'manageNotes']);
|
|
Gate::define('view notes', [NotePolicy::class, 'viewNotes']);
|
|
|
|
Gate::define('send invoice', [InvoicePolicy::class, 'send']);
|
|
Gate::define('send estimate', [EstimatePolicy::class, 'send']);
|
|
Gate::define('send payment', [PaymentPolicy::class, 'send']);
|
|
|
|
Gate::define('delete multiple items', [ItemPolicy::class, 'deleteMultiple']);
|
|
Gate::define('delete multiple customers', [CustomerPolicy::class, 'deleteMultiple']);
|
|
Gate::define('delete multiple users', [UserPolicy::class, 'deleteMultiple']);
|
|
Gate::define('delete multiple invoices', [InvoicePolicy::class, 'deleteMultiple']);
|
|
Gate::define('delete multiple estimates', [EstimatePolicy::class, 'deleteMultiple']);
|
|
Gate::define('delete multiple expenses', [ExpensePolicy::class, 'deleteMultiple']);
|
|
Gate::define('delete multiple payments', [PaymentPolicy::class, 'deleteMultiple']);
|
|
Gate::define('delete multiple recurring invoices', [RecurringInvoicePolicy::class, 'deleteMultiple']);
|
|
|
|
Gate::define('view dashboard', [DashboardPolicy::class, 'view']);
|
|
|
|
Gate::define('view report', [ReportPolicy::class, 'viewReport']);
|
|
|
|
Gate::define('owner only', [OwnerPolicy::class, 'managedByOwner']);
|
|
}
|
|
|
|
public function bootBroadcast()
|
|
{
|
|
Broadcast::routes(['middleware' => 'api.auth']);
|
|
}
|
|
|
|
/**
|
|
* Configure Spatie Media Library to use the FileDisk system.
|
|
*
|
|
* Resolves the media disk from the `media_disk_id` setting,
|
|
* falling back to the default FileDisk. This ensures media
|
|
* uploads go to a private disk by default.
|
|
*/
|
|
private function configureMediaDisk(): void
|
|
{
|
|
try {
|
|
$mediaDiskId = Setting::getSetting('media_disk_id');
|
|
$disk = $mediaDiskId
|
|
? FileDisk::find($mediaDiskId)
|
|
: FileDisk::where('set_as_default', true)->first();
|
|
|
|
if ($disk) {
|
|
// Register the disk config without changing the global default.
|
|
// setConfig() mutates filesystems.default which causes side effects.
|
|
$prefix = env('DYNAMIC_DISK_PREFIX', 'temp_');
|
|
$diskName = $prefix.$disk->driver;
|
|
$credentials = collect(json_decode($disk->credentials));
|
|
$baseConfig = config('filesystems.disks.'.$disk->driver, []);
|
|
|
|
foreach ($baseConfig as $key => $value) {
|
|
if ($credentials->has($key)) {
|
|
$baseConfig[$key] = $credentials[$key];
|
|
}
|
|
}
|
|
|
|
config(['filesystems.disks.'.$diskName => $baseConfig]);
|
|
config(['media-library.disk_name' => $diskName]);
|
|
}
|
|
} catch (\Exception $e) {
|
|
// DB not yet migrated or settings table missing — use config default
|
|
}
|
|
}
|
|
}
|