F
Filamentβ€’4mo ago
Wim

Multi-tenant: search across all products

I have a multitenant application. My tenant is called 'organization'. I want a user to be able to ask information about a product by sending a message. I have therefore a MessageResource with below snippet. The idea is that a user can search across all products in the database, not only the products that he's owning (=assigned to his organization). Below code works but only shows the products linked to the organization. Select::make('product_id') ->label('Product') ->columnSpan(1) ->searchable() ->getSearchResultsUsing(function ($search) { if (strlen($search) < 3) { return []; } return Product::where('name', 'like', "%{$search}%") ->limit(50) ->get() ->pluck('name', 'id'); }) ->getOptionLabelUsing(fn ($value): ?string => Product::find($value)?->name) ->disabled(false), I also have the following: protected static function booted(): void { static::addGlobalScope('organization', function (Builder $query) { if (auth()->hasUser()) { $query->where('organization_id', auth()->user()->organization_id); } }); } This explains of course why I only see the products for the organization. I read that Filament does scoping to tenant automatically, so the above global scope seems redundant. Still I wanted to have it to have a secure feeling. Two quesions: 1) can I safely remove the global scope? 2) Is there a way I could still enforce a scope, except for this one resource (MessageResource)? Any suggestions?
Solution:
You would combine those. Sorry I was focusing on the resource itself but you actually need it on the select πŸ™ˆ
Jump to solution
8 Replies
toeknee
toekneeβ€’4mo ago
You can leave it in place just set the resource scope to be false
Dennis Koch
Dennis Kochβ€’4mo ago
can I safely remove the global scope?
Not sure whether the constraint is applied everywhere. It is applied for resources, but can't find anything for Select relationships.
2) Is there a way I could still enforce a scope, except for this one resource (MessageResource)?
If you have a global scope: Overwrite getEloquentQuery() and add ->withoutGlobalScope('organization'). To disable scoping of Filament overwrite public static function isScopedToTenant() and return false.
Wim
Wimβ€’4mo ago
Confused a bit: 1) Not having a static::addGlobalScope on the Product Model works 2) Having a static::addGlobalScope on the Product Model does not give all products (which is understandable). Overwriting public static function isScopedToTenant() to false, it not giving all the products. 3) Having a static::addGlobalScope on the Product Model and overwrite the getEloquentQuery()in the MessageResource is sth I cannot do as it is already used for the MessageResource (the retrieval of the products is done in the MessageResource and there is already a getEloquentQuery() in place) 4) When I nevertheless add the getEloquentQuery() with a return Animal::query()->withoutGlobalScope('organization'); I get only the Products belonging to the organization again.
Dennis Koch
Dennis Kochβ€’4mo ago
Overwriting public static function isScopedToTenant() to false, it not giving all the products.
That only overwrites Filaments scoping. Not your global scope
I cannot do as it is already used for the MessageResource (the retrieval of the products is done in the MessageResource and there is already a getEloquentQuery() in place)
I don't understand. When you already have a getEloquentQuery() then just add the code there?
When I nevertheless add the getEloquentQuery() with a return Animal::query()->withoutGlobalScope('organization'); I get only the Products belonging to the organization again.
You still need isScopedByTenant() do undo Filament's scoping Summary: If you only use Filament's scoping, just change isScopedByTenant. If you have an additional global scope, you need to additionally remove that via getEloquentQuery()
Wim
Wimβ€’4mo ago
It might be because it's Friday eve here, but how would I be able to combine the below. The first one is what is existing already and the second one I need to add. public static function getEloquentQuery(): Builder { return Topic::query(); } public static function getEloquentQuery(): Builder { return Product::query()->withoutGlobalScope('organization'); }
Solution
Dennis Koch
Dennis Kochβ€’4mo ago
You would combine those. Sorry I was focusing on the resource itself but you actually need it on the select πŸ™ˆ
Dennis Koch
Dennis Kochβ€’4mo ago
For the select I guess it might be enough to set getSearchResultsUsing() and return a query without the scope
Wim
Wimβ€’4mo ago
Hmmm, stupid I did not think about it, but it works ->getSearchResultsUsing(function ($search) { if (strlen($search) < 3) { return []; } return Product::where('name', 'like', "%{$search}%")->withoutGlobalScope('organization') ->limit(50) ->get() ->pluck('name', 'id'); })
Want results from more Discord servers?
Add your server