1

我目前的项目涉及一个遗留代码库,它以有限的方式使用 Django 的模型;syncdb没有被使用(即模型不是 Django 管理的)。我需要根据权限限制对某些列的访问(即 view_all 权限将显示所有列,而没有权限会将用户限制为几个基本列)。此权限将适用于不同的表。

我正在考虑这样做的方式是简单地使用 SQL 插入一个新的auth_permission. 但是,该content_type_id列使这变得复杂:我的理解是内容类型适用于一个模型,而这(正如我所说)将需要适用于不同的表,并且我无法可靠地运行syncdb.

有没有其他人按照这些思路实施了一些东西?您是否使用了 Django 基础架构,还是为了安全而最终使用了单独的表?您是在信号级别还是在使用模型的每个点都实现了这一点?

谢谢!

4

4 回答 4

2

您始终可以围绕虚拟对象创建自定义权限,即:

class ColumnLevelPermissions(models.Model):

    class Meta:
        permissions = (
             ("can_view_column1", "Can view column 1"),
             ("can_view_column2", "Can view column 2"),
        )

然后创建一个包装器来过滤你的数据库调用(你说你的模型不是由 Django models.Model 管理的):

class SelectManager(object):
    def get_columns(user):
        allowed_columns = []
        if user.has_perm('app.can_view_column1'):
            allowed_columns.append('column1')
        return allowed_columns

唯一需要决定的是如何使用它。您可以将数据库中的对象创建为 dict(),如果出现在 allowed_columns 中,只需按键过滤对象中的列。然而,这意味着您将从数据库中读取一些冗余数据。另一种解决方案是根据列修改“选择”查询,尽管这不是很安全的方法。

有关如何在代码中存储和读取对象的更多信息可能有助于定义最佳方法。

于 2012-06-01T20:51:41.703 回答
2

在我看来,您实际上是在寻找权限组。它们可以很容易地独立创建模型。用户组不需要包含任何实际权限。

您可以检查用户是否在特定组中:

def user_in_group(user, group_name):
    return user.groups.filter(name=group_name).count()

你可以像这样使用它:

def my_view(request):
    if user_in_group(request.user, 'view_all'):
        # do the things
    else:
        # do the other things

# limit this view to 'view_all' users
@user_passes_test(lambda u: user_in_group(u, 'view_all'))
def my_other_view(request):
    # and do some more things

我不知道你是什么意思

您是在信号级别还是在使用模型的每个点都实现了这一点?

显然,对于任何授权方法,您都需要在查看模型的任何地方插入检查并插入逻辑以仅显示允许的列(例如在模板中呈现列的子集)。

为了确保不会访问错误的列,您可以编写限制对适当字段/列的访问的代理类,并使用代理实例而不是模型实例。

class SomeModelProxy(object):
    def __init__(self, model_instance, user):
        self.instance = model_instance
        self.user = user

    def save(self, *args, **kwargs):
        self.instance.save(*args, **kwargs)

    # define other methods that are needed...

    def __getattr__(self, name):
        if not name in get_allowed_columns_for_user_somehow(self.user):
            raise AttributeError

        return getattr(self.instance, name)

    def __setattr__(self, name, value):
        if not name in get_allowed_columns_for_user_somehow(self.user):
            raise AttributeError

        setattr(self.instance, name, value)
于 2012-06-03T23:22:05.447 回答
0

也许可以帮助你。我从未使用过它,但我认为您可以使用它。

您可以为一组用户创建一些权限,然后根据请求该页面/模板的人(使用简单的“if”模板标签)显示一些列或其他列。这可能有点乏味,但它可以帮助你完成你正在寻找的东西。

希望能帮助到你!

于 2012-06-03T06:19:45.763 回答
0

如果我理解正确,您需要根据用户/消费者的某些属性显示任何表的所有/部分对象。用户将无法部分访问某些行并完全访问其他行,这是全有或全无。

这与 ContentTypes 框架无关,后者允许级别的多态关系。您只需要过滤视图中的公开字段。

如果您使用标准的用户/组类,您可以为每个表添加权限“see_complete_xxx”,并分配组,然后在视图中(这是一个 api 可能会遍历字段并将它们转换为 json/xml/无论如何)仅序列化组的允许字段。

符合以下条件的东西:

from django.forms.models import model_to_dict

class MyModel(models.Model):

    def serialize_full(self):
        return model_to_dict(self)

    def serialize_restricted(self):
        return model_to_dict(self, self.low_level_access_fields)

    def serialize_to_dict(self, user):
        if self.user_can_view_all(user):
            return self.serialize_full
        else:
            return self.serialize_restricted

    @classmethod
    def user_can_view_all(cls, user)
        return user.has_perm('my_model.see_all')

    @classmethod
    def low_level_access_fields(cls)
        return ["id", "name", "nickname"]

您可以将大部分代码提取到 mixin 中,并在需要的地方使用它。

于 2012-06-06T11:42:11.047 回答