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

Roundup Issue Tracker: http://roundup-tracker.org/