Django-tenants: Restrict access to public schema
I am trying to create a multi tenant app (with shared database and isolated schema) using this Django-Tenants package.
And I've followed the example videos to setup a demo: video1 and video2
app clients (models.py)
from django.db import models
from django_tenants.models import TenantMixin, DomainMixin
class Client(TenantMixin):
name = models.CharField("Customer name", max_length=100)
created_on = models.DateField(auto_now_add=True)
# default true, schema will be automatically created and synced when it is saved
auto_create_schema = True
class Domain(DomainMixin):
pass
app sweet_tenant (models.py)
from django.db import models
from applications.sweet_shared.models import SweetType
class Sweet(models.Model):
sweet_type = models.ForeignKey(SweetType, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
price = models.DecimalField(default=0, decimal_places=3, max_digits=8)
def __str__(self):
return self.name
app sweet_shared (models.py)
from django.db import models
class SweetType(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
settings
# Application definition
SHARED_APPS = [
"django_tenants", # mandatory
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# shared apps
"applications.clients",
"applications.sweet_shared",
]
TENANT_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# your tenant-specific apps
"applications.sweet_tenant",
)
INSTALLED_APPS = SHARED_APPS + [app for app in TENANT_APPS if app not in SHARED_APPS]
BEHAVIOUR
Public schema are shared with all tenants. Any tenant can see any data form public schema if you don't filter. This is a normal behavior
Tenants (clients) are created in the public schema.
NEEDS
I dont want that these data (tenants) can be seen by any tenant, because it will contain private client data. Each tenant only needs to see his data and only the SaaS owner can see all data (superuser in public schema).
PROBLEM
I have added this code (see code below) into the admin.py file to filter tenant's data. This works fine. But the problem is that I have not been able to detect when it is not a tenant and is the superuser of the public schema. Or is there a better way to achieve it?
from django.contrib import admin
from django_tenants.admin import TenantAdminMixin
from django.db import connection
from .models import Client
class ClientAdmin(TenantAdminMixin, admin.ModelAdmin):
list_display = (
"name",
"schema_name",
"created_on",
)
def get_readonly_fields(self, request, obj=None):
if obj: # editing an existing object
return self.readonly_fields + ('schema_name', 'created_on')
return self.readonly_fields
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.filter(name=connection.tenant)
admin.site.register(Client, ClientAdmin)