Mercurial > p > roundup > code
comparison doc/reference.txt @ 8154:67a0fc4f9934 permission-performance
Improve section on filter function
The security Permission now can have a filter function, document the
usage in more detail.
| author | Ralf Schlatterbeck <rsc@runtux.com> |
|---|---|
| date | Mon, 11 Nov 2024 11:25:55 +0100 |
| parents | 7b6615fb37fc |
| children | 3f720edd9594 |
comparison
equal
deleted
inserted
replaced
| 8139:de58ff07890e | 8154:67a0fc4f9934 |
|---|---|
| 1512 The second form is preferred as it makes it easier to implement more | 1512 The second form is preferred as it makes it easier to implement more |
| 1513 complex permission schemes. An `example in upgrading.html | 1513 complex permission schemes. An `example in upgrading.html |
| 1514 <upgrading.html#enhancement-to-check-command-for-permissions>`_ | 1514 <upgrading.html#enhancement-to-check-command-for-permissions>`_ |
| 1515 shows the use of ``ctx``. | 1515 shows the use of ``ctx``. |
| 1516 | 1516 |
| 1517 **filter | |
| 1518 A function to be executed on the results of a ``filter`` call of the | |
| 1519 schema ``Class`` before displaying the results in an ``index`` | |
| 1520 template. Calling a ``filter`` method on all results is usually faster | |
| 1521 than calling a ``check`` method (see previous paragraph) on *each | |
| 1522 individual result*. The ``filter`` method has the signature:: | |
| 1523 | |
| 1524 filter(db, userid, klass) | |
| 1525 | |
| 1526 where ``db`` is the database handle, ``userid`` is the user attempting | |
| 1527 access and ``klass`` is the ``Class`` in the schema. | |
| 1528 The ``filter`` function must return a list of dictionaries of | |
| 1529 parameters of the `Class.filter`` call. Results found during a query | |
| 1530 executed by an index template are passed through the filter calls | |
| 1531 computed by the ``filter`` function. An empty list of filter | |
| 1532 parameters indicates no access. Note that defining a ``filter`` | |
| 1533 function also needs the definition of a ``check`` function for | |
| 1534 checking individual items for visibility. A ``check`` function is | |
| 1535 manufactured automatically from a ``filter`` function in no ``check`` | |
| 1536 function is defined. | |
| 1537 | |
| 1538 Note that the filter option is not supported for the Search | |
| 1539 permission. Since the filter function is called *after* the search was | |
| 1540 already performed a filter function does not make any sense. | |
| 1541 | |
| 1542 An example ``filter`` function for the ``view_query`` check function | |
| 1543 in the query checks above would look like:: | |
| 1544 | |
| 1545 def filter_query(db, userid, klass): | |
| 1546 return [{'filterspec': {'private_for': ['-1', userid]}}] | |
| 1547 | |
| 1548 This would be called by the framework for all queries found when | |
| 1549 displaying queries. It filters for all queries where the | |
| 1550 ``private_for`` field is the userid or empty. This matches the | |
| 1551 definition of the ``view_query`` function above where permission is | |
| 1552 granted if the ``private_for`` field indicates the query is owned by | |
| 1553 the user, or the ``private_for`` field is empty indicating that the | |
| 1554 query is public. If we want to modify the check to also allow acess if | |
| 1555 the user is the ``creator`` of a query we would change the filter | |
| 1556 function to:: | |
| 1557 | |
| 1558 def filter_query(db, userid, klass): | |
| 1559 f1 = {'filterspec': {'private_for': ['-1', userid]}} | |
| 1560 f2 = {'filterspec': {'creator': userid}} | |
| 1561 return [f1, f2] | |
| 1562 | |
| 1563 This is an example where we need multiple filter calls to model an | |
| 1564 "or" condition, the user has access if either the ``private_for`` | |
| 1565 check passes *or* the user is the creator of the query. | |
| 1566 | |
| 1567 Now consider an example where we have a class ``organisation`` and the | |
| 1568 ``issue`` class has a ``Link`` to ``organisation`` as has the ``user`` | |
| 1569 class. Users may only see issues that belong to their own | |
| 1570 ``organisation``. A ``check`` function for this would be:: | |
| 1571 | |
| 1572 def view_issue(db, userid, itemid): | |
| 1573 user = db.user.getnode(userid) | |
| 1574 if not user.organisation: | |
| 1575 return False | |
| 1576 issue = db.issue.getnode(itemid) | |
| 1577 if user.organisation == issue.organisation: | |
| 1578 return True | |
| 1579 | |
| 1580 The corresponding ``filter`` function:: | |
| 1581 | |
| 1582 def filter_issue(db, userid, klass): | |
| 1583 user = db.user.getnode(userid) | |
| 1584 if not user.organisation: | |
| 1585 return [] | |
| 1586 return [{'filterspec': {'organisation': user.organisation}}] | |
| 1587 | |
| 1588 This filters for all issues where the organisation is the same as the | |
| 1589 organisation of the user. Note how the filter fails early returning an | |
| 1590 empty list (meaning "no access") if the user happens to not have an | |
| 1591 organisation. | |
| 1592 | |
| 1517 **properties** | 1593 **properties** |
| 1518 A sequence of property names that are the only properties to apply the | 1594 A sequence of property names that are the only properties to apply the |
| 1519 new Permission to (eg. ``... klass='user', properties=('name', | 1595 new Permission to (eg. ``... klass='user', properties=('name', |
| 1520 'email') ...``) | 1596 'email') ...``) |
| 1521 **props_only** | 1597 **props_only** |
| 1562 | 1638 |
| 1563 Allowed to see content of object regardless of spam status | 1639 Allowed to see content of object regardless of spam status |
| 1564 (View for "file": ('content', 'summary') only) | 1640 (View for "file": ('content', 'summary') only) |
| 1565 | 1641 |
| 1566 **Invalid properties for file: ['summary'] | 1642 **Invalid properties for file: ['summary'] |
| 1567 | |
| 1568 **filter | |
| 1569 A function that complements a check function: It is used when | |
| 1570 searching for viewable items. The filter function allows to filter in | |
| 1571 SQL (for an SQL backend) rather than calling the check function for | |
| 1572 each item after a query. It must return a list of dictionaries | |
| 1573 containing parameters for the hyperdb.Class.filter method. An empty | |
| 1574 list indicates no access. The signature of the filter function is:: | |
| 1575 | |
| 1576 def filter(db, userid, klass): | |
| 1577 | 1643 |
| 1578 | 1644 |
| 1579 Example Scenarios | 1645 Example Scenarios |
| 1580 ~~~~~~~~~~~~~~~~~ | 1646 ~~~~~~~~~~~~~~~~~ |
| 1581 | 1647 |
