aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Baumgartner <dev@igsor.net>2023-03-02 16:40:43 +0100
committerMatthias Baumgartner <dev@igsor.net>2023-03-02 16:40:43 +0100
commit6b9379d75198082054c35e44bc2cd880353a7485 (patch)
tree1c6f88b10eb4b532a26f2a9dc26bc938e81e7032
parent28a021483c13e974e00b6159f0653b0727df9d10 (diff)
downloadbsfs-6b9379d75198082054c35e44bc2cd880353a7485.tar.gz
bsfs-6b9379d75198082054c35e44bc2cd880353a7485.tar.bz2
bsfs-6b9379d75198082054c35e44bc2cd880353a7485.zip
hardening
-rw-r--r--bsfs/graph/graph.py16
-rw-r--r--bsfs/graph/nodes.py8
-rw-r--r--bsfs/graph/resolve.py8
-rw-r--r--bsfs/query/validator.py10
-rw-r--r--test/graph/test_resolve.py2
-rw-r--r--test/query/test_validator.py4
6 files changed, 27 insertions, 21 deletions
diff --git a/bsfs/graph/graph.py b/bsfs/graph/graph.py
index ade51a5..1b4c212 100644
--- a/bsfs/graph/graph.py
+++ b/bsfs/graph/graph.py
@@ -36,12 +36,6 @@ class Graph():
# access controls.
_ac: ac.AccessControlBase
- # query resolver.
- _resolver: resolve.Filter
-
- # query validator.
- _validate: validate.Filter
-
def __init__(
self,
backend: TripleStoreBase,
@@ -50,9 +44,6 @@ class Graph():
# store members
self._backend = backend
self._ac = access_control
- # helper classes
- self._resolver = resolve.Filter(self._backend.schema)
- self._validate = validate.Filter(self._backend.schema)
# ensure Graph schema requirements
self.migrate(self._backend.schema)
@@ -94,9 +85,6 @@ class Graph():
# migrate schema in backend
# FIXME: consult access controls!
self._backend.schema = schema
- # re-initialize members
- self._resolver.schema = self.schema
- self._validate.schema = self.schema
# return self
return self
@@ -164,12 +152,12 @@ class Graph():
# get node type
type_ = self.schema.node(node_type)
# resolve Nodes instances
- query = self._resolver(type_, query)
+ query = resolve.Filter(self._backend.schema).resolve(type_, query)
# add access controls to query
query = self._ac.filter_read(type_, query)
# validate query
if query is not None:
- self._validate(type_, query)
+ validate.Filter(self._backend.schema).validate(type_, query)
# query the backend and return the (non-materialized) result
return self._backend.get(type_, query)
diff --git a/bsfs/graph/nodes.py b/bsfs/graph/nodes.py
index 84996c7..74f4c4f 100644
--- a/bsfs/graph/nodes.py
+++ b/bsfs/graph/nodes.py
@@ -25,7 +25,9 @@ __all__: typing.Sequence[str] = (
## code ##
class Nodes():
- """
+ """Container for graph nodes, provides operations on nodes.
+
+ NOTE: Should not be created directly but only via `bsfs.graph.Graph`.
NOTE: guids may or may not exist. This is not verified as nodes are created on demand.
"""
@@ -255,8 +257,8 @@ class Nodes():
filter = self._ac.filter_read(self.node_type, filter) # type: ignore [assignment]
# validate queries
- validate.Filter(self._backend.schema)(self.node_type, filter)
- validate.Fetch(self._backend.schema)(self.node_type, fetch)
+ validate.Filter(self._backend.schema).validate(self.node_type, filter)
+ validate.Fetch(self._backend.schema).validate(self.node_type, fetch)
# process results, convert if need be
def triple_iter():
diff --git a/bsfs/graph/resolve.py b/bsfs/graph/resolve.py
index 213ac4c..0ba1e36 100644
--- a/bsfs/graph/resolve.py
+++ b/bsfs/graph/resolve.py
@@ -40,6 +40,14 @@ class Filter():
root_type: bsc.Node,
node: typing.Optional[ast.filter.FilterExpression],
):
+ """Alias for `Resolve.resolve`."""
+ return self.resolve(root_type, node)
+
+ def resolve(
+ self,
+ root_type: bsc.Node,
+ node: typing.Optional[ast.filter.FilterExpression],
+ ):
if node is None:
return None
return self._parse_filter_expression(root_type, node)
diff --git a/bsfs/query/validator.py b/bsfs/query/validator.py
index 6e3afa1..b259ea0 100644
--- a/bsfs/query/validator.py
+++ b/bsfs/query/validator.py
@@ -37,6 +37,10 @@ class Filter():
self.schema = schema
def __call__(self, root_type: bsc.Node, query: ast.filter.FilterExpression):
+ """Alias for `Filter.validate`."""
+ return self.validate(root_type, query)
+
+ def validate(self, root_type: bsc.Node, query: ast.filter.FilterExpression):
"""Validate a filter *query*, assuming the subject having *root_type*.
Raises a `bsfs.utils.errors.ConsistencyError` if the query violates the schema.
@@ -237,7 +241,11 @@ class Fetch():
def __init__(self, schema: bsc.Schema):
self.schema = schema
- def __call__(self, root_type: bsc.Node, query: ast.fetch.FetchExpression):
+ def __call__(self, root_type: bsc.Node, query: ast.filter.FilterExpression):
+ """Alias for `Fetch.validate`."""
+ return self.validate(root_type, query)
+
+ def validate(self, root_type: bsc.Node, query: ast.fetch.FetchExpression):
"""Validate a fetch *query*, assuming the subject having *root_type*.
Raises a `bsfs.utils.errors.ConsistencyError` if the query violates the schema.
diff --git a/test/graph/test_resolve.py b/test/graph/test_resolve.py
index 0223c49..accb565 100644
--- a/test/graph/test_resolve.py
+++ b/test/graph/test_resolve.py
@@ -25,7 +25,7 @@ class TestFilter(unittest.TestCase):
"""
- def test_call(self):
+ def test_call(self): # tests resolve implicitly
schema = bsc.from_string('''
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
diff --git a/test/query/test_validator.py b/test/query/test_validator.py
index ca93118..bbfd2e6 100644
--- a/test/query/test_validator.py
+++ b/test/query/test_validator.py
@@ -70,7 +70,7 @@ class TestFilter(unittest.TestCase):
''')
self.validate = Filter(self.schema)
- def test_call(self):
+ def test_call(self): # tests validate implicitly
# root_type must be a _schema.Node
self.assertRaises(TypeError, self.validate, 1234, None)
self.assertRaises(TypeError, self.validate, '1234', None)
@@ -309,7 +309,7 @@ class TestFetch(unittest.TestCase):
''')
self.validate = Fetch(self.schema)
- def test_call(self):
+ def test_call(self): # tests validate implicitly
# call accepts correct expressions
self.assertTrue(self.validate(self.schema.node(ns.bsfs.Entity),
ast.fetch.Fetch(ns.bse.tag, ast.fetch.Value(ns.bse.label, 'value'))))