There's no reason your models can't just implement __parent__ and
__name__ as properties themselves. These have nothing to do with
HTTP. (No need to know about the request for traversal!)
An example using SQLAlchemy:
https://github.com/Pylons/Kotti/blob/master/kotti/resources.py#L108
So how would you apply this to a normal SQLAlchemy database, that may
have the concept of name and parent but not in the resource structure?
In particular, an ordinary 1:many relationship where the parent has
several children with a backref to itself, but not using the words
"name" and "parent".
class Main(Base):
id = sa.Column(sa.types.Integer, nullable=False, auto_increment=True)
subs = orm.relationship("Sub", backref="main")
class Sub(Base):
id = sa.Column(sa.types.Integer, nullable=False, auto_increment=True)
main_id = sa.Column(sa.types.Integer, sa.ForeignKey("Main.id"),
nullable=False)
In this case, the 'id' fields can serve as the .__name__, converting
them to a string if necessary. And the 'main' backref is equivalent to
.__parent__. So would the name and parent simply return these
properties? Do we need to do anything to prevent unnecessary queries
for parent?
For large tables, I generally defer the fields that are only used on
the details page and searching -- i.e., not on index pages -- in a
deferral group called 'details'. So if you fetched a Sub and referred
to its parent (probably wanting only the ID and title fields for a
hyperlink, and perhaps a date for sorting), only the fields used
'everywhere' would be loaded. I guess that would "just work" in a
Resource scenario.
Of course, when fetching a sub, there's no place in the API to specify
whether you'll be wanting all its detail fields, unless you query the
database directly, in which case you can't go through the resource
tree.
--
Mike Orr <slugg...@gmail.com>
Yes, they would.
> Do we need to do anything to prevent unnecessary queries
> for parent?
After you traversed down to that item, __parent__ will likely already
be in the SQLA identity map cache, so going up back up to the
parent(s) shouldn't cost you any queries.
Dividing your db fields into 'details' and not sounds like a good idea.
OK. Any tips for attaching an ACL to them? Especially in the case
where permissions are record-specific. For instance, I have a
situation where one group can view and edit all records, another group
can only view, a third set of users (not a group) can view/edit only
this record or a few records, and a fourth set of users can view this
record or a few records but not edit them. Would I just specify:
[(ALLOW, "g:manager1", "view"),
(ALLOW, "g:manager1", "edit"),
(ALLOW, "g:manager2", "view"),
(ALLOW, "user1", "view"), #... user2, user3 ...
(ALLOW, "user1", edit"), # ... user2, user3...
(ALLOW, "user4", "view), # ... user5, user6..
].
How do these interact with the permission arg in the view
configuration, and with the strings coming from the authenticator?
What does a DENY element mean, and how does it interact with the view
config? Does ALLOW mean this permission string is included, and deny
means it's excluded? So the permission arg causes a check whether that
string is excluded? Why would you need DENY at all then if the default
is deny?
--
Mike Orr <slugg...@gmail.com>
For those groups (and users) that have permissions globally ("can
view/edit all records"), you can put the entries at the root. With
the standard ACLAuthorizationPolicy, it'll get inherited down the
traversal path to all children records:
root.__acl__ = [
(ALLOW, "g:manager1", "view"),
(ALLOW, "g:manager1", "edit"),
(ALLOW, "g:manager2", "view"),
]
The entries that control access to individual records are attached to
exactly those instances:
bobsfolder.__acl__ = [(ALLOW, "bob", ("view", "edit"))]
> How do these interact with the permission arg in the view
> configuration, and with the strings coming from the authenticator?
The authenticator will provide user and group names like "bob" and
"g:manager2". The view permissions correspond to "view" and "edit"
here.
> What does a DENY element mean, and how does it interact with the view
> config? Does ALLOW mean this permission string is included, and deny
> means it's excluded? So the permission arg causes a check whether that
> string is excluded? Why would you need DENY at all then if the default
> is deny?
I haven't ever used DENY, but I suppose it's useful for when you want
to take away permissions down the path. Imagine if Bob wanted his
home folder not to be readable by "g:manager2", he could use a "deny"
ACE to block the inheritance.