Magic-Link und Pressekontakt-Zugang zu einer Seite (/anmeldelink) zusammengeführt; altes Login-Modal entfernt, /pressekontakt-zugang leitet weiter. - ContactAccessService deckt jetzt Firmen-E-Mail UND Pressekontakt-E-Mail ab, portalübergreifend (ohne PortalScope). Eine E-Mail mehrfach hinterlegt → genau ein Account, dem alle Firmen + Kontakte zugeordnet werden. - Zugeordnete Firmen erhalten Pivot-Rolle 'responsible' (Schreibzugriff auf Stammdaten, Kontakte, Pressemitteilungen) statt nur 'member'; bestehende Lese-Pivots werden hochgestuft, Owner bleiben unangetastet. - Neuer Login-Listener (SyncCompanyMembershipsOnLogin) frischt die Zuordnungen bei JEDEM Login (Magic-Link, Passwort, Google) auf – auch nachträglich (API) hinzugekommene Firmen/Kontakte mit gleicher E-Mail greifen. - Auth-Bereich erzwingt Hellmodus: aus dem Portal übernommene .dark-Klasse wird am <html> entfernt (Login war im Dark Mode hängengeblieben). - Tests: Firmen-E-Mail-Login, Multi-Firmen-Aggregation, Schreibzugriff/Upgrade, Per-Login-Re-Sync, Auth-Hellmodus. Sicherheits-Doku aktualisiert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
107 lines
4 KiB
PHP
107 lines
4 KiB
PHP
<?php
|
|
|
|
namespace App\Providers;
|
|
|
|
use App\Contracts\NewsletterSyncClient;
|
|
use App\Helpers\ThemeHelper;
|
|
use App\Http\Middleware\EnsureUserIsAdmin;
|
|
use App\Http\Middleware\LogSlowAdminRequests;
|
|
use App\Listeners\ActivateUserAfterVerification;
|
|
use App\Listeners\SyncCompanyMembershipsOnLogin;
|
|
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\Auth\Events\Login;
|
|
use Illuminate\Auth\Events\Registered;
|
|
use Illuminate\Auth\Events\Verified;
|
|
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
|
use Illuminate\Database\Events\QueryExecuted;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Event;
|
|
use Illuminate\Support\Facades\URL;
|
|
use Illuminate\Support\ServiceProvider;
|
|
use Laravel\Cashier\Cashier;
|
|
use Livewire\Livewire;
|
|
use Spatie\Permission\Models\Permission;
|
|
use Spatie\Permission\Models\Role;
|
|
|
|
class AppServiceProvider extends ServiceProvider
|
|
{
|
|
/**
|
|
* Register any application services.
|
|
*/
|
|
public function register(): void
|
|
{
|
|
$this->app->bind(NewsletterSyncClient::class, NullNewsletterSyncClient::class);
|
|
$this->app->singleton(PressReleaseService::class);
|
|
$this->app->singleton(AdminRequestPerformanceMetrics::class);
|
|
}
|
|
|
|
/**
|
|
* Bootstrap any application services.
|
|
*/
|
|
public function boot(): void
|
|
{
|
|
$scheme = request()->header('X-Forwarded-Proto')
|
|
?? request()->server('HTTP_X_FORWARDED_PROTO')
|
|
?? (request()->secure() ? 'https' : 'http');
|
|
|
|
if ($scheme === 'https') {
|
|
URL::forceScheme('https');
|
|
}
|
|
|
|
// Registrierung → Verifizierungsmail; bestätigter Klick → Aktivierung.
|
|
Event::listen(Registered::class, SendEmailVerificationNotification::class);
|
|
Event::listen(Verified::class, ActivateUserAfterVerification::class);
|
|
|
|
// Bei jedem Login Firmen-/Kontakt-Zuordnungen (gleiche E-Mail) auffrischen.
|
|
Event::listen(Login::class, SyncCompanyMembershipsOnLogin::class);
|
|
|
|
// Stripe Tax berechnet die USt im Checkout automatisch nach den
|
|
// gleichen Regeln wie der VatResolver im MAN-Kreis (DE mit Steuer,
|
|
// EU nur mit USt-ID befreit, Drittland befreit). Aktiviert zugleich
|
|
// die USt-ID-Abfrage im Stripe Checkout.
|
|
Cashier::calculateTaxes();
|
|
|
|
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);
|
|
|
|
DB::listen(fn (QueryExecuted $query) => app(AdminRequestPerformanceMetrics::class)->record($query));
|
|
|
|
Livewire::addPersistentMiddleware([
|
|
EnsureUserIsAdmin::class,
|
|
LogSlowAdminRequests::class,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Set the asset URL dynamically based on the current theme
|
|
*/
|
|
protected function setDynamicAssetUrl(): void
|
|
{
|
|
try {
|
|
$assetUrl = ThemeHelper::getAssetUrl();
|
|
config(['app.asset_url' => $assetUrl]);
|
|
} catch (\Exception $e) {
|
|
// Fallback to default if theme detection fails
|
|
config(['app.asset_url' => 'https://assets.pressekonto.test']);
|
|
}
|
|
}
|
|
}
|