Open thubamamba opened 1 month ago
Keep in mind "Authentication != Authorization".
What's your DRF DEFAULT_PERMISSION_CLASSES
set to? By default, it's AllowAny
.
The django-tenant-users
app will by default Authenticate people globally. It's up to you to determine how to Authorize users per tenant. If you want to segment it where a user has full access to the APIs of a given tenant, then take a look at the TenantAccessMiddleware to see one way of doing that, and convert that logic into a DRF PERMISSIONS_CLASSES
.
Here is my REST_FRAMEWORK config:
REST_FRAMEWORK = {
"NON_FIELD_ERRORS_KEY": "errors",
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework_simplejwt.authentication.JWTAuthentication",
],
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.IsAuthenticated",
],
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
"PAGE_SIZE": 10,
}
Thanks for the docs, I will peruse and see if I can get it done. Do you maybe have plans to have an example DRF implemention?
Do you maybe have plans to have an example DRF implemention?
Not really as it's pretty "vanilla".
If you think it'd be helpful, more than happy to merge in a DRF Permission Class as an example that shows how you can prevent users who are not members (meaning the TenantUser.tenants
doesn't contain the given tenant) from accessing the Tenant's APIs. Feel free to open a PR!
Do you maybe have plans to have an example DRF implemention?
Not really as it's pretty "vanilla".
If you think it'd be helpful, more than happy to merge in a DRF Permission Class as an example that shows how you can prevent users who are not members (meaning the
TenantUser.tenants
doesn't contain the given tenant) from accessing the Tenant's APIs. Feel free to open a PR!
Hey @Dresdn, thank you for your willingness to help. I have opened the PR as requested.
@Dresdn We are facing the same questions right now, so I just wanted to briefly ask whether I fully understood your statements (also in the PR :)).
We are using django-tenants
+ django-tenants-users
+ django_restframework
+ djoser
+ django_simplejwt
. We obtain a JWT and supply it as Header.
We tried adding a Middleware, but in middlewares, we don't have the request.user
object. However, in permission classes, we have it. I've seen issues in django_simplejwt
, so I assume this is correct.
Now, in order to protect tenant-aware views (i.e. UserA
who is assigned to TenantA
should be able to access tenanta.myapp.com/api/v1/products
, but NOT tenantb.myapp.com/api/v1/products
), all we had to do in our proof of concept was to add a custom permission class like so:
class HasTenantAccess(BasePermission):
def has_permission(self, request: WSGIRequest, view: View) -> bool:
tenant = get_current_tenant() # typehint is wrong
return tenant.user_set.filter(id=request.user.id).exists()
This uses your utils class, fetches the tenant and then checks whether the given user is a member of this tenant. Usage is like so:
@permission_classes([IsAuthenticated, HasTenantAccess])
class ProjectViewSet(viewsets.ModelViewSet):
queryset = Project.objects.all()
serializer_class = ProjectSerializer
This will disallow anonymous access AND check whether the user is allowed to this tenant. So if UserA
accesses this endpoint on the TenantB
subdomain, they will receive an error:
{
"detail": "You do not have permission to perform this action."
}
Now: Is this the proper way how you would envision this and what you meant with your statements?
If so, I'll be happy to create a PR with an example for the documentation on this.
Thank you! :-)
That's exactly what I was thinking @Tugark.
The question is: Where to put it? The tenant_users.permissions
and tenant_users.tenants
modules drive me nuts working with the package (why not put everything just in tenant_users
?!?), and I think doing tenant_users.permissions.permissions
is silly.
Curious what you come up with!
I have been trying to find an implementation on Django Rest Framework, to no avail. Reading the docs, I don't see anything that I have missed, I am able to create public and additional tenants, however, when testing, users who don't even belong to a tenant are able to create resources for those respective tenants. I really would appreciate the guidance here. :
In the custom user, I have:
Worth noting is that I am using SimpleJWT, with Djoser and the following is my config: