金字塔中某个资源的许可是not hard to check。我想知道如何确定权限类型和与某条路由相对应的资源。
详细信息。假设我添加了路径
config.add_route('resource.edit', '/t/{resource_id:\d+}/edit',
factory = FactoryFactory('resource') ))
其中FactoryFactory
是返回工厂的函数。在这种情况下,无论可能是什么,它都会返回“resources”的工厂。后来,我这样说:
@view_config(
route_name='resource.edit',
renderer='resource-edit.pt',
permission='edit'
)
def edit(resource_object, request):
...
在某些时候,我会在网站上生成一个链接到
的输入元素request.route_url('resource.edit', resource_id=some_input)
编辑:根据要求,我会向您提供确切的模板代码,希望这可以让您更好地了解情况。我们使用的模板引擎是Chameleon。
<a href="${request.route_url('resource.edit', resource_id=res.id)}"
class="btn btn-info morespacing"><i class="icon-edit"></i>edit</a>
现在我想要的是这样的:
<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>
换句话说:如果用户有权首先执行编辑操作,我想显示此输入元素 。
现在,我可以举一个例子说明哪些方法有效但对我没有吸引力,因为它不灵活。我编写了一个辅助函数
def can_edit(request, factory_type, res_id):
resource = FactoryFactory(factory_type)(res_id)
return has_permission('edit', resource, request)
然后我写
<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>
这对我来说没什么吸引力,因为关于工厂和有关权限的信息已被编码到路径中,所以我觉得我应该能够通过简单地提供它来访问它路线的名称。
因此,我正在寻找一种方法来获取资源和来自的权限路径信息,即来自字符串'resource.edit'
和资源ID some_input
。这可能吗?如果是,怎么样?
提前非常感谢你。
答案 0 :(得分:3)
问题:
因此,我正在寻找一种获取资源的方法 仅来自路线信息的许可,即来自字符串的许可 &#39; resource.edit&#39;和资源id some_input。这可能吗?如果 是的,怎么样?
Pyramid无法知道用户(当前请求)是否能够在您提供资源之前访问您的资源。你可以参考
Assigning ACLs to your Resource Objects
正如您所看到的,Pyramid将查看资源对象的__ACL__属性(以及资源的祖先的__ACL__),然后确定谁拥有对此资源的哪种权限,因此,这是不可能的使用金字塔默认授权策略。
要解决您的问题,您可以自定义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>
更新
然后我认为您需要使用introspector来获取工厂并创建像这样的资源
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)
答案 1 :(得分:3)
如果你想从路线中提取工厂 - 使用金字塔内省
@view_config(route_name='bar')
def show_current_route_pattern(request):
introspector = request.registry.introspector
route_name = request.matched_route.name
route_intr = introspector.get('routes', route_name)
factory = route_intr['factory'])
...
详细了解内省here。
答案 2 :(得分:1)
回答你的问题:不,你没有从路线获得有关许可的信息。路线只匹配视图。可以使用许多不同方式使用权限保护视图和资源。您的安全策略通常与用户,资源和视图相关,而不是与路由相关。
可能这个建议对你有任何帮助。
给定资源的这条路线
config.add_route('resource.view', '/t/{resource_id:\d+}',
factory = FactoryFactory('resource') ))
您创建一个匹配此路线的视图。路线工厂将制作资源作为上下文。 在视图中封装与权限相关的代码。
@view_config(
route_name='resource.view',
renderer='resource-view.pt',
permission='view'
)
def view_page(resource_object, request):
can_edit = has_permission('edit', resource_object, request)
#do some more stuff - extend the dictionary passed to the renderer
...
return dict(
res = resource_object,
can_edit = can_edit,
)
在模板中使用'can_edit'来控制此链接或任何其他标记的可见性。
<a tal:condition="can_edit"
href="${request.route_url('resource.edit', resource_id=res.id)}"
class="btn btn-info morespacing"><i class="icon-edit"></i>edit</a>
您可以通过计算URL来改进示例,以便在视图代码中编辑资源。
@view_config(
route_name='resource.view',
renderer='resource-view.pt',
permission='view'
)
def view_page(resource_object, request):
can_edit = has_permission('edit', resource_object, request)
edit_url = request.route_url('resource.edit', resource_id=resource_object.id)
#do some more stuff - extend the dictionary passed to the renderer
...
return dict(
can_edit = can_edit,
edit_url = edit_url,
)
这导致了紧凑的模板代码并提高了视图代码的可测试性。
<a tal:condition="can_edit"
href="${edit_url}"
class="btn btn-info morespacing"><i class="icon-edit"></i>edit</a>
为了使代码对任何金字塔开发者更常见,我想使用framework选项从请求中获取上下文。
@view_config(
route_name='resource.view',
renderer='resource-view.pt',
permission='view'
)
def view_page(request):
context = request.context
can_edit = has_permission('edit', context, request)
edit_url = request.route_url('resource.edit', resource_id=context.id)
#do some more stuff - extend the dictionary passed to the renderer
...
return dict(
can_edit = can_edit,
edit_url = edit_url,
)
关于您的申请,我想推荐这些金字塔样本应用程序:
答案 3 :(得分:0)
你曾经使用过......
http://ziggurat-foundations.readthedocs.org/en/latest/
在此范围内,您可以轻松测试特定的用户权限,因此您可以在模板或代码中轻松过滤用户权限。
t = session.query(UserPermission).\
filter(UserPermission.user_id == 'userid').\
filter(UserPermission.perm_name == 'yourpermission')).first()
然后在模板(显示的Jinja2示例)中,您可以执行以下操作:
{% if t %}
<!-- show edit link -->
{% endif %}
或者,如果您正在进行用户查询,则可以将加入与当前查询联系起来。
答案 4 :(得分:0)
您可以将权限存储在资源上(持久性或仅作为类的attr):
def dynamic_resource_permission(context, request):
permission = getattr(context, 'view_permission', 'view')
if not has_permission(context, permission):
raise HTTPForbidden()
return True
@view_config(
route_name='resource.edit',
renderer='resource-edit.pt',
permission='edit',
custom_predicates=(dynamic_resource_permission,),
)
def edit(resource_object, request):
....
PS:我没有运行上面的内容,但上面的一些变体应该有效。