金字塔:检查路线名称的权限

Jes*_*ain 8 python permissions python-2.7 pyramid

这是不难检查在金字塔某个资源的权限.我想知道如何确定权限类型和与某个路由相对应的资源.

细节.假设我添加了一条路线

config.add_route('resource.edit', '/t/{resource_id:\d+}/edit',
    factory = FactoryFactory('resource') ))
Run Code Online (Sandbox Code Playgroud)

FactoryFactory返回工厂的函数在哪里.在这种情况下,它返回"资源"的工厂,无论可能是什么.后来,我这样做:

@view_config(
    route_name='resource.edit',
    renderer='resource-edit.pt',
    permission='edit'
)
def edit(resource_object, request):
    ...
Run Code Online (Sandbox Code Playgroud)

在某些时候,我将在网站上生成一个链接到的输入元素

request.route_url('resource.edit', resource_id=some_input)
Run Code Online (Sandbox Code Playgroud)

编辑:根据要求,我会给你确切的模板代码,希望这能让你更好地了解情况.我们使用的模板引擎是Chameleon.

    <a href="${request.route_url('resource.edit', resource_id=res.id)}" 
       class="btn btn-info morespacing"><i class="icon-edit"></i>edit</a>
Run Code Online (Sandbox Code Playgroud)

现在我想要的是这样的:

    <a tal:condition="h.route_accessible(request, 'resource.edit', res.id)" 
       href="${request.route_url('resource.edit', resource_id=res.id)}" 
       class="btn btn-info morespacing"><i class="icon-edit"></i>edit</a>
Run Code Online (Sandbox Code Playgroud)

换句话说:我只想在用户有权首先执行编辑操作时才显示此输入元素.


现在,我可以举一个例子说明什么会起作用但对我没有吸引力,因为它不灵活.我编写了一个辅助函数

def can_edit(request, factory_type, res_id):
    resource = FactoryFactory(factory_type)(res_id)
    return has_permission('edit', resource, request)
Run Code Online (Sandbox Code Playgroud)

然后我写

    <a tal:condition="h.can_edit(request, 'resource', res.id)" 
       href="${request.route_url('resource.edit', resource_id=res.id)}" 
       class="btn btn-info morespacing"><i class="icon-edit"></i>edit</a>
Run Code Online (Sandbox Code Playgroud)

这对我来说没有吸引力,因为关于工厂的信息有关许可的信息已被编码到路线中,所以我觉得我应该能够通过简单地提供路线的名称来访问它.


因此,我正在寻找一种方法来仅从路由信息,即从字符串'resource.edit'和资源ID 获取资源和权限some_input.这可能吗?如果有,怎么样?

非常感谢你提前.

Fan*_*Lin 4

对于你的问题:

因此,我正在寻找一种仅从路由信息(即从字符串“resource.edit”和资源id some_input)获取资源和权限的方法。这可能吗?如果是,怎么办?

在您向用户(当前请求)提供资源之前,金字塔无法知道该用户(当前请求)是否能够访问您的资源。您可以参考

将 ACL 分配给资源对象

正如您所看到的,Pyramid 将查看资源对象的 __ACL__ 属性(以及资源​​祖先的 __ACL__ 属性),然后确定谁对该资源拥有什么样的权限,因此,使用 Pyramid 默认授权策略是不可能的。

为了解决您的问题,您可以自定义AuthorizationPolicy,制定自己的授权规则,或者您可以轻松地从 ID 创建资源。

想想看,如果您有owner资源对应表的字段,并且您需要检查当前用户是否是特定资源的所有者,那么无论如何您都需要从数据库获取该资源。因此,无论如何,您都需要创建一个提供 __ACL__ 属性的资源。所以,我的建议是,让创建资源变得更容易,让它像这样Resource(res.id),这样你就可以像这样编写你的模板

<a tal:condition="has_permission('edit', Resource(res.id), request)" 
   href="${request.route_url('resource.edit', resource_id=res.id)}" 
   class="btn btn-info morespacing"><i class="icon-edit"></i>edit</a>
Run Code Online (Sandbox Code Playgroud)

更新

然后我认为你需要的是使用内省器来获取工厂并创建这样的资源

def has_permission_for_route(request, route_name, permission, res_id):
    introspector = request.registry.introspector
    route_name = request.matched_route.name
    route_intr = introspector.get('routes', route_name)
    factory = route_intr['factory']

    resource = factory(request, res_id=res_id)
    return has_permission(permission, resource, request)
Run Code Online (Sandbox Code Playgroud)