TenantAtlas/app/Filament/Resources/Workspaces/WorkspaceResource.php
ahmido a989ef1a23 feat: workspace context enforcement (specs 070–072) (#85)
Implements specs 070–072 (workspace foundation, workspace-scoped tenant selection, managed-tenants workspace enforcement).

Highlights
- Adds Workspace + WorkspaceMembership models/migrations + middleware to persist/enforce current workspace context.
- Scopes tenant selection to the current workspace.
- Makes legacy `/admin/managed-tenants*` routes redirect into workspace-scoped URLs.
- Enforces tenant routes under `/admin/t/{tenant}` to 404 when workspace context is missing or mismatched.
- Fixes Filament page Blade wrappers so header actions render on choose-workspace / choose-tenant / no-access pages.

Verification
- Pint: `vendor/bin/sail bin pint --dirty`
- Tests: `vendor/bin/sail artisan test --compact tests/Feature/Guards/NoAdHocFilamentAuthPatternsTest.php tests/Feature/Workspaces tests/Feature/Filament/ChooseTenantIsWorkspaceScopedTest.php tests/Feature/Filament/ChooseTenantRequiresWorkspaceTest.php tests/Feature/Filament/TenantSwitcherUrlResolvesTenantTest.php tests/Feature/ManagedTenants tests/Feature/AdminNewRedirectTest.php`

Notes
- Filament v5 / Livewire v4 compatible.
- Panel provider registration stays in `bootstrap/providers.php` (Laravel 11+ rule).
- No new heavy frontend assets added.

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Reviewed-on: #85
2026-02-02 10:07:41 +00:00

63 lines
1.7 KiB
PHP

<?php
namespace App\Filament\Resources\Workspaces;
use App\Models\Workspace;
use BackedEnum;
use Filament\Forms;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Tables;
use Filament\Tables\Table;
use UnitEnum;
class WorkspaceResource extends Resource
{
protected static ?string $model = Workspace::class;
protected static bool $isScopedToTenant = false;
protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-squares-2x2';
protected static string|UnitEnum|null $navigationGroup = 'Settings';
public static function form(Schema $schema): Schema
{
return $schema
->schema([
Forms\Components\TextInput::make('name')
->required()
->maxLength(255),
Forms\Components\TextInput::make('slug')
->required()
->maxLength(255)
->unique(ignoreRecord: true),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name')
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('slug')
->searchable()
->sortable(),
])
->actions([
Tables\Actions\EditAction::make(),
]);
}
public static function getPages(): array
{
return [
'index' => Pages\ListWorkspaces::route('/'),
'create' => Pages\CreateWorkspace::route('/create'),
'edit' => Pages\EditWorkspace::route('/{record}/edit'),
];
}
}