aboutsummaryrefslogtreecommitdiff
path: root/src/hydrilla/proxy/state.py
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-07-27 15:56:24 +0200
committerWojtek Kosior <koszko@koszko.org>2022-08-10 17:25:05 +0200
commit879c41927171efc8d77d1de2739b18e2eb57580f (patch)
treede0e78afe2ea49e58c9bf2c662657392a00139ee /src/hydrilla/proxy/state.py
parent52d12a4fa124daa1595529e3e7008276a7986d95 (diff)
downloadhaketilo-hydrilla-879c41927171efc8d77d1de2739b18e2eb57580f.tar.gz
haketilo-hydrilla-879c41927171efc8d77d1de2739b18e2eb57580f.zip
unfinished partial work
Diffstat (limited to 'src/hydrilla/proxy/state.py')
-rw-r--r--src/hydrilla/proxy/state.py279
1 files changed, 251 insertions, 28 deletions
diff --git a/src/hydrilla/proxy/state.py b/src/hydrilla/proxy/state.py
index fc01536..e22c9fe 100644
--- a/src/hydrilla/proxy/state.py
+++ b/src/hydrilla/proxy/state.py
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
-# Haketilo proxy data and configuration.
+# Haketilo proxy data and configuration (interface definition through abstract
+# class).
#
# This file is part of Hydrilla&Haketilo.
#
@@ -25,49 +26,271 @@
# in a proprietary program, I am not going to enforce this in court.
"""
-This module contains logic for keeping track of all settings, rules, mappings
-and resources.
+This module defines API for keeping track of all settings, rules, mappings and
+resources.
"""
# Enable using with Python 3.7.
from __future__ import annotations
-import typing as t
import dataclasses as dc
+import typing as t
-from threading import Lock
from pathlib import Path
+from abc import ABC, abstractmethod
+from enum import Enum
+
+from immutables import Map
+
+from ..versions import VerTuple
+from ..url_patterns import ParsedPattern
+
+
+class EnabledStatus(Enum):
+ """
+ ENABLED - User wished to always apply given mapping when it matched.
+
+ DISABLED - User wished to never apply given mapping.
+
+ AUTO_ENABLED - User has not configured given mapping but it will still be
+ used when automatic application of mappings is turned on.
+
+ NO_MARK - User has not configured given mapping and it won't be used.
+ """
+ ENABLED = 'E'
+ DISABLED = 'D'
+ AUTO_ENABLED = 'A'
+ NO_MARK = 'N'
+
+@dc.dataclass(frozen=True, unsafe_hash=True)
+class Ref:
+ """...."""
+ id: str
+
+
+# mypy needs to be corrected:
+# https://stackoverflow.com/questions/70999513/conflict-between-mix-ins-for-abstract-dataclasses/70999704#70999704
+@dc.dataclass(frozen=True, unsafe_hash=True) # type: ignore[misc]
+class RepoRef(Ref):
+ """...."""
+ @abstractmethod
+ def remove(self, state: 'HaketiloState') -> None:
+ """...."""
+ ...
+
+ @abstractmethod
+ def update(
+ self,
+ state: 'HaketiloState',
+ *,
+ name: t.Optional[str] = None,
+ url: t.Optional[str] = None
+ ) -> 'RepoRef':
+ """...."""
+ ...
+
+ @abstractmethod
+ def refresh(self, state: 'HaketiloState') -> 'RepoIterationRef':
+ """...."""
+ ...
-from ..pattern_tree import PatternTree
-from .store import HaketiloStore
-from . import policies
-def make_pattern_tree_with_builtin_policies() -> PatternTree[policies.Policy]:
+@dc.dataclass(frozen=True, unsafe_hash=True) # type: ignore[misc]
+class RepoIterationRef(Ref):
"""...."""
- # TODO: implement
- return PatternTree()
+ pass
-tree_field = dc.field(default_factory=make_pattern_tree_with_builtin_policies)
-@dc.dataclass
-class HaketiloState(HaketiloStore):
+@dc.dataclass(frozen=True, unsafe_hash=True) # type: ignore[misc]
+class MappingRef(Ref):
"""...."""
- pattern_tree: PatternTree[policies.Policy] = tree_field
- default_allow: bool = False
+ @abstractmethod
+ def disable(self, state: 'HaketiloState') -> None:
+ """...."""
+ ...
+
+ @abstractmethod
+ def forget_enabled(self, state: 'HaketiloState') -> None:
+ """...."""
+ ...
- state_lock: Lock = dc.field(default_factory=Lock)
- def select_policy(self, url: str, allow_disabled=False) -> policies.Policy:
+@dc.dataclass(frozen=True, unsafe_hash=True) # type: ignore[misc]
+class MappingVersionRef(Ref):
+ """...."""
+ @abstractmethod
+ def enable(self, state: 'HaketiloState') -> None:
"""...."""
- with self.state_lock:
- pattern_tree = self.pattern_tree
+ ...
+
+@dc.dataclass(frozen=True, unsafe_hash=True) # type: ignore[misc]
+class ResourceRef(Ref):
+ """...."""
+ pass
+
- try:
- for policy_set in pattern_tree.search(url):
- # if policy.enabled or allow_disabled:
- # return policy
- pass
+@dc.dataclass(frozen=True, unsafe_hash=True) # type: ignore[misc]
+class ResourceVersionRef(Ref):
+ """...."""
+ pass
- return policies.FallbackBlockPolicy()
- except Exception as e:
- return policies.ErrorBlockPolicy(e)
+
+@dc.dataclass(frozen=True)
+class PayloadKey:
+ """...."""
+ payload_ref: 'PayloadRef'
+
+ mapping_identifier: str
+ # mapping_version: VerTuple
+ # mapping_repo: str
+ # mapping_repo_iteration: int
+ pattern: ParsedPattern
+
+ def __lt__(self, other: 'PayloadKey') -> bool:
+ """...."""
+ return (
+ self.mapping_identifier,
+ # other.mapping_version,
+ # self.mapping_repo,
+ # other.mapping_repo_iteration,
+ self.pattern
+ ) < (
+ other.mapping_identifier,
+ # self.mapping_version,
+ # other.mapping_repo,
+ # self.mapping_repo_iteration,
+ other.pattern
+ )
+
+@dc.dataclass(frozen=True)
+class PayloadData:
+ """...."""
+ payload_ref: 'PayloadRef'
+
+ mapping_installed: bool
+ explicitly_enabled: bool
+ unique_token: str
+ pattern: ParsedPattern
+ eval_allowed: bool
+ cors_bypass_allowed: bool
+
+@dc.dataclass(frozen=True)
+class FileData:
+ type: str
+ name: str
+ contents: bytes
+
+@dc.dataclass(frozen=True, unsafe_hash=True) # type: ignore[misc]
+class PayloadRef(Ref):
+ """...."""
+ @abstractmethod
+ def get_data(self, state: 'HaketiloState') -> PayloadData:
+ """...."""
+ ...
+
+ @abstractmethod
+ def get_mapping(self, state: 'HaketiloState') -> MappingVersionRef:
+ """...."""
+ ...
+
+ @abstractmethod
+ def get_script_paths(self, state: 'HaketiloState') \
+ -> t.Iterable[t.Sequence[str]]:
+ """...."""
+ ...
+
+ @abstractmethod
+ def get_file_data(self, state: 'HaketiloState', path: t.Sequence[str]) \
+ -> t.Optional[FileData]:
+ """...."""
+ ...
+
+
+class MappingUseMode(Enum):
+ """
+ AUTO - Apply mappings except for those explicitly disabled.
+
+ WHEN_ENABLED - Only apply mappings explicitly marked as enabled. Don't apply
+ unmarked nor explicitly disabled mappings.
+
+ QUESTION - Automatically apply mappings that are explicitly enabled. Ask
+ whether to enable unmarked mappings. Don't apply explicitly disabled
+ ones.
+ """
+ AUTO = 'A'
+ WHEN_ENABLED = 'W'
+ QUESTION = 'Q'
+
+@dc.dataclass(frozen=True)
+class HaketiloGlobalSettings:
+ """...."""
+ mapping_use_mode: MappingUseMode
+ default_allow_scripts: bool
+ repo_refresh_seconds: int
+
+
+class MissingItemError(ValueError):
+ """...."""
+ pass
+
+
+class HaketiloState(ABC):
+ """...."""
+ @abstractmethod
+ def get_repo(self, repo_id: str) -> RepoRef:
+ """...."""
+ ...
+
+ @abstractmethod
+ def get_repo_iteration(self, repo_iteration_id: str) -> RepoIterationRef:
+ """...."""
+ ...
+
+ @abstractmethod
+ def get_mapping(self, mapping_id: str) -> MappingRef:
+ """...."""
+ ...
+
+ @abstractmethod
+ def get_mapping_version(self, mapping_version_id: str) \
+ -> MappingVersionRef:
+ """...."""
+ ...
+
+ @abstractmethod
+ def get_resource(self, resource_id: str) -> ResourceRef:
+ """...."""
+ ...
+
+ @abstractmethod
+ def get_resource_version(self, resource_version_id: str) \
+ -> ResourceVersionRef:
+ """...."""
+ ...
+
+ @abstractmethod
+ def get_payload(self, payload_id: str) -> PayloadRef:
+ """...."""
+ ...
+
+ @abstractmethod
+ def add_repo(self, name: t.Optional[str], url: t.Optional[str]) \
+ -> RepoRef:
+ """...."""
+ ...
+
+ @abstractmethod
+ def get_settings(self) -> HaketiloGlobalSettings:
+ """...."""
+ ...
+
+ @abstractmethod
+ def update_settings(
+ self,
+ *,
+ mapping_use_mode: t.Optional[MappingUseMode] = None,
+ default_allow_scripts: t.Optional[bool] = None,
+ repo_refresh_seconds: t.Optional[int] = None
+ ) -> None:
+ """...."""
+ ...