Implement multi-tenancy support with OAuth2 authentication for tenant admins, Stripe integration for event purchases and credits ledger, new Filament resources for event purchases, updated API routes and middleware for tenant isolation and token guarding, added factories/seeders/migrations for new models (Tenant, EventPurchase, OAuth entities, etc.), enhanced tests, and documentation updates. Removed outdated DemoAchievementsSeeder.

This commit is contained in:
2025-09-17 19:56:54 +02:00
parent 5fbb9cb240
commit 42d6e98dff
84 changed files with 6125 additions and 155 deletions

View File

@@ -0,0 +1,135 @@
<?php
namespace App\Http\Controllers\Api\Tenant;
use App\Http\Controllers\Controller;
use App\Http\Requests\Tenant\SettingsStoreRequest;
use App\Models\Tenant;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
class SettingsController extends Controller
{
/**
* Get the tenant's settings.
*
* @param Request $request
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
$tenant = $request->tenant;
return response()->json([
'message' => 'Settings erfolgreich abgerufen.',
'data' => [
'id' => $tenant->id,
'settings' => $tenant->settings ?? [],
'updated_at' => $tenant->settings_updated_at?->toISOString(),
],
]);
}
/**
* Update the tenant's settings.
*
* @param SettingsStoreRequest $request
* @return JsonResponse
*/
public function update(SettingsStoreRequest $request): JsonResponse
{
$tenant = $request->tenant;
// Merge new settings with existing ones
$currentSettings = $tenant->settings ?? [];
$newSettings = array_merge($currentSettings, $request->validated()['settings']);
$tenant->update([
'settings' => $newSettings,
'settings_updated_at' => now(),
]);
return response()->json([
'message' => 'Settings erfolgreich aktualisiert.',
'data' => [
'id' => $tenant->id,
'settings' => $newSettings,
'updated_at' => now()->toISOString(),
],
]);
}
/**
* Reset tenant settings to defaults.
*
* @param Request $request
* @return JsonResponse
*/
public function reset(Request $request): JsonResponse
{
$tenant = $request->tenant;
$defaultSettings = [
'branding' => [
'logo_url' => null,
'primary_color' => '#3B82F6',
'secondary_color' => '#1F2937',
'font_family' => 'Inter, sans-serif',
],
'features' => [
'photo_likes_enabled' => true,
'event_checklist' => true,
'custom_domain' => false,
'advanced_analytics' => false,
],
'custom_domain' => null,
'contact_email' => $tenant->contact_email,
'event_default_type' => 'general',
];
$tenant->update([
'settings' => $defaultSettings,
'settings_updated_at' => now(),
]);
return response()->json([
'message' => 'Settings auf Standardwerte zurückgesetzt.',
'data' => [
'id' => $tenant->id,
'settings' => $defaultSettings,
'updated_at' => now()->toISOString(),
],
]);
}
/**
* Validate custom domain availability.
*
* @param Request $request
* @return JsonResponse
*/
public function validateDomain(Request $request): JsonResponse
{
$domain = $request->input('domain');
if (!$domain) {
return response()->json(['error' => 'Domain ist erforderlich.'], 400);
}
// Simple validation - in production, check DNS records or database uniqueness
if (!preg_match('/^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/', $domain)) {
return response()->json([
'available' => false,
'message' => 'Ungültiges Domain-Format.',
]);
}
// Check if domain is already taken by another tenant
$taken = Tenant::where('custom_domain', $domain)->where('id', '!=', $request->tenant->id)->exists();
return response()->json([
'available' => !$taken,
'message' => $taken ? 'Domain ist bereits vergeben.' : 'Domain ist verfügbar.',
]);
}
}