Loï*_*oix 9 python acl routes pyramid
我真的不知道ACL是如何工作的.我知道这很酷,可以节省我很多时间和痛苦.但目前我有点失落.金字塔的所有示例都使用遍历.我专门使用URL Dispatch.我不确定如何构建一个资源树结构.
这是一个代码示例:
class QuestionFactory(object):
def __init__(self, request):
self.__acl__ = default[:]
self.uid = authenticated_userid(request)
self.qid = request.matchdict.get('id')
if self.qid:
self.question = request.db.questions.find_one({'_id': ObjectId(self.qid)})
if str(self.question.get('owner')) == self.uid:
self.__acl__.append((Allow, userid, 'view'))
Run Code Online (Sandbox Code Playgroud)
问题是,它有效.但我必须为每种类型的资源定义一个新工厂.我不知道我应该知道我试图通过URL Dispatch和Factory访问哪个资源.我会看到类似的东西
/accounts/{account} //Owners only but viewable by anyone
/messages/{message} //Owners only
/configs/{config} //Admin only
/pages/{page} //Admins only but viewable by anyone
Run Code Online (Sandbox Code Playgroud)
那说我在这里有这样的结构
Root -\
+-- account
+-- message
+-- config
+-- page
Run Code Online (Sandbox Code Playgroud)
这些工厂中的每一个都有它自己特殊的acl.另一件事是/ accounts是主页面.它没有id或任何东西.另外/ accounts/new也是一个特例.它不是id,而是创建新项目的视图.
我正在使用具有GET/PUT/DELETE/POST要求的宁静风格.我不太确定我应该如何自动将url与资源和正确的acl匹配.如果我在我的根中定义一个像上面这样的特殊工厂就没有问题.
编辑
除了一些事情,我确实得到了它.我终于想到了解遍历的目的是什么.例如,我们有这个网址:/ comments/9494f0eda/new,/ comments/{comment}/new
我们可以在我们的资源树或甚至3个节点中使用Node.
首先检查RootFactory,然后根据我们的遍历进行检查.它将获取RootFactory的comments属性,然后是Comment Factory的"comment"和CommentFactory的"new"或者Object本身的"new"
我不像迈克尔的例子那样使用工厂作为字典
它看起来非常像:
class RessourceFactory(object):
def __init__(self, parent, name):
self.__acl__ = []
self.__name__ = name
self.__parent__ = parent
self.uid = parent.uid
self.locale = parent.locale
self.db = parent.db
self.req = parent.req
Run Code Online (Sandbox Code Playgroud)
这是我的基础资源对象.在每个步骤中,它都会将信息从父级复制到新子级.我当然可以冒出我的属性..上下文.parent ._ parent _.uid但是那不是那么好.
我没有使用dict属性的原因.我添加使其适用
/评论
由于某些原因,它确实创建了我的CommentFactory但没有返回它,因为不需要密钥.
所以我的root工厂看起来像这样:
class RootFactory(object):
def __init__(self, request):
self.__acl__ = default[:]
self.req = request
self.db = request.db
self.uid = authenticated_userid(request)
self.locale = request.params.get('locale', 'en')
def __getitem__(self, key):
if key == 'questions':
return QuestionFactory(self, 'questions')
elif key == 'pages':
return PageFactory(self, 'pages')
elif key == 'configs':
return ConfigFactory(self, 'configs')
elif key == 'accounts':
return AccountFactory(self, 'accounts')
return self
Run Code Online (Sandbox Code Playgroud)
如果没有找到任何项目,RootFactory如果没有返回,它将返回一个新的Factory.由于我的代码基于Michael的代码,因此Factory构造函数有第二个参数.我不确定是否保留它作为一个QuestionFactory很清楚处理"问题"所以不需要在这里命名工厂.它应该已经知道它的名字了.
class QuestionFactory(RessourceFactory):
def __init__(self, parent, name):
RessourceFactory.__init__(self, parent, name)
self.__acl__.append((Allow, 'g:admin', 'view'))
self.__acl__.append((Allow, 'g:admin', 'edit'))
self.__acl__.append((Allow, 'g:admin', 'create'))
self.__acl__.append((Allow, 'g:admin', 'delete'))
self.__acl__.append((Allow, Everyone, 'create'))
def __getitem__(self, key):
if key=='read':
return self
self.qid = key
self.question = self.db.questions.find_one({'_id': ObjectId(self.qid)})
if str(self.question.get('owner')) == self.uid:
log.info('Allowd user %s' % self.uid)
self.__acl__.append((Allow, self.uid, 'view'))
self.__acl__.append((Allow, self.uid, 'edit'))
self.__acl__.append((Allow, self.uid, 'delete'))
return self
Run Code Online (Sandbox Code Playgroud)
这就是几乎所有逻辑都会去的地方.在init中我设置了acl,它将在getitem中为/ questions工作,它将适用于/ questions/{id}/*
由于我自己回归,任何通过这个RessourceFactory的getitem将指向自己,除非我为某些特殊情况返回一个新工厂.这样做的原因是我的上下文不仅仅是数据库或对象中的对象.
我的上下文处理多个事情,比如用户ID,语言环境等......当acl完成后,我有一个准备好使用的新上下文对象.它删除了视图中的大部分逻辑.
我可以设置事件来查询locale和uid,但它确实适合这里.如果我需要任何新东西,我只需编辑我的RootFactory和RessourceFactory将它们复制到子工厂.
这样,如果某些事情必须在所有视图中发生变化,那么根本就没有冗余.
看起来您对某些对象/行级安全功能感兴趣,只允许帐户所有者查看其数据.我会引用你之前关于这个主题的SO回答,以及我在URL Dispatch中为auth工作的教程,该教程是围绕这个答案构建的.具体来说,您可能希望查看2.object_security链接的github项目中的演示以及解释资源树的文档,作为我网站上呈现的html的一部分.
https://github.com/mmerickel/pyramid_auth_demo
http://michael.merickel.org/projects/pyramid_auth_demo/
如果您对这些资源有任何疑问,我将很乐意在此进一步阐述.