Skip to content

Commit bb08d50

Browse files
committed
Improve section on filter function
The security Permission now can have a filter function, document the usage in more detail.
1 parent f18687f commit bb08d50

File tree

1 file changed

+76
-10
lines changed

1 file changed

+76
-10
lines changed

doc/reference.txt

Lines changed: 76 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,82 @@ complex permission schemes. An `example in upgrading.html
15141514
<upgrading.html#enhancement-to-check-command-for-permissions>`_
15151515
shows the use of ``ctx``.
15161516

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+
15171593
**properties**
15181594
A sequence of property names that are the only properties to apply the
15191595
new Permission to (eg. ``... klass='user', properties=('name',
@@ -1565,16 +1641,6 @@ shows the use of ``ctx``.
15651641

15661642
**Invalid properties for file: ['summary']
15671643

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-
15781644

15791645
Example Scenarios
15801646
~~~~~~~~~~~~~~~~~

0 commit comments

Comments
 (0)