def tenant_restricted(klass):
    """
    Decorator for model classes.  Restricts queryable records to ones that have their tenant set as the
    user's tenant in the request, or all records if the user doesn't have a set tenant.  Also removes the
    ability to change or set the tenant field in the admin for these users too.
    """
    tenant_model = get_tenant_model()
    if klass == tenant_model:
        return klass
    is_auth_user_model = settings.AUTH_USER_MODEL == "%s.%s" % (klass._meta.app_label, klass._meta.object_name)

    # Get all the Manager objects from the class
    potential_attrs = [attr for attr in dir(klass) if not attr.startswith("_")]
    managers = [getattr(klass, m) for m in potential_attrs if isinstance(getattr(klass, m), models.Manager)]

    # Update each Manager object so that it can only query data linked to the current user's tenant
    for manager in managers:
        _monkeypatch_get_query_set(manager)

    # Ensure the model's save method always sets the tenant to the current user's tenant
    # _monkeypatch_save(klass)

    # Make sure any tenant field's in the class can't be edited in the admin, and that it defaults to the
    # tenant assigned to the logged in user in the request.
    # The AUTH_USER_MODEL can have the tenant field managed by user's with a tenant of None, so the editable field
    # for the AUTH_USER_MODEL's tenant fields is handled in the admin form class.
    for tenant_field in tenant_model._get_tenant_fields_in(klass):
        klass._meta.get_field(tenant_field).default = get_tenant_from_request
        klass._meta.get_field(tenant_field).editable = is_auth_user_model

    return klass
def _new_get_query_set_method(self):
    """
    Replacement query set that forces the default manager of a model to restrict itself to the
    user's tenant from the request (no restriction if the user doesn't have a tenant).

    NOTE: Monkey patched in via the @tenant_restricted decorator.
    """
    qs = self.old_get_query_set_method()
    tenant = get_tenant_from_request()
    if tenant:
        tenant_model = get_tenant_model()
        for tenant_field in tenant_model._get_tenant_fields_in(self.model):
            qs = qs.filter(**{tenant_field: tenant})
    return qs
示例#3
0
def auth_model_tenant_fields():
    return get_tenant_model()._get_tenant_fields_in(get_user_model())