344 lines
10 KiB
PHP
344 lines
10 KiB
PHP
<?php
|
|
|
|
namespace App\Providers;
|
|
|
|
use App\Domain\DomainContext;
|
|
use App\Services\DomainService;
|
|
use Illuminate\Cache\RateLimiting\Limit;
|
|
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\RateLimiter;
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
/**
|
|
* Enhanced Route Service Provider
|
|
*
|
|
* This service provider implements the new domain-aware routing system
|
|
* that loads routes based on the current domain context.
|
|
*/
|
|
class RouteServiceProvider extends ServiceProvider
|
|
{
|
|
/**
|
|
* The path to the "home" route for your application.
|
|
*/
|
|
public const HOME = '/home';
|
|
|
|
/**
|
|
* Define your route model bindings, pattern filters, etc.
|
|
*/
|
|
public function boot()
|
|
{
|
|
$this->configureRateLimiting();
|
|
|
|
$this->routes(function () {
|
|
// Load API routes first (domain-independent)
|
|
Route::prefix('api')
|
|
->middleware('api')
|
|
->group(base_path('routes/api.php'));
|
|
|
|
// Load web routes with domain awareness
|
|
Route::middleware('web')
|
|
->group(function () {
|
|
$this->loadDomainAwareRoutes();
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Load routes based on current domain context
|
|
*/
|
|
protected function loadDomainAwareRoutes(): void
|
|
{
|
|
// Try to get domain context (might not be available during route caching)
|
|
$domainContext = $this->getDomainContext();
|
|
|
|
// Load shared routes first (always available)
|
|
$this->loadSharedRoutes();
|
|
|
|
// Load domain-specific routes if context is available
|
|
if ($domainContext) {
|
|
$this->loadDomainSpecificRoutes($domainContext);
|
|
} else {
|
|
// Fallback: load all routes for route caching or when context is unavailable
|
|
$this->loadAllRoutes();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get current domain context
|
|
*/
|
|
protected function getDomainContext(): ?DomainContext
|
|
{
|
|
try {
|
|
return app('domain.context');
|
|
} catch (\Exception $e) {
|
|
// Context not available (e.g., during route caching)
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load shared routes that are available across all domains
|
|
*/
|
|
protected function loadSharedRoutes(): void
|
|
{
|
|
// Legal pages (datenschutz, impressum, agb)
|
|
Route::group([], base_path('routes/shared/legal.php'));
|
|
|
|
// Common functionality (health checks, modals, etc.)
|
|
Route::group([], base_path('routes/shared/common.php'));
|
|
}
|
|
|
|
/**
|
|
* Load routes specific to the current domain
|
|
*/
|
|
protected function loadDomainSpecificRoutes(DomainContext $context): void
|
|
{
|
|
match ($context->type) {
|
|
'main' => $this->loadMainDomainRoutes(),
|
|
'main-shop' => $this->loadShopDomainRoutes(),
|
|
'crm' => $this->loadCrmDomainRoutes(),
|
|
'portal' => $this->loadPortalDomainRoutes(),
|
|
'checkout' => $this->loadCheckoutDomainRoutes(),
|
|
'user-shop' => $this->loadUserShopDomainRoutes(),
|
|
default => null // Unknown domains are handled by middleware
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Load all routes (fallback for route caching)
|
|
*/
|
|
protected function loadAllRoutes(): void
|
|
{
|
|
// Load all domain-specific routes
|
|
$this->loadMainDomainRoutes();
|
|
$this->loadShopDomainRoutes();
|
|
$this->loadCrmDomainRoutes();
|
|
$this->loadPortalDomainRoutes();
|
|
$this->loadCheckoutDomainRoutes();
|
|
$this->loadUserShopDomainRoutes();
|
|
}
|
|
|
|
/**
|
|
* Load main domain routes (mivita.care)
|
|
*/
|
|
protected function loadMainDomainRoutes(): void
|
|
{
|
|
Route::group([
|
|
'middleware' => ['domain.resolver'],
|
|
'domain' => $this->getMainDomain(),
|
|
], base_path('routes/domains/main.php'));
|
|
}
|
|
|
|
/**
|
|
* Load shop domain routes (mivita.shop)
|
|
*/
|
|
protected function loadShopDomainRoutes(): void
|
|
{
|
|
Route::group([
|
|
'middleware' => ['domain.resolver'],
|
|
'domain' => $this->getShopDomain(),
|
|
], base_path('routes/domains/shop.php'));
|
|
}
|
|
|
|
/**
|
|
* Load CRM domain routes (my.mivita.care)
|
|
*/
|
|
protected function loadCrmDomainRoutes(): void
|
|
{
|
|
Route::group([
|
|
'middleware' => ['domain.resolver'],
|
|
'domain' => $this->getCrmDomain(),
|
|
], base_path('routes/domains/subdomains/crm.php'));
|
|
}
|
|
|
|
/**
|
|
* Load portal domain routes (in.mivita.care)
|
|
*/
|
|
protected function loadPortalDomainRoutes(): void
|
|
{
|
|
Route::group([
|
|
'middleware' => ['domain.resolver'],
|
|
'domain' => $this->getPortalDomain(),
|
|
], base_path('routes/domains/subdomains/portal.php'));
|
|
}
|
|
|
|
/**
|
|
* Load checkout domain routes (checkout.mivita.care)
|
|
*/
|
|
protected function loadCheckoutDomainRoutes(): void
|
|
{
|
|
Route::group([
|
|
'middleware' => ['domain.resolver'],
|
|
'domain' => $this->getCheckoutDomain(),
|
|
], base_path('routes/domains/subdomains/checkout.php'));
|
|
}
|
|
|
|
/**
|
|
* Load user shop domain routes ({slug}.mivita.care)
|
|
*/
|
|
protected function loadUserShopDomainRoutes(): void
|
|
{
|
|
Route::group([
|
|
'middleware' => ['domain.resolver'],
|
|
'domain' => $this->getUserShopDomain(),
|
|
], base_path('routes/domains/subdomains/user-shops.php'));
|
|
}
|
|
|
|
/**
|
|
* Get main domain pattern
|
|
*/
|
|
protected function getMainDomain(): string
|
|
{
|
|
$domain = config('app.domain', 'mivita');
|
|
$tld = config('app.tld_care', '.care');
|
|
return $domain . $tld;
|
|
}
|
|
|
|
/**
|
|
* Get shop domain pattern
|
|
*/
|
|
protected function getShopDomain(): string
|
|
{
|
|
$domain = config('app.domain', 'mivita');
|
|
$tld = config('app.tld_shop', '.shop');
|
|
return $domain . $tld;
|
|
}
|
|
|
|
/**
|
|
* Get CRM domain pattern
|
|
*/
|
|
protected function getCrmDomain(): string
|
|
{
|
|
$subdomain = rtrim(config('app.pre_url_crm', 'my.'), '.');
|
|
$domain = config('app.domain', 'mivita');
|
|
$tld = config('app.tld_care', '.care');
|
|
return $subdomain . '.' . $domain . $tld;
|
|
}
|
|
|
|
/**
|
|
* Get portal domain pattern
|
|
*/
|
|
protected function getPortalDomain(): string
|
|
{
|
|
$subdomain = rtrim(config('app.pre_url_portal', 'in.'), '.');
|
|
$domain = config('app.domain', 'mivita');
|
|
$tld = config('app.tld_care', '.care');
|
|
return $subdomain . '.' . $domain . $tld;
|
|
}
|
|
|
|
/**
|
|
* Get checkout domain pattern
|
|
*/
|
|
protected function getCheckoutDomain(): string
|
|
{
|
|
$subdomain = rtrim(config('app.pre_url_checkout', 'checkout.'), '.');
|
|
$domain = config('app.domain', 'mivita');
|
|
$tld = config('app.tld_care', '.care');
|
|
return $subdomain . '.' . $domain . $tld;
|
|
}
|
|
|
|
/**
|
|
* Get user shop domain pattern (wildcard subdomain)
|
|
*/
|
|
protected function getUserShopDomain(): string
|
|
{
|
|
$domain = config('app.domain', 'mivita');
|
|
$tld = config('app.tld_care', '.care');
|
|
return '{subdomain}.' . $domain . $tld;
|
|
}
|
|
|
|
/**
|
|
* Configure the rate limiters for the application
|
|
*/
|
|
protected function configureRateLimiting()
|
|
{
|
|
// API rate limiting
|
|
RateLimiter::for('api', function (Request $request) {
|
|
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
|
|
});
|
|
|
|
// Domain-specific rate limiting
|
|
RateLimiter::for('crm', function (Request $request) {
|
|
return Limit::perMinute(120)->by($request->user()?->id ?: $request->ip());
|
|
});
|
|
|
|
RateLimiter::for('portal', function (Request $request) {
|
|
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
|
|
});
|
|
|
|
RateLimiter::for('checkout', function (Request $request) {
|
|
return Limit::perMinute(30)->by($request->ip());
|
|
});
|
|
|
|
RateLimiter::for('user-shop', function (Request $request) {
|
|
return Limit::perMinute(100)->by($request->ip());
|
|
});
|
|
|
|
// Login rate limiting
|
|
RateLimiter::for('login', function (Request $request) {
|
|
return [
|
|
Limit::perMinute(5)->by($request->email . $request->ip()),
|
|
Limit::perMinute(10)->by($request->ip()),
|
|
];
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get route caching path based on domain
|
|
*/
|
|
public function getCachedRoutesPath()
|
|
{
|
|
// Use different cache files for different environments
|
|
$environment = app()->environment();
|
|
return $this->app->bootstrapPath("cache/routes-v7-{$environment}.php");
|
|
}
|
|
|
|
/**
|
|
* Determine if routes are cached
|
|
*/
|
|
public function routesAreCached()
|
|
{
|
|
return $this->app->routesAreCached();
|
|
}
|
|
|
|
/**
|
|
* Load the cached routes for the application
|
|
*/
|
|
public function loadCachedRoutes()
|
|
{
|
|
$this->app->booted(function () {
|
|
require $this->getCachedRoutesPath();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Register domain-specific route macros
|
|
*/
|
|
protected function registerRouteMacros(): void
|
|
{
|
|
// Macro for domain-aware redirects
|
|
Route::macro('domainRedirect', function (string $domainType, string $path = '/', int $status = 302) {
|
|
return function () use ($domainType, $path, $status) {
|
|
$domainService = app(DomainService::class);
|
|
$url = $domainService->buildUrl($domainType, $path);
|
|
return redirect($url, $status);
|
|
};
|
|
});
|
|
|
|
// Macro for user shop routes
|
|
Route::macro('userShop', function (callable $callback) {
|
|
return Route::group([
|
|
'middleware' => ['domain.resolver', 'user-shop.validate'],
|
|
], $callback);
|
|
});
|
|
|
|
// Macro for CRM routes
|
|
Route::macro('crm', function (callable $callback) {
|
|
return Route::group([
|
|
'middleware' => ['domain.resolver', 'auth'],
|
|
'prefix' => '',
|
|
], $callback);
|
|
});
|
|
}
|
|
}
|