Source code for Acquire.Storage._aclrule



__all__ = ["ACLRule"]


def _max(a, b):
    """Function to do most-permissive addition of two bools

        True + True = True
        True + False = True
        False + True = True
        False + False = False

        True + None = True
        None + True = True

        False + None = False
        None + False = False

        None + None = None
    """
    if a is None:
        return b
    elif b is None:
        return a
    elif a is True:
        return True
    else:
        return b


def _sub(a, b):
    """Function to do subtraction of two bools

        True - True = False
        True - False = True
        False - True = False
        False - False = False

        True - None = True
        None - True = False

        False - None = False
        None - False = None

        None - None = None
    """
    if b is True:
        return False
    else:
        return a


def _min(a, b):
    """Function to do least-permission addition of two bools

        True * True = True
        True * False = False
        False * True = False
        False * False = False

        True * None = True
        None * True = True

        False * None = False
        None * False = False

        None - None = None
    """
    if a is None:
        return b
    elif b is None:
        return a
    elif a is False:
        return False
    else:
        return b


[docs]class ACLRule: """This class holds the access control list (ACL) rule for a particular user accessing a particular resource """ def __init__(self, is_owner=None, is_readable=None, is_writeable=None, is_executable=None): """Construct a default rule. By default this rule has fully-inherit permissions (nothing is set either way) """ if is_owner is None: self._is_owner = None elif is_owner: self._is_owner = True else: self._is_owner = False if is_readable is None: self._is_readable = None elif is_readable: self._is_readable = True else: self._is_readable = False if is_writeable is None: self._is_writeable = None elif is_writeable: self._is_writeable = True else: self._is_writeable = False if is_executable is None: self._is_executable = None elif is_executable: self._is_executable = True else: self._is_executable = False def __str__(self): s = [] if self.is_owner(): s.append("owner") elif self.inherits_owner(): s.append("inherits_owner") if self.is_writeable(): s.append("writeable") elif self.inherits_writeable(): s.append("inherits_writeable") if self.is_readable(): s.append("readable") elif self.inherits_readable(): s.append("inherits_readable") if self.is_executable(): s.append("executable") elif self.inherits_executable(): s.append("inherits_executable") if len(s) == 0: return "ACLRule::denied" else: return "ACLRule(%s)" % ", ".join(s) def __eq__(self, other): if isinstance(other, self.__class__): return self.__dict__ == other.__dict__ else: return False def __add__(self, other): """Add two rules together - this will combine the parts additively, i.e. the most-permissive options are set in the return value """ if not isinstance(other, ACLRule): raise TypeError( "You can only combine together pairs of ACLRules") return ACLRule( is_owner=_max(self._is_owner, other._is_owner), is_writeable=_max(self._is_writeable, other._is_writeable), is_readable=_max(self._is_readable, other._is_readable), is_executable=_max(self._is_executable, other._is_executable)) def __sub__(self, other): """Subtract 'other' from these rules - if 'other' is False the this is set to False """ if not isinstance(other, ACLRule): raise TypeError( "You can only combine together pairs of ACLRules") return ACLRule( is_owner=_sub(self._is_owner, other._is_owner), is_writeable=_sub(self._is_writeable, other._is_writeable), is_readable=_sub(self._is_readable, other._is_readable), is_executable=_sub(self._is_executable, other._is_executable)) def __mul__(self, other): """Combine two rules together - this will combine the parts subtractively, i.e. the least permissive options are set in the return value """ if not isinstance(other, ACLRule): raise TypeError( "You can only combine together pairs of ACLRules") return ACLRule( is_owner=_min(self._is_owner, other._is_owner), is_writeable=_min(self._is_writeable, other._is_writeable), is_readable=_min(self._is_readable, other._is_readable), is_executable=_min(self._is_executable, other._is_executable))
[docs] @staticmethod def owner(): """Return the ACLRule of an owner""" return ACLRule(is_owner=True, is_readable=True, is_writeable=True, is_executable=True)
[docs] @staticmethod def executer(): """Return the ACLRule of an executer""" return ACLRule(is_owner=False, is_executable=True, is_writeable=True, is_readable=True)
[docs] @staticmethod def writer(): """Return the ACLRule of a writer""" return ACLRule(is_owner=False, is_readable=True, is_writeable=True, is_executable=False)
[docs] @staticmethod def reader(): """Return the ACLRule of a reader""" return ACLRule(is_owner=False, is_readable=True, is_writeable=False, is_executable=False)
[docs] @staticmethod def denied(): """Return a "denied" (no-access at all) permission rule""" return ACLRule(is_owner=False, is_readable=False, is_writeable=False, is_executable=False)
[docs] @staticmethod def null(): """Return a null (inherit all permissions) rule""" return ACLRule(is_owner=None, is_readable=None, is_writeable=None, is_executable=None)
[docs] @staticmethod def inherit(): """Return the ACL rule that means 'inherit permissions from parent'""" return ACLRule(is_owner=None, is_readable=None, is_writeable=None, is_executable=None)
[docs] def is_owner(self): """Return whether or not the user is the owner of this resource""" return self._is_owner
[docs] def is_readable(self): """Return whether or not the user can read this resource""" return self._is_readable
[docs] def is_writeable(self): """Return whether or not the user can write to this resource""" return self._is_writeable
[docs] def is_executable(self): """Return whether or not the user can execute this resource""" return self._is_executable
[docs] def inherits_owner(self): """Return whether or not this inherits the owner status from upstream """ return self._is_owner is None
[docs] def inherits_readable(self): """Return whether or not this inherits the reader status from upstream """ return self._is_readable is None
[docs] def inherits_writeable(self): """Return whether or not this inherits the writeable status from upstream """ return self._is_writeable is None
[docs] def inherits_executable(self): """Return whether or not this inherits the executable status from upstream """ return self._is_executable is None
[docs] def inherits_all(self): """Return whether or not this rule inherits all permissions""" return (self._is_owner is None) and \ (self._is_readable is None) and \ (self._is_writeable is None) and \ (self._is_executable is None)
[docs] def is_fully_resolved(self): """Return whether or not this rule is fully resolved""" return (self._is_owner is not None) and \ (self._is_readable is not None) and \ (self._is_writeable is not None) and \ (self._is_executable is not None)
[docs] def denied_all(self): """Return whether or not this rule shows that everything is denied """ return (self._is_owner is False) and \ (self._is_readable is False) and \ (self._is_writeable is False) and \ (self._is_executable is False)
def _force_resolve(self, unresolved=False): """This returns a fully resolved ACL, where anything that is not resolved is set equal to 'unresolved' """ if unresolved: unresolved = True else: unresolved = False is_owner = self._is_owner is_readable = self._is_readable is_writeable = self._is_writeable is_executable = self._is_executable if is_owner is None: is_owner = unresolved if is_readable is None: is_readable = unresolved if is_executable is None: is_executable = unresolved if is_writeable is None: is_writeable = unresolved return ACLRule(is_owner=is_owner, is_writeable=is_writeable, is_readable=is_readable, is_executable=is_executable)
[docs] def resolve(self, must_resolve=True, **kwargs): """Resolve these rules based on the information supplied in 'kwargs'. Notably, if any of our rules are 'inherit', the this will look for an ACLRule called "upstream" to inherit the rule. If 'must_resolve' is true, then this function must always return a fully-resolved ACLRule """ if self.is_fully_resolved(): return self if "unresolved" in kwargs: unresolved = kwargs["unresolved"] else: unresolved = False if "upstream" not in kwargs: if must_resolve: return self._force_resolve(unresolved=unresolved) else: return self upstream = kwargs["upstream"] if not upstream.is_fully_resolved(): del kwargs["upstream"] upstream = upstream.resolve(must_resolve=must_resolve, **kwargs) if must_resolve and (not upstream.is_fully_resolved()): upstream = upstream._force_resolve(unresolved=unresolved) is_owner = self._is_owner is_readable = self._is_readable is_writeable = self._is_writeable is_executable = self._is_executable if is_owner is None: is_owner = upstream._is_owner if is_readable is None: is_readable = upstream._is_readable if is_writeable is None: is_writeable = upstream._is_writeable if is_executable is None: is_executable = upstream._is_executable return ACLRule(is_owner=is_owner, is_writeable=is_writeable, is_readable=is_readable, is_executable=is_executable)
[docs] def set_owner(self, is_owner=True): """Set the user as an owner of the bucket""" if is_owner: self._is_owner = True else: self._is_owner = False
[docs] def set_readable(self, is_readable=True): """Set the readable rule to 'is_readable'""" if is_readable: self._is_readable = True else: self._is_readable = False
[docs] def set_writeable(self, is_writeable=True): """Set the writeable rule to 'is_writeable'""" if is_writeable: self._is_writeable = True else: self._is_writeable = False
[docs] def set_inherits_owner(self): """Set that this ACL inherits ownership from its parent""" self._is_owner = None
[docs] def set_inherits_readable(self): """Set that this ACL inherits readable from its parent""" self._is_readable = None
[docs] def set_inherits_writeable(self): """Set that this ACL inherits writeable from its parent""" self._is_writeable = None
[docs] def set_readable_writeable(self, is_readable_writeable=True): """Set both the readable and writeable rules to 'is_readable_writeable' """ if is_readable_writeable: self._is_readable = True self._is_writeable = True else: self._is_readable = False self._is_writeable = False
[docs] def to_data(self): """Return this object converted to a json-serialisable object""" if self.inherits_all(): return "inherits" elif self == ACLRule.owner(): return "owner" elif self == ACLRule.reader(): return "reader" elif self == ACLRule.writer(): return "writer" elif self == ACLRule.denied(): return "denied" elif self == ACLRule.executer(): return "executer" else: data = {} data["is_owner"] = self._is_owner data["is_readable"] = self._is_readable data["is_writeable"] = self._is_writeable return data
[docs] @staticmethod def from_data(data): """Return this object constructed from the passed json-deserialised dictionary """ if data is None: return None if isinstance(data, str): if data == "inherits": return ACLRule.inherit() elif data == "owner": return ACLRule.owner() elif data == "reader": return ACLRule.reader() elif data == "writer": return ACLRule.writer() elif data == "executer": return ACLRule.executer() elif data == "denied": return ACLRule.denied() is_owner = None is_readable = None is_writeable = None if "is_owner" in data: if data["is_owner"]: is_owner = True elif data["is_owner"] is not None: is_owner = False if "is_readable" in data: if data["is_readable"]: is_readable = True elif data["is_readable"] is not None: is_readable = False if "is_writeable" in data: if data["is_writeable"]: is_writeable = True elif data["is_writeable"] is not None: is_writeable = False return ACLRule(is_owner=is_owner, is_writeable=is_writeable, is_readable=is_readable)