diff --git a/app/Filament/SuperAdmin/Pages/Auth/Login.php b/app/Filament/SuperAdmin/Pages/Auth/Login.php index c6711d5..31361e6 100644 --- a/app/Filament/SuperAdmin/Pages/Auth/Login.php +++ b/app/Filament/SuperAdmin/Pages/Auth/Login.php @@ -40,7 +40,7 @@ class Login extends BaseLogin implements HasForms } // SuperAdmin-spezifisch: Prüfe auf SuperAdmin-Rolle, keine Tenant-Prüfung - if ($user->role !== 'super_admin') { + if (! $user->isSuperAdmin()) { $authGuard->logout(); throw ValidationException::withMessages([ diff --git a/app/Filament/SuperAdmin/Pages/GuestPolicySettingsPage.php b/app/Filament/SuperAdmin/Pages/GuestPolicySettingsPage.php index 7eb87d5..b8d3096 100644 --- a/app/Filament/SuperAdmin/Pages/GuestPolicySettingsPage.php +++ b/app/Filament/SuperAdmin/Pages/GuestPolicySettingsPage.php @@ -45,11 +45,11 @@ class GuestPolicySettingsPage extends Page public int $join_token_failure_decay_minutes = 5; - public int $join_token_access_limit = 120; + public int $join_token_access_limit = 300; public int $join_token_access_decay_minutes = 1; - public int $join_token_download_limit = 60; + public int $join_token_download_limit = 120; public int $join_token_download_decay_minutes = 1; @@ -69,9 +69,9 @@ class GuestPolicySettingsPage extends Page $this->per_device_upload_limit = (int) ($settings->per_device_upload_limit ?? 50); $this->join_token_failure_limit = (int) ($settings->join_token_failure_limit ?? 10); $this->join_token_failure_decay_minutes = (int) ($settings->join_token_failure_decay_minutes ?? 5); - $this->join_token_access_limit = (int) ($settings->join_token_access_limit ?? 120); + $this->join_token_access_limit = (int) ($settings->join_token_access_limit ?? 300); $this->join_token_access_decay_minutes = (int) ($settings->join_token_access_decay_minutes ?? 1); - $this->join_token_download_limit = (int) ($settings->join_token_download_limit ?? 60); + $this->join_token_download_limit = (int) ($settings->join_token_download_limit ?? 120); $this->join_token_download_decay_minutes = (int) ($settings->join_token_download_decay_minutes ?? 1); $this->join_token_ttl_hours = (int) ($settings->join_token_ttl_hours ?? 168); $this->share_link_ttl_hours = (int) ($settings->share_link_ttl_hours ?? 48); diff --git a/app/Http/Controllers/Api/Tenant/EventController.php b/app/Http/Controllers/Api/Tenant/EventController.php index 413a9a5..5c10775 100644 --- a/app/Http/Controllers/Api/Tenant/EventController.php +++ b/app/Http/Controllers/Api/Tenant/EventController.php @@ -16,6 +16,7 @@ use App\Models\Package; use App\Models\PackagePurchase; use App\Models\Photo; use App\Models\Tenant; +use App\Models\User; use App\Services\EventJoinTokenService; use App\Support\ApiError; use Illuminate\Http\JsonResponse; @@ -88,12 +89,15 @@ class EventController extends Controller $tenant = Tenant::findOrFail($tenantId); } + $actor = $request->user(); + $isSuperAdmin = $actor instanceof User && $actor->isSuperAdmin(); + // Package check is now handled by middleware $validated = $request->validated(); $tenantId = $tenant->id; - $requestedPackageId = $validated['package_id'] ?? null; + $requestedPackageId = $isSuperAdmin ? $request->integer('package_id') : null; unset($validated['package_id']); $tenantPackage = $tenant->tenantPackages() @@ -108,6 +112,10 @@ class EventController extends Controller $package = Package::query()->find($requestedPackageId); } + if (! $package && $isSuperAdmin) { + $package = $this->resolveOwnerPackage(); + } + if (! $package && $tenantPackage) { $package = $tenantPackage->package ?? Package::query()->find($tenantPackage->package_id); } @@ -121,7 +129,7 @@ class EventController extends Controller $requiresWaiver = $package->isEndcustomer(); $latestPurchase = $requiresWaiver ? $this->resolveLatestPackagePurchase($tenant, $package) : null; $existingWaiver = $latestPurchase ? data_get($latestPurchase->metadata, 'consents.digital_content_waiver_at') : null; - $needsWaiver = $requiresWaiver && ! $existingWaiver; + $needsWaiver = ! $isSuperAdmin && $requiresWaiver && ! $existingWaiver; if ($needsWaiver && ! $request->boolean('accepted_waiver')) { throw ValidationException::withMessages([ @@ -182,7 +190,7 @@ class EventController extends Controller $eventData = Arr::only($eventData, $allowed); - $event = DB::transaction(function () use ($tenant, $eventData, $package) { + $event = DB::transaction(function () use ($tenant, $eventData, $package, $isSuperAdmin) { $event = Event::create($eventData); EventPackage::create([ @@ -193,7 +201,7 @@ class EventController extends Controller 'gallery_expires_at' => $package->gallery_days ? now()->addDays($package->gallery_days) : null, ]); - if ($package->isReseller()) { + if ($package->isReseller() && ! $isSuperAdmin) { $note = sprintf('Event #%d created (%s)', $event->id, $event->name); if (! $tenant->consumeEventAllowance(1, 'event.create', $note)) { @@ -229,6 +237,15 @@ class EventController extends Controller ->first(); } + private function resolveOwnerPackage(): ?Package + { + $ownerPackage = Package::query() + ->where('slug', 'pro') + ->first(); + + return $ownerPackage ?? Package::query()->find(3); + } + private function recordEventStartWaiver(Tenant $tenant, Package $package, ?PackagePurchase $purchase): void { $timestamp = now(); diff --git a/app/Http/Controllers/Api/Tenant/EventMemberController.php b/app/Http/Controllers/Api/Tenant/EventMemberController.php index da05f3c..733114d 100644 --- a/app/Http/Controllers/Api/Tenant/EventMemberController.php +++ b/app/Http/Controllers/Api/Tenant/EventMemberController.php @@ -135,7 +135,7 @@ class EventMemberController extends Controller $user->password = Hash::make(Str::random(32)); } - if ($user->tenant_id && (int) $user->tenant_id !== (int) $tenant->id && $user->role !== 'super_admin') { + if ($user->tenant_id && (int) $user->tenant_id !== (int) $tenant->id && ! $user->isSuperAdmin()) { throw ValidationException::withMessages([ 'email' => __('Dieser Benutzer ist einem anderen Mandanten zugeordnet.'), ]); @@ -143,9 +143,9 @@ class EventMemberController extends Controller $user->tenant_id = $tenant->id; - if ($role === 'tenant_admin' && $user->role !== 'super_admin') { + if ($role === 'tenant_admin' && ! $user->isSuperAdmin()) { $user->role = 'tenant_admin'; - } elseif (! in_array($user->role, ['tenant_admin', 'super_admin'], true)) { + } elseif (! in_array($user->role, ['tenant_admin', 'super_admin', 'superadmin'], true)) { $user->role = 'member'; } diff --git a/app/Http/Controllers/Api/Tenant/TenantAdminTokenController.php b/app/Http/Controllers/Api/Tenant/TenantAdminTokenController.php index 6978af4..8997d72 100644 --- a/app/Http/Controllers/Api/Tenant/TenantAdminTokenController.php +++ b/app/Http/Controllers/Api/Tenant/TenantAdminTokenController.php @@ -193,11 +193,11 @@ class TenantAdminTokenController extends Controller $abilities[] = 'tenant:'.$user->tenant_id; } - if (in_array($user->role, ['tenant_admin', 'admin', 'super_admin'], true)) { + if (in_array($user->role, ['tenant_admin', 'admin', 'super_admin', 'superadmin'], true)) { $abilities[] = 'tenant-admin'; } - if ($user->role === 'super_admin') { + if ($user->isSuperAdmin()) { $abilities[] = 'super-admin'; } @@ -219,7 +219,7 @@ class TenantAdminTokenController extends Controller private function ensureUserCanAccessPanel(User $user): void { - if (in_array($user->role, ['tenant_admin', 'admin', 'super_admin'], true)) { + if (in_array($user->role, ['tenant_admin', 'admin', 'super_admin', 'superadmin'], true)) { return; } diff --git a/app/Http/Controllers/Api/Tenant/TenantFeedbackController.php b/app/Http/Controllers/Api/Tenant/TenantFeedbackController.php index fedac7d..a7f1880 100644 --- a/app/Http/Controllers/Api/Tenant/TenantFeedbackController.php +++ b/app/Http/Controllers/Api/Tenant/TenantFeedbackController.php @@ -9,8 +9,8 @@ use App\Models\User; use App\Notifications\TenantFeedbackSubmitted; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use Illuminate\Validation\Rule; use Illuminate\Support\Facades\Notification; +use Illuminate\Validation\Rule; class TenantFeedbackController extends Controller { @@ -56,7 +56,7 @@ class TenantFeedbackController extends Controller ]); $recipients = User::query() - ->where('role', 'super_admin') + ->whereIn('role', ['super_admin', 'superadmin']) ->whereNotNull('email') ->get(); diff --git a/app/Http/Controllers/Api/TenantAuth/TenantAdminPasswordResetController.php b/app/Http/Controllers/Api/TenantAuth/TenantAdminPasswordResetController.php index acf29aa..3ad5fbb 100644 --- a/app/Http/Controllers/Api/TenantAuth/TenantAdminPasswordResetController.php +++ b/app/Http/Controllers/Api/TenantAuth/TenantAdminPasswordResetController.php @@ -80,7 +80,7 @@ class TenantAdminPasswordResetController extends Controller private function canAccessEventAdmin(User $user): bool { - if (in_array($user->role, ['tenant_admin', 'admin', 'super_admin'], true)) { + if (in_array($user->role, ['tenant_admin', 'admin', 'super_admin', 'superadmin'], true)) { return true; } diff --git a/app/Http/Controllers/Auth/AuthenticatedSessionController.php b/app/Http/Controllers/Auth/AuthenticatedSessionController.php index abc82fe..e80184e 100644 --- a/app/Http/Controllers/Auth/AuthenticatedSessionController.php +++ b/app/Http/Controllers/Auth/AuthenticatedSessionController.php @@ -155,7 +155,7 @@ class AuthenticatedSessionController extends Controller } // Super admins go to Filament superadmin panel - if ($user && $user->role === 'super_admin') { + if ($user && $user->isSuperAdmin()) { return '/super-admin'; } diff --git a/app/Http/Controllers/TenantAdminAuthController.php b/app/Http/Controllers/TenantAdminAuthController.php index 9ea3366..5bf898b 100644 --- a/app/Http/Controllers/TenantAdminAuthController.php +++ b/app/Http/Controllers/TenantAdminAuthController.php @@ -12,7 +12,7 @@ class TenantAdminAuthController extends Controller $user = Auth::user(); // Allow only tenant_admin and super_admin - if ($user && in_array($user->role, ['tenant_admin', 'super_admin'])) { + if ($user && in_array($user->role, ['tenant_admin', 'super_admin', 'superadmin'], true)) { return view('admin'); } diff --git a/app/Http/Controllers/TenantAdminGoogleController.php b/app/Http/Controllers/TenantAdminGoogleController.php index 28e278f..06d5a67 100644 --- a/app/Http/Controllers/TenantAdminGoogleController.php +++ b/app/Http/Controllers/TenantAdminGoogleController.php @@ -46,7 +46,7 @@ class TenantAdminGoogleController extends Controller /** @var User|null $user */ $user = User::query()->where('email', $email)->first(); - if (! $user || ! in_array($user->role, ['tenant_admin', 'super_admin'], true)) { + if (! $user || ! in_array($user->role, ['tenant_admin', 'super_admin', 'superadmin'], true)) { return $this->sendBackWithError($request, 'google_no_match', 'No tenant admin account is linked to this Google address.'); } diff --git a/app/Http/Middleware/CreditCheckMiddleware.php b/app/Http/Middleware/CreditCheckMiddleware.php index 1c49b6c..e9a5c5e 100644 --- a/app/Http/Middleware/CreditCheckMiddleware.php +++ b/app/Http/Middleware/CreditCheckMiddleware.php @@ -3,6 +3,7 @@ namespace App\Http\Middleware; use App\Models\Tenant; +use App\Models\User; use App\Services\Packages\PackageLimitEvaluator; use App\Support\ApiError; use Closure; @@ -26,7 +27,7 @@ class CreditCheckMiddleware ]); } - if ($this->requiresCredits($request)) { + if ($this->requiresCredits($request) && ! $this->shouldBypassCreditCheck($request, $tenant)) { $violation = $this->limitEvaluator->assessEventCreation($tenant); if ($violation !== null) { @@ -43,6 +44,24 @@ class CreditCheckMiddleware return $next($request); } + private function shouldBypassCreditCheck(Request $request, Tenant $tenant): bool + { + $user = $request->user(); + if (! $user instanceof User) { + return false; + } + + if (! $user->isSuperAdmin()) { + return false; + } + + if (! $user->tenant_id) { + return false; + } + + return (int) $user->tenant_id === (int) $tenant->id; + } + private function requiresCredits(Request $request): bool { return $request->isMethod('post') diff --git a/app/Http/Middleware/EnsureTenantAdminToken.php b/app/Http/Middleware/EnsureTenantAdminToken.php index d0586b1..8805443 100644 --- a/app/Http/Middleware/EnsureTenantAdminToken.php +++ b/app/Http/Middleware/EnsureTenantAdminToken.php @@ -42,7 +42,7 @@ class EnsureTenantAdminToken /** @var Tenant|null $tenant */ $tenant = $user->tenant; - if (! $tenant && $user->role === 'super_admin') { + if (! $tenant && $user->isSuperAdmin()) { $requestedTenantId = $this->resolveRequestedTenantId($request); if ($requestedTenantId !== null) { @@ -50,14 +50,14 @@ class EnsureTenantAdminToken } } - if (! $tenant && $user->role !== 'super_admin') { + if (! $tenant && ! $user->isSuperAdmin()) { return $this->forbiddenResponse('Tenant context missing for user.'); } if ($tenant) { $request->attributes->set('tenant_id', $tenant->id); $request->attributes->set('tenant', $tenant); - } elseif ($user->role === 'super_admin') { + } elseif ($user->isSuperAdmin()) { $requestedTenantId = $this->resolveRequestedTenantId($request); if ($requestedTenantId !== null) { $request->attributes->set('tenant_id', $requestedTenantId); @@ -96,7 +96,7 @@ class EnsureTenantAdminToken */ protected function allowedRoles(): array { - return ['tenant_admin', 'super_admin', 'admin']; + return ['tenant_admin', 'super_admin', 'superadmin', 'admin']; } protected function forbiddenRoleMessage(): string diff --git a/app/Http/Middleware/EnsureTenantCollaboratorToken.php b/app/Http/Middleware/EnsureTenantCollaboratorToken.php index df474c6..77d6190 100644 --- a/app/Http/Middleware/EnsureTenantCollaboratorToken.php +++ b/app/Http/Middleware/EnsureTenantCollaboratorToken.php @@ -9,7 +9,7 @@ class EnsureTenantCollaboratorToken extends EnsureTenantAdminToken { protected function allowedRoles(): array { - return ['tenant_admin', 'super_admin', 'admin', 'member']; + return ['tenant_admin', 'super_admin', 'superadmin', 'admin', 'member']; } protected function forbiddenRoleMessage(): string diff --git a/app/Http/Middleware/PackageMiddleware.php b/app/Http/Middleware/PackageMiddleware.php index e2b91b4..093e700 100644 --- a/app/Http/Middleware/PackageMiddleware.php +++ b/app/Http/Middleware/PackageMiddleware.php @@ -3,6 +3,7 @@ namespace App\Http\Middleware; use App\Models\Tenant; +use App\Models\User; use App\Services\Packages\PackageLimitEvaluator; use App\Support\ApiError; use Closure; @@ -26,7 +27,7 @@ class PackageMiddleware ]); } - if ($this->requiresPackageCheck($request)) { + if ($this->requiresPackageCheck($request) && ! $this->shouldBypassPackageCheck($request, $tenant)) { $violation = $this->detectViolation($request, $tenant); if ($violation !== null) { @@ -43,6 +44,24 @@ class PackageMiddleware return $next($request); } + private function shouldBypassPackageCheck(Request $request, Tenant $tenant): bool + { + $user = $request->user(); + if (! $user instanceof User) { + return false; + } + + if (! $user->isSuperAdmin()) { + return false; + } + + if (! $user->tenant_id) { + return false; + } + + return (int) $user->tenant_id === (int) $tenant->id; + } + private function requiresPackageCheck(Request $request): bool { return $request->isMethod('post') && ( diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index fa0d496..e98f509 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -112,7 +112,7 @@ class RedirectIfAuthenticated extends BaseMiddleware return '/event-admin/dashboard'; } - if ($user && $user->role === 'super_admin') { + if ($user && $user->isSuperAdmin()) { return '/super-admin'; } diff --git a/app/Http/Middleware/SuperAdminAuth.php b/app/Http/Middleware/SuperAdminAuth.php index 1678b31..9e157c7 100644 --- a/app/Http/Middleware/SuperAdminAuth.php +++ b/app/Http/Middleware/SuperAdminAuth.php @@ -4,9 +4,9 @@ namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; -use Symfony\Component\HttpFoundation\Response; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Log; +use Symfony\Component\HttpFoundation\Response; class SuperAdminAuth { @@ -21,17 +21,17 @@ class SuperAdminAuth return $next($request); } - if (!Auth::check()) { + if (! Auth::check()) { abort(403, 'Nicht angemeldet.'); } $user = Auth::user(); - Log::info('SuperAdminAuth: User ID ' . $user->id . ', role: ' . $user->role); + Log::info('SuperAdminAuth: User ID '.$user->id.', role: '.$user->role); - if ($user->role !== 'super_admin') { - abort(403, 'Zugriff nur für SuperAdmin. User ID: ' . $user->id . ', Role: ' . $user->role); + if (! $user->isSuperAdmin()) { + abort(403, 'Zugriff nur für SuperAdmin. User ID: '.$user->id.', Role: '.$user->role); } return $next($request); } -} \ No newline at end of file +} diff --git a/app/Http/Requests/Tenant/EventStoreRequest.php b/app/Http/Requests/Tenant/EventStoreRequest.php index deb5009..c76fe09 100644 --- a/app/Http/Requests/Tenant/EventStoreRequest.php +++ b/app/Http/Requests/Tenant/EventStoreRequest.php @@ -30,6 +30,7 @@ class EventStoreRequest extends FormRequest 'event_date' => ['required', 'date', 'after_or_equal:today'], 'location' => ['nullable', 'string', 'max:255'], 'event_type_id' => ['required', 'exists:event_types,id'], + 'package_id' => ['nullable', 'integer', 'exists:packages,id'], 'max_participants' => ['nullable', 'integer', 'min:1', 'max:10000'], 'public_url' => ['nullable', 'url', 'max:500'], 'custom_domain' => ['nullable', 'string', 'max:255'], diff --git a/app/Models/GuestPolicySetting.php b/app/Models/GuestPolicySetting.php index 92b1c8a..c32735b 100644 --- a/app/Models/GuestPolicySetting.php +++ b/app/Models/GuestPolicySetting.php @@ -41,9 +41,9 @@ class GuestPolicySetting extends Model 'per_device_upload_limit' => 50, 'join_token_failure_limit' => (int) config('join_tokens.failure_limit', 10), 'join_token_failure_decay_minutes' => (int) config('join_tokens.failure_decay_minutes', 5), - 'join_token_access_limit' => (int) config('join_tokens.access_limit', 120), + 'join_token_access_limit' => (int) config('join_tokens.access_limit', 300), 'join_token_access_decay_minutes' => (int) config('join_tokens.access_decay_minutes', 1), - 'join_token_download_limit' => (int) config('join_tokens.download_limit', 60), + 'join_token_download_limit' => (int) config('join_tokens.download_limit', 120), 'join_token_download_decay_minutes' => (int) config('join_tokens.download_decay_minutes', 1), 'join_token_ttl_hours' => 168, 'share_link_ttl_hours' => (int) config('share-links.ttl_hours', 48), diff --git a/app/Models/User.php b/app/Models/User.php index b53683c..9591f8b 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -69,6 +69,16 @@ class User extends Authenticatable implements FilamentHasTenants, FilamentUser, ]; } + public function isSuperAdmin(): bool + { + return self::isSuperAdminRole($this->role); + } + + public static function isSuperAdminRole(?string $role): bool + { + return in_array($role, ['super_admin', 'superadmin'], true); + } + /** * Retrieve the user by the given credentials. */ @@ -127,12 +137,12 @@ class User extends Authenticatable implements FilamentHasTenants, FilamentUser, public function canAccessPanel(Panel $panel): bool { - if (! $this->email_verified_at && $this->role !== 'super_admin') { + if (! $this->email_verified_at && ! $this->isSuperAdmin()) { return false; } return match ($panel->getId()) { - 'superadmin' => $this->role === 'super_admin', + 'superadmin' => $this->isSuperAdmin(), 'admin' => $this->role === 'tenant_admin', default => false, }; @@ -140,7 +150,7 @@ class User extends Authenticatable implements FilamentHasTenants, FilamentUser, public function canAccessTenant(Model $tenant): bool { - if ($this->role === 'super_admin') { + if ($this->isSuperAdmin()) { return true; } @@ -155,7 +165,7 @@ class User extends Authenticatable implements FilamentHasTenants, FilamentUser, public function getTenants(Panel $panel): array|Collection { - if ($this->role === 'super_admin') { + if ($this->isSuperAdmin()) { return Tenant::query()->orderBy('name')->get(); } diff --git a/app/Policies/PurchaseHistoryPolicy.php b/app/Policies/PurchaseHistoryPolicy.php index 60cd8f9..2e63737 100644 --- a/app/Policies/PurchaseHistoryPolicy.php +++ b/app/Policies/PurchaseHistoryPolicy.php @@ -12,12 +12,11 @@ class PurchaseHistoryPolicy public function viewAny(User $user): bool { - return $user->role === 'super_admin'; + return $user->isSuperAdmin(); } public function view(User $user, PurchaseHistory $purchaseHistory): bool { - return $user->role === 'super_admin'; + return $user->isSuperAdmin(); } } - diff --git a/app/Policies/TenantPolicy.php b/app/Policies/TenantPolicy.php index 5bb1c1a..18acfe3 100644 --- a/app/Policies/TenantPolicy.php +++ b/app/Policies/TenantPolicy.php @@ -15,7 +15,7 @@ class TenantPolicy */ public function viewAny(User $user): bool { - return $user->role === 'super_admin'; + return $user->isSuperAdmin(); } /** @@ -35,7 +35,7 @@ class TenantPolicy */ public function create(User $user): bool { - return $user->role === 'super_admin'; + return $user->isSuperAdmin(); } /** @@ -43,7 +43,7 @@ class TenantPolicy */ public function update(User $user, Tenant $tenant): bool { - return $user->role === 'super_admin'; + return $user->isSuperAdmin(); } /** @@ -51,7 +51,7 @@ class TenantPolicy */ public function delete(User $user, Tenant $tenant): bool { - return $user->role === 'super_admin'; + return $user->isSuperAdmin(); } /** @@ -59,6 +59,6 @@ class TenantPolicy */ public function suspend(User $user, Tenant $tenant): bool { - return $user->role === 'super_admin'; + return $user->isSuperAdmin(); } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index afa8356..64ede0a 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -155,7 +155,11 @@ class AppServiceProvider extends ServiceProvider $key = $tenantId ? 'tenant:'.$tenantId : ('ip:'.($request->ip() ?? 'unknown')); - return Limit::perMinute(100)->by($key); + return Limit::perMinute(600)->by($key); + }); + + RateLimiter::for('guest-api', function (Request $request) { + return Limit::perMinute(300)->by('guest-api:'.($request->ip() ?? 'unknown')); }); RateLimiter::for('tenant-auth', function (Request $request) { diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 703b1a0..a55e429 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -46,7 +46,7 @@ class AuthServiceProvider extends ServiceProvider }); Gate::before(function (User $user): ?bool { - return $user->role === 'super_admin' ? true : null; + return $user->isSuperAdmin() ? true : null; }); } } diff --git a/app/Services/Audit/SuperAdminAuditLogger.php b/app/Services/Audit/SuperAdminAuditLogger.php index bfb54d0..4ebd942 100644 --- a/app/Services/Audit/SuperAdminAuditLogger.php +++ b/app/Services/Audit/SuperAdminAuditLogger.php @@ -83,7 +83,7 @@ class SuperAdminAuditLogger private function shouldLog(?User $actor): bool { - if (! $actor || $actor->role !== 'super_admin') { + if (! $actor || ! $actor->isSuperAdmin()) { return false; } diff --git a/app/Support/TenantAuth.php b/app/Support/TenantAuth.php index 82d5d39..81e419e 100644 --- a/app/Support/TenantAuth.php +++ b/app/Support/TenantAuth.php @@ -24,15 +24,15 @@ class TenantAuth } $user = $request->user(); - if ($user && in_array($user->role, ['tenant_admin', 'admin', 'super_admin', 'member'], true)) { - if ($user->role !== 'super_admin' || (int) $user->tenant_id === (int) $tenantId) { + if ($user && in_array($user->role, ['tenant_admin', 'admin', 'super_admin', 'superadmin', 'member'], true)) { + if (! $user->isSuperAdmin() || (int) $user->tenant_id === (int) $tenantId) { return $user; } } $user = User::query() ->where('tenant_id', $tenantId) - ->whereIn('role', ['tenant_admin', 'admin', 'member']) + ->whereIn('role', ['tenant_admin', 'admin', 'super_admin', 'superadmin', 'member']) ->orderByDesc('email_verified_at') ->orderBy('id') ->first(); diff --git a/config/join_tokens.php b/config/join_tokens.php index eb535f2..cb3e3b4 100644 --- a/config/join_tokens.php +++ b/config/join_tokens.php @@ -4,9 +4,9 @@ return [ 'failure_limit' => (int) env('JOIN_TOKEN_FAILURE_LIMIT', 10), 'failure_decay_minutes' => (int) env('JOIN_TOKEN_FAILURE_DECAY', 5), - 'access_limit' => (int) env('JOIN_TOKEN_ACCESS_LIMIT', 120), + 'access_limit' => (int) env('JOIN_TOKEN_ACCESS_LIMIT', 300), 'access_decay_minutes' => (int) env('JOIN_TOKEN_ACCESS_DECAY', 1), - 'download_limit' => (int) env('JOIN_TOKEN_DOWNLOAD_LIMIT', 60), + 'download_limit' => (int) env('JOIN_TOKEN_DOWNLOAD_LIMIT', 120), 'download_decay_minutes' => (int) env('JOIN_TOKEN_DOWNLOAD_DECAY', 1), ]; diff --git a/database/seeders/SuperAdminSeeder.php b/database/seeders/SuperAdminSeeder.php index b07414a..47d752e 100644 --- a/database/seeders/SuperAdminSeeder.php +++ b/database/seeders/SuperAdminSeeder.php @@ -2,9 +2,11 @@ namespace Database\Seeders; +use App\Models\Tenant; +use App\Models\User; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\Hash; -use App\Models\User; +use Illuminate\Support\Str; class SuperAdminSeeder extends Seeder { @@ -12,12 +14,49 @@ class SuperAdminSeeder extends Seeder { $email = env('ADMIN_EMAIL', 'admin@example.com'); $password = env('ADMIN_PASSWORD', 'ChangeMe123!'); - User::updateOrCreate(['email'=>$email], [ + $user = User::updateOrCreate(['email' => $email], [ 'first_name' => 'Super', 'last_name' => 'Admin', 'password' => Hash::make($password), 'role' => 'super_admin', ]); + + $tenantSlug = env('OWNER_TENANT_SLUG', 'owner-tenant'); + $tenantName = env('OWNER_TENANT_NAME', 'Owner Tenant'); + + $tenant = Tenant::query()->firstOrCreate( + ['slug' => $tenantSlug], + [ + 'name' => $tenantName, + 'email' => $email, + 'contact_email' => $email, + 'user_id' => $user->id, + 'is_active' => true, + 'is_suspended' => false, + 'settings' => [ + 'contact_email' => $email, + ], + ], + ); + + if (! $tenant->slug) { + $tenant->forceFill(['slug' => Str::slug($tenantName)])->save(); + } + + if (! $tenant->user_id) { + $tenant->forceFill(['user_id' => $user->id])->save(); + } + + if (! $tenant->email) { + $tenant->forceFill(['email' => $email])->save(); + } + + if (! $tenant->contact_email) { + $tenant->forceFill(['contact_email' => $email])->save(); + } + + if ($user->tenant_id !== $tenant->id) { + $user->forceFill(['tenant_id' => $tenant->id])->save(); + } } } - diff --git a/playwright-report/index.html b/playwright-report/index.html index 49893aa..f3ac1d9 100644 --- a/playwright-report/index.html +++ b/playwright-report/index.html @@ -82,4 +82,4 @@ Error generating stack: `+n.message+`