is there a way to use spatie roles with teams id and filament multenancy on V3 ?
im trying to implement tenancy on v3 using filament multitenancy and also use spatie roles team functionality
https://spatie.be/docs/laravel-permission/v5/basic-usage/teams-permissions
at this point i can use roles and permissions and create the role with the tenant id associated butt i can'tmake it work in the relationship manager
any help will be appreciated ๐
any help will be appreciated ๐
Teams permissions | laravel-permission
laravel-permission
73 Replies
@justjosef hello, here is the post!
What exactly is not working? You're not getting the tenant-specific roles?
@ds_9206 ?
yes
im not having the tenant specific roles when im trying to attach the roles to the model user
even if the role has the teams_id with the team id asociated
+1
Confirmed, same issue with me, the tenant_id isn't included automatically
You have to adapt the queries in the relation manager to only fetch, show, associate (and so on) the roles for the current client by scoping the used queries
Hi, thanks for reply, the problem is not related to scope query, in my case, I can create roles on its CreatePanel, but if I create it using relation manager, an error says :
General error: 1364 Field 'team_id' doesn't have a default value
yeah, because the field/parameter is not set. You have to set it to current team id on creation
but we should not set it since we're already in the right tenant Id, you may check my repository and test it :
https://github.com/aeq-dev/filamentv3-bug-7511
GitHub
GitHub - aeq-dev/filamentv3-bug-7511
Contribute to aeq-dev/filamentv3-bug-7511 development by creating an account on GitHub.
Yes, you are 'in' the right tenant, but how would the relation manager know to set an arbitrary parameter on the model (
team_id
on role
) to the current tenant id?by the same method where we can create role without using relation manager and without setting the team id
How do you do that? In your linked repository, I don't see a RoleResource
In my case it's the package
user belongstomany package
I see, so it's a different question, not about the roles per se
Lol yes just noticed that sorry ๐
But the same applies here. For main resources, filament handles setting of the team_id, if that corresponds to your tenant model. But the relation manager doesn't do that. You have to set it yourself, e.g. by modifying the CreateAction
Thanks man
same for me
could you ggive me an example please?
Here's the code where I tried 3 methods but still doesn't work :
->headerActions([
Tables\Actions\CreateAction::make()
->before(function (array $data) {
$data['school_id'] = auth()->user()->school_id;
//dd($data['school_id']);
return $data;
})
/* ->using(function (array $data, string $model): Model {
array_push($data, ['school_id' => auth()->user()->school_id]);
dd($data);
return $model::create($data);
}) */
/* ->mutateFormDataUsing(function (array $data, RelationManager $livewire): array {
$data['school_id'] = $livewire->ownerRecord->school_id;
dd($data['school_id']);
return $data;
}), */
i've tried in tinkerwell the Roles::whereBelongsTo($tenant) and it works but when i try the same but instead $tenant Filament::getTenant()
doesnt work
even i've tried $query->whereBelongsTo($tenant)
after tried with Roles::whereBelongsTo($tenant it returns the right roles for the tenant but doesnt save it to the db
im stuck at that point
Yes this is the problem
i've tried on the method ->mutateFormDataUsing(function (array $data, RelationManager $livewire): array {
$data['school_id'] = $livewire->ownerRecord->school_id;
dd($data['school_id']);
return $data;
}),
obviously with my data, i've copied the method from above on ly for example
@ds_9206 that should work, if you set
team_id
to Filament::getTenant()->id
@ds_9206 if it works please share with us your code ๐
it works to get the roles with ->mutateFormDataUsing(function (Builder $query): array {
return Roles::whereBelongsTo(Filament::getTenant())
}),
but that it's not saving to the database the role attached to the user
also im using the attachaction
not the createaction
as you can see in my example above (1st message of this thread)
wait, so you're not creating a role, but attaching an existing one to a model? Then the role should already have the team_id set
but it's not
when i create the roles it works fine
im just trying to attach the role to the user
and then what error do you get? something's off here
can you share code?
yes, please wait
this works for the attach dialog but not when i save the attachment
when i click on the attach button it doesnt attach
Is there an error?
Nope, just doesn't attach to the user
this is when i do
Is there a new entry in the
model_has_roles
table?nope, the same entry
i doesnt create anything
even using
->using(function (array $data, string $model): Model {
return $model::create($data); }) it doesn't create nothing I've done thios `
return $model::create($data); }) it doesn't create nothing I've done thios `
but i got this
following the spatie docs for attach a role to a user
have you set the global team_id as per the docs?
yes
I've in a middleware this
setPermissionsTeamId(Filament::getTenant()->id);
$user = Auth::user();
// unset cached model relations so new team relations will get reloaded
$user->unsetRelation('roles', 'permissions');
this is the entire middleware
<?php
namespace App\Http\Middleware;
use App\Models\Company;
use Auth;
use Closure;
use Filament\Facades\Filament;
use Illuminate\Http\Request;
class UserCanAccessToTenantMiddleware
{
public function handle(Request $request, Closure $next)
{
if (Auth::check()) {
$isTenantOwner = $request->user()->company->contains(function (Company $value, int $key) {
return $value->id === Filament::getTenant()->id;
});
if ($isTenantOwner || $request->user()->hasRole('Super Admin')) {
setPermissionsTeamId(Filament::getTenant()->id);
$user = Auth::user();
// unset cached model relations so new team relations will get reloaded
$user->unsetRelation('roles', 'permissions');
return $next($request);
} else {
return abort(404,);
}
}
return $next($request);
}
}
what's the content of your roles table?
im only working with the "administrador" role
this - to me - is the smoking gun. I think there's something else going on, nothing to do with Filament.
If you can't assign the role to the user manually, it won't work in the Relationmanager
I'd check the stack trace to see what's going on and why it can't find the Administrador role, even if it exists
im getting this after a few seconds on the attachment modal
also the Administrador role is there it's just doesn't store in the db
if i attach the role manual it doesn't show on the relation tabe
also im using this trait for tenancy roles with filament
<?php
namespace App\Models\Support;
use App\Models\Company;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Spatie\Permission\Traits\HasRoles as SpatieHasRoles;
trait HasRoles
{
use SpatieHasRoles;
public function rolesOnTenant(Company $tenant): BelongsToMany
{
$originalTenantId = getPermissionsTeamId();
setPermissionsTeamId($tenant);
$roles = $this->roles();
setPermissionsTeamId($originalTenantId);
return $roles;
}
public function syncRolesOnTenant(
Company $tenant,
array|\Spatie\Permission\Contracts\Role|\Illuminate\Support\Collection|string|int $roles
): self
{
$originalTenantId = getPermissionsTeamId();
setPermissionsTeamId($tenant);
$this->syncRoles($roles);
setPermissionsTeamId($originalTenantId);
return $this;
}
public function assignRoleOnTenant(
Company $tenant,
array|string|int|\Spatie\Permission\Contracts\Role|\Illuminate\Support\Collection $role
): self
{
$originalTenantId = getPermissionsTeamId();
setPermissionsTeamId($tenant);
$this->assignRole($role);
setPermissionsTeamId($originalTenantId);
return $this;
}
}
At the moment I appreciate your help, it's a little late in my city and I'm dying of sleep and in part that doesn't help me to think well, I appreciate your help and I hope tomorrow I can continue counting on it, I wish you have a good day / night as appropriate
ok, you're doing so much custom stuff, it's hard to grasp what might be wrong
But as I see it, this is not a filament-related problem
have a nice night!
ialso think this is not a filament problem, im just asking for help on how can i integrate that with filament
really i love how it works filament
and i would like to implement this
im thinking to continue searching how to do this
thanks a lot
Please do! I think it's an issue of how you're using the spatie package, maybe ask there, or in the general laravel discord. But I'd mark this question as resolved as it's not related to filament itself. If you get the problem figured out, the approach I showed you will work, I'm sure.
Otherwise you can ask again, and I give permission to mention me in that case.
For me, I've just resolved it by adding a hidden input ๐
Hidden::make('school_id')
->default($this->ownerRecord->school_id),
While this may solve youโre issue. It is unsafe to do anything with idโs in hidden fields since they can be manipulated on the front end before saving the data back to the database.
you should use a function like mutateFormDataBeforeFill
https://filamentphp.com/docs/3.x/panels/resources/security#protecting-model-attributes
Thanks for help but it doesn't work :/
With Filament, it's difficult to understand sometimes, but everything is based on the
team_id
already that you don't need to assign a team_id
in roles. I would get rid of that completely on the roles side and change your tables to have the team_id field, or have pivot tables like post_user for Posts that belong to a User
The rest is handled at the highest level of multi tenancy
As far as I know, there isn't a way yet to have multiple Roles with multiple Teams for 1 User
You can only have 1 Role with multiple Teams for 1 User. The rest is handled through the specific table themselves (like a posts
table), where a team_id is set to the specific record (or through a pivot table)
This has taken me a lot to understand too, so I get where you're coming from, but there's no way to set the team_id to the roles table as far as I've found. Instead, it's set at the resource level (Posts, Articles, etc) and in their specific tables or through pivot relationship which is still only using the team ID and the Model ID (no Role ID)
The only time you need team_id
in the role assignment table, is when 1 User has multiple Roles for different Teams
You can also use Policies (through laravel Policies) to setup permissions but that's pretty much it - as far as I know
@BKF Dev @DSI understand and I thank you for the explanation, but in my case I need the role by team, for example, a role can exist in a team (company in my case) but not in another. That is why I need it, until now I have made it work only when I want to "attach" a role to a user, the role relationship manager returns only those that have been related to that team regardless of whether they belong to that team or not.
@JamesAutoDude
when i do
`
i got
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'company_id' in where clause is ambiguous
@DS So I see you are trying to put all roles into an array that belong to that specific company... I would move this to the Company model as a function:
And then you can just call that relationship instead of running the query directly, especially so it's in 1 central location in case you need to change it in the future for all spots that need to grab the roles...
Let me see about the rest though
Do you maybe have a demo repo of this?
@tuto1902 Do you think you can assist with this? ๐ฎ I know you know a ton about this stuff ๐
https://filamentphp.com/docs/3.x/panels/resources/relation-managers#attaching-and-detaching-records
@DS also check that relationship and make sure it's returning what it should, use
dd($roles)
in controller function (before the return) and it should output the values it grabbed
I think I wrote the relationship incorrectly as well :/Sure @JamesAutoDude Iโll get myself acquainted with the issue in this post before I can offer a response. Iโll do my best to assist ๐๐ป
@JamesAutoDude it returns roles but when do that i got `
I've a repo but its a private repo if you need i can give you part of the related code or i can make a new public repo replicating the problem if you want
if i remove the teams functionality from spatie everything work as spected but i really need to use spatie roles teams functionality with filament any help will be really appreciated
I think you may want to remove the teams functionality from Spatie and utilize Filament to do the rest for you. We just need to figure out how to set the company_id to a user/role
as a suggestion we can add the company_id to the roles and use a custom HasRoles trait to change the roles for each company ... if i can make it work i would make a PR to filament hoping it works for someone else, i really like filament and i want to somehow be able to contribute something. Thanks for your help.
@JamesAutoDude
I don't really have anything else to add on this one. The HasRoles trait sounds like a good plan. ๐๐ป
I think the best solution is here in this pr : https://github.com/bezhanSalleh/filament-shield/pull/216
We may discover all resources & pages from all panels, and then we can access to shied page on one admin panel
GitHub
Discovery by makzumi ยท Pull Request #216 ยท bezhanSalleh/filament-sh...
Hi Bezhan,
Followed your lead from my last PR and I added a new feature to show all resources, pages, widgets from different panels in a single panel.
Hope this one makes it,
Thanks
Added new confi...
i dont think that will be the best solution @BKF Dev because in that solution to the problem its not related to this one... it would be a work around but not solves my problem, anyway thanks for sharing this here...
@tuto1902 i've implemented the HasRoles trait and it works but sometimes i got some errors
What kind of errors are you getting?
i could find it, i've make a post here in the discord channel but it says something related to the query, please let me find it
sorry, it was here ๐ the error is this "SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'company_id' in where clause is ambiguous "
im using "company" as the relation for tenancy
Coud you share the HasRoles trait you've coded ?
hello! yes, sure,
Thanks,
I think spatie permission has team_id on its config file, we can use it as tenant_id
it can be changed as the proyect needs and as you say in the config, it can be used as the tenant_id