Search code examples
pythonpermissionsflaskaclflask-principal

Combining RoleNeed's with Flask Principal


I'm trying to create a permission that requires that the user has role A or role B.

According to Python Flask Principal documentation, the following line creates a permission that requires the user has roleA AND roleB.

combined_permission = Permission(RoleNeed('roleA'), RoleNeed('roleB'))

Do you know how to create a permission relying on a OR instead of a AND ?


Solution

  • As it currently stands, needs of a combined permission are checked with an OR. Quoting from the documentation:

    class flask_principal.Permission(*needs)
    Represents needs, any of which must be present to access a resource

    If you want an AND instead, simply sub-class the Permission class and override the allows method to check that intersection of the sets is the same as the needs of the permission in the first place:

    class RequiresAll(Permission):
        def allows(self, identity):
            if not has_all(self.needs, identity.provides):
                return False
    
            if self.excludes and self.excludes.intersection(identity.provides):
                return False
    
            return True
    
    def has_all(needed=None, provided=None):
        if needed is None:
            return True
    
        if provided is None:
            provided = set()
    
        shared = needed.intersection(provided)
        return shared == needed