fix: workspace membership + middleware owner fallback

- DemoDataSeeder now creates workspace_members record for owner + sets default_workspace_id
- ResolveWorkspace middleware accepts workspace owners even without explicit member record
- Applied membership fix for nexxo@nimuli.com via PHP (existing installs)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
boban 2026-05-16 11:17:54 +02:00
parent 52d52824bc
commit ef0105098b
2 changed files with 11 additions and 1 deletions

View File

@ -20,7 +20,9 @@ class ResolveWorkspace
// 404 instead of 403 — don't leak existence across workspace boundaries
$user = $request->user();
if (! $user || ! $user->workspaceMemberships()->where('workspace_id', $workspace->id)->exists()) {
$isMember = $user && $user->workspaceMemberships()->where('workspace_id', $workspace->id)->exists();
$isOwner = $user && $workspace->owner_id === $user->id;
if (! $isMember && ! $isOwner) {
abort(404);
}

View File

@ -5,6 +5,7 @@ namespace Database\Seeders;
use App\Domains\Analytics\Models\Click;
use App\Domains\Link\Models\Link;
use App\Domains\Workspace\Models\Workspace;
use App\Domains\Workspace\Models\WorkspaceMember;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Carbon;
@ -24,6 +25,13 @@ class DemoDataSeeder extends Seeder
]
);
// Ensure owner has a membership record and default workspace set
WorkspaceMember::firstOrCreate(
['workspace_id' => $workspace->id, 'user_id' => $user->id],
['role' => 'owner', 'joined_at' => now()]
);
$user->updateQuietly(['default_workspace_id' => $workspace->id]);
$this->command->info("Workspace: {$workspace->name} ({$workspace->ulid})");
$slugs = ['nimuli', 'get-started', 'pricing', 'blog', 'docs', 'github', 'twitter', 'linkedin', 'youtube', 'discord', 'product', 'api', 'signup', 'login-link', 'partner', 'careers', 'press', 'legal', 'status', 'support'];