api-foundry-query-engine 0.8.33__tar.gz → 0.8.34__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/PKG-INFO +1 -1
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/dao/sql_update_query_handler.py +86 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/pyproject.toml +1 -1
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/.gitignore +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/LICENSE +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/.pre-commit-config.yaml +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/__init__.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/adapters/adapter.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/adapters/case_change_adapter.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/adapters/gateway_adapter.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/adapters/security_adapter.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/connectors/connection.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/connectors/connection_factory.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/connectors/oracle_connector.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/connectors/postgres_connection.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/dao/batch_operation_handler.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/dao/dao.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/dao/operation_dao.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/dao/sql_custom_query_handler.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/dao/sql_delete_query_handler.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/dao/sql_insert_query_handler.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/dao/sql_query_handler.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/dao/sql_restore_query_handler.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/dao/sql_select_query_handler.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/dao/sql_subselect_query_handler.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/lambda_handler.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/operation.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/services/service.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/services/transactional_service.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/utils/api_model.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/utils/app_exception.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/utils/claims_check.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/utils/dependency_resolver.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/utils/gateway_operation.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/utils/logger.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/utils/reference_resolver.py +0 -0
- {api_foundry_query_engine-0.8.33 → api_foundry_query_engine-0.8.34}/api_foundry_query_engine/utils/token_decoder.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: api-foundry-query-engine
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.34
|
|
4
4
|
Summary: The AWS lambda service handler use by the `api_foundry` project is a powerful tool designed to automate the deployment of REST APIs on AWS using Lambda services to access and interact with relational databases (RDBMS). This project leverages the OpenAPI specification to define and manage the APIs
|
|
5
5
|
Project-URL: Documentation, https://github.com/DanRepik/api-foundry
|
|
6
6
|
Project-URL: Source, https://github.com/DanRepik/api-foundry
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Match
|
|
1
3
|
from api_foundry_query_engine.dao.sql_query_handler import SQLSchemaQueryHandler
|
|
2
4
|
from api_foundry_query_engine.operation import Operation
|
|
3
5
|
from api_foundry_query_engine.utils.app_exception import ApplicationException
|
|
@@ -10,6 +12,68 @@ class SQLUpdateSchemaQueryHandler(SQLSchemaQueryHandler):
|
|
|
10
12
|
) -> None:
|
|
11
13
|
super().__init__(operation, schema_object, engine)
|
|
12
14
|
|
|
15
|
+
def _template_where(self, expr: str) -> str:
|
|
16
|
+
"""Template substitution for WHERE clause expressions with claim values."""
|
|
17
|
+
if not expr:
|
|
18
|
+
return expr
|
|
19
|
+
|
|
20
|
+
def _quote(val: object) -> str:
|
|
21
|
+
if val is None:
|
|
22
|
+
return "NULL"
|
|
23
|
+
if isinstance(val, (int, float)):
|
|
24
|
+
return str(val)
|
|
25
|
+
s = str(val).replace("'", "''")
|
|
26
|
+
return f"'{s}'"
|
|
27
|
+
|
|
28
|
+
def _replace(m: Match[str]) -> str:
|
|
29
|
+
key = m.group(1)
|
|
30
|
+
claims = self.operation.claims or {}
|
|
31
|
+
return _quote(claims.get(key))
|
|
32
|
+
|
|
33
|
+
return re.sub(r"\$\{claims\.([A-Za-z0-9_]+)\}", _replace, expr)
|
|
34
|
+
|
|
35
|
+
def _row_where_clause(self) -> str:
|
|
36
|
+
"""
|
|
37
|
+
Generate row-level WHERE clause based on write permissions.
|
|
38
|
+
Only applies to UPDATE operations, not CREATE.
|
|
39
|
+
"""
|
|
40
|
+
perms = getattr(self.schema_object, "permissions", None) or {}
|
|
41
|
+
# provider-first default
|
|
42
|
+
if "default" in perms:
|
|
43
|
+
provider = perms.get("default", {}) or {}
|
|
44
|
+
write_map = provider.get("write", {}) or {}
|
|
45
|
+
role_permissions = perms.get("default", {})
|
|
46
|
+
else:
|
|
47
|
+
# legacy role-first -> synthesize write map
|
|
48
|
+
write_map = {}
|
|
49
|
+
role_permissions = perms
|
|
50
|
+
for role, role_perms in perms.items():
|
|
51
|
+
if isinstance(role_perms, dict):
|
|
52
|
+
write_map[role] = role_perms.get("write")
|
|
53
|
+
|
|
54
|
+
filters = []
|
|
55
|
+
for role in self.operation.roles or []:
|
|
56
|
+
# Check for role-level WHERE clause (hybrid approach)
|
|
57
|
+
role_where = None
|
|
58
|
+
if isinstance(role_permissions.get(role), dict):
|
|
59
|
+
role_where = role_permissions[role].get("where")
|
|
60
|
+
|
|
61
|
+
# Check for operation-level WHERE clause
|
|
62
|
+
operation_where = None
|
|
63
|
+
rule = write_map.get(role)
|
|
64
|
+
if isinstance(rule, dict):
|
|
65
|
+
operation_where = rule.get("where")
|
|
66
|
+
|
|
67
|
+
# Operation-level takes precedence, fallback to role-level
|
|
68
|
+
where_clause = operation_where if operation_where else role_where
|
|
69
|
+
|
|
70
|
+
if isinstance(where_clause, str) and where_clause.strip():
|
|
71
|
+
filters.append(self._template_where(where_clause))
|
|
72
|
+
|
|
73
|
+
if not filters:
|
|
74
|
+
return ""
|
|
75
|
+
return "(" + ") OR (".join(filters) + ")"
|
|
76
|
+
|
|
13
77
|
@property
|
|
14
78
|
def sql(self) -> str:
|
|
15
79
|
concurrency_property = self.schema_object.concurrency_property
|
|
@@ -109,3 +173,25 @@ class SQLUpdateSchemaQueryHandler(SQLSchemaQueryHandler):
|
|
|
109
173
|
f"Subject does not have permission to update properties: {invalid_columns}",
|
|
110
174
|
)
|
|
111
175
|
return f" SET {', '.join(columns)}"
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def search_condition(self) -> str:
|
|
179
|
+
"""
|
|
180
|
+
Override to add permission-based WHERE clause for UPDATE operations.
|
|
181
|
+
"""
|
|
182
|
+
# Get the base search condition from parent class
|
|
183
|
+
base_condition = super().search_condition
|
|
184
|
+
|
|
185
|
+
# Get row-level permission filters
|
|
186
|
+
row_filter = self._row_where_clause()
|
|
187
|
+
|
|
188
|
+
# If we have both, combine them
|
|
189
|
+
if base_condition and row_filter:
|
|
190
|
+
# base_condition already has " WHERE ", so add AND
|
|
191
|
+
return f"{base_condition} AND ({row_filter})"
|
|
192
|
+
elif row_filter:
|
|
193
|
+
# Only row filter, add WHERE prefix
|
|
194
|
+
return f" WHERE ({row_filter})"
|
|
195
|
+
else:
|
|
196
|
+
# Only base condition or neither
|
|
197
|
+
return base_condition
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|