Django Tenants + Tenant Users - Assigning Permissions

Hi all

I’m currently refactoring a project I’ve been working on and am looking to use Django Tenants and Django Tenants users to seperate out users between specific schemas.

My goal is:

  • Create a user per tenant
  • User should be able to log in to the Django Admin with restricted permissions (is_staff=True, is_superuser=False)
  • User should be assigned a default group with change | add | view permissions on an object

The unit tests I’ve written are passing however I’m not seeing the user permissions or group created locally within the tenant schema.

When I come to login as the user within the tenant admin site no permissions are assigned.

I’ve read back over the Django Tenants and Django Tenants Users docs in detail but must be missing something logical.

Code currently looks like:

      # Set up the user
        self.user = User.objects.create_user(email="operator@example.com", password="password", name="Mike")

        # Provison a tenant
        self.domain = provision_tenant(
            tenant_name="Operator",
            tenant_slug="operator",
            user_email="operator@example.com",
            is_staff=True,
            tenant_extra_data={
                "is_trial": False,
                "is_active": True,
            }
        )

        # Get the tenant
        tenant = Tenant.objects.get(name="Operator")

        # Create a user permissions object
        user_permissions = UserTenantPermissions.objects.create(
            profile=tenant.owner,
            is_staff=True,
            is_superuser=False,
        )

        # Create a group at the tenant level
        group = Group.objects.create(name="Operator Admin")

        # Add the group to the user permissions
        user_permissions.groups.add(group)

        # Create a group
        group, created = Group.objects.get_or_create(name="Operator Admin")
        group.permissions.add(
            Permission.objects.get(codename="view_trip"),
            Permission.objects.get(codename="add_trip"),
            Permission.objects.get(codename="change_trip"),
        )

        # Add the group to the user permissions
        user_permissions.groups.add(group)
        user_permissions.save()

Tenant Model looks like this currently:

class Tenant(TenantBase):
    name = models.CharField(max_length=settings.AUTH_USER_NAME_MAX_LENGTH, unique=True)
    owner = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='owned_tenant')
    is_trial = models.BooleanField(default=False, blank=True)
    is_active = models.BooleanField(default=False, blank=True)
    created_on = models.DateField(auto_now_add=True)

    # Handle groups and permissions
    auto_create_group_on_schema_create = True
    auto_create_group_on_user_create = True
    auto_create_permissions_on_schema_create = True
    auto_create_permissions_on_user_create = True

    # Tenant specific configuration
    auto_create_schema = True
    auto_drop_schema = True

    def __str__(self):
        return self.name

Settings TENANT_APPS looks like:

"""
    These app's data are stored on their specific schemas
"""
TENANT_APPS = [
    # The following Django contrib apps must be in TENANT_APPS
    "django.contrib.contenttypes",
    "django.contrib.auth",
    "django.contrib.admin",
    "django.contrib.sessions",
    "django.contrib.messages",
    "tenant_users.permissions",
    # tenant-specific apps
    "trips",
]

Ok I’ve actually solved the issue.

What I realised was the issue was that I wasn’t pointing at the local tenant schema.

Either with schema_context or tenant.activate() both work.

Code updated:

# Set up the user
        cls.user = User.objects.create_user(email="operator@example.com", password="password", name="Mike")

        # Provision a tenant
        cls.domain = provision_tenant(
            tenant_name="Operator",
            tenant_slug="operator",
            user_email="operator@example.com",
            is_staff=True,
            tenant_extra_data={
                "is_trial": False,
                "is_active": True,
            }
        )

        # Get the tenant
        tenant = Tenant.objects.get(name="Operator")

        # Set the schema context
        with schema_context(tenant.schema_name):
            # Check if UserTenantPermissions object already exists
            user_permissions, created = UserTenantPermissions.objects.get_or_create(
                profile=tenant.owner,
                defaults={
                    "is_staff": True,
                    "is_superuser": False,
                }
            )

            # Update the attributes of the existing UserTenantPermissions object
            user_permissions.is_staff = True
            user_permissions.is_superuser = False
            user_permissions.save()

            # Create a group at the tenant level
            group, created = Group.objects.get_or_create(name="Operator Admin")

            # Add the group to the user permissions
            user_permissions.groups.add(group)

            # Add permissions to the group
            permissions = [
                Permission.objects.get(codename="view_trip"),
                Permission.objects.get(codename="add_trip"),
                Permission.objects.get(codename="change_trip"),
            ]
            group.permissions.set(permissions)