Source code for pigauth._matcher

import abc
from types import SimpleNamespace
from typing import Iterable

from ._auth import Permission


[docs]class MatchContext(SimpleNamespace): """MatchContext is passed to matchers""" pass
class PermissionMatcher: """Abstract PermissionMatcher""" for_modifier: str @abc.abstractmethod def matches(self, permission: Permission, context: MatchContext) -> bool: """Match permission""" class RequiresMatcher(PermissionMatcher): """Matches modifiers required by permission against supplied modifiers""" def __init__(self, modifier_names: Iterable[str]): self.modifier_names = list(modifier_names) def matches(self, permission: Permission, context: MatchContext) -> bool: return all( [ required_modifier in self.modifier_names for required_modifier in permission.requires ] ) class RegexMatcher(PermissionMatcher): """Matches permission ID against regular expression pattern""" def __init__(self, regex): self.regex = regex def matches(self, permission: Permission, context: MatchContext) -> bool: return bool(self.regex.fullmatch(permission.permission_id)) class AnyMatcher(PermissionMatcher): """Matches if any of the supplied matchers matches""" def __init__(self, matchers: Iterable[PermissionMatcher]) -> None: self.matchers = list(matchers) def matches(self, permission: Permission, context: MatchContext) -> bool: return any([matcher.matches(permission, context) for matcher in self.matchers]) class AllMatcher(PermissionMatcher): """Matches if all of the supplied matchers match""" def __init__(self, matchers: Iterable[PermissionMatcher]) -> None: self.matchers = list(matchers) def matches(self, permission: Permission, context: MatchContext) -> bool: return all([matcher.matches(permission, context) for matcher in self.matchers]) class ModifierMatcherFactory: """Create PermissionMatcher instance for modifier name""" MODIFIER_ATTR_NAME = "for_modifier" def __call__(self, modifier_name: str): for klass in PermissionMatcher.__subclasses__(): if getattr(klass, self.MODIFIER_ATTR_NAME, None) == modifier_name: return klass() return None