Je n'ai vraiment aucune idée du fonctionnement d'ACL. Je sais que c'est plutôt cool et que ça pourrait me faire gagner beaucoup de temps et de douleur. Mais actuellement je suis un peu perdu. Tous les exemples de pyramides utilisent la traversée. J'utilise exclusivement l'envoi d'URL. Je ne suis pas sûr de comprendre comment je peux construire une arborescence de ressources.Pyramid ACL sans traversée
Voici un exemple de code:
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'))
La chose est que, cela fonctionne. Mais je dois définir une nouvelle usine pour chaque type de ressource. Je ne suis pas certain de savoir comment je suis censé savoir à quelle ressource j'essaie d'accéder via URL Dispatch et Factory. Je vois quelque chose comme ça
/accounts/{account} //Owners only but viewable by anyone
/messages/{message} //Owners only
/configs/{config} //Admin only
/pages/{page} //Admins only but viewable by anyone
Cela dit ici, j'aurais une telle structure
Root -\
+-- account
+-- message
+-- config
+-- page
Chacun de ces usine a sa propre acl spéciale. L'autre chose est que/comptes est la page principale. Il n'a pas d'identifiant ou quoi que ce soit. Aussi/accounts/new est aussi un cas particulier. Ce n'est pas un identifiant mais l'idée de créer un nouvel objet. J'utilise un style reposant avec l'exigence GET/PUT/DELETE/POST. Je ne suis pas sûr de savoir comment je suis censé faire correspondre l'URL à une ressource et à la bonne ACL automatiquement. Si je définis dans ma racine une usine spéciale comme ci-dessus, il n'y a pas de problèmes.
modifier
Je ne l'ai eu à travailler à l'exception de certaines choses. Je pense finalement que je comprends quel est le but de la traversée. Par exemple avec nous avons cet url:/comments/9494f0eda/new, /comments/{comment}/new
Nous pourrions avoir à Node dans notre arbre de ressources ou même 3 nœuds.
La RootFactory sera inspectée en premier, puis selon notre parcours. Il obtiendra le commentaire attribut de RootFactory, puis « commentaire » de l'usine de commentaires et la « nouvelle » de CommentFactory ou de l'objet lui-même
Je ne l'utilise pas d'usine comme dict comme dans l'exemple de Michael
Il ressemble beaucoup à ça:
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
Ceci est mon objet de base. À chaque pas, il copie l'information du parent au nouvel enfant. Je pourrais certainement faire exploser mon attribut ... le contexte. parent ._ parent _.uid mais ce n'est pas génial.
La raison pour laquelle je n'utilise pas l'attribut dict. J'ajoute de faire cela fonctionne avec
/Commentaires
Pour certaines raisons, il a fait créer mon CommentFactory mais il n'a pas retourné comme il n'y avait pas besoin d'une clé.
Donc, ma racine usine à peu près ressembler à ceci:
si aucun élémentclass 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
se trouve, RootFactory se retourner sinon, il retourne une nouvelle usine. Puisque je base mon code sur le code de Michael, il y a un second paramètre pour le constructeur de Factory. Je ne suis pas certain de le garder comme QuestionFactory est bien conscient de gérer les "questions" donc il n'est pas nécessaire de nommer l'usine ici. Il devrait déjà connaître son nom.
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
Voilà où presque toute la logique ira. Dans le initialisation je mis acl qui fonctionnera pour/questions dans le getitem cela fonctionnera pour/questions/{id}/*
Depuis que je se retourne, tout getitem passé ce RessourceFactory pointera vers lui-même si je reviens une nouvelle usine pour un cas particulier. La raison en est que mon contexte n'est pas seulement un objet dans la base de données ou un objet.
Mon contexte gère plusieurs choses comme l'ID utilisateur, les paramètres régionaux et ainsi de suite ... lorsque l'acl est terminé, j'ai un nouvel objet de contexte prêt à l'emploi. Il supprime la plupart de la logique dans les vues.
Je pourrais probablement définir des événements pour interroger les paramètres régionaux et l'uid, mais cela correspond vraiment ici. Si j'ai besoin de quelque chose de nouveau, il me suffit d'éditer mon RootFactory et RessourceFactory pour les copier dans une factory enfant. De cette façon, si quelque chose doit changer à travers toutes les vues, il n'y a pas de redondance du tout.
Je ne sais pas, j'ai déjà tous lu ça. Comme je l'ai dit dans le titre ... J'essaie d'y parvenir sans traverser. J'ai essayé une fois et ça a foiré mes routes et rien n'a marché. Je ne crois pas que j'ai une hiérarchie d'arbres aussi. puisque j'ai des pages, des messages, etc., mais aucun objet ne se rapporte vraiment à un autre. Donc une telle chose/foo/bar/baz ne me parle pas beaucoup. –
J'ai fait quelques tests et ça pourrait marcher après tout ... Je vais écrire quelque chose demain je dois dormir avant mon examen demain. –
Les liens que je vous ai donnés utilisent l'envoi d'URL ... le système d'authentification de pyramid fonctionne hiérarchiquement en traversant une arborescence d'objets. C'est ainsi que fonctionne ACLAuthorizationPolicy. Je serais surpris si vous "liez déjà tout ça" parce que je viens de réécrire cette démo la nuit dernière et je travaille activement dessus. ;-) –