def can_access(self, user, allow_admin=True):
        """Checks if the user can access the object.

        :param user: The :class:`.User` to check. May be None if the
                     user is not logged in.
        :param allow_admin: If admin users should always have access
        """

        override = self._check_can_access_override(user, allow_admin=allow_admin)
        if override is not None:
            return override

        # Usually admins can access everything, so no need for checks
        if allow_admin and user and user.is_admin:
            rv = True
        # If there's a valid access key we can skip all other ACL checks
        elif self.allow_access_key and self.check_access_key():
            rv = True
        elif self.protection_mode == ProtectionMode.public:
            # if it's public we completely ignore the parent protection
            # this is quite ugly which is why it should only be allowed
            # in rare cases (e.g. events which might be in a protected
            # category but should be public nonetheless)
            rv = True
        elif self.protection_mode == ProtectionMode.protected:
            # if it's protected, we also ignore the parent protection
            # and only check our own ACL
            if any(user in entry.principal for entry in iter_acl(self.acl_entries)):
                rv = True
            elif isinstance(self, ProtectionManagersMixin):
                rv = self.can_manage(user, allow_admin=allow_admin)
            else:
                rv = False
        elif self.protection_mode == ProtectionMode.inheriting:
            # if it's inheriting, we only check the parent protection
            # unless `inheriting_have_acl` is set, in which case we
            # might not need to check the parents at all
            if self.inheriting_have_acl and any(user in entry.principal for entry in iter_acl(self.acl_entries)):
                rv = True
            else:
                # the parent can be either an object inheriting from this
                # mixin or a legacy object with an AccessController
                parent = self.protection_parent
                if parent is None:
                    # This should be the case for the top-level object,
                    # i.e. the root category, which shouldn't allow
                    # ProtectionMode.inheriting as it makes no sense.
                    raise TypeError('protection_parent of {} is None'.format(self))
                elif hasattr(parent, 'can_access'):
                    rv = parent.can_access(user, allow_admin=allow_admin)
                else:
                    raise TypeError('protection_parent of {} is of invalid type {} ({})'.format(self, type(parent),
                                                                                                parent))
        else:
            # should never happen, but since this is a sensitive area
            # we better fail loudly if we have garbage
            raise ValueError('Invalid protection mode: {}'.format(self.protection_mode))

        override = self._check_can_access_override(user, allow_admin=allow_admin, authorized=rv)
        return override if override is not None else rv
Example #2
0
    def contains_user(self, name, user):
        """Checks if a user is in an ACL.

        To pass this check, the user can either be in the ACL itself
        or in a group in the ACL.

        :param name: Setting name
        :param user: A :class:`.User`
        """
        from fossir.util.user import iter_acl
        return any(user in principal for principal in iter_acl(self.get(name)))
    def contains_user(self, event, name, user):
        """Checks if a user is in an ACL.

        To pass this check, the user can either be in the ACL itself
        or in a group in the ACL.

        :param event: Event (or its ID)
        :param name: Setting name
        :param user: A :class:`.User`
        """
        return any(user in principal
                   for principal in iter_acl(self.get(event, name)))
Example #4
0
def test_iter_acl():
    user = User()
    user_p = MagicMock(principal=user, spec=['principal'])
    ipn = IPNetworkGroup()
    ipn_p = MagicMock(principal=ipn, spec=['principal'])
    local_group = GroupProxy(123, _group=MagicMock())
    local_group_p = MagicMock(principal=local_group, spec=['principal'])
    remote_group = GroupProxy('foo', 'bar')
    remote_group_p = MagicMock(principal=remote_group, spec=['principal'])
    acl = [
        ipn, user_p, remote_group, local_group_p, user, local_group,
        remote_group_p, ipn_p
    ]
    assert list(iter_acl(iter(acl))) == [
        user_p, user, ipn, ipn_p, local_group_p, local_group, remote_group,
        remote_group_p
    ]
    def can_be_overridden(self, user, room=None, explicit_only=False):
        """Determines if a user can override the blocking

        The following persons are authorized to override a blocking:
        - owner (the one who created the blocking)
        - any users on the blocking's ACL
        - unless explicitOnly is set: admins and room owners (if a room is given)
        """
        if not user:
            return False
        if self.created_by_user == user:
            return True
        if not explicit_only:
            if rb_is_admin(user):
                return True
            elif room and room.is_owned_by(user):
                return True
        return any(user in principal for principal in iter_acl(self.allowed))
    def can_manage(self, user, role=None, allow_admin=True, check_parent=True, explicit_role=False):
        """Checks if the user can manage the object.

        :param user: The :class:`.User` to check. May be None if the
                     user is not logged in.
        :param: role: The management role that is needed for the
                      check to succeed.  If not specified, full
                      management privs are required.  May be set to
                      the string ``'ANY'`` to check if the user has
                      any management privileges.  If the user has
                      `full_access` privileges, he's assumed to have
                      all possible roles.
        :param allow_admin: If admin users should always have access
        :param check_parent: If the parent object should be checked.
                             In this case the role is ignored; only
                             full management access is inherited to
                             children.
        :param explicit_role: If the specified role should be checked
                              explicitly instead of short-circuiting
                              the check for fossir admins or managers.
                              When this option is set to ``True``, the
                              values of `allow_admin` and `check_parent`
                              are ignored.  This also applies if `role`
                              is None in which case this argument being
                              set to ``True`` is equivalent to
                              `allow_admin` and `check_parent` being set
                              to ``False``.
        """
        if role is not None and role != 'ANY' and role not in get_available_roles(type(self)):
            raise ValueError("role '{}' is not valid for '{}' objects".format(role, type(self).__name__))

        if user is None:
            # An unauthorized user is never allowed to perform management operations.
            # Not even signals may override this since management code generally
            # expects session.user to be not None.
            return False

        # Trigger signals for protection overrides
        rv = values_from_signal(signals.acl.can_manage.send(type(self), obj=self, user=user, role=role,
                                                            allow_admin=allow_admin, check_parent=check_parent,
                                                            explicit_role=explicit_role),
                                single_value=True)
        if rv:
            # in case of contradictory results (shouldn't happen at all)
            # we stay on the safe side and deny access
            return all(rv)

        # Usually admins can access everything, so no need for checks
        if not explicit_role and allow_admin and user.is_admin:
            return True

        if any(user in entry.principal
               for entry in iter_acl(self.acl_entries)
               if entry.has_management_role(role, explicit=(explicit_role and role is not None))):
            return True

        if not check_parent or explicit_role:
            return False

        # the parent can be either an object inheriting from this
        # mixin or a legacy object with an AccessController
        parent = self.protection_parent
        if parent is None:
            # This should be the case for the top-level object,
            # i.e. the root category
            return False
        elif hasattr(parent, 'can_manage'):
            return parent.can_manage(user, allow_admin=allow_admin)
        else:
            raise TypeError('protection_parent of {} is of invalid type {} ({})'.format(self, type(parent), parent))