visibility.py 2.27 KB
Newer Older
1 2 3
"""
Visibility Transformer implementation.
"""
4
from openedx.core.lib.block_structure.transformer import BlockStructureTransformer, FilteringTransformerMixin
5
from .utils import collect_merged_boolean_field
6 7


8
class VisibilityTransformer(FilteringTransformerMixin, BlockStructureTransformer):
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
    """
    A transformer that enforces the visible_to_staff_only field on
    blocks by removing blocks from the block structure for which the
    user does not have access. The visible_to_staff_only field on a
    block is percolated down to its descendants, so that all blocks
    enforce the visibility settings from their ancestors.

    For a block with multiple parents, access is denied only if
    visibility is denied for all its parents.

    Staff users are exempted from visibility rules.
    """
    VERSION = 1

    MERGED_VISIBLE_TO_STAFF_ONLY = 'merged_visible_to_staff_only'

    @classmethod
    def name(cls):
        """
        Unique identifier for the transformer's class;
        same identifier used in setup.py.
        """
        return "visibility"

    @classmethod
34
    def _get_visible_to_staff_only(cls, block_structure, block_key):
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
        """
        Returns whether the block with the given block_key in the
        given block_structure should be visible to staff only per
        computed value from ancestry chain.
        """
        return block_structure.get_transformer_block_field(
            block_key, cls, cls.MERGED_VISIBLE_TO_STAFF_ONLY, False
        )

    @classmethod
    def collect(cls, block_structure):
        """
        Collects any information that's necessary to execute this
        transformer's transform method.
        """
50 51 52 53 54 55
        collect_merged_boolean_field(
            block_structure,
            transformer=cls,
            xblock_field_name='visible_to_staff_only',
            merged_field_name=cls.MERGED_VISIBLE_TO_STAFF_ONLY,
        )
56

57
    def transform_block_filters(self, usage_info, block_structure):
58 59
        # Users with staff access bypass the Visibility check.
        if usage_info.has_staff_access:
60
            return [block_structure.create_universal_filter()]
61

62 63
        return [
            block_structure.create_removal_filter(
64
                lambda block_key: self._get_visible_to_staff_only(block_structure, block_key),
65 66
            )
        ]