12-05-2026 Frontend dev
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run

This commit is contained in:
Kevin Adametz 2026-05-12 18:32:33 +02:00
parent 405df0a122
commit 5b8bdf4182
779 changed files with 480564 additions and 6241 deletions

View file

@ -2,8 +2,29 @@
namespace App\Providers;
use App\Contracts\NewsletterSyncClient;
use App\Helpers\ThemeHelper;
use App\Http\Middleware\EnsureUserIsAdmin;
use App\Http\Middleware\LogSlowAdminRequests;
use App\Models\AdminPreset;
use App\Models\Category;
use App\Models\CategoryTranslation;
use App\Models\Company;
use App\Models\Contact;
use App\Models\NewsletterSubscription;
use App\Models\PressRelease;
use App\Models\User;
use App\Observers\AdminPerformanceCacheObserver;
use App\Services\Admin\AdminRequestPerformanceMetrics;
use App\Services\Newsletter\NullNewsletterSyncClient;
use App\Services\PressRelease\PressReleaseService;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
use Livewire\Livewire;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
class AppServiceProvider extends ServiceProvider
{
@ -12,7 +33,9 @@ class AppServiceProvider extends ServiceProvider
*/
public function register(): void
{
//
$this->app->bind(NewsletterSyncClient::class, NullNewsletterSyncClient::class);
$this->app->singleton(PressReleaseService::class);
$this->app->singleton(AdminRequestPerformanceMetrics::class);
}
/**
@ -20,19 +43,31 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot(): void
{
// Force HTTPS when running behind a proxy (like Traefik)
if ($this->app->environment('local', 'production')) {
$scheme = request()->header('X-Forwarded-Proto')
?? request()->server('HTTP_X_FORWARDED_PROTO')
?? (request()->secure() ? 'https' : 'http');
if ($scheme === 'https') {
URL::forceScheme('https');
}
// Trust proxies for correct request detection
$this->app['request']->server->set('HTTPS', 'on');
AdminPreset::observe(AdminPerformanceCacheObserver::class);
Category::observe(AdminPerformanceCacheObserver::class);
CategoryTranslation::observe(AdminPerformanceCacheObserver::class);
Company::observe(AdminPerformanceCacheObserver::class);
Contact::observe(AdminPerformanceCacheObserver::class);
NewsletterSubscription::observe(AdminPerformanceCacheObserver::class);
PressRelease::observe(AdminPerformanceCacheObserver::class);
User::observe(AdminPerformanceCacheObserver::class);
Permission::observe(AdminPerformanceCacheObserver::class);
Role::observe(AdminPerformanceCacheObserver::class);
// Set dynamic asset URL based on current domain/theme
// This is needed for Vite to use the correct asset subdomain
//config(['app.asset_url' => 'https://assets.businessportal24.test']);
DB::listen(fn (QueryExecuted $query) => app(AdminRequestPerformanceMetrics::class)->record($query));
//$this->setDynamicAssetUrl();
Livewire::addPersistentMiddleware([
EnsureUserIsAdmin::class,
LogSlowAdminRequests::class,
]);
}
/**
@ -41,11 +76,11 @@ class AppServiceProvider extends ServiceProvider
protected function setDynamicAssetUrl(): void
{
try {
$assetUrl = \App\Helpers\ThemeHelper::getAssetUrl();
$assetUrl = ThemeHelper::getAssetUrl();
config(['app.asset_url' => $assetUrl]);
} catch (\Exception $e) {
// Fallback to default if theme detection fails
config(['app.asset_url' => 'https://assets.pr-copilot.test']);
config(['app.asset_url' => 'https://assets.presseportale.test']);
}
}
}

View file

@ -6,12 +6,14 @@ use App\Actions\Fortify\CreateNewUser;
use App\Actions\Fortify\ResetUserPassword;
use App\Actions\Fortify\UpdateUserPassword;
use App\Actions\Fortify\UpdateUserProfileInformation;
use App\Http\Responses\RoleAwareLoginResponse;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
use Laravel\Fortify\Actions\RedirectIfTwoFactorAuthenticatable;
use Laravel\Fortify\Contracts\LoginResponse;
use Laravel\Fortify\Fortify;
use Livewire\Volt\Volt;
@ -22,7 +24,7 @@ class FortifyServiceProvider extends ServiceProvider
*/
public function register(): void
{
//
$this->app->singleton(LoginResponse::class, RoleAwareLoginResponse::class);
}
/**

View file

@ -2,7 +2,9 @@
namespace App\Providers;
use Illuminate\Routing\UrlGenerator;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Vite;
use Illuminate\Support\ServiceProvider;
@ -32,9 +34,9 @@ class ThemeServiceProvider extends ServiceProvider
// Standard-Werte für Domain, die nicht in der Konfiguration sind
$domainConfig = [
'name' => config('app.name'),
'theme' => 'portal',
'view_prefix' => 'portal',
'assets_dir' => 'build/portal',
'theme' => 'b2in',
'view_prefix' => 'b2in',
'assets_dir' => 'build/b2in',
'url' => config('app.url'),
'domain_name' => config('app.domain_name'),
];
@ -55,35 +57,54 @@ class ThemeServiceProvider extends ServiceProvider
$domainConfig = array_merge($domainConfig, $confiDomains[$themeOverride]);
}
// Dynamische ASSET_URL basierend auf der aktuellen Domain setzen
// Verhindert CORS-Probleme, da Assets immer von derselben Domain geladen werden
$assetUrl = $domainConfig['url'];
// Grundlegende Konfiguration im Anwendungskontext verfügbar machen
config([
'app.theme' => $domainConfig['theme'],
'app.view_prefix' => $domainConfig['view_prefix'],
'app.domain_name' => $domainConfig['domain_name'],
'app.url' => $domainConfig['url'],
'app.asset_url' => $domainConfig['asset_url'] ?? $domainConfig['url'],
'app.asset_url' => $assetUrl, // Dynamische Asset-URL für die aktuelle Domain
]);
// URL-Generator für die aktuelle Domain konfigurieren
// Dies ist wichtig, damit asset() und url() die richtige Domain verwenden
URL::forceRootUrl($domainConfig['url']);
URL::forceScheme(parse_url($domainConfig['url'], PHP_URL_SCHEME) ?: 'https');
// WICHTIG: Asset-Root direkt im UrlGenerator setzen
// Der asset() Helper verwendet einen separaten Asset-Root
/** @var UrlGenerator $urlGenerator */
$urlGenerator = app('url');
$urlGenerator->useAssetOrigin($assetUrl);
// Spezifischere Daten für die Views verfügbar machen
View::share('theme', $domainConfig['theme']);
View::share('viewPrefix', $domainConfig['view_prefix']);
View::share('domainName', $domainConfig['domain_name']);
View::share('domainConfig', $domainConfig);
View::share('domainUrl', $domainConfig['url']);
View::share('assetUrl', $assetUrl);
// Vite-Assets-Konfiguration für die aktuelle Domain
if (! app()->runningInConsole() && isset($domainConfig['assets_dir'])) {
Vite::useBuildDirectory($domainConfig['assets_dir']);
if (! app()->runningInConsole()) {
if (isset($domainConfig['assets_dir'])) {
Vite::useBuildDirectory($domainConfig['assets_dir']);
}
// Setze die Asset-URL für Vite Dev-Server
if (isset($domainConfig['asset_url'])) {
// Erstelle temporäre Hot-File mit der richtigen Asset-URL
$hotFile = public_path('hot');
if (file_exists($hotFile)) {
file_put_contents($hotFile, $domainConfig['asset_url']);
}
Vite::useHotFile($hotFile);
if (app()->environment('local')) {
// Entwicklung: Vite Dev Server mit HMR
$viteDevServerUrl = env('VITE_DEV_SERVER_URL', 'https://assets.presseportale.test');
Vite::useHotFile(public_path('hot'));
config(['app.vite_dev_server_url' => $viteDevServerUrl]);
View::share('viteDevServerUrl', $viteDevServerUrl);
} else {
// Produktion: Assets von der aktuellen Domain laden (kein CORS nötig)
Vite::useScriptTagAttributes(['crossorigin' => false]);
Vite::useStyleTagAttributes(['crossorigin' => false]);
}
}
}